0

Before asking this question, I have read: fgetc(stdin) in a loop is producing strange behaviour. I am writing a program to ask the user if they want to exit. Here is my code:

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

int ask_to_exit()
{
    int choice;
    while(choice!='y'||choice!='n')
    {   printf("Do you want to continue?(y/n):");
        while((fgetc(stdin)) != '\n');
        choice = fgetc(stdin);
        if(choice=='y') return 0;
        else if(choice=='n') return 1;
        else printf("Invalid choice!\n");
    }
}

int main()
{
    int exit = 0;
    while(!exit)
    {
        exit = ask_to_exit();
    }
    return 0;
}

Since fflush(stdin) is undefined behaviour, I did not use it. After following the solution in the other question, I still get the error. Here is a test run of the above program:

$./a.out
Do you want to continue?(y/n):y<pressed enter key>
<pressed enter key>
Invalid choice!
Do you want to continue?(y/n):y<pressed enter key>
<pressed enter key>
Invalid choice!
Do you want to continue?(y/n):n<pressed enter key>
<pressed enter key>
Invalid choice!
Do you want to continue?(y/n):n<pressed enter key>
n<pressed enter key>
<program exits>
pro neon
  • 253
  • 1
  • 12
  • 1
    Using `choice` variable without initializing it! – H.S. Mar 13 '18 at 05:27
  • does that matter?? I am checking with while(choice!='y'||choice!='n') , so even if it is not initialized ,it will not be 'y' or 'n',so it should work,right?? – pro neon Mar 13 '18 at 05:31
  • `do... while()` loop is more appropriate for such cases, instead of `while` loop. – H.S. Mar 13 '18 at 05:31
  • 1
    Yes it matters. Using a local variable without initializing is undefined behavior – H.S. Mar 13 '18 at 05:33
  • even after using do...while() loop, it has the same error. – pro neon Mar 13 '18 at 05:34
  • 2
    `choice!='y'||choice!='n'` is *always* true. If it is one, it can't possibly be the other. If it is neither, still true. If it is *both*, call your university astrophysics department, because you've discovered a worm hole. – WhozCraig Mar 13 '18 at 05:35
  • Your loop discards all the input and keeps the `\n` – M.M Mar 13 '18 at 06:46
  • yes, as stated by Stephen Dorcy. – pro neon Mar 13 '18 at 06:47
  • @WhozCraig: the first time through the loop, choice has not been initialised so its value is indeterminate. And an indeterminate value might compare equal to `'y`'` and then immediately compare equal to `'n'`. No astrophysics required; see http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_260.htm – rici Mar 13 '18 at 06:53
  • ok I got the point. – pro neon Mar 13 '18 at 06:54
  • Note that the choice of `exit` as the name for a variable isn't a particularly good idea. It means you can no longer call the function of that name in the function where you define the variable. It isn't technically wrong; it is ill-advised. – Jonathan Leffler Mar 13 '18 at 08:02

2 Answers2

1

You need to get some input before checking the value of choice or it will be uninitialized. And also, you are draining the left-over input before grabbing the first character, you should do it after:

int ask_to_exit()
{
    int choice;

    do
    {
        printf("Do you want to continue?(y/n):");
        choice = fgetc(stdin);

        while (fgetc(stdin) != '\n');

        if (choice == 'y') {
            return 0;
        } else if (choice == 'n') {
            return 1;
        } else {
            printf("Invalid choice!\n");
        }
    } while (1);
}

ouput:

Do you want to continue?(y/n):g
Invalid choice!
Do you want to continue?(y/n):h
Invalid choice!
Do you want to continue?(y/n):j
Invalid choice!
Do you want to continue?(y/n):k
Invalid choice!
Do you want to continue?(y/n):m
Invalid choice!
Do you want to continue?(y/n):y
Do you want to continue?(y/n):y
Do you want to continue?(y/n):y
Do you want to continue?(y/n):n
Press any key to continue . . .
Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
0

I see the following problems in your code.

  1. You are using choice before initializing it.
  2. You are skipping a line of input before reading anything into choice.

Error noticed by @WhozCraig:

choice!='y'||choice!='n' is always true.

I suggest:

int ask_to_exit()
{
   int choice;
   while ( 1 )
   {
      printf("Do you want to continue?(y/n):");
      choice = fgetc(stdin);
      if ( choice == 'y' )
      {
         return 0;
      }
      if ( choice == 'n' )
      {
         return 1;
      }

      printf("Invalid choice!\n");

      // Skip rest of the line.
      int c;`
      while( (c = fgetc(stdin)) != EOF && c != '\n');

      // If EOF is reached, return 0 also.
      if ( c == EOF )
      {
         return 0;
      }
   }
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • The return values are ok, `0` is returned for `y`, which makes `while(!exit)` true, and so the program continues. Returning `1` for `n` causes `while(!exit)` to be false, and the program exits. – Stephen Docy Mar 13 '18 at 05:39