0

I have just started off with C programming and while I was trying to write a programme to accept only y or n characters I came across that

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

int main()
{
  char ch;
  printf("Do you want to continue\n");

  for (;;)
    {
      ch=getchar();
      if (ch=='Y' || ch=='y')
        {
            printf("Sure!\n");
            break;
        }
        else if (ch=='N'||ch=='n')
        {
            printf("Alright! All the best!\n");
            break;
        }
        else
        {
            printf("You need to say either Yes/No\n");
            fflush(stdin);
        }

    }
    return(0);
}

When I run this code, and type in any other character other than Y/y or N/n, I receive the last printf statement (You need to say either Yes/No) as output twice. I understand that this is happening because it considers enter, i.e, '\n' as another character. Using fflush doesn't help as it's an infinite loop. How else can I modify it so that the last statement is displayed only once?

Arshitha
  • 33
  • 1
  • 8
  • `char ch` should be `int ch` please read more about [getchar](http://www.tutorialspoint.com/c_standard_library/c_function_getchar.htm) function – Michi Dec 12 '15 at 23:58
  • `fflush(stdin)` is undefined behaviour. No further research required. – too honest for this site Dec 12 '15 at 23:59
  • 1
    @Olaf: For better or worse, using `fflush(stdin)` is defined behaviour if the platform is Microsoft; it is undefined on other platforms. The gory details are at [Using `fflush(stdin)`](http://stackoverflow.com/questions/2979209/using-fflushstdin). Until we know which platform, your statement is too sweeping. – Jonathan Leffler Dec 13 '15 at 00:01
  • 1
    @JonathanLeffler: I stricktly follow the tags given. The C tag implies C standard, which is very [clear about that](http://port70.net/~nsz/c/c11/n1570.html#7.21.5.2p2). Hmm, I wonder if an implementation does define a behaviour the standard states is undefined: does that make the implementation non-compliant? :-) – too honest for this site Dec 13 '15 at 00:04
  • @JonathanLeffler I'm not sure the link sheds that much light on the subject anyway. The notes (yours) say both linux and windows define `fflush` for input streams (and in the same way) -- however, `fflush (stdin)` does *not* empty the input buffer, so I'm lost on the distinction you are drawing here -- help? – David C. Rankin Dec 13 '15 at 00:06
  • @Michi: Why should it matter whether I declare it as char or int? The problem still remains. I did try with int, I still have the same issue. – Arshitha Dec 13 '15 at 00:07
  • @ArshithaBasavaraj: Because a `char` very likely cannot hold all possible return values of a function which returns an `int`! This is very critical for `getchar`, as you should check for `EOF`. – too honest for this site Dec 13 '15 at 00:08
  • 1
    @JonathanLeffler's comment is relevant. Since MSVC does implement `fflush(stdin)` the code behaves well. Since OP's system does not, the prompt is printed twice: once for the undesired char, once for the `newline` which follows. – Weather Vane Dec 13 '15 at 00:11
  • @ArshithaBasavaraj Please check my Answer – Michi Dec 13 '15 at 00:12
  • @olaf I understand that. I did try declaring it as int, no luck. When I asked how it mattered, I meant wrt the problem I'm facing, which is, that the enter escape sequence is not being cleared by fflush(stdin) – Arshitha Dec 13 '15 at 00:14
  • @ArshithaBasavaraj: It is a problem on its own. Just be happy to get some extra hints. – too honest for this site Dec 13 '15 at 00:15
  • @olaf I guess it is, Thanks! :) – Arshitha Dec 13 '15 at 08:27

4 Answers4

1

You can use a loop to read any characters left using getchar():

  ch=getchar();
  int t;
  while ( (t=getchar())!='\n' && t!=EOF );

The type of ch should int as getchar() returns an int. You should also check if ch is EOF.

fflush(stdin) is undefined behaviour per C standard. Though, it's defined for certain platforms/compilers such as Linux and MSVC, you should avoid it in any portable code.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • I have small doubt, why is it that we use && in the while loop statement? Why doesn't an || condition work? – Arshitha Dec 14 '15 at 22:00
  • Because we want to break the infinite loop if *either* of that condition is false. If, for example, the function returns `EOF` to signal "no more input", then using `||` will lead to infinite loop as `(t=getchar())!='\n'` will be true. In `if (A || B)`, the condition `B` will not be evaluated if `A` is true. See [short circuit evaluation](https://en.wikipedia.org/wiki/Short-circuit_evaluation). So `&&` is the correct way. – P.P Dec 14 '15 at 22:03
0

Another option - use scanf ignoring white spaces.

Instead of ch=getchar();, just need scanf( " %c", &ch );

With this you can also get rid of fflush(stdin);

artm
  • 17,291
  • 6
  • 38
  • 54
0

Like is said in my comment you should use int ch instead of char ch because the return type of getchar which is int.

To clean stdin you could do something like the following:

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

int main(void){
  int ch,cleanSTDIN;
  printf("Do you want to continue\n");

  for (;;)
    {
      ch = getchar();
      while((cleanSTDIN = getchar()) != EOF && cleanSTDIN != '\n');
      if (ch=='Y' || ch=='y')
        {
            printf("Sure!\n");
            break;
        }
        else if (ch=='N'||ch=='n')
        {
            printf("Alright! All the best!\n");
            break;
        }
        else
        {
            printf("You need to say either Yes/No\n");
        }

    }
    return(0);
}

Any way a do while will probably do the job for you:

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

int main(void){
    char ch;
    int check;

    do {
        printf("Do you want to continue: ");

        if ((scanf("%c",&ch)) == 1){
            while((check=getchar()) != EOF && check != '\n');

            if ((ch == 'y') || (ch == 'Y')){
                printf("Alright! All the best!\n");
                break;
            } else if((ch == 'n') || (ch == 'N')){
                printf("You choosed %c\n",ch);
                break;
            }else{
                printf("You need to say either Yes/No\n");
            }
        }else{
            printf("Error");
            exit(1);
        }

    }while (1);

    return 0;
}

Output1:

Do you want to continue: g
You need to say either Yes/No
Do you want to continue: y
Alright! All the best!

Output2:

Do you want to continue: n
You choosed n
Michi
  • 5,175
  • 7
  • 33
  • 58
0

Or we can simply use another break; statement after the last printf().

Xoog
  • 908
  • 1
  • 10
  • 30