2014-10-27 63 views
6

我想让代码运行直到用户输入一个整数值。如何扫描整数?

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

我也做了以下内容:


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

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

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

这怎么可以避免?

+0

这是很相似? http://stackoverflow.com/questions/23610457/how-can-i-distinguish-between-integer-and-character-when-using-scanf – 2014-10-27 08:42:59

+2

它不是'扫描浮动',而是停在第一个非数字。它也会通过输入“5xyzNotAFloatNumber”来做到这一点。 – usr2564301 2014-10-27 08:43:09

+0

所以不能用'scanf'完成?所以一定要使用'fgets'? – user1336087 2014-10-27 08:46:07

回答

18
  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)); 
+0

嗯看起来像循环将退出,如果用户只输入''\ n''。不知道这对OP是否重要。 – chux 2014-10-27 14:23:26

+0

@chux这是故意的基本错误处理。 – 2014-10-27 15:11:57

4

尝试使用在scanf以下模式,它会读取行,直到结束:

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

你不会需要的getchar(),因为scanf函数内循环将读取整个行。浮点数与scanf模式不匹配,并且提示符会再次询问整数。

+0

'scanf(“%d \ n”,&n)'只读入整行(然后是一些),如果输入了'int'。如果没有输入“int”,则输入保留在“stdin”中。使用'“\ n”'不仅会消耗'\ n'',而且会扫描任意数量的空格,直到输入非空格。那个'char'然后被放回到'stdin'中。因此''\ n''输入时'scanf()'不会立即返回。 – chux 2014-10-27 14:33:33

4

使用fgetsstrtol

一个指向按照s整数表示的第一个字符被存储在由p指向的对象时,如果*p是不同的,以\n那么你有一个坏输入。

#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    char *p, s[100]; 
    int 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: %d\n", n); 
    return 0; 
} 
+0

解释你为什么改变了你所做的事情可能很有用。目前看来,你只是在你的风格 – raam86 2014-10-27 08:52:10

+0

@ raam86 ...基本上复制我的答案。 – 2014-10-27 08:52:39

+5

@TheParamagneticCroissant,我没有看过你的答案,你认为你是唯一使用'fgets'和'strtol'的人吗? ;) – 2014-10-27 08:53:34

3

我知道这可以用fgetsstrtol做,我想知道如何能使用scanf()(如果可能)来完成。

至于其他的答案说,scanf是不是真的适合这个,fgetsstrtol是另一种(尽管fgets有,它很难在输入检测到一个0字节,也不可能告诉缺点什么已经在0字节之后输入,如果有的话)。

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

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

可替换地,前和%*1[\n]与分配-抑制后使用%n。但是请注意,(从Debian manpage):

这不是一个变换例,但它可以与*分配抑制字符得到抑制。 C标准说:“执行%n指令不会增加执行完成时返回的赋值计数”,但更正似乎与此相矛盾。 可能明智的做法是不对%n转换对返回值的影响作出任何假设。

2

如果你正在使用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 
} 
2

使用fgets()更好。

要解决仅使用scanf()进行输入,请扫描int以及以下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; 
} 

该方法不重新提示用户是否只进入空白诸如仅输入

+0

在每次传递循环中,设置NextChar ='\ 0';然而,在某些操作系统中'\ n'是一个多字符项目,所以定义为'int NextChar = 0然后当没有字符输入时它会重新提示 – user3629249 2014-10-28 03:25:44

+0

@ user3629249感谢这个想法 - 不要认为它会工作。当没有输入'char'时(例如:只有''\ n''),scanf()将不会返回,直到输入一个非空格。 ''%d“'使'scanf()'消耗白色空间直到EOF或非空白。所以设置'NextChar'这个或那个不会有什么区别。 – chux 2014-10-28 03:36:15

+0

@chux如果只接受正整数,你会如何修改?修改第一个if if(count> = 1 && n> 0 && NextChar =='\ n')'似乎不起作用。如果我们给出例如'-125',Stdout不会做出反应,但我们必须再次输入输入才能显示消息。 – BugShotGG 2015-03-02 10:43:47

2

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

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

虽然这确实允许用户输入类似12.0,或12e0等。

+1

注意:当输入为“abcd”时,代码仍留在'stdin'中。另外,请使用输入“2147483647”或“0.9999999999”来尝试。 – chux 2014-10-27 15:17:21