我希望代码能够运行,直到用户输入整数值。
该代码适用于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 :(得分:26)
scanf()
。fgets()
获取整行。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));
答案 1 :(得分:4)
使用fgets
和strtol
,
指向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;
}
答案 2 :(得分:3)
尝试在scanf
中使用以下模式。它将一直读到行尾:
scanf("%d\n", &n)
由于getchar()
将读取整行,因此您不会需要循环内的scanf
。浮点数不会与scanf
模式匹配,提示符将再次请求整数。
答案 3 :(得分:3)
我知道如何使用
fgets
和strtol
完成此操作,我想知道如何使用scanf()
(如果可能)来完成此操作。
正如其他答案所说,scanf
并非真的适合这种情况,fgets
和strtol
是另一种选择(尽管fgets
的缺点是{&1}} #39;难以检测到输入中的0字节,并且无法判断0字节后输入的内容(如果有的话)。
为了完整起见(假设有效输入是整数后跟换行符):
while(scanf("%d%1[\n]", &n, (char [2]){ 0 }) < 2)
或者,在%n
之前和之后使用%*1[\n]
进行分配抑制。但请注意(来自Debian manpage):
虽然可以使用
*
赋值抑制字符来抑制转换,但这不是转换。 C标准说:&#34;执行%n
指令不会增加执行完成时返回的赋值计数&#34;但是更正似乎与此相矛盾。 可能明智的做法是不对%n
转换对返回值的影响做出任何假设。
答案 4 :(得分: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
}
答案 5 :(得分: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;
}
如果用户只输入空格,例如 Enter ,则此方法不会重新提示。
答案 6 :(得分:2)
一个可能的解决方案是向后思考它:接受一个浮动作为输入,如果浮点数不是整数,则拒绝输入:
int n;
float f;
printf("Please enter an integer: ");
while(scanf("%f",&f)!=1 || (int)f != f)
{
...
}
n = f;
虽然这允许用户输入类似12.0或12e0等的内容
答案 7 :(得分:0)
也许不是最佳解决方案...但仅使用 scanf 和 strtol
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {false, true} bool;
bool isIntString(char* input ) {
int i;
for (i = 0; i < strlen(input); i++) {
if(input[i] < '0' || input[i] > '9') {
return false;
}
}
return true;
}
int main()
{
char s[10];
char *end;
bool correct = false;
int result;
printf("Type an integer value: ");
do {
scanf("%s",s);
if ( isIntString(s)) {
correct = true;
result = strtol(s, &end, 10);
break;
} else {
printf("you typed %s\n",s);
printf("\ntry again: ");
}
} while (!correct);
printf("Well done!! %d\n",result);
return 0;
}