string array with garbage character at end
Asked Answered
S

7

13

I have a char array buffer that I am using to store characters that the user will input one by one. My code below works but has a few glitches that I can't figure out:

  1. when I execute a printf to see what's in Buffer, it does fill up but I get garbage characters at the end
  2. it won't stop at 8 characters despite being declared as char Buffer[8];

Can somebody please explain to me what is going on and perhaps how I could fix this? Thanks.

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);

}

Output:

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 is 123456789!

Stephanystephen answered 6/11, 2008 at 23:6 Comment(0)
H
30

You have to end the string with a \0 character. That's why they are called zero terminated strings.

It is also wise to allocate 1 extra char to hold the \0.

Habitude answered 6/11, 2008 at 23:7 Comment(3)
Awesome. Thanks. Just one question though: what's the point of buffer[8] ?Stephanystephen
buffer[8] tells the compiler to set aside 8 bytes of memory for your array. Your string could be shorter than this (by doing "buffer[4] = 0;" for example) but it can't (or shouldn't) be longer.Brahmi
Buffer[8] is a buffer for 7 chars and one terminator ;-).Habitude
B
8

The only thing you are passing to the printf() function is a pointer to the first character of your string. printf() has no way of knowing the size of your array. (It doesn't even know if it's an actual array, since a pointer is just a memory address.)

printf() and all the standard c string functions assume that there is a 0 at the end of your string. printf() for example will keep printing characters in memory, starting at the char that you pass to the function, until it hits a 0.

Therefore you should change your code to something like this:

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);

}
Brahmi answered 6/11, 2008 at 23:10 Comment(0)
P
3

In addition to the previous comments about zero termination, you also have to accept responsibility for not overflowing your own buffer. It doesn't stop at 8 characters because your code is not stopping! You need something like the following (piggy-backing onto Jeremy's suggestion):

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

}

In other words, make sure to stop accepting data when the maximum length has been reached, regardless of what the environment tries to push at you.

Prussia answered 6/11, 2008 at 23:20 Comment(2)
@Jonathan: I assumed that DATA_LENGTH was the primary app domain concept and the size of Buffer was the dependent value, not vice versa. There might be other uses of DATA_LENGTH that had nothing to do with Buffer, and therefore shouldn't mention it.Prussia
@Prussia though your code above is not correct (while statement comment out of position), you deserve an upvote because setting the next character to '\0' IS THE SOLUTION. i recommend editing to "Buffer[i] = charInput; Buffer[i+1] = '\0'; i++;" for clarity, though your implementation is not incorrect, only harder to debug because you set 2 variables in the same line (question of style, i guess).Turnbull
M
0

If you are programming in C or C++, you have to remember that: 1) the strings are finished with a \0 character. 2) C does not have boundary check at strings, they are just character arrays.

Mowbray answered 6/11, 2008 at 23:11 Comment(0)
E
0

It's odd that no-one has mentioned this possibility:

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);
}

This notation in the printf() format string specifies the maximum length of the string to be displayed, and does not require null termination (though null termination is ultimately the best way to go -- at least once you leave this loop).

The while loop is more plausible than a simple if, and this version ensures that you do not overflow the end of the buffer (but does not ensure you leave enough space for a trailing NUL '\0'. If you want to handle that, use sizeof(Buffer) - 1 and then add the NUL after the loop.

Earshot answered 7/11, 2008 at 6:28 Comment(0)
S
0

Since Buffer is not initialized, it starts with all 9 garbage values. From the observed output, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th and 2 immediate next memory location(outside the array) elements are clearly 'T', 'T', 'W', '\0', '\0', '=', '\0', '\0', '\0'.

Strings consume all the characters up until they see NULL character. That is why, in every iteration, as the array elements are assigned one by one, buffer is printed up to the part where a garbage NULL is present.

That is to say, string has an undefined behavior if the character array doesn't end with '\0'. You can avoid this by having an extra space for '\0' at the end of the buffer.

Siamang answered 12/12, 2016 at 13:36 Comment(0)
M
-1

You might also want to look into using a stringstream.

Marquee answered 6/11, 2008 at 23:14 Comment(1)
stringstream is not C related.Fourteen

© 2022 - 2024 — McMap. All rights reserved.