【问题标题】:C - Can't read user integer inputC - 无法读取用户整数输入
【发布时间】:2018-02-01 19:13:12
【问题描述】:

我正在尝试使用以下代码读取用户整数输入。我知道 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);
    }
}

我尝试运行它,首先输入 4,这给了我You didn't enter a number. 我再次尝试使用“四十”并得到相同的结果。我在这里想念什么?我想要做的就是获得一个整数值的基本用户输入,验证只输入了一个整数。我不需要很长,因为这些值都在 3000 到 4000 之间。

【问题讨论】:

  • last 是一个指针,但你将它与\0 比较,即int。你没有收到任何警告吗?
  • 不,我得到的唯一警告是未使用的变量,它们是其他东西的一部分。

标签: c user-input fgets strtol


【解决方案1】:

last != '\0' 等价于last != NULL。您正在测试 last 是否为空指针,但它从来都不是,因为 strtol 从不将 *endptr 设置为 NULL

您可能应该这样做:

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

(第一个条件处理buf为空字符串的情况。)

您的输入代码存在次要问题:

fgets(buf, 256, stdin);

此行不检查 fgets 的返回值以确保 buf 已填充,并且它不会删除任何用户输入的尾随换行符。

改为这样做:

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

至于'\0'为什么在这里充当空指针:

如果在指针上下文中使用,任何值为 0 的整数常量表达式都会隐式转换为空指针。 '\0' 就是这样一个零值的整数表达式,你将它与一个指针进行比较,所以它在指针上下文中。

【讨论】:

  • 试过了,我仍然收到You didn't enter a number. 消息,即使我用 5 测试了这个。
  • @user3308219 那是因为buf 在你的程序中是"5\n",而不是"5"
  • @user3308219 哦,我有 != 我打算使用 ==
【解决方案2】:

if(last != '\0') 更改为 if( *last != '\0')。您想查看last 指向的内容

来自https://linux.die.net/man/3/strtol

如果 endptr 不为 NULL,strtol() 存储第一个地址 *endptr 中的无效字符。如果根本没有数字,strtol() 将 nptr 的原始值存储在 *endptr 中(并返回 0)。

在 特别是,如果 *nptr 不是 '\0' 但 **endptr 在返回时是 '\0',则 整个字符串都有效。

【讨论】:

    【解决方案3】:

    对于 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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-07
      • 2014-08-18
      • 2022-01-11
      • 1970-01-01
      • 2014-02-14
      • 2017-02-02
      • 1970-01-01
      相关资源
      最近更新 更多