• Corey Miller (unregistered)

    Not on a machine with a compiler right now but will that compile?

  • felix (cs)

    Amazingly enough, it compiles and even runs, at least with GCC.

    An explanation would be interesting...

  • bobday (cs)
    Dan:
    First!
    Oh baby
  • Mickey (unregistered) in reply to felix
    felix:
    Amazingly enough, it compiles and even runs, at least with GCC.

    An explanation would be interesting...

    It treates it as 2 separate loops. Let me re-format it so you seee it.

    while(path != NULL) 
    {      
        ptr = strchr(path,':');      
        if(ptr != NULL)        
        {          
            *ptr++ = '\0';      
        }      
    
        RegisterPath(CreateSymbol(path));      
        path = ptr;  
    } 
    
    while (path != NULL)
        ;
    
  • Simon Bradley (unregistered)

    Why shouldn't it compile? The second loop is a no-op. It has a null statement; and it's always run zero times, since the first loop only exits once ptr == NULL.

  • Bob Villanosa (unregistered) in reply to felix
    felix:
    Amazingly enough, it compiles and even runs, at least with GCC.

    An explanation would be interesting...

    An explanation would be boring.

    But here goes.

    Try this analoguous code:

    x = 15;
    while (x > 0)
    {
      x--;
    }
    while (x > 0);
    

    A while-loop can have an empty body, in which case nothing happens on each iteration. A commonly-seen usage of this is in the infinite loop: while(true);

  • tp (unregistered)

    Move the second while statement to its own line and essentially the code is:

    while(path != NULL) { // do some stuff... ... } while(path != NULL) { // Do nothing } Since you have just broken out of the first loop, the condition for breaking out of the second is already met, so happily you don't get stuck forever in the second empty loop.

  • Longtime C guy (unregistered)

    Yeah, it's a while loop followed by a one-line while loop. Since the only way out of the first loop is for path==NULL, the second loop does nothing -- it tests once and exits.

    Dumb, but mostly harmless.

    Other junk:

    • It orphans the memory allocated by strdup().
    • It registers the last path twice.

    Is there just a single path in getenv("MODULE_PATH")? or are there multiple paths, like this: c:\foobar;c:\foo;c:\bar If not, then I guess CreateSymbol(path) has to extract the paths by finding the path separator character.

  • felix (cs) in reply to Mickey
    Mickey:
    It treates it as 2 separate loops. Let me re-format it so you seee it.

    Duh! Now I understand why some people love Python's syntax. Thank you for the explanation.

  • snoofle (cs) in reply to Longtime C guy

    Must...resist...urge...to...obfuscate...

  • mav (unregistered) in reply to snoofle

    Wow, now THAT code is a genuine WTF. Ugly. Damn ugly.

  • snoofle (cs) in reply to snoofle
    snoofle:
    Must...resist...urge...to...obfuscate...
    gaaaa...
    int x = 3;
    while (x > 0) {
      System.out.println(x);
      x--;
    } while (x>0)
        for (int i=0; i<3; i++) {
             System.out.println("This will never print");
        } while (x>0);
    
  • Pottymouth (unregistered)

    Seems they had a do-while, and changed it to a normal while without removing the do-while exit condition. Since the code kept working, nobody noticed. More of a whoops than a WTF.

  • Bob (unregistered)
    Dan:
    First!
    Do you shout that after sex too?
  • snoofle (cs) in reply to Bob
    Bob:
    Dan:
    First!
    Do you shout that after sex too?
    Ouch!
  • EmmanuelD (unregistered)

    Where did he find a compiler that happen to have an Alzheimer Syndrom?

    (or, as the captcha hints, a compiler that drinks too much cognac?)

  • foo (unregistered) in reply to Pottymouth
    Pottymouth:
    Seems they had a do-while, and changed it to a normal while without removing the do-while exit condition. Since the code kept working, nobody noticed. More of a whoops than a WTF.

    It's the sort of Whoops The F. (WTF Pronounced Whuh-Tee-ef? instead of the more pervasive Dubya-Tee-Ef!) that makes you wonder what else they weren't paying attention to. It's healthy to maintain a little paranoia when you run across a few of these in a project. The next WTF might be substantial.

  • foo (unregistered) in reply to Pottymouth
    Pottymouth:
    Seems they had a do-while, and changed it to a normal while without removing the do-while exit condition. Since the code kept working, nobody noticed. More of a whoops than a WTF.

    It's the sort of Whoops The F. (WTF Pronounced Whuh-Tee-ef? instead of the more pervasive Dubya-Tee-Ef!) that makes you wonder what else they weren't paying attention to. It's healthy to maintain a little paranoia when you run across a few of these in a project. The next WTF might be substantial.

  • DOA (unregistered) in reply to Bob
    Bob:
    Dan:
    First!
    Do you shout that after sex too?
    hehehehehehe
  • fennec (cs)

    I'm idly wondering if this used to be a do-while and then got converted.

  • boourns (unregistered)

    Maybe it's intentional, just to remind the coder of the exit condition. Although I guess if that were the case, it would be better to just to put it in a comment.

  • dkf (unregistered) in reply to Longtime C guy
    Longtime C guy:
    Other junk: - It orphans the memory allocated by strdup().
    But if it had omitted the strdup(), that would have been a Real WTF!
    Longtime C guy:
    - It registers the last path twice.
    Does it? Are you sure about that?
  • fucker (unregistered) in reply to DOA

    Final proof that all intelligent people have abandoned this site.

    Shit, what does that make me ?

  • fucker (unregistered) in reply to DOA
    DOA:
    Bob:
    Dan:
    First!
    Do you shout that after sex too?
    hehehehehehe

    And the quote doesn't appear. Nice.

  • Wintaki (unregistered) in reply to felix

    Yes it compiles. It is valid. To understand, look at this:

    int x=5; while(x) --x;

    That is a while loop without a block - just a single statement. Likewise, the statement is optional - or maybe better, an empty statement can be used:

    while(true);

    That will loop forever.

    So the code in the WTF, something like:

    while(fp!=NULL) { // do whatever } while(fp!=NULL);

    It is the same as:

    // first loop while(fp!=NULL) { // do whatever }

    // now a second, completely unrelated loop: while(fp!=NULL);

  • snoofle (cs)
    The Article:
    char * path = strdup(getenv("MODULE_PATH"));  /* ... */  while(path != NULL) {      
      ptr = strchr(path,':');      
      if(ptr != NULL) {          
         *ptr++ = '\0';      
      }      
      RegisterPath(CreateSymbol(path));      
      path = ptr;  
    } while (path != NULL);
    
    .

    Ahem:

    for (String s : System.getProperty("MODULE_PATH").split(":")) {
      RegisterPath(CreateSymbol(s));
    }
    
  • PC Paul (unregistered) in reply to snoofle
    snoofle:
    The Article:
    char * path = strdup(getenv("MODULE_PATH"));  /* ... */  while(path != NULL) {      
      ptr = strchr(path,':');      
      if(ptr != NULL) {          
         *ptr++ = '\0';      
      }      
      RegisterPath(CreateSymbol(path));      
      path = ptr;  
    } while (path != NULL);
    
    .

    Ahem:

    for (String s : System.getProperty("MODULE_PATH").split(":")) {
      RegisterPath(CreateSymbol(s));
    }
    
    Now do it in the same language. A cross-language call just to do this is probably a little unjustified...
  • PC Paul (unregistered) in reply to PC Paul
    PC Paul:
    snoofle:
    The Article:
    char * path = strdup(getenv("MODULE_PATH"));  /* ... */  while(path != NULL) {      
      ptr = strchr(path,':');      
      if(ptr != NULL) {          
         *ptr++ = '\0';      
      }      
      RegisterPath(CreateSymbol(path));      
      path = ptr;  
    } while (path != NULL);
    
    .

    Ahem:

    for (String s : System.getProperty("MODULE_PATH").split(":")) {
      RegisterPath(CreateSymbol(s));
    }
    
    Now do it in the same language. A cross-language call just to do this is probably a little unjustified...

    Aaaagggghh!!

    The REAL WTF is.. well, I don't need to tell you, I'm sure.

  • Skybert (cs) in reply to Longtime C guy
    Longtime C guy:
    - It registers the last path twice.

    No it doesn't. Testing shows it processes a path like "/etc:/usr/lib:/whatever" just fine.

  • totolamoto (unregistered)

    And it can crash also quite easily. strdup does not like a NULL pointer, and getenv returns one, when the given variable is not defined.

  • snoofle (cs) in reply to PC Paul
    PC Paul:
    PC Paul:
    snoofle:
    The Article:
    char * path = strdup(getenv("MODULE_PATH"));  /* ... */  while(path != NULL) {      
      ptr = strchr(path,':');      
      if(ptr != NULL) {          
         *ptr++ = '\0';      
      }      
      RegisterPath(CreateSymbol(path));      
      path = ptr;  
    } while (path != NULL);
    
    .

    Ahem:

    for (String s : System.getProperty("MODULE_PATH").split(":")) {
      RegisterPath(CreateSymbol(s));
    }
    
    Now do it in the same language. A cross-language call just to do this is probably a little unjustified...

    Aaaagggghh!!

    The REAL WTF is.. well, I don't need to tell you, I'm sure.

    Actually, Java is written in C++, and JNI (with a hint or two to the compiler) lets you make calls to C[++] quite easily, but that wasn't the point!

  • Bob1234 (unregistered) in reply to snoofle

    Mayhap it is. Perhaps you can. But calling Java from C++ I think is the issue snoofle was talking about.

    "System.getProperty"

  • Irrelevant (cs) in reply to PC Paul
    PC Paul:
    PC Paul:
    Now do it in the same language. A cross-language call just to do this is probably a little unjustified...
    Aaaagggghh!!

    The REAL WTF is.. well, I don't need to tell you, I'm sure.

    ...that you should be using XML for that cross-language call?

    Specifically, a continuous feed dot-matrix printer, wooden table, webcam, and an OCR program written in XSLT.

  • Atza Nice Idea (unregistered) in reply to Irrelevant
    Irrelevant:
    PC Paul:
    PC Paul:
    Now do it in the same language. A cross-language call just to do this is probably a little unjustified...
    Aaaagggghh!!

    The REAL WTF is.. well, I don't need to tell you, I'm sure.

    ...that you should be using XML for that cross-language call?

    Specifically, a continuous feed dot-matrix printer, wooden table, webcam, and an OCR program written in XSLT.

    You, Sir, are pure evil
    bows in awe

  • Dan (unregistered) in reply to snoofle

    Sex?

  • AT (unregistered) in reply to snoofle
    snoofle:
    Ahem:
    for (String s : System.getProperty("MODULE_PATH").split(":")) {
      RegisterPath(CreateSymbol(s));
    }
    

    Whether that is an improvement or not depends whether code simplicity is more, or less, important than code efficiency.

    The original C version makes a single copy of the original string, and iterates through it in place very efficiently.

    The Java version will do something like copy the string (twice, likely), parse it, copy each part into a new string object, and shove all of them into an array or list object, which is then iterated over to retrieve each part.

    If this was part of a routine that was called very frequently, you'll almost certainly see a very significant difference in performance between the two.

    Syntactic simplicity comes at a price...

  • Longtime C guy (unregistered) in reply to Skybert

    Ah, I suppose. I didn't know that ':' was meant as a separator. I thought it was the colon in a Windows/DOS drive spec.

    Like this:

    #include <stdio.h> #include <stdlib.h>

    void RegisterPath(int i) { } int CreateSymbol(const char path) { return printf ("<%s>\n", path); } int _tmain(int argc, _TCHAR argv[]) { char *path = strdup("c:\Hello world"); while (path != NULL) { char *ptr = strchr(path, ':'); if (NULL != ptr) *ptr++ = '\0';

    	RegisterPath(CreateSymbol(path)); 
    	path = ptr;
    }
    

    }

    And the output is:

    <c> <\Hello world>
  • e**2n (unregistered)

    What a beauty! The WTF is really cute and nice.

    CAPTCHA calls that 'tastey'.

  • Kostas (unregistered) in reply to snoofle
    for (String s : System.getProperty("MODULE_PATH").split(":")) {

    RegisterPath(CreateSymbol(s));

    }

    And the code will crash if the enviroment variable does not exist. Congrats, you managed to write worse code than the original.
  • ikegami (unregistered) in reply to Corey Miller
    Corey Miller:
    Not on a machine with a compiler right now but will that compile?

    Not only will it compile, but it will run correctly.

    Given that

    while (condition)
       single_statement;

    is valid C & C++, and given that

    { ... } while (condition);

    is a single statement,

    while (condition) {
       ...
    } while (condition);

    is equivalent to

    while (condition) {
       {
          ...
       } while (condition);
    }
  • strcmp (unregistered)

    strtok is best of both worlds, and available in standard C:

    char *path = strdup(getenv("MODULE_PATH")), *ptr, *saveptr;
    for (ptr = path; ptr = strtok_r(ptr, ":", &saveptr); ptr = NULL)
      RegisterPath(CreateSymbol(ptr));
    free(path);
    
  • strcmp (unregistered) in reply to ikegami
    ikegami:
    ..., and given that
    { ... } while (condition);

    is a single statement, ...

    do { ... } while (condition);

    is a single statement, (or shorter:

    do ... while (condition);
    if
    ...
    happens to be one statement)

  • Harakan (unregistered)

    I think the worst thing about this one is thinking what happens later... imagine the code in the middle of the loop is a bit longer, then someone comes along and changes the first while() condition (e.g. adding an extra term) - suddenly the "no-op" loop becomes an infinite hang... not pretty.

  • Maximilianop (cs) in reply to Dan
    Bob:
    Dan:
    First!
    Do you shout that after sex too?
    What is
    Dan:
    Sex?
    that's what I call a self answered question...
  • JL (unregistered) in reply to Harakan
    Harakan:
    I think the worst thing about this one is thinking what happens later... imagine the code in the middle of the loop is a bit longer, then someone comes along and changes the first while() condition (e.g. adding an extra term) - suddenly the "no-op" loop becomes an infinite hang... not pretty.
    That or if someone decides to put in a "break" statement to exit the while loop early. The extra while loop is definitely not harmless.
  • TSK (unregistered)

    while - while is actually a possible structure, testing both at the beginning and at the end of the loop (I thought I have seen once at a time a language built with it). In C and C++, it can be simulated by:

    DO WHILE (condA) { (pseudocode) } REPEAT WHILE (condB);

    while (condA) { if (!condB) break; }

    Don Knuth even mentioned it in one of of his papers as a possible practical structure (it was at a time C was still a young language).

  • Anon (unregistered)

    It's possible that the 2nd while statement was meant as a comment to indicate what loop the } was terminating. It's not a terrible habit to get into, especially for students, assuming you remember that it's a comment.

    Ex:

    int main() {

    while (run = true) { switch(condition) { case 1: blah++; case 2: blah--; } //switch(condition) } //while } //int main

  • TAOCP (unregistered) in reply to TSK
    TSK:
    while - while is actually a possible structure, testing both at the beginning and at the end of the loop (I thought I have seen once at a time a language built with it). In C and C++, it can be simulated by:

    DO WHILE (condA) { (pseudocode) } REPEAT WHILE (condB);

    while (condA) { if (!condB) break; }

    Don Knuth even mentioned it in one of of his papers as a possible practical structure (it was at a time C was still a young language).

    Aside from middle of the block exits, wouldn't:

    while(condA && condB)

    perform the same function more efficiently?

    That Knuth person must not know anything about programming! ;P

    (Had to spell "onomatopoeia" twice to post this!!)

  • Sgt. Preston (unregistered) in reply to TAOCP
    TAOCP:
    TSK:
    while - while is actually a possible structure, testing both at the beginning and at the end of the loop (I thought I have seen once at a time a language built with it). In C and C++, it can be simulated by:

    DO WHILE (condA) { (pseudocode) } REPEAT WHILE (condB);

    while (condA) { if (!condB) break; }

    Don Knuth even mentioned it in one of of his papers as a possible practical structure (it was at a time C was still a young language).

    Aside from middle of the block exits, wouldn't:

    while(condA && condB)

    perform the same function more efficiently?

    That Knuth person must not know anything about programming! ;P

    (Had to spell "onomatopoeia" twice to post this!!)

    while(condA && condB) is not exactly the same as

    while(condA) { blah; blah; } repeat while(condB);

    The double while() in our wtf checks one condition at the start of the loop and the other at the end, not both at the same time. So the loop would be executed at least once regardless of the state of the second condition.

  • Will (unregistered) in reply to TAOCP
    TAOCP:
    Aside from middle of the block exits, wouldn't:

    while(condA && condB)

    perform the same function more efficiently?

    No. Your code checks both conditions at the top of the loop, whereas the given code checks one at the top and one at the bottom. So condA won't be checked the last time through the loop, and obviously any side effects of checking condA won't occur.

Leave a comment on “While-While”

Log In or post as a guest

Replying to comment #:

« Return to Article