2

I tried to have defensive programming having input as an integer but the program would go into infinite loop if I entered a character. I then switched to having input as a character, but it does the loop twice. Once for the wrong character and once for the end of line keystroke.

Is there any way to get the loop, just once?

code:

int main(int argc, char *argv[])
{
    char choice='5';
    while (choice != '1' && choice !='2' && choice !='3' && choice!='4' && choice!='0')
        {
             printf("Parakalw epilekste ena apo ta parakatw\n\n");
             printf("1.\tKafe 1.5 euro\n");
             printf("2.\tKafe me gala 1.8 euro\n");
             printf("3.\tSokolata 2.1euro\n");
             printf("4.\tSokolata me gala 2.4 euro\n");
             printf("0.\tExodos\n\n");
             printf("parakalw eisagete thn epilogh sas: ");
             scanf("%c",&choice);
        }
system("PAUSE");    
return 0;
}
n17n
  • 81
  • 5
  • Why not an integer like `int n; scanf ("%d",&n);`? – Mikhail Mar 05 '13 at 19:31
  • it goes into an infinite loop if n = any character instead of a number – n17n Mar 05 '13 at 19:34
  • @NikolaosTsouktakos: that's because scanf will fail to read a number, and the way your loop is written it'll keep trying, using the same input for ever. – teppic Mar 05 '13 at 19:44

2 Answers2

2

Use scanf(" %c", &choice) to make it skip over whitespace, otherwise your linefeed is left in stdin after picking the character, and it will be read in the next scanf call. The space before the specifier means it will match any kind of whitespace character (spaces, tabs and returns).

teppic
  • 8,039
  • 2
  • 24
  • 37
  • is that sort of "defensive programming" important? Should I look it up further or move along? – n17n Mar 05 '13 at 19:28
  • It's always good to check that a user inputs a valid value. A common approach is to use a loop with a switch statement to process the input, with a default case that prints an error message. – teppic Mar 05 '13 at 19:29
2

For defensive programming (what ever you mean by that exactly), I would not use scanf at all, it is so easy to make mistakes with it.

Instead, read input line with fgets, then parse that as needed, then use trimming, custom parsing code or possibly sscanf, probably after some validation.

Also, you'd better check return value of any *scanf function, always. Check both for actual error, and how many items were actually scanned.

hyde
  • 60,639
  • 21
  • 115
  • 176