C - getchar() 没有正确读取输入的第二个字符

C - getchar() doesn't read the second character of an input correctly

我正在尝试使用 getchar() 读取输入数字的所有数字并将它们存储在数组中。但是每次我 运行 程序的第二个数字都会出错。

这是我的代码:

int ch = 0;
int digits[0];
int i = 0;

while ((ch = getchar()) != '\n') {
    digits[i] = ch - '0';
    i++;
}

为了说明会出什么问题,我插入了两个 printf:

while ((ch = getchar()) != '\n') {
    printf("%d ", ch);
    digits[i] = ch - '0';
    printf("%d\n", ch);
    i++;
}

例如,当我输入1100,我得到:

49 49

49 1

48 48

48 48

当我在一个单独的循环中打印数组时,输出是:

1 10 0 0

当我输入 66666 时,我得到:

54 54

54 6

54 54

54 54

54 5

数组为:

6 10 6 6 6

我尝试了一堆不同长度的其他数字,每次第二个数字都会发生同样奇怪的事情,而且只有第二个数字。有谁知道这是为什么?非常感谢!

int digits[0];

你有一个包含零位数字的数组。

int digits[32];     /* or some reasonable size, check for overflow... */

正如已经两次指出的那样,您的数组大小为零,因此无法容纳您试图放入其中的所有数字。

因此,当写入数组中的任何位置时,您 实际上 正在写入用于其他内容的内存,例如保存 ch。显然,您的程序期望(不存在的)digits[1] 所在的位置恰好存储了 ch。因此,您正在用 ch - '0'.

覆盖 ch

然后,当离开 ch 的范围时,程序可以自由地在那里编写其他内容。 (因为显然不再需要内存了。)显然它决定写一些有价值的东西 10。这会导致“奇怪”的输出。

请注意,在数组边界之外写入和读取是未定义的行为,并且可能产生比这更严重的副作用。以后尽量避免。

every time I run the program something goes wrong with the second digit.

这是因为您已将数组 digit 声明为 zero-size array,并且编译器没有为您的数组分配任何内存。因此,写入数组中的任何位置实际上将写入为其他目的分配的内存位置(如为其他变量分配的),而且它会有 undefined behavior

所以,你得到的结果是由于 UNDEFINED BEHAVIOR 并且在你的情况下,使用带有 digit 的索引写入任何位置实际上是写入分配给程序中其他变量的内存并且您通过 digit[1] 获得的内存位置恰好是分配给程序中类型 char 的变量 ch 的内存位置。因此,写入内存位置 digit[1] 将修改您的 ch 变量。因为,它是 undefined behavior,您的程序可能会得到一个 Segmentation Fault

要解决您的问题,请声明数组 digit 足够大。

#define SIZE_DIGITS  /* Sufficient Size required by your application */
int digit[SIZE_DIGITS];

但是,在标准 C 和 C++ 中,zero-size array 是不允许的,如果您使用的是 GCC,请使用 -pedantic 选项进行编译。它会给出警告,说:

zero.c:3:6: warning: ISO C forbids zero-size array 'a' [-pedantic]

如果是 C++,它会给出类似的警告。

此外,zero-size 数组作为结构的最后一个元素非常有用,该结构实际​​上是 header 对应 variable-length object。它们在 GNU C.The 结构中允许使用 zero-size array 作为最后一个元素称为 variable-length structure。您可以阅读更多相关信息 here

发布的代码有一些小问题:

  1. array digits[] 被设置为 0 大小,所以不能容纳任何数字所以试图在 digits[x] 中放置任何东西会破坏堆栈

  2. while() 循环,即使 digits[] 被正确声明,也不会停止输入字符(只要不是 EOF 和换行符)所以可以溢出任何数组尺码

  3. 发布的代码不监视 EOF 条件

这里有一些代码可以正常工作,最多只允许 32 位数字

#include <stdio.h>

#define MAX_DIGITS (32)

int main( void )
{

    int ch = 0;
    int digits[ MAX_DIGITS ];


    int i = 0;
    while ( i < MAX_DIGITS && ( (ch = getchar()) != EOF && '\n' !=  ch) ) 
    {
        printf("%d ", ch);
        digits[i] = ch - '0';
        printf("%d\n", digits[i]);
        i++;
    }
}

这是一个示例输入

1 2 3 4 5 6

和结果输出

49 1
32 -16
50 2
32 -16
51 3
32 -16
52 4
32 -16
53 5
32 -16
54 6

注意:32 -16来自输入中的空格,因此为了获得最佳结果,应修改代码以忽略数字输入以外的其他内容