массив строк с символом мусора в конце - PullRequest
12 голосов
/ 07 ноября 2008

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

  1. когда я выполняю printf для просмотра содержимого буфера, он заполняется, но в конце я получаю символы мусора
  2. он не остановится на 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!

Ответы [ 7 ]

28 голосов
/ 07 ноября 2008

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

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

8 голосов
/ 07 ноября 2008

Единственное, что вы передаете функции 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);

}
3 голосов
/ 07 ноября 2008

В дополнение к предыдущим комментариям о нулевом завершении, вы также должны принять на себя ответственность за не переполнение вашего собственного буфера. Это не останавливается на 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++; 

}

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

0 голосов
/ 12 декабря 2016

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

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

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

0 голосов
/ 07 ноября 2008

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

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

0 голосов
/ 07 ноября 2008

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

0 голосов
/ 07 ноября 2008

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

...