C语言 如何只扫描整数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26583717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:30:10  来源:igfitidea点击:

How to scanf only integer?

cscanf

提问by user1336087

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

我希望代码一直运行,直到用户输入一个整数值。

The code works for char and char arrays.

该代码适用于 char 和 char 数组。

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 if the user inputs a float value scanfwill accept it.

问题是如果用户输入一个浮点值scanf会接受它。

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

How can that be avoided?

如何避免这种情况?

回答by The Paramagnetic Croissant

  1. You take scanf().
  2. You throw it in the bin.
  3. You use fgets()to get an entire line.
  4. You use strtol()to parse the line as an integer, checking if it consumed the entire line.
  1. 你拿scanf()
  2. 你把它扔进垃圾箱。
  3. fgets()用来得到一整条线。
  4. 您用于strtol()将行解析为整数,检查它是否消耗了整行。
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));

回答by David Ranieri

Use fgetsand strtol,

使用fgetsstrtol,

A pointer to the first character following the integer representation in sis stored in the object pointed by p, if *pis different to \nthen you have a bad input.

指向 in 整数表示后第一个字符的指针s存储在 指向的对象中p,如果*p与 不同,\n则输入错误。

#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;
}

回答by mafso

I know how this can be done using fgetsand strtol, I would like to know how this can be done using scanf()(if possible).

我知道如何使用fgets和完成此操作strtol,我想知道如何使用scanf()(如果可能)来完成此操作。

As the other answers say, scanfisn't really suitable for this, fgetsand strtolis an alternative (though fgetshas the drawback that it's hard to detect a 0-byte in the input and impossible to tell what has been input after a 0-byte, if any).

正如其他答案所说,scanf并不真正适合于此,fgets并且strtol是一种替代方法(尽管fgets有一个缺点,即很难检测到输入中的 0 字节,并且无法判断在 0 字节之后输入了什么,如果任何)。

For sake of completeness (and assuming valid input is an integer followed by a newline):

为了完整起见(并假设有效输入是一个整数,后跟一个换行符):

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

Alternatively, use %nbefore and after %*1[\n]with assignment-suppression. Note, however (from the Debian manpage):

或者,使用%nbefore 和 after%*1[\n]与赋值抑制。但是请注意(来自Debian 联机帮助页):

This is not a conversion, although it can be suppressed with the *assignment-suppression character. The C standard says: "Execution of a %ndirective does not increment the assignment count returned at the completion of execution" but the Corrigendum seems to contradict this. Probably it is wise not to make any assumptions on the effect of %nconversions on the return value.

这不是转换,尽管可以使用*赋值抑制字符来抑制它。C 标准说:“%n指令的执行不会增加执行完成时返回的赋值计数”,但勘误表似乎与此相矛盾。可能明智的做法是不对%n转换对返回值的影响做出任何假设。

回答by John Bode

If you're set on using scanf, you can do something like the following:

如果您开始使用scanf,则可以执行以下操作:

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
}

回答by chux - Reinstate Monica

Using fgets()is better.

使用fgets()效果更好。

To solve only using scanf()for input, scan for an intand the following char.

要解决仅scanf()用于输入的问题,请扫描 anint和以下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 re-prompt if user only enters white-space such as only Enter.

如果用户仅输入诸如 only 之类的空白,则此方法不会重新提示Enter

回答by hcs

A possible solution is to think about it backwards: Accept a float as input and reject the input if the float is not an integer:

一个可能的解决方案是向后考虑:接受浮点数作为输入,如果浮点数不是整数则拒绝输入:

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

Though this does allow the user to enter something like 12.0, or 12e0, etc.

尽管这确实允许用户输入诸如 12.0 或 12e0 之类的内容。

回答by vicsana1

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

尝试在scanf. 它将一直读到行尾:

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

You won't need the getchar()inside the loop since scanfwill read the whole line. The floats won't match the scanfpattern and the prompt will ask for an integer again.

您不需要getchar()循环内部,因为scanf它将读取整行。浮点数与scanf模式不匹配,提示将再次要求输入整数。