views:

1381

answers:

6

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!

+15  A: 

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.

Gamecat
Awesome. Thanks.Just one question though: what's the point of buffer[8] ?
Steve
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.
yjerem
Buffer[8] is a buffer for 7 chars and one terminator ;-).
Gamecat
+4  A: 

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

}
yjerem
A: 

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.

A: 

You might also want to look into using a stringstream.

Brian
stringstream is not C related.
quinmars
+1  A: 

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] = '\0';

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

}

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.

joel.neely
Use sizeof(Buffer)!
Jonathan Leffler
@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.
joel.neely
A: 

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.

Jonathan Leffler