Thread: infinite while loop

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    58

    infinite while loop

    Hi Guys,

    let say I have a code like the one below, how can make it stop at the scanf everytime? If I enter a wrong input like a char, it start to loop all the way.

    Code:
    while(sel_case != 0)
    {
        scanf("%d",&sel_case);
    
        switch(sel_case)
        {
              case 1:  
                            test1();
              break;
             
             ~ case 10
        }
    }

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Didn't I tell you to check the return values of the functions you use?
    Code:
    if ( scanf( "%d", &sel_case ) == 1 )
    At a minimum.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    58
    Let say if I put it this way, when I try to submit a char, it would have return me an error message. But I still couldn't stop the loop from looping. Do I need to flush or anything ? So that the function can stop at the scanf everytime I enter a char ?

    Code:
    while(sel_case != 0)
    {
       if ( scanf( "%d", &sel_case ) == 1 )
      {
    
        switch(sel_case)
        {
              case 1:  
                            test1();
              break;
             
             ~ case 10
        }
       else
       {
           printf("Wrong input!!");
       }
    
    }

  4. #4
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Your loop won't stop because once the stream ( stdin in your case ) has an error it won't let you input anything in the next pass. One way would be to call
    clearerr(stdin); if the input has failed.
    But better still would be to use fgets() to read a line of input into a char buffer and use sscanf() to extract the data you want.
    Kurt

  5. #5
    Registered User
    Join Date
    Nov 2006
    Posts
    65
    I don't think clearerr will work. You need something similar to flushing stdin, because scanf often leaves unused input in the input stream (including newlines).
    http://faq.cprogramming.com/cgi-bin/...&id=1043284392
    However, as ZuK said, the best solution might be to simply avoid scanf. See the FAQs for how to read in a string and convert it to a number later.

  6. #6
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by coder8137
    I don't think clearerr will work.
    Why shouldn't it. That's why we have it, but I agree that it wouldn't help much on eof-condition.

    Quote Originally Posted by coder8137
    something similar to flushing stdin.
    Don't understand what that would be. Fact is there isn't a fflush(stdin).

    Kurt

  7. #7
    Registered User
    Join Date
    Nov 2006
    Posts
    65
    Why shouldn't it. That's why we have it, but I agree that it wouldn't help much on eof-condition.
    As far as I know, the problem is not that an error has occured when reading from stdin. Rather the problem is that scanf doesn't actually read all the data in the buffer, since the data doesn't match the search string (i.e. it's not numeric). Therefore the input stream will continue to contain some non-numeric data. From that point on, the user will never be asked for new input, because there's already something in the buffer (which scanf can't use). So, the end result is an infite loop.

    To stop it, you could use getchar (until new line or EOF), which will get rid of the stale data in the buffer (by fetching & discarding it). But as the FAQ says, it's not ideal (mainly when the buffer is empty and you still try to "flush" it by calling getchar).

  8. #8
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    To stop it, you could use getchar (until new line or EOF), which will get rid of the stale data in the buffer (by fetching & discarding it). But as the FAQ says, it's not ideal (mainly when the buffer is empty and you still try to "flush" it by calling getchar).
    That's not the problem here. The op is asking for an int ("%d") if the user enters something that cannot be interpreted as an int ( e.g. "a\n" ) then the stream ( stdin ) will enter the error state. Once a stream has an error there is no way to leave that errorstate other then calling clearerr() or closing and reopening the stream. Any attempt to read from a stream that has an error will just fail ( do nothing ).
    What you are talking about is that when you mix different methods of reading from a stream ( like scanf() followed by fgets() ) there might be data left in the buffer that might appear like fgets has failed, in this case it helps to "flush" the input stream before calling fgets.
    Kurt

  9. #9
    Registered User
    Join Date
    Nov 2006
    Posts
    65
    I still disagree, hehe. The stream doesn't enter the error state at all. Scanf just keeps trying on wrong data, which never gets cleared. Try it out:

    Original Example... Infinite loop on non digit input:
    Code:
    #include <stdio.h>
    
    int main(void) {
      int sel_case = 1;
      while(sel_case != 0) {
        if ( scanf( "%d", &sel_case ) == 1 ) {
          printf("You entered: %d", sel_case);
        } else {
          printf("Wrong input!!");
        }
      }
      return 0;
    }
    Using clearerr (still infinite loop):
    Code:
    #include <stdio.h>
    
    int main(void) {
      int sel_case = 1;
      while(sel_case != 0) {
        if ( scanf( "%d", &sel_case ) == 1 ) {
          printf("You entered: %d", sel_case);
        } else {
          printf("Wrong input!!");
          clearerr(stdin);
        }
      }
      return 0;
    }
    Simulating Flushing the buffer. Error message prints only once for me.
    Code:
    #include <stdio.h>
    
    int main(void) {
      int sel_case = 1;
      while(sel_case != 0) {
        if ( scanf( "%d", &sel_case ) == 1 ) {
          printf("You entered: %d", sel_case);
        } else {
          printf("Wrong input!!");
          /* clearerr(stdin); */
          while((sel_case = getchar()) != '\n' && sel_case != EOF);
        }
      }
      return 0;
    }

  10. #10
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Sorry. Been trying something similar too. You are right.
    Guess that I was talking about how streams work in c++.
    Forget anything I said about the subject. Will make some tests next time before I post nonsense.
    Kurt

  11. #11
    Registered User
    Join Date
    Nov 2006
    Posts
    65
    clearerr(stdin); are you sure the command is not fflush(stdin)?

  12. #12
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by KoG Metalgod
    clearerr(stdin); are you sure the command is not fflush(stdin)?
    More or less. fflush(stdin) is UB, but works with VC.
    Kurt

  13. #13
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by KoG Metalgod
    clearerr(stdin); are you sure the command is not fflush(stdin)?
    FAQ > Explanations of... > Why fflush(stdin) is wrong
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  14. #14
    Registered User
    Join Date
    Nov 2006
    Posts
    65
    was just going on what I read in K+R C, I guess its better to get it wrong on a forum then that in a program/final exam. I will check it out.

  15. #15
    Registered User
    Join Date
    Mar 2004
    Posts
    19
    Hi Beon

    Your Code is
    Code:
    while(sel_case != 0)
    {
       if ( scanf( "%d", &sel_case ) == 1 )
      {
    
        switch(sel_case)
        {
              case 1:  
                            test1();
              break;
             
             ~ case 10
        }
       else
       {
           printf("Wrong input!!");
       }
    
    }
    You didn't break the while loop it run infinetely...
    means for example if you entered sel_case=1 it will go into the switch case and call test1() and break the switch case (not while loop)..next time it again check the sel_case that time it wont be a '0' thats why it is going infinite loop...if you want to come out of loop only in case of wrong input then use 'break' in else statement..

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 06-14-2009, 11:24 PM
  2. Cosine fucntion and infinite loop.
    By youareafever in forum C Programming
    Replies: 2
    Last Post: 11-07-2008, 04:45 AM
  3. Infinite Loop with GetAsyncKeyState
    By guitarist809 in forum Windows Programming
    Replies: 1
    Last Post: 04-18-2008, 12:09 PM
  4. Switch statement = infinite loop
    By Lucid003 in forum C++ Programming
    Replies: 10
    Last Post: 10-10-2005, 12:46 AM
  5. stays in loop, but it's not an infinite loop (C++)
    By Berticus in forum C++ Programming
    Replies: 8
    Last Post: 07-19-2005, 11:17 AM