• John (unregistered)

    I always understood that in C an assignment returned the value assigned, not whether the assignment was successful or not.

    eg. if (a=b)

    This evaluates to the value of b. essentially, if b is non zero then do something.

    This if ((a = b) == 0) as suggested by another poster, wouldn't assign and test for success because the assignment would return the value of b, not a true/false. In fact, (a=b)==0 iff b==0.

    This is the basis of C style string manipulation, where strings are null (ie, zero) terminated. I'd probably expect a warning from any decent compiler but it's perfectly valid and useful.

  • (cs) in reply to no name
    no name:
    Neat, but "bet&&you++can't&&handle++this!"
    Damn, you just broke wopr's algorithm and saved us from world war III.

    By the way, FBI traced your IP ( "hackers" the movie style, you know, like 127.282.160.8 ) and is coming at your house.

  • Justin (unregistered) in reply to Mike

    When you use recursive operations there is a stack depth you can not exceed and it varies from computer to computer.

    http://www.devx.com/tips/Tip/14276

    Stack overflow in this example would be caused by strings somewhere around 2000-10000 chars in length.

    This isn't a bug with .Net hehe

    Justin www.AboutJustin.com

  • rotu (unregistered) in reply to Josh

    c++ do have replace function in the standard string class.

    Oh right, you don't actually know that.

  • Kalle (unregistered)

    Would that work?

    nosp([], []) :- !. 
    nosp([32|Lr], Lrn) :- nosp(Lr, Lrn), !.
    nosp([F|Lr], FLrn) :- nosp(Lr, Lrn), append([F],Lrn,FLrn).
    
  • My Name (unregistered)
    // Handles NULL, parameterized c, 2 lines body, max chars per line <= 80
    void remove_char(char *str, char c) {
        if(!str) return;
        for(char *itr = str - 1; (*++itr = *str++); *itr == c ? itr-- : itr);
    }

    Btw, it's amazing how many of the versions posted here don't work.

  • My Name (unregistered)
    (* Polymorphic Filter *)
    
    fun filter(c, nil  ) = nil
      | filter(c, x::xs) = if x = c then filter(c,xs) else x::filter(c,xs);
  • My Name (unregistered)
    // Polymorphic
    // Handles NULL, parameterized c, 2 lines body, max chars per line <= 80
    
    template <class T>
    void filter(T *xs, T t) {
        if(!xs) return;
        for(T *itr = xs - 1; (*++itr = *xs++); *itr == t ? itr-- : itr);
    }

    K, this is the final one.

  • My Name (unregistered)
    fun filter(c, nil  ) = nil
      | filter(c, x::xs) = if x = c then filter(c,xs) else x::filter(c,xs);
    
    fun remove_spaces str = filter(#" ", str);
    fun remove_foobars xs = filter("foobar", xs);
    fun remove_idiots  xs = filter("idiots", xs);
    fun remove_sixties xs = filter(60, xs);

    I lied.

  • (cs)

    God, I'm glad I know regular expressions :)

  • D (unregistered) in reply to nausea

    VB6 does have a replace function, it is VB5 that had poor in-built string manipulation functions

    myvariable = REPLACE (myvariable, " ", "")

  • El Jay (unregistered)

    COBOL. I want an implmentation in Cobol. That should be cool.

  • Raphael (unregistered) in reply to Michael
    Michael:
    char* RemoveSpaces( char *str ) { if ( NULL == str ) return NULL;
      char * to = str, *from = str;
      char c;
    
      do {
        c = *from++;
        if (c != ' ') *to++ = c;
      } while (c != '\0');
    
      return str;
    

    }

    Both this, and the original 'reference implementation' suffer from the same fault: they use pointer arithmetic. Relatively harmless in this particular case, but dangerous and inefficient in general.

    Once you start modifying pointers you defeat the commpiler's optimiser. I know that K&R, and most programming courses, say to do it this way, but your code will run faster if you use two integer subscripts to index from[] and to[]. Let the compiler convert this to pointer arithmetic: it will do it much more efficiently than you can.

    As for safety, if you use a subscript you have something you can debug; if all you have is a pointer, who knows what are valid pointer values and what are not?

  • Anonymous (unregistered) in reply to Coolvibe

    Ick, strlen for no good reason.

  • Anonymous Tart (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;
    }
    

    Last one from me, this is the C++ Enterprise Version.

    #include <streambuf>
    #include <iostream>
    
    class char_filter_buf : public std::streambuf
    {
        typedef std::streambuf streambuf_type;
    
    public:
        explicit char_filter_buf(streambuf_type& buf, char kill_char)
            : streambuf_type()
            , m_stream(buf)
            , m_kill_char(kill_char)
        { }
    
    private:
    
        virtual int
        overflow(int c)
        { return process_character(c); }
    
        virtual std::streamsize
        xsputn(const char * dat, std::streamsize n)
        {
            std::streamsize i = 0;
            for (; i < n && process_character(dat[i]) != EOF; ++i)
                ;
            return i;
        }
    
        int 
        process_character(int c)
        {
            if (c != m_kill_char && c != EOF) 
            {
                c = m_stream.sputc(c);
            }
            return c;
        }
    
        streambuf_type& m_stream;
        char m_kill_char;
    };
    
    class char_filter_init_helper
    {
    protected:
        char_filter_init_helper(std::streambuf& buf, char kill_char)
            : m_buf(buf, kill_char)
        { }
    
        char_filter_buf m_buf;
    };
    
    class char_filter : virtual char_filter_init_helper, public std::ostream
    {
    public:
        char_filter(std::ostream& destination, char kill_char)
            : char_filter_init_helper(*destination.rdbuf(), kill_char)
            , std::ostream(&m_buf)
            , m_dest(destination)
        {
        }
    private:
        std::ostream& m_dest;
    
    };
    
    int main()
    {
        char_filter out(std::cout, ' ');
    
        out << "This is filtered output, removing all spaces. Huzzah.";
    
        return 0;
    }
    
  • Oliver (unregistered) in reply to mav

    Hi,

    he used NULL instead of 0 hence it definately is C not C++

  • Revenger (unregistered)

    It looks like VB code to me, so I tried to do this the hard way:

    Sub RemoveSpaces() Dim MyStr As String MyStr = Replace(MyStr, " ", "", 1) End Sub

    Oneliner ... :-)

  • (cs) in reply to David Wolever
    David Wolever:
    LizardKing:
    rbowes:
    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.

    Heres a dime, now get yourself a better compiler.

    ... I'm confused. How is a compiler that can assign the value of 'a' to the integer '3' BETTER than one that will refuse?

    chris@tietokone $ cat test.c
    #include <stdio.h>
    
    int
    main(int argc, char *argv[])
    {
            int a;
    
            if (a = 3)
                    printf("Bad programmer\n");
    
            if ((a = 3))
                    printf("Good programmer\n");
    
            return 0;
    }
    chris@tietokone $ gcc -Wall -Werror -o test test.c
    test.c: In function `main':
    test.c:8: warning: suggest parentheses around assignment used as truth value
    

    You do compile with warnings on don't you?

  • Oli (unregistered) in reply to Sebastián
    Your implementation is not C++, is plain C.

    Dude, C++ is the superset of C, therefore any C program is also a C++ program...

  • (cs) in reply to Anonymouse >°.°<
    Anonymouse >°.°<:
    Here's my version of this function, written completely in Whitespace. It was going to be written as a one-liner, but that would have caused the page to scroll horizontally quite a bit, so it's been split up into multiple lines.
    Removes spaces from input.
                                                          
                                                          
                                                            
                                                             
                                                              
                                                              
                                                              
                                                              
                                                              
                                                              
                      

    For the next challenge. Two representations of this routine, one in Brainfuck & one in Whitespace, in the same file, with the programs interleaved. Split both of them up in such a way that the comments - you do comment, don't you? - make sense for both programs.

  • (cs) in reply to Andy Ross
    Andy Ross:
    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; }

    Now call despace_in_place(NULL);

  • (cs) in reply to Oli
    Oli:
    Your implementation is not C++, is plain C.

    Dude, C++ is the superset of C, therefore any C program is also a C++ program...

    That is strictly not true. C++ is close to being a superset, but consider the following valid C program:

    int main ()
    {
      int private = 0;
      return private;
    }
    
  • hmmmm... (unregistered) in reply to Revenger
    Revenger:
    It looks like VB code to me
    Really? I suggest you look harder, either that or good luck using try...catch in VB6 !

    It's VB.NET, the end.

  • Spike Buzznik (unregistered) in reply to NateP
    NateP:
    "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?"

    You are correct that the incoming string is a copy but it is returning a string too...

    Private Function RemoveSpace(ByVal strFldName As String) As String ... RemoveSpace = RemoveSpace & Mid(strFldName, i, 1) ...

    In VB .NET, you "return" a value by setting the method name to a value so long as the method signature ends with AS [type]. If there is no "as [type]" it is essentially a void method.

    In .Net, the preferred way to return a value from a method (or Function in VB.Net) is actually NOT to assign to [FunctionName], but to use "return [value]", as is the case with C# or most other "C"-ish languages.

    I suppose backward compatibility brings out the worst in some programmers, though...

    Also, a void method is declared as a "Sub" in VB. A "Function" always returns a value, and if no type is specified, "System.Object" is assumed.

  • Anonymous (unregistered) in reply to noone
    noone:
    rbowes:
    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.

    This style is no longer necessary as any reasonably modern compiler can throw a warning or error

    Not all languages are compiled. It's still a useful habit imho.

  • JGW (unregistered)

    Obfuscators of the world, unite:

    void remove(char* s, char c) {
    for(char*p=s;*p=*s;p+=(*s++!=c));
    }
  • JGW (unregistered)

    Forgot to account for null:

    void remove(char* s, char c) {
    for(char*p=s;s&&(*p=*s);(p+=(*s++!=c)));
    }

    Not tight, but fun :)

  • darryl (unregistered)
    Befunge-93:
    <v"This is   a test"0
    <p>v>017p

    #:<p8p71+1:g71 _v#-*48:_v# ^ $< $ g8p71:-1_v#:g71< v >$

    <,_@#:

    For those few of you that don't read Befunge-93 fluently: the 6-line block in the middle is the main function, which takes a null-terminated string off the stack, and pushes a new string on the stack, without spaces. The first and last lines are a wrapper for testing (the first line puts a string on the stack and jumps to the function; the last line prints the string currently on the stack and terminates).

    Tested with http://www.quirkster.com/befunge/befunge.html.

  • David Walker (unregistered) in reply to NateP
    NateP:
    In VB .NET, you "return" a value by setting the method name to a value so long as the method signature ends with AS [type]. If there is no "as [type]" it is essentially a void method.

    Wrong. If you do not specify the return type, it defaults to "object".

    If Option Strict is on, you are required to specify the return type.

  • Doug (unregistered) in reply to G-Unit

    I agree... .NET is an amazing platform to develop on. In my experience, while VB.NET shouldn't be considered a "toy language", those who develop on it are "toy developers"... Oh, I'm sure there are very good developers that choose to use VB.NET--many of us here just haven't met them yet. =)

  • (cs) in reply to LizardKing
    LizardKing:
    You do compile with warnings on don't you?

    Well sure, but who ever looks at those???

  • Andrew (unregistered) in reply to Robin Barker
    Robin Barker:
    perl: sub removeSpaces { $_[0] =~ s/ //g; }
    Perl: sub remove_spaces { # Identical but noticeably faster $_[0] =~ tr/ //d; } (captcha: ninjas!)
  • David Walker (unregistered) in reply to Guy
    Guy:
    Since a string in VB.Net is a reference type passing it ByVal is passing the value of the reference. The unmanaged equivalent would be passing a pointer to the string data. If you pass a string ByRef then you are passing a pointer to a pointer to the string data.

    You left out the sarcasm tags. In any event, this is not how VB.NET works. The callee sees a copy of the string when it uses the passed variable.

  • stilgar (unregistered) in reply to My Name

    templates, the other way round ;)

    template<char T>
    void rm_char(char* str)
    {
    	char *s=str,*d=str;
    	while(*s) { if (*s!=T) *d++ = *s; s++; }
    	if (d) *d=0;
    }
    
    rm_char<' '>(str);
    
  • David Walker (unregistered) in reply to Mario
    Mario:

    String is a reference type, so ByVal means this function is getting a pointer, and may change the original string. This is one of the biggest mistakes in VB.Net(*) ... In conclusion, in the example, the string will have not have changed, and the return value is the new string.

    (*) Even with a "toy language", one needs to learn how to use it before attempting.

    You have it backwards. If a string is passed ByRef, a REFERENCE is passed -- essentially a pointer to the original.

    With ByVal, the VALUE (a copy of the value of a variable) is passed, and you cannot change the original.

    With every language, one needs to learn how to use it before attempting.

  • David Walker (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.

    I get undefinedundefinedundefinedundefined... as the result no matter what I put in. Windows XP/IE7.

  • the_real_tel (unregistered) in reply to CynicalTyler

    CynicalTyler is a genius. :-)

  • (cs)

    Speaking of O(n) algorithms, why not generate every subset of the string (in the original order) and return the one that is the longest but doesn't contain any spaces?

  • (cs) in reply to David Walker
    David Walker:
    I get undefinedundefinedundefinedundefined... as the result no matter what I put in. Windows XP/IE7.

    Damn, I guess IE7 can save us from WOPR too. My PC's power is toasted, couldn't test :'(

    ( and, indeed, insert anti-microsoft sarcasm here )

  • Anonymous (unregistered)

    Here's a Python version that is more dedicated to the subject of this site ;-)

    WTF = 'Hello    World   ab c '
    ''.join([c for c in WTF if c!=' '])
  • Anonymouse (unregistered)

    How about in MUF?

    : do-strip explode 1 swap 1 for pop swap strcat repeat ;

    : main "this is a string" " " do-strip ;

  • dax (unregistered) in reply to cfreeman

    This is how I would've done it, only tested in bash: (usage: var=removeSpaces "string here")

    # This function prints the output!
    function removeSpaces () {
        tmp=`tmpfile`
        gcc -x c -o $tmp - <<HERE
    #include <stdio.h>
    int main(int argc, char **argv)
    {
        char *to = argv[1], *from = argv[1];
        while( *from != '\0' ) {
            if( *to != ' ' ) *to++ = *from;
                from++;
        }
        fprintf(stdout, "%s", to);
        return 0;
    }
    HERE
    
        "$tmp" $*
        rm -f "$tmp"
    }

    (captcha: pinball - what this thread is playing with my brain as the ball)

  • Andrew (unregistered) in reply to Ade
    Ade:
    In VB / VBA / VBS when you declare a function like this, the function name is also the name of the Variable whose value is returned, in this case the variable RemoveSpace will contain the string that is returned

    This was also true in FORTRAN77 FUNCTION subprograms. It's an old idea. Here's a not-quite right F77 version, but it's in the spirt of the exercise. Oddly, it's not as bad a the VB one!

    FUNCTION REMOV(ST) CHARACTER*300 REMOV, ST INTEGER LEN

    • do something to remove spaces... LEN = LENGTH(ST) 5 DO T = 1,LEN IF ST(T:T).EQ.' ' THEN ST(T:LEN) = ST(T+1:LEN) ENDIF CONTINUE 5 REMOV = ST RETURN END
  • Andrew (unregistered) in reply to El Jay
    El Jay:
    COBOL. I want an implmentation in Cobol. That should be cool.

    Maybe the INSPECT verb will work?!? COBOL has formatting built-ins to normalise records.

    INSPECT MY-STRING-VALUE REPLACING ALL SPACES BY ''.

  • (cs) in reply to Nandurius
    Nandurius:
    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 :)

    Unicode doesn't have characters, it has codepoints. Unicode encodings have bytes that represent codepoints.

  • Anonymous (unregistered)

    If that was an old version of VB, then that would be the most condensed version, as there is no way to actually remove spaces from a string in one line, to my knowledge.

  • Fluffy the destroyer of Worlds (unregistered) in reply to Mike

    I know!

    string& RemoveSpace(string &s) { return while(fork()); }

  • Joseph Newton (unregistered) in reply to facetious
    facetious:
    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.

    Uh, well, okay...

    D:\my_path>perl -w
    use strict;
    use warnings;
    my $line = 'line with spaces';
    sub remove_spaces {
      my $line = $_[0];
      $line =~ s/ +//g;
      return $line;
    }
    my $clean_line = remove_spaces($line);
    print "de-spaced line is $clean_line\n";
    
    ^Z
    de-spaced line is linewithspaces
    

    The string in this case is in memory. The function thus takes two extra lines [one to get the argument, one to return the result], but still gets the job done. The rest of the code shown is the standard stuff that has to be in any Perl program, if one is not to be taken to task by the Perly monks.

    In all fairness, though, the the regex used has quite a bit of C code under the hood. The advantage in this case is that the underlying code only had to be written once, and the result functionality is available readily, without re-inventing that wheel.

  • Joseph Newton (unregistered) in reply to Harrow
    Harrow:
    In Delphi:
    function cmRemoveSpaces( asSRC : string ) : string;
    ...
    cmRemoveSpaces(copy(asSRC,MM+1,LL-MM));
          end;
    end;

    ...which should be bloated enough for anyone.

    -Harrow.

    Coolness. You inspired me. Pascal was the first language I learned--on paper. I never had a chance to use it, though, except under the hood in C++[?] Builder.

    I now have another browser window open at: http://sourceforge.net/project/showfiles.php?group_id=2174 and as soon as I get to the coffee shop where I have access to a high-speed connection, I will download and intall it, for the sake of nostalgia.

  • hmmmm... (unregistered) in reply to Anonymous
    Anonymous:
    If that was an old version of VB, then that would be the most condensed version, as there is no way to actually remove spaces from a string in one line, to my knowledge.
    How "old" ? VB6:
    MsgBox Replace("This has spaces", " ", "")
    That's one line ?

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

Log In or post as a guest

Replying to comment #:

« Return to Article