5

Below is some simple code that should accept integer input from the console. It works fine until invalid (non integer) input is given.

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5   int x = 0;
 6   int inp = 0;
 7   int nums[20]; 
 8   int idx = 0;
 9   for(;;){
10     printf("Enter an integer: ");
11     inp=scanf("%d", &x);
12     if(inp == 0){
13       printf("Error: not an integer\n");
14     }
15     else{
16       if(idx<20){
17         nums[idx] = x;
18         idx++;
19       }
20     } 
21   }
22   return 0;
23 }

Here is output from gdb that shows me stepping through the program after entering the value "g". Look at how it jumps to line 18, and then fails to look for further input from the user.

Starting program: /Users/jeffersonhudson/xxxx/hw1 
Enter an integer: g

Breakpoint 1, main () at hw1.c:12
12          if(inp == 0){
(gdb) n
13              printf("Error: not an integer\n");
(gdb) n
Error: not an integer
0x0000000100000ee4  18                  idx++;
(gdb) n
10          printf("Enter an integer: ");
(gdb) n
11          inp=scanf("%d", &x);
(gdb) n

Breakpoint 1, main () at hw1.c:12
12          if(inp == 0){
(gdb) 

This is the output of the program once you give it bad input:

Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
Enter an integer: Error: not an integer
^C

Could someone please help me figure out what I am doing wrong here?

Jefferson Hudson
  • 728
  • 1
  • 10
  • 22

3 Answers3

7

Inside your code, when you detect if(inp == 0), this actually means scanf() did not read anything, because the first token it found was not an integer nor whitespace. Therefore it did not advance on the input, and it is up to you to discard it, otherwise it gets stuck continuously not reading anything.

There are two easy ways you can fix it with scanf:

1) When you detect that inp == 0, just call a scanf("%*s"); to throw away the string token.

2) Read it into an array of char, and retrieve the integer value with atoi(str). For example:

int idx = 0;
char aux[250]; // watchout for buffer overflows.
for(;;){
    printf("Enter an integer: ");
    scanf("%s", aux); // look at ways to avoid overflows here
    inp = atoi(aux);
    if(inp == 0 && aux[0] != '0'){
      printf("Error: not an integer\n");
    }
    ...

Notice however, the second example above will treat input such as 10abc as an integer of value 10. You can do a quick scan through the data if you really want to enforce no non-integer characters are present. And I believe it is out of the scope of your homework, but you should be aware of problems regarding buffer overflows for the future :)

i Code 4 Food
  • 2,144
  • 1
  • 15
  • 21
  • What about the jump to line 18? The else block in which it is contained shouldn't be executed, so how did we get there? – Jefferson Hudson May 23 '13 at 23:48
  • @JeffersonHudson you will never get to line 18 once you type something that's not a number. You get stuck in line 12 - the `if(inp == 0)` will be true and **boom**. – Nik Bougalis May 23 '13 at 23:49
  • @Nik Bougalis what then is gdb telling me here? 0x0000000100000ee4 18 idx++; – Jefferson Hudson May 23 '13 at 23:56
  • @NikBougalis: I suspect that gdb might be fibbing/confused a bit on the `idx++;` line - does `idx` actually get incremented? Also, are you by any chance debugging a build that has some optimizations enabled? What's the command line used to compile the program? – Michael Burr May 24 '13 at 00:05
  • 1
    @MichaelBurr compiler optimization was also my first though. If any sort of optimization is enabled it will seriously mess up debuggers. – Brandon Yates May 24 '13 at 00:14
  • @JeffersonHudson: FWIW I get the expected behavior in gdb (ie., it goes next to line 21 after the "not an integer" `printf`). This is with MinGW 4.7.2 and gdb 7.3 on Windows. Also with gcc 4.6.1 and gdb 7.4.1 on Linux. What platform and tool versions are you using? – Michael Burr May 24 '13 at 04:34
-1

you must have enter an invalid character, like a space/carriage return/...

Flush the stdin in order to clear the buffer.

fflush(stdin) ANSI C

Community
  • 1
  • 1
MLeblanc
  • 1,816
  • 12
  • 21
-1
inp=scanf("%d", &x);

replace to

inp=scanf("%d", &x);
while('\n'!=getchar());
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70