12

我有一个 char 数组缓冲区,用于存储用户将一一输入的字符。我下面的代码有效,但有一些我无法弄清楚的小故障:

  1. 当我执行 printf 以查看 Buffer 中的内容时,它确实填满了,但最后我得到了垃圾字符
  2. 尽管被声明为 char Buffer[8],但它不会在 8 个字符处停止;

有人可以向我解释发生了什么,也许我该如何解决这个问题?谢谢。

char Buffer[8]; //holds the byte stream
int i=0;

if (/* user input event has occurred */) 
{
        Buffer[i] = charInput;
        i++;

        // Display a response to input
        printf("Buffer is %s!\n", Buffer);

}

输出:

tagBuffer 是 1┬┬w!
tagBuffer 是 12┬w!
tagBuffer 是 123w!
tagBuffer 是 1234!
tagBuffer 是 12345!
tagBuffer 是 123456=!
tagBuffer 是 1234567!
tagBuffer 是 12345678!

tagBuffer 是 123456789!

4

7 回答 7

29

您必须以 \0 字符结束字符串。这就是为什么它们被称为零终止字符串。

分配 1 个额外的字符来保存 \0 也是明智的。

于 2008-11-06T23:07:35.897 回答
8

您传递给 printf() 函数的唯一内容是指向字符串第一个字符的指针。printf() 无法知道数组的大小。(它甚至不知道它是否是一个实际的数组,因为指针只是一个内存地址。)

printf() 和所有标准的 c 字符串函数都假定字符串末尾有一个 0。例如 printf() 将在内存中保留打印字符,从您传递给函数的字符开始,直到它达到 0。

因此,您应该将代码更改为以下内容:

char Buffer[9]; //holds the byte stream
int i=0;

if( //user input event has occured ) 
{
        Buffer[i] = charInput;
        i++;

        Buffer[i] = 0; // You can also assign the char '\0' to it to get the same result.

        // Display a response to input
        printf("Buffer is %s!\n", Buffer);

}
于 2008-11-06T23:10:14.207 回答
3

除了前面关于零终止的评论之外,您还必须承担不溢出自己的缓冲区的责任。它不会在 8 个字符处停止,因为您的代码没有停止!您需要以下内容(支持 Jeremy 的建议):

#define DATA_LENGTH 8
#define BUFFER_LENGTH (DATA_LENGTH + 1)

char Buffer[BUFFER_LENGTH]; //holds the byte stream
int charPos=0;  //index to next character position to fill

while (charPos <= DATA_LENGTH  ) { //user input event has occured
    Buffer[i] = charInput;

    Buffer[i+1] = '\0';

    // Display a response to input
    printf("Buffer is %s!\n", Buffer);

    i++; 

}

换句话说,请确保在达到最大长度时停止接受数据,无论环境试图向您推送什么。

于 2008-11-06T23:20:11.050 回答
0

如果您使用 C 或 C++ 编程,您必须记住:1) 字符串以 \0 字符结尾。2) C 对字符串没有边界检查,它们只是字符数组。

于 2008-11-06T23:11:58.023 回答
0

奇怪的是没有人提到这种可能性:

char Buffer[8]; //holds the byte stream
int i = 0;

while (i < sizeof(Buffer) && (charInput = get_the_users_character()) != EOF)
{
    Buffer[i] = charInput;
    i++;

    // Display a response to input
    printf("Buffer is %.*s!\n", i, Buffer);
}

printf() 格式字符串中的这个符号指定了要显示的字符串的最大长度,并且不需要空终止(尽管空终止最终是最好的方法——至少在你离开这个循环之后)。

while循环比简单的更合理,if并且此版本确保您不会溢出缓冲区的末尾(但不能确保您为尾随 NUL 留出足够的空间'\0'。如果您想处理它,请使用sizeof(Buffer) - 1然后添加 NUL循环之后。

于 2008-11-07T06:28:56.910 回答
0

由于Buffer未初始化,它以所有 9 个垃圾值开始。从观察到的输出中,第 2、第 3、第 4、第 5、第 6、第 7、第 8 和第 2 个直接下一个内存位置(数组外)元素显然是'T', 'T', 'W', '\0', '\0', '=', '\0', '\0', '\0'.

字符串会消耗所有字符,直到它们看到 NULL 字符。这就是为什么在每次迭代中,当数组元素被一一分配时,缓冲区被打印到存在垃圾 NULL 的部分。

也就是说,如果字符数组不以 . 结尾,则 string 具有未定义的行为'\0''\0'您可以通过在缓冲区末尾留出额外空间来避免这种情况。

于 2016-12-12T13:36:18.213 回答
-1

您可能还想研究使用stringstream.

于 2008-11-06T23:14:36.367 回答