为什么scanf不能读取我的输入?

3
我想使用scanf()来读取以下表格:
Q 1 3
U 2 6
Q 2 5
U 4 8

这是我的代码:
#include <stdio.h>
#include <stdlib.h>

void main() {
    int *a;
    int i, j;

    a = (int *) malloc(4 * 3 *sizeof(int));

    printf("input:\n");
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 3; j++) {
           scanf("%d", a + 3 * i + j);
        }
    }

    printf("output:\n");

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 3; j++) {
           printf("%d  ", a[3*i+j]);
        }
        printf("\n");
    }   
}

enter image description here

然而,当我输入第一行Q 1 3时,程序就结束了。我不知道为什么?


注:本文涉及IT技术相关内容。

1
声明 achar 指针并使用 scanf(" %c", a + 3 * i + j);。在 %c 前加一个空格是有意的。还要将 printf("%d ", a[3*i+j]); 更改为 printf("%c ", a[3*i+j]);。(我假设输入中只使用一位数字)。 - haccks
请不要发布动态GIF图像。最好完全不要发布图像,只需将文本剪切/粘贴到问题中,并将其标记为代码。 - Barmar
3个回答

5
这是因为你的程序想要读取一个用%d表示的数字,但你提供了一个非数字输入,如Q,导致scanf失败。
然而,你的程序没有注意到scanf的返回值,并且在失败状态下不断调用它。程序认为它正在获取一些数据,但实际上并没有。
要修复这个问题,请在读取非数字字符时更改代码以传递%c%s,检查scanf的返回值,并在scanf失败时摆脱无效输入。
当你调用scanf时,它会返回它提供的与%说明符相对应的值的数量。以下是如何检查scanf的返回值:
if (scanf("%d", a + 3 * i + j) == 1) {
    ...                   // The input is valid
} else {
    fscanf(f, "%*[^\n]"); // Ignore to end of line
}

1
因为字母 Q 不是数字,所以 scanf 将失败并保持输入缓冲区不变。因此,下一次迭代中的 scanf 将看到相同的 Q 并再次失败,如此循环往复...

这意味着实际上没有将任何内容读入您分配的内存中,并且您打印未初始化的内存,导致出现 未定义的行为

解决问题的一种可能的方法是读取(使用例如 fgets),然后使用 sscanf 一次性解析整行。也许像这样:

for (i = 0; i < 4; i++) {
    char buffer[64];
    if (fgets(buffer, sizeof buffer, stdin) != NULL) {
        char c;  // The character
        int a, b;  // The integer values
        sscanf(buffer, "%c %d %d", &c, &a, &b);
        a[3 * i + 0] = c;
        a[3 * i + 1] = a;
        a[3 * i + 2] = b;
    }
}

我建议您实际初始化分配的内存,特别是如果您不打算使用其中的部分但仍然要打印它。

那么我想知道如何处理它? - xyz
1
@ShutaoTang scanf 返回成功匹配的项目数... - LPs

0
要么使用具有正确 ASCII 值的 int 变量的 scanf(),要么使用 char 变量的 scanf(),但在两种情况下都使用 %c 进行打印。Q 的 ASCII 代码为 81,U 的 ASCII 代码为 85。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接