質問

I know that this while loop issue is very common, and it is usually caused by a newline in a input stream. However, I wasn't able to fix my while loop, and I don't really understand why it's happening in my case.

Consider the following example:

 int main()
 {
   int option = -1;
   char buffer[100];
   while (option != 10)
    {
     while(printf("Enter menu choice: \n"), gets(buffer), option < 0)
           {
             some code here dealing with buffer and assigning input to option...
           }
     printf("something\n");
     }
    return 0;
  }

Ignore the implementation of this code (e.g store the input in integer instead of string, etc.) as it's just a simplified version of my case for while loop. What concerns me is then I have to enter the number twice before it actually goes through the loop.

Output:

Enter menu choice: 1

Enter menu choice: 1

All lights are turned on Light settings: 1111 1111 1111 1111

I am not sure why it's happening in this case...Thanks!

UPDATE: Thank you for your answers. I have fixed code by rewriting my while() condition

while(printf("\nEnter menu choice: \n"), gets(buffer),  option = checkMenuOption(buffer), option < 0 && strcmp(buffer, ""));
役に立ちましたか?

解決 2

The printf() and the gets() are within the while test, before the evaluation of option.

In fact, with the current behavior you don't actually have to enter the number twice: You have to enter the number once and then type anything so gets() will return.

Edit: I added a few details on is how it runs:

  • Instruction pointer reaches the very beginning of the while statement, begins evaluating its condition
    • calls printf()
    • calls gets()
    • evaluates option < 0, which is true.
  • Body of the while statement
    • code parses string, sets option to a value above zero.
  • Instruction pointer is looped back to evaluating the condition
    • calls printf()
    • calls gets()
    • evaluates option < 0, which is false.
  • while loop terminates
    • calls printf("something\n");

It's visible here that the buffer, once filled by gets(), is only read by the code in the first iteration, and is ignored on the second one.

他のヒント

May I recommend that you use fgets instead of gets? It's far safer and can be used to prevent buffer overrun.

Also, I've rewritten your code a little bit, would this do what you're interested in?

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

int main()
{
    int option = -1;

    char buffer[100];

    while (option != 10)
    {
        printf("Enter menu choice: \n");

        fgets(buffer, 100, stdin); /* get input from the standard input
                                      and save it in the buffer array */

        option = atoi(buffer); /* convert input to integer */
    }

    return 0;
}

If the user typed in '10', the program will quit:

$ ./a.out 
Enter menu choice: 
10
$

If you want to keep the old code here it is:

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


int main()
{
    int option = -1;
    char buffer[100];
    while (option != 10)
    {
        while(printf("Enter menu choice: \n"), gets(buffer), option = atoi(buffer), option < 0)
        {

        }
        printf("something\n");
    }
    return 0;
}

The problem was that you weren't assigning option anything in the loop condition. During the first test, option was still not 10, it's only in the body that it becomes 10. After the first run option is assigned 10 (or whatever you've entered) the while loop has still not evaluated it and that's why it prints the statement again and it asks you to enter a value.

You can rewrite the loop like this to test my claim (make sure the code updating option is still in the body):

while(option < 0 && printf("Enter menu choice: \n") && gets(buffer))

And finally, do not use commas, as statements separated by commas will always be executed (I assume this is not what you want here, in other cases it could be perfectly fine), it's only the last member of the list that is tested for true/false. Have a look at this.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top