• Mhendren (unregistered) in reply to foo
    foo:
    Do we get bonus point for obfuscation?

    void foo(char *in, char *out) { while(*out++=in==' '?++in:*in)in++; }

    ok, but you lose a point because you don't handle multiple spaces.

    static void remove_spaces (char s) { charp,*q;for (p=q=s; *p; *p != ' ' ? *q++ = *p++ : *p++);*q='\0'; }

    This was my ternary operator version.

  • Mario (unregistered) in reply to XIU
    XIU:
    Since this code is VB.NET it would just have been string.Replace(" ", "") The try catch is *probably* there for when the argument is null (Nothing in VB?) so that the function will return an empty string.
    I see no reason to use try catch to check for "nothing":

    If Not strFldNm is nothing then [blabla] Else return string.empty End If

    No overhead of exceptions here, and nothing with spaces removed is an empty string.

  • Zygo (unregistered) in reply to noone
    noone:
    And in the off chance you need to do an assignment and a test in one step, you simply use the following:

    if ((a = b) == 0)

    Compiler lets it through clean and it is very clear the assignment is intended.

    Until some damn fool writes:

    if ((a = b) == TRUE)

    then the whole thing falls flat on its face.

    Really, C++ only has a fixed set of about 30 operators, even if you count the duplicate union/binary operators like * and -. Yes you can redefine the behavior of some of them sometimes, but in C++ you can't make up new operators on the fly like "@!$" or "<<<", so your investment in memorizing the full set will pay off until the next revision of the ISO standard, probably even longer since they don't add new operators on every revision.

    It can't be that hard for people to finally learn what all the operators they use in C++ actually mean, so they can use assignment when they mean assignment and equality when they mean equality. If you can count parentheses and deference operators you can bloody well count equal signs too. There's no excuse for people who get confused and write

      if (**(*a[i])->it.S::foo() = **(*b[i])->it.S::foo)())

    when they obviously meant

      if (**(*a[i])->it.S::foo() == **(*b[i])->it.S::foo())

    Now try maintaining code written in a language which ships with 100+ operators for built-in types and allows users to define more at runtime--as in 'I think I'll define operator #$%@^@$!^$++ in this function...'

  • Zygo (unregistered) in reply to nausea
    nausea:
    If someone submitted this as a WTF, they shouldn't be working on the code. It seems to be some code migrated from VB6, which didn't have the .Replace functionality (if I remember correctly). The above function *was* actually a reasonably efficient way to remove spaces from a string in VB6. In .Net, you could of course just write the entire function as:

    myString.Replace(" ", "")

    A try block with an empty catch block in a string manipulating function is "reasonably efficient"?

  • (cs)

    Okay, I really couldn't resist my previous proposition.

    So here is the link to the parallel AJAX implementation of removewhitespaces

    iswhitespace.php just returns nothing if the parameter is a space, or else echoes the string provided. For extra fun I added random sleep to the php ... erm I mean extra heavy parallel processing to check if it's really a whitespace, to emulate real-life enterprisey conditions.

  • Andy Ross (unregistered)

    Scanned through four pages, and at a brief glance it seems I have the tightest one yet:

    void despace_in_place(char* s) { char* o = s; for(o = s; *s; s++) if(*s != ' ') *o++ = *s; *o = 0; }

  • protonfish (unregistered)
    aikii:
    Okay, I really couldn't resist my previous proposition.

    So here is the link to the parallel AJAX implementation of removewhitespaces

    iswhitespace.php just returns nothing if the parameter is a space, or else echoes the string provided. For extra fun I added random sleep to the php ... erm I mean extra heavy parallel processing to check if it's really a whitespace, to emulate real-life enterprisey conditions.

    Wow! I love how the characters appear randomly like when a movie hacker is cracking a password.

  • (cs) in reply to protonfish
    protonfish:
    Wow! I love how the characters appear randomly like when a movie hacker is cracking a password.

    That's exactly what happens. The WOPR tries to get the secret launch codes for the nuclear missiles by removing whitespaces from the bible. I love that scene of war games when he finds one digit at a time ! Well, brute force has to be photogenic.

  • Mario (unregistered)

    One addition, a more interesting way to do this in VB.Net...

      Public Shared Function Removespaces(ByVal strFldNm As String) As String
        Removespaces = String.Copy(CType(IIf(strFldNm = Nothing, String.Empty, strFldNm), String)).Replace(" ", "")
      End Function
    
  • Zygo (unregistered) in reply to Iago
    Iago:
    The "make my code ugly by reversing conditionals" approach fails as soon as you compare variables: writing "if (b = a)" for "if (a == b)" is not going to help!

    Just write:

    if (const_cast<const A &>(a) = b)

    This will work regardless of compiler warning settings, although it fails if somebody defines bool A::operator=(foo) const.

  • Zygo (unregistered) in reply to Zygo

    [quote user="Zygo"]

      if (**(*a[i])->it.S::foo() =  **(*b[i])->it.S::foo)())
      if (**(*a[i])->it.S::foo() == **(*b[i])->it.S::foo())

    Apparently there's no excuse for people who get extra )'s when they cut and paste either.

  • wolf550e (unregistered)

    I vote for autoconverted from legacy VB. We have coverted some old code from VB6 and it looked a bit like that in VB.net. Most of it has since been converted to the correct dotNET-ish way of doing things (using the standard library, OOP, try/catch vs. on error goto, etc.), but one can still find some gems like this hidden away in svn.

  • schlenk (unregistered)

    Tcl one, boring:

    string map {{ } {}} $str

    Michael

  • Joseph Newton (unregistered) in reply to Anonymous Tart
    Anonymous Tart:
    Virtually same algorithm, paramaterised the char to strip out, and more c-ified it.
    char* strip(char * src, char remove)
    {   
        char *p,*s; 
        p = s = src;
        for (; s && *s; ++s)
            if (remove != *s)
                *(p++) = *s;
        if (p)
            *p = '\0';
        return src;
    } 
    

    Your c++ one was interesting, in that it used C strings. A real C++ example would be..

    std::string&
    strip(std::string& str, const char remove)
    {
        str.erase(
            std::remove_if(str.begin(), str.end(), 
                    std::bind2nd(std::equal_to<char>(), remove)),
            str.end());
        return str;
    }
    

    Then there's Perl: D:\my_path>perl -e "($line = 'line with spaces') =~ s/ //g; print $line;" linewithspaces

    ..and that is in a DOS prompt, a less-than-friendly environment for perl -e

    [Captcha [and hang]: dubya -- what's good for Saddam...]

  • BillyBob (unregistered) in reply to WIldpeaks
    WIldpeaks:
    CrystalMethod:
    I don't know what toy programming language that first example is (VB? Pascal?), byt surely the "ByVal" means the function is passed a copy of the string, and therefore has no change to the string in the caller?
    Anyone with half a brain would recognize that it's not pascal. It's obvious VB, that's the only (afaik) with ByVal...

    Which languages can you be ignorant of and still be considered to have atleast half a brain? ;-)

  • Cheetah (unregistered)

    With 4 pages of responses, am I the only one so far to note that the VB function in the article only removes spaces in a very weird sense?

    1. It never modifies the input, fine, normal mode of operation.
    2. The only thing it ever concatenates onto the return value are the spaces! The return will be a string with all the spaces in the input "removed" and put together. E.g. RemoveSpaces("Hi There Bob") = "[space][space]".

    How could the author have not noticed this, and if they did, why would they possibly need that string of spaces? I've needed to count spaces before, but never extract them out into their own string.

  • (cs) in reply to aikii
    aikii:
    For extra fun I added random sleep to the php ... erm I mean extra heavy parallel processing to check if it's really a whitespace, to emulate real-life enterprisey conditions.

    /me cries from holding back fits of laughter in the cubicle farm

  • NefariousWheel (unregistered) in reply to Not telling you...

    Or in VMS DCL:

    new_line = f$edit(line, "COMPRESS")

  • (cs) in reply to Maks Verver

    Maybe it's just me, but the original function doesn't look like it does what we all think it does.

    It seems to be putting each space in RemoveSpaces, but not removing them from the original string in any way. Ie, if your incoming string was "hi there, sir", at the end of the function the string would remain intact and RemoveSpaces would be " ". Am I missing something? (I don't do any VB, so maybe I am)

  • po_boy (unregistered)

    /usr/bin/tr -d " "

    Captcha: SevereAnalBleeding

  • Nevin ":-)" (unregistered)

    If you really want to do it in place to a C style string in C++, the following one liner should work:

    std::remove(s, s + strlen(s) + 1, ' ');

  • BillyBob (unregistered) in reply to Botzinger Gulm
    Botzinger Gulm:
    It's not quite one-liner but close.
    void strnfilter(char* str, int c, size_t n)
    

    calling that function string_filter would cost you 3 characters but would have improved the readability of your code enormously.

  • facetious (unregistered) in reply to Cheetah
    Cheetah:
    With 4 pages of responses, am I the only one so far to note that the VB function in the article only removes spaces in a very weird sense?
    1. It never modifies the input, fine, normal mode of operation.
    2. The only thing it ever concatenates onto the return value are the spaces! The return will be a string with all the spaces in the input "removed" and put together. E.g. RemoveSpaces("Hi There Bob") = "[space][space]".

    How could the author have not noticed this, and if they did, why would they possibly need that string of spaces? I've needed to count spaces before, but never extract them out into their own string.

    Not quite there, eh..

    Check the line closely: If (x[i] == " ") Then Else y = y & x[i] Endif

    There's an "Else" in there - this terminates the "when the character is a space" condition and goes to the "when the character is not a space" condition.

  • foo (unregistered) in reply to Mhendren

    int foo(char *in, char *out) { return (*out = *in) && foo(++in, (*in)^' '?++out:out); }

    returns 0 on success.

    Obfuscation and recursion, what more could one possibly want?!

  • facetious (unregistered) in reply to BillyBob
    BillyBob:
    Botzinger Gulm:
    It's not quite one-liner but close.
    void strnfilter(char* str, int c, size_t n)
    

    calling that function string_filter would cost you 3 characters but would have improved the readability of your code enormously.

    Perhaps, but it isn't just string_filter.. It's filter_n_characters_of_string. And nobody wants to type that whole thing out. So what would you do? string_n_filter? Equally meaningless. Go with strnfilter - at least that's a common usage in C (what with strncpy and strncat and etc..).

  • FooBaz (unregistered) in reply to bstorer
    bstorer:
    Real Programmers use Prolog:
    is_not_space(Char):-	\+ char_type(Char,space).
    despace(Spaced,Despaced):-	sublist(is_not_space,Spaced,X), string_to_list(Despaced,X).
    
    In SWI-Prolog we get:
    47 ?- despace("This is a string!",X).
    X = "Thisisastring!" 
    Yes
    
    Zylon:
    This all would have been much more interesting if the task was instead to remove all EXTRA spaces, leaving only single spaces, if any.
    Not in Ruby:
    str.squeeze! ' '
    

    Oho! I was hoping someone would post it in Prolog! But what will the interpreter do if I call despace(_, "Thisisastring!" ). I bet it goes crazy trying to find every combination. ;)

  • facetious (unregistered) in reply to po_boy
    po_boy:
    /usr/bin/tr -d " "

    Captcha: SevereAnalBleeding

    ... apparently (and it isn't just you, I've noticed at least 5 others) people don't understand that using programs on a command line to solve this problem is not actually solving the problem.

    The programmer has designed the function to remove spaces from strings in memory. While it's possible that he only uses the function on files that he reads into memory, it's more likely that he's using it for different purposes.

    But if you want to go ahead and start up a whole new process just so you can eliminate spaces from your in-core strings, go right ahead. ..wtf.

  • Harrow (unregistered)

    In Delphi:

    function cmRemoveSpaces( asSRC : string ) : string;
    var LL, MM : integer;
    begin
       LL := length(asSRC);
       if LL<1 then
          result := null;
       else
          if LL=1 then begin
             if asSRC=' ' then result := null
             else result := asSRC;
          end else begin
             MM := LL div 2;
             result := cmRemoveSpaces(copy(asSRC,1,MM))+
                            cmRemoveSpaces(copy(asSRC,MM+1,LL-MM));
          end;
    end;

    ...which should be bloated enough for anyone.

    -Harrow.

  • foo (unregistered) in reply to FooBaz
    Oho! I was hoping someone would post it in Prolog! But what will the interpreter do if I call despace(_, "Thisisastring!" ). I bet it goes crazy trying to find every combination. ;)
    It would depend on the ordering of the rules.

    Assuming the rule for "not a space" is first, you'd most likely get the same string.

  • Mike (unregistered) in reply to Sack Scratcherton
    Sack Scratcherton:
    Mine takes advantage of the Dictionary generic from .NET 2.0. The dictionary is indexed by each unique character in the string, with the value for each item being a list of all occurrences of that character.

    Are you going to release this under GPL? I'd love to have this in my PowerString library. I'm slowly replacing all the Microsoft 'string' bits with my own. First I replaced their rubbish immutable 'string' struct with my own 'string' class ... you can modify any char without having to create a new object. I can't believe Microsoft made such a basic mistake with the framework ...

  • (cs) in reply to FooBaz
    Oho! I was hoping someone would post it in Prolog! But what will the interpreter do if I call despace(_, "Thisisastring!" ). I bet it goes crazy trying to find every combination. ;)
    1 ?- despace(_, "Thisisastring!").
    No
    
    That's if you do it with the revised version of is_not_space. With the original version:
    14 ?- sublist(old_is_not_space,_,"Thisisgoingtohurt").
    ERROR: Out of global stack
    
  • facetious (unregistered)

    I'm thinking that "bloated" would look more like ...

    def remove_spaces(x): is_space = [] no_spaces = ""

    for i in xrange(len(x)):
        if x[i] == " ":
            is_space.append(True)
        elif x[i] != " ":
            is_space.append(False)
    
    for i in xrange(len(is_space)):
        if is_space[i] == True:
            no_spaces = no_spaces
        elif is_space[i] == False:
            no_spaces = no_spaces + x[i]
    
    return no_spaces
    

    Which .. of course .. is exactly the same as:

    remove_spaces = lambda x: filter(lambda y: y != " ",x)

    (..and slightly worse than remove_spaces = lambda x: "".join(x.split(" "))..)

    Hmm.. I should consider starting a paid-by-the-line code-refactorer job..

  • (cs)

    From the original article:

    char* RemoveSpaces( char *str ) { if ( NULL == str ) return NULL;

      char * to = str;
    
      for ( char* from = str ; '\0' != *from ; ++from )
          if ( ' ' != *from )
              *(to++) = *from;
    
      *to = '\0';
      return str;
    

    }

    This "reference" implementation is also sub-optimal. Depending on the input string, it can actually work slower than the "WTF" version. Especially when there is no space to remove; in that case, the "WTF" version simple does one strchr (supposedly highly-optimzed) which returns NULL, while the "better" version copies the whole string over itself. Can we call that premature optimization?

    Here is how it should be:

    char* RemoveSpaces( char *str ) { if ( NULL == str ) return NULL;

      char *from = strchr(str, ' ');
    
      if ( NULL == from ) return str;
    
      char* to = from++;
    
      for ( ; '\0' != *from ; ++from )
          if ( ' ' != *from )
              *(to++) = *from;
    
      *to = '\0';
      return str;
    

    }

  • (cs)

    REM Windows batch file implementation @echo off setlocal set spaceless= :loop if "%1empty"=="empty" goto :end set spaceless=%spaceless%%1 shift goto :loop :end echo %spaceless% endlocal

  • (cs)

    I'm a bit bothered by how many people still think byte-wise string manipulation (esp. in C) is the way to go. With UNICODE, characters can be one, two, three even four bytes. Please get away from ASCII string maniupulation. It's just not cool anymore :)

  • Ferday (unregistered)
    package com.usefulstuff.removers;
    
    public class SpacesRemover {
    
        public static String removeSpaces(String input) {
            String output = input;
            boolean done = false;
            boolean fromLeft = true; // what direction?
            while (!done) {
                try {
                    output = removeOneSpace(output, fromLeft);
                } catch (SpacesMissingException e) {
                    // yay, we are done
                    done = true;
                    return output; // return immediately (faster)
                }
                // search from the other side next time (will be more efficient)
                if (fromLeft == true) {
                    fromLeft = false;
                } else {
                    fromLeft = true;
                }
            }
            // return did not work, try again
            return removeSpaces(input);
        }
    
        private static String removeOneSpace(String input, boolean fromLeft)
            throws SpacesMissingException {
            String output = "no~spaces$123"; // need to use unlikely value
            if (fromLeft) {
                // from left to right
                for (int i = 0; i < input.length(); i++) {
                    char maybeSpace = input.charAt(i);
                    if (maybeSpace == ' ') {
                        output = input.substring(0, i) + input.substring(i + 1);
                        i = 99; // add more 9s to support longer strings 
                    }
                }
            } else {
                // from right to left
                for (int i = input.length() - 1; i >= 0; i--) {
                    char maybeSpace = input.charAt(i);
                    if (maybeSpace == ' ') {
                        output = input.substring(0, i) + input.substring(i + 1);
                        i = -99;
                    }
                }
            }
            if (output == "no~spaces$123") {
                throw new SpacesMissingException("nospacesleft");
            } else {
                return output;
            }
        }
    
        private static class SpacesMissingException extends Exception {
    
            public SpacesMissingException() {
                this("nomessage");
            }
    
            public SpacesMissingException(String message) {
                super();
            }
        }
    
    }
    
  • grg (unregistered) in reply to rbowes
    rbowes:
    CrystalMethod:
    It is C++, just look at the way the conditionals are all the wrong way round, for example:
    '\0' != *from
    I don't know how serious you are about that, but the main reason that I do that when programming in any language is to avoid the accident:

    if(a = 3) { ... }

    Which will compile fine. On the other hand:

    if(3 = a) { ... }

    Will fail right away. Even as an experienced programmer I occasionally make that mistake.

    [code] cobain:$ cat test.c
    int main() { int a = 0; if (a=1) printf("foo\n"); }

    cobain:$ cc test.c
    cobain:$ cc -Wall test.c
    test.c: In function main': test.c:4: warning: suggest parentheses around assignment used as truth value test.c:5: warning: implicit declaration of functionprintf' test.c:6: warning: control reaches end of non-void function [\code]

    Anyone who claims that if(a = 3) {...} could be problematic clearly doesn't no their way around a compiler. Despite using Wall for anything I've coded, I don't recall ever having seen this warning for my own code - is it really such a problem?

    C4PTCH4: fukkoff

    PS: my initals are G.R.G, but I'm not the grg from the other WTF.

  • Simetrical (unregistered) in reply to noone

    x86 assembler (32-bit MASM):

    ; Accepts a pointer to a null-terminated string in ESI ; as input, buffer in EDI for output removeSpaces PROC PUSHA

    DoRemove: CMP [esi], 0 JE FinishedRemove CMP [esi], ' ' JE DontCopy MOVSB JMP DoRemove DontCopy: INC esi JMP DoRemove

    FinishedRemove: MOVSB ; move null byte POPA RET

    removeSpaces ENDP

    Not very well optimized, I'm afraid. I was trying to work out a way to use one of the REP instructions, but I'm not sure how, since you have to check for two equalities. You could calculate the string length first and use that in ECX, but then you'd have to use SCASB to find the spaces and do all sorts of value juggling to copy them properly with MOVSB, since that doesn't change flags. Either way, this is probably much faster than any algorithm presented so far except maybe some of the C ones.

    noone:
    This style is no longer necessary as any reasonably modern compiler can throw a warning or error if you type "if (a = 3)" instead of "if (a == 3)".
    Not an option in interpreted languages. Python doesn't allow assignment in conditions at all, and I hear Perl doesn't with use strict, but PHP has no protection whatsoever. Not even a runtime notice.
  • Kryczek (unregistered) in reply to Sebastián

    No, it IS C++ because in plain C one cannot declare variables anywhere inside a block, as Derrick did for "to"

  • BillyBob (unregistered) in reply to facetious
    facetious:
    BillyBob:
    Botzinger Gulm:
    It's not quite one-liner but close.
    void strnfilter(char* str, int c, size_t n)
    

    calling that function string_filter would cost you 3 characters but would have improved the readability of your code enormously.

    Perhaps, but it isn't just string_filter.. It's filter_n_characters_of_string. And nobody wants to type that whole thing out. So what would you do? string_n_filter? Equally meaningless. Go with strnfilter - at least that's a common usage in C (what with strncpy and strncat and etc..).

    Hmm, this is true. I just didn't expect anyone to actually continue with C's terrible naming conventions. ;-)

    Anyway, I'm happy with string_filter unless you are going to provide a function to work on the entire string as well as this one.

    (filter_string is also a better name than string_filter :-)

  • Jerry Kindall (unregistered)

    The fastest way to do many string manipulations in AppleScript is to split the string into a list based on some delimiter character (using the global AppleScript property "AppleScript's text item delimiters") and then join that list back into a string using different delimiters. So:

    on remove_spaces(s) set AppleScript's text item delimiters to " " set s to text items of s -- makes list of space-delimited substrings of s set AppleScript's text item delimiters to "" set s to s as Unicode text -- rejoins list into string with empty delimiters return s end remove_spaces

    remove_spaces("This is a test") --> Thisisatest

  • Free (unregistered)

    The Catch block is for when there is at least one space removed and the index will go out of bounds.

    xsl does a lot of things badly, but others very well. String functions are not so hot, but I think you could get rid of a space with translate.

  • My Name (unregistered)

    // C

    void remove_char(char *str, char c) { if(!str) return;

    char itr = str - 1; while((++itr = *str++)) if(*itr == c) itr--; }

    // ML

    fun remove_char c xs : char list = let fun rc ( nil) = nil | rc (x::xs) = if x = c then rc(xs) else x::rc(xs) in rc xs end;

  • Tigger (unregistered) in reply to cfreeman

    Being readable, however, just ain't one of them.

  • My Name (unregistered) in reply to My Name
    My Name:
    // C

    void remove_char(char *str, char c) { if(!str) return;

    char itr = str - 1; while((++itr = *str++)) if(*itr == c) itr--; }

    // ML

    fun remove_char c xs : char list = let fun rc ( nil) = nil | rc (x::xs) = if x = c then rc(xs) else x::rc(xs) in rc xs end;

    The indentation didn't show up on my code: that was not intentional.

  • bramster (unregistered)

    inspect(string," ","");

  • Canumbler (unregistered)

    3 void removeS(char* str) { 4 int off = 0; 5 while(*str++ != NULL) { 6 if((*str = *(str + off)) == ' ') { 8 str--; 9 off++; 10 } 11 } 12 }

    haha, that was kinda fun

  • Canumbler (unregistered) in reply to Canumbler
    Canumbler:
    void removeS(char* str) {
        int off = 0;
        while(*str++ != NULL) {
           if((*str = *(str + off)) == ' ') {
              str--;
              off++;
           }
        }
    }
    

    damn bbcode. Anyway, pretty happy with that

  • Canumbler (unregistered)

    Time to get really mean :D

    void removeS(char* str) {
       for(int off=0; *str = *(str+off);*str++)
          (*str == ' ') ? *str--,off++ :*str;
    }
    

    O(N) complexity, which is as good as it gets. For whoever said the original function is quicker earlier.. you're an idiot, how do you think strchr SEARCHES for that space? The search is O(N) to begin with.

  • no name (unregistered) in reply to aikii
    aikii:
    Okay, I really couldn't resist my previous proposition.

    So here is the link to the parallel AJAX implementation of removewhitespaces

    iswhitespace.php just returns nothing if the parameter is a space, or else echoes the string provided. For extra fun I added random sleep to the php ... erm I mean extra heavy parallel processing to check if it's really a whitespace, to emulate real-life enterprisey conditions.

    Neat, but "bet&&you++can't&&handle++this!"

Leave a comment on “Removing Spaces, the Easy Way”

Log In or post as a guest

Replying to comment #:

« Return to Article