0

所以我真的不明白为什么scanf搞砸了[0]。当我打印出数组时,a[0] 为空,而我想要 a[0] 的位置存储在 a[1] 中。

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

int main(int argc, char *argv[])
{
    char *a[128];
    int i;
    int num;

    scanf("%d", &num);

    for (i = 0; i < 2; i++) {
        a[i] = malloc(50*sizeof(char));
        fgets(a[i], 100, stdin);
    }

    printf("[0] = %s [1] = %s", a[0], a[1]);

    return 0;
}
4

1 回答 1

3

scanf()没有a[0]通过以某种方式破坏其存储区域来弄乱您的 . 这对于混合不同的输入“方法”来说是一个非常大的问题。

您的scanf/fgets组合实际发生的scanf是获取整数,但没有读取您在该数字末尾输入的换行符,因此第一个fgets选择了它。

ISO 标准是这样说明的(按照指定的顺序):

输入空白字符(由 isspace 函数指定)将被跳过,除非规范包含 [、c 或 n 说明符。

从流中读取输入项,除非规范包含 n 说明符。输入项被定义为最长的输入字符序列,它不超过任何指定的字段宽度,并且是匹配输入序列的前缀。

输入项之后的第一个字符(如果有)保持未读状态。

第一段和最后一段很重要。第一个表示跳过前导空格,最后一个表示尾随空格留在输入流中以供稍后读取。


但是,我会告诉你什么可能会搞砸(取决于输入行的长度),事实上你为每个字符分配了 50 个字符空间,a[i]然后最多读取 100 个字符。那是未定义的行为。


如果您想要一个健壮的输入解决方案来正确处理缓冲区大小、检测太长的行、丢弃这些行的其余部分等等,请参阅此答案

或者,如果你想用非基于行的行为来模拟基于行的行为scanf(并且你确定你的行总是小于 100 字节),你可以改变:

scanf("%d", &num);

进入:

char junk[100];
scanf ("%d", &num);
fgets (junk, sizeof (junk), stdin);

这样它就可以抓住并扔掉其余的线。

并且您应该确保最大大小参数fgets与可用内存量相匹配(例如通过sizeof在上面的代码中使用)。

另一件事,请不要通过乘以使代码复杂化sizeof(char)- 根据标准,该值始终为 1。

于 2012-10-09T04:23:14.833 回答