0

I'm trying to create a program that asks to type something and check if it is an integer. If it is an integer, then print "the integer is ...". Else, print "try again" and waits for another input. However, the program prints an infinite number of "try again" if you type in a character. Here's the source code:

#include <stdio.h>
#include <stdbool.h>

int main()
{
  int inp;
  bool t = 1;
  printf("type an integer\n");
  while (t) {
    if (scanf("%i", &inp) == 1) { 
      printf("The integer is %i", inp);
      t = 0;
    } else {
      printf("try again");
      scanf("%i", &inp);
    }
  }
}
pxc3110
  • 243
  • 3
  • 14
  • 1
    There is no code to read the non-numeric input. Add some. Else the non-numeric input remains in `stdin`. – chux - Reinstate Monica Jul 25 '17 at 01:19
  • You're more likely to get help if you use to some kind of reasonable whitespace convention. What you had was gross. I've edited it. – Gene Jul 25 '17 at 01:22
  • Did it occur to you that the `scanf` will return the number of input items successfully matched and assigned? – Paul Jul 25 '17 at 01:22
  • You might try something like `scan("%*s%i");` to read the integer after `try again`. What you have skips whitespace before the integer, but you need to get rid of the non-whitespace characters. The `%*s` skips any string of non-whitespace but doesn't assign it to a variable. The `%i` automatically skips leading whitespace. This still isn't perfect. – Gene Jul 25 '17 at 01:25
  • @paul Not sure what you mean? – pxc3110 Jul 25 '17 at 01:27
  • @gene fixed. thanks for reminding me – pxc3110 Jul 25 '17 at 01:29
  • Actually now that I think if it, you'd do better with `scan("%*[^-0-9]%i", &inp)`, but you can still break this with some inputs. The bottom line is that `scanf` isn't a great tool for this use case. – Gene Jul 25 '17 at 01:33
  • Did you tried removing the scanf from Else statement? As when you don't enter a number, it will go to while and then check in if again and scan again as well. I think you don't want this behaviour – anugrah Jul 25 '17 at 01:34
  • @anugrah doesn't seem to work – pxc3110 Jul 25 '17 at 01:36
  • @pxc3110 Sorry, I just misunderstood.>_ – Paul Jul 25 '17 at 01:37
  • @pxc3110 That wasn't the solution, but I believe the 2nd scanf shouldn't be there as well. – anugrah Jul 25 '17 at 01:37
  • @gene did you mean "scanf" instead of "scan"? I tried and the infinite loop went away but it didn't work exactly the way I intended it to. When I typed an integer it would say "try again", and when I typed a character such as "w", it didn't print "try again". – pxc3110 Jul 25 '17 at 01:45
  • One approach is to check each and every character of the number or string and then do a check like if (ch-'0'==(int)(ch)). This will make sure the input is a number! – anugrah Jul 25 '17 at 01:47
  • Also, look at this link https://www.daniweb.com/programming/software-development/threads/386198/only-accept-integer-input-with-scanf – anugrah Jul 25 '17 at 01:48
  • @anugrah Your link is very helpful and I'll take time studying it. Thanks a lot. – pxc3110 Jul 25 '17 at 02:08
  • See [this](https://stackoverflow.com/a/45180914/971127) – BLUEPIXY Jul 25 '17 at 02:27

4 Answers4

2

OP's code fail to consume the offending non-numeric input. It remains in stdin, for the next input function. As it is unfortunately just another scanf("%i", &inp) which fails the same way - infinite loop.

After attempting to read an int, read the rest of the line.

#include <stdio.h>
#include <stdbool.h>

int main() {
  int inp;
  int scan_count;
  printf("Type an integer\n");
  do {
    scan_count = scanf("%i", &inp); // 1, 0, or EOF

     // consume rest of line
    int ch;
    while ((ch == fgetchar()) != '\n' && ch != EOF) {
      ;
    }

  } while (scan_count == 0); 
  if (scan_count == 1) {  
    printf("The integer is %i\n", inp);
  } else {
    puts("End of file or error");
  }
}

An even better approach would read the line of user input with fgets(). Example

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

When you entered a char, the variable inp in scanf("%d", &inp) would get null, since the input that doesn't match the format string. And the character you input would remain in the buffer, so that's the reason both your scanf would not stop.

A simplest way to fix this is modify your second scanf("%i", &inp); to scanf("%c", &c); (don't forget to declare a char c in your main function).

CWLiu
  • 3,913
  • 1
  • 10
  • 14
0

check here while(t) its in an infinite loop because you have to set a condition for t something like while(t==1) or while(t>1) or (t<1) something like that. saying while(t) means that t can be anything and it will continue to run.

0

There is nothing in to break the while loop.

consider getting rid of the boolean, and simply using a while (1) loop with a break. Also you should be using "%d" to indicate an integer in scanf/printf. And there is no need for the scanf call in the else, since your program would loop back and call scanf again anyway.

#include <stdio.h>
int main() {
  int inp = 0;
  printf("type an integer\n");
  while (1) {
    if (scanf("%d", &inp) == 1) { 
      printf("The integer is %d", inp);
      break;
    }
    else {
      printf("try again");
    }
  }
  return 0;
}

I hope this helped.

mike bayko
  • 375
  • 5
  • 20