Строковый массив с символом мусора в конце

У меня есть буфер массива char, который я использую для хранения символов, которые пользователь будет вводить один за другим. Мой код ниже работает, но имеет несколько сбоев, которые я не могу понять:

  • когда я выполняю printf, чтобы увидеть, что в буфере, он заполняется, но я получаю символы мусора в конце
  • он не останавливается на 8 символов, несмотря на то, что объявлен как char Buffer [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 is 1┬┬w!
tagBuffer is 12┬w!
tagBuffer is 123w!
tagBuffer is 1234!
tagBuffer is 12345!
tagBuffer is 123456=!
tagBuffer is 1234567!
tagBuffer is 12345678!

tagBuffer - 123456789!

Ответ 1

Вы должны закончить строку символом \0. Вот почему они называются нулевыми завершенными строками.

Также целесообразно выделить 1 дополнительный char для хранения\0.

Ответ 2

Единственное, что вы передаете функции printf(), - это указатель на первый символ вашей строки. printf() не имеет возможности узнать размер вашего массива. (Он даже не знает, является ли это фактическим массивом, поскольку указатель - это просто адрес памяти.)

printf(), и все стандартные функции строки c предполагают, что в конце строки находится 0. printf(), например, сохранит печатные символы в памяти, начиная с char, который вы передадите функции, пока не достигнет 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);

}

Ответ 3

В дополнение к предыдущим комментариям о нулевом завершении, вы также должны нести ответственность за то, что не переполнили свой собственный буфер. Он не останавливается на 8 символах, потому что ваш код не останавливается! Вам нужно что-то вроде следующего (копирование на предложение Джереми):

#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++; 

}

Другими словами, обязательно прекратите принимать данные, когда максимальная длина будет достигнута, независимо от того, что среда пытается нажимать на вас.

Ответ 4

Если вы программируете на C или С++, вы должны помнить, что: 1) строки заканчиваются символом \0. 2) C не имеет граничной проверки в строках, это просто массивы символов.

Ответ 5

Странно, что никто не упомянул об этой возможности:

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 после цикла.

Ответ 6

Так как Buffer не инициализируется, он начинается со всех 9 значений мусора. Из наблюдаемых выходов 2, 3, 4, 5, 6, 7, 8 и 2 сразу следующие ячейки памяти (вне массива) четко обозначены 'T', 'T', 'W', '\0', '\0', '=', '\0', '\0', '\0'.

Строки уничтожают все символы до тех пор, пока не увидите символ NULL. Поэтому на каждой итерации, когда элементы массива присваиваются один за другим, буфер печатается до той части, где присутствует мусор NULL.

То есть, строка имеет поведение undefined, если массив символов не заканчивается на '\0'. Вы можете избежать этого, добавив дополнительное пространство для '\0' в конце буфера.

Ответ 7

Вы также можете посмотреть на использование stringstream.