How to scan only an integer?

I want the code to execute until the user enters an integer value.

The code works for char and char arrays.

I have done the following:


#include<stdio.h> int main() { int n; printf("Please enter an integer: "); while(scanf("%d",&n) != 1) { printf("Please enter an integer: "); while(getchar() != '\n'); } printf("You entered: %d\n",n); return 0; } 

The problem is that the user enters a float scanf value that will accept it.

 Please enter an integer: abcd Please enter an integer: a Please enter an integer: 5.9 You entered: 5 

How can this be avoided?

+11
source share
7 answers
  • You take scanf() .
  • You throw it in the basket.
  • You use fgets() to get the whole string.
  • You use strtol() to parse the string as an integer, checking if it consumed the entire string.
 char *end; char buf[LINE_MAX]; do { if (!fgets(buf, sizeof buf, stdin)) break; // remove \n buf[strlen(buf) - 1] = 0; int n = strtol(buf, &end, 10); } while (end != buf + strlen(buf)); 
+30
source

Use fgets and strtol ,

The pointer to the first character following the integer representation in s is stored in the object indicated by p , if *p is different from \n , then you have the wrong input.

 #include <stdio.h> #include <stdlib.h> int main(void) { char *p, s[100]; long n; while (fgets(s, sizeof(s), stdin)) { n = strtol(s, &p, 10); if (p == s || *p != '\n') { printf("Please enter an integer: "); } else break; } printf("You entered: %ld\n", n); return 0; } 
+7
source

Try using the following pattern in scanf . It will read to the end of the line:

 scanf("%d\n", &n) 

You won't need getchar() inside the loop, since scanf will read the entire line. The floating-point number will not match the scanf pattern, and the prompt will again ask for an integer.

+4
source

I know how to do this with fgets and strtol , I would like to know how to do this using scanf() (if possible).

As others say, scanf not suitable for this, fgets and strtol is an alternative (although fgets has the disadvantage that it is difficult to detect a 0-byte input and it is impossible to say what was entered after 0-byte if there is one).

For completeness (and if the valid input is an integer followed by a new line):

 while(scanf("%d%1[\n]", &n, (char [2]){ 0 }) < 2) 

Alternatively, use %n before and after %*1[\n] with assignment suppression. Please note, however (from the Debian man page ):

This is not a conversion, although it can be suppressed with an assignment suppression symbol * . The C standard says, "Executing the %n directive does not increase the assignment counter returned at completion," but the Patch seems to contradict this. It is probably wise not to make any assumptions about the effect of the %n transformations on the return value.

+4
source

If you use scanf , you can do something like the following:

 int val; char follow; int read = scanf( "%d%c", &val, &follow ); if ( read == 2 ) { if ( isspace( follow ) ) { // input is an integer followed by whitespace, accept } else { // input is an integer followed by non-whitespace, reject } } else if ( read == 1 ) { // input is an integer followed by EOF, accept } else { // input is not an integer, reject } 
+3
source

Using fgets() better.

To allow only use of scanf() for input, scan int and the following char .

 int ReadUntilEOL(void) { char ch; int count; while ((count = scanf("%c", &ch)) == 1 && ch != '\n') ; // Consume char until \n or EOF or IO error return count; } #include<stdio.h> int main(void) { int n; for (;;) { printf("Please enter an integer: "); char NextChar = '\n'; int count = scanf("%d%c", &n, &NextChar); if (count >= 1 && NextChar == '\n') break; if (ReadUntilEOL() == EOF) return 1; // No valid input ever found } printf("You entered: %d\n", n); return 0; } 

This approach does not request again if the user enters only a space, for example, only Enter .

+3
source

A possible solution is to think about it back: accept float as input and reject input if float is not an integer:

 int n; float f; printf("Please enter an integer: "); while(scanf("%f",&f)!=1 || (int)f != f) { ... } n = f; 

Although this allows the user to enter something like 12.0 or 12e0, etc.

+3
source

Source: https://habr.com/ru/post/977266/


All Articles