【问题标题】:Passing a non-digit char after an integer to scanf将整数后的非数字字符传递给 scanf
【发布时间】:2021-01-23 03:11:48
【问题描述】:
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  int n, k;
  scanf("%d %d", &n, &k);
  printf("%d %d\n", n, k);

  return 0;
}

在上面的示例代码中传递给输入

1 2

会产生预期的输出

1 2

但是在这两个数字之间传递任何字符,例如

1. 21 d 3

会导致以下奇怪的输出

1 32766

我想知道为什么会发生这种情况,因为我认为 scanf 会跳过任何非数字输入。

【问题讨论】:

  • 在使用它解析的变量(你认为)之前总是检查scanf的返回值。以输入1. 2为例,在读取n后解析在.字符处停止,第二个值k不被修改。
  • 32766 奇怪地接近 2 Bytes 可以存储的最大数,不知道是不是跟它有关

标签: c


【解决方案1】:

您应该检查scanf 的返回值,它告诉您读取到传递的参数中的数据数量,这里是k。 在您的情况下,返回值将为零,因为%d 不能用于读取C 中的char。如果第一个输入是 char,它将为 0,如果第一个值是 int,则为 1,第二个值是 char,如果两个值都是 int,则为 2。

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

int main(void)
{
    int n, k, rc;
    rc = scanf("%d %d", &n, &k);
    if (rc != 2) 
    {
        printf("scanf failed to set the values for n and k\n");
    }
    else
    {
        printf("valid input for n and k\n");
    }
    printf("%d %d\n", n, k);
    return 0;
}

所以int k 未初始化,因此它将存储一些随机值,因为scanf 未能设置此变量的值。

【讨论】:

  • 当您将字符值传递给%d 时,它具有未定义的行为,导致变量k 的值在32766 附近
  • 这非常有帮助,谢谢,有没有传递停止输入流的字符?
  • @dxiv 更新代码检查scanf的返回值
  • if (rc == 0) 这应该是if (rc != 2),以验证是否已读入两个值。
  • 是的,我错过了条件,现在更新代码。因此,如果scanf 未能读取第一个值,它将返回0,如果第二个值失败,它将返回1,如果一切正常,它将返回2。关于存储到变量中的随机数字,它可能取决于操作系统。
【解决方案2】:

评论太长了。)以下回答了 OP 从评论中提出的后续问题。

到底有没有可以跳过停止输入流的字符?

scanf 可能不是最好或最简单的方法,但仍然可以使用%n 格式说明符来做到这一点,它在解析期间将偏移量返回到原始字符串中。下面是一个例子,它使用sscanf,但可以很容易地适应scanf

#include <stdio.h>

void read_three_ints(const char *str) {
    int a, n1, b, n2, c;
    int ret = sscanf(str, "%d %n%d %n%d", &a, &n1, &b, &n2, &c);
    switch(ret)
    {
    case 3:
        printf("'%s': a = %d, b = %d, c = %d\n", str, a, b, c);
        break;
    case 2:
        printf("'%s': a = %d, b = %d, error parsing c = `%s`\n", str, a, b, str + n2);
        break;
    case 1:
        printf("'%s': a = %d, error parsing b = `%s`\n", str, a, str + n1);
        break;
    case 0:
        printf("'%s': error parsing a\n", str);
        break;
    default:
        printf("'%s': scanf error %d\n", str, ret);
        break;
    }
}

int main()
{
    read_three_ints("1 2 3");
    read_three_ints("1 2 x");
    read_three_ints("1, 2 ");
    read_three_ints(";1   ");
    read_three_ints("");
    return 0;
}

Output:

'1 2 3': a = 1, b = 2, c = 3
'1 2 x': a = 1, b = 2, error parsing c = `x`
'1, 2 ': a = 1, error parsing b = `, 2 `
';1   ': error parsing a
'': scanf error -1

【讨论】:

    猜你喜欢
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多