简体   繁体   English

C-无法读取用户整数输入

[英]C - Can't read user integer input

I'm trying to read user integer input with the following code. 我正在尝试使用以下代码读取用户整数输入。 I'm aware that strtol returns a long value. 我知道strtol返回一个长值。

long color = 1;
char buf[256];
char * last;

while(color != 0){
    printf("Enter a color (0 to stop): ");
    fgets(buf, 256, stdin);

    color = strtol(buf, &last, 10);

    if(last != '\0'){
        printf("You didn't enter a number.\n");
    }
    else{
        printf("%d\n", color);
    }
}

I tried running this, first entering 4, which gave me You didn't enter a number. 我尝试运行此程序,首先输入4,这给了我You didn't enter a number. I tried it again with "forty" and got the same result. 我再次尝试了“四十”,并得到了相同的结果。 What am I missing here? 我在这里想念什么? All I want to do is get basic user input for an integer value that verifies only an integer was entered. 我要做的就是获取基本用户输入的整数值,该值验证仅输入了整数。 I don't need a long because the values will all be between 3000 and 4000. 我不需要很长时间,因为这些值都在3000到4000之间。

Change that if(last != '\\0') to if( *last != '\\0') . if(last != '\\0')更改为if( *last != '\\0') You want to check what last points to 您想检查last 指向什么

From https://linux.die.net/man/3/strtol https://linux.die.net/man/3/strtol

If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. 如果endptr不为NULL,则strtol()将第一个无效字符的地址存储在* endptr中。 If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). 如果根本没有数字,strtol()会将nptr的原始值存储在* endptr中(并返回0)。

In particular, if *nptr is not '\\0' but **endptr is '\\0' on return, the entire string is valid. 特别是,如果返回时* nptr不是'\\ 0',而** endptr是'\\ 0',则整个字符串都是有效的。

last != '\\0' is equivalent to last != NULL . last != '\\0'等同于last != NULL You're testing whether last is a null pointer, which it never is, because strtol never sets *endptr to NULL . 您正在测试last是否是空指针,而从来没有,因为strtol从未将*endptr设置为NULL

You should probably do this instead: 您可能应该这样做:

if (last == buf || *last != '\0')

(The first condition handles the case where buf is an empty string.) (第一个条件处理buf是空字符串的情况。)

There's a secondary problem in your input code: 输入代码中存在第二个问题:

fgets(buf, 256, stdin);

This line does not check the return value of fgets to make sure buf was filled, and it does not remove the trailing newline of any user input. 该行不会检查fgets的返回值以确保buf已被填充,并且不会删除任何用户输入的结尾换行符。

Do this instead: 改为这样做:

if (!fgets(buf, 256, stdin)) {
    break;
}
buf[strcspn(buf, "\n")] = '\0';

As for why '\\0' acts as a null pointer here: 至于为什么'\\0'在这里充当空指针:

Any integer constant expression with value zero is implicitly converted to a null pointer if used in a pointer context. 如果在指针上下文中使用,则任何值为零的整数常量表达式都会隐式转换为空指针。 '\\0' is such a zero-valued integer expression, and you're comparing it to a pointer, so it is in pointer context. '\\0'是一个零值整数表达式,您正在将其与指针进行比较,因此它位于指针上下文中。

For OP's specific case, it is sufficient to test for extra non-numeric text after the number. 对于OP的特定情况,测试数字后是否有多余的非数字文本就足够了。

char buf[256];

if (fgets(buf, sizeof buf, stdin)) Handle_EndOfFile();
char *last;
long color = strtol(buf, &last, 10);

while (isspace(*last)) last++; // tolerate trailing white-space like '\n'

// Do not compare the pointer, compare what it points to
// if(last != '\0'){
if (*last || color < 3000 || color > 4000) {
  Handle_NonNumeric("You didn't enter a number in 3000-4000 range.\n");
} else {
  foo(color); // Success
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM