Michael O'hearn
Michael O'hearn

Reputation: 91

Copying strings in C

I'm learning about strings in c. I am using code::blocks as a compiler, even though it's not just for c. So, the problem with the code below is that the output for string2 is the stored 5 characters plus string1's output. I'll show you:

#include <stdio.h>
#include <string.h>          /* make strncpy() available */

int main()
{
char string1[]= "To be or not to be?";
char string2[6];

/* copy first 5 characters in string1 to string2 */
strncpy (string2, string1, 5);

printf("1st string: %s\n", string1);
printf("2nd string: %s\n", string2);
return 0;
}

Output is:

1st string contains: To be or not to be? 
2nd string contains: To be To be or not to be?

If you ask me, that's a lot more than 5 characters...

Upvotes: 2

Views: 441

Answers (6)

Keith Thompson
Keith Thompson

Reputation: 263277

strncpy(), in spite of its name, is not simply a safer bounds-specified version of strcpy(). It's an obscure function with obscure semantics, and I would argue that it shouldn't have been included in the C standard library.

strncat(), on the other hand, is a safer bounds-specified version of strcat().

Here's one solution:

char string1[]= "To be or not to be?";
char string2[6];

string2[0] = '\0';
strncat (string2, string1, 5);

Upvotes: 0

Felice Pollano
Felice Pollano

Reputation: 33252

You are not terminating string2 with '\0', so the printf overruns. Try to do:

memset(string2,0,6);

before using string2. or, since you know you are copying 5 chars, after strncpy:

string2[5] ='\0';

so you properly terminate correctly the string.

pay attention to the fact that you should put '\0' after exactly the number of characters you did copy, otherwise you will see garbage even in the middle of the string.

Upvotes: 3

user411313
user411313

Reputation: 3990

strncpy has limitations, see above. have a look at sprintf like

sprintf( string2, "%.*s", sizeof(string2)-1, string1 );

Upvotes: 0

Vinicius Kamakura
Vinicius Kamakura

Reputation: 7778

From the strncpy man page:

No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.

Since the original string is greater in length than 5, no NULL is being added.

As others have pointed out, to add some safety to it:

strncpy (string2, string1, sizeof(string2));
string2[sizeof(string2)-1] = '\0';

Note that if string2 is obtained through a malloc():

char * string2 = malloc(123); //sizeof(string2) == sizeof(void *) and not 123

And the above code would fail.

For the sake of completeness, here is the code: http://ideone.com/eP4vd

Upvotes: 10

Gdogg
Gdogg

Reputation: 147

Basically both strings are on the stack next to each other in memory, and there is no null terminator after string2, so when it's printing it's printing the "To be" from string2 + random one byte value (string2[5]) + string1 ("To be or not to be") before hitting a null byte.

If that random one byte value was 0, it would stop. and you would get the print you expect.

Upvotes: 1

Mihai Maruseac
Mihai Maruseac

Reputation: 21435

Your string2 doesn't contain \0 thus this string is not terminated. When you are printing it it goes outside its bounds and prints whatever it finds there until it finds a \0.

After each strncpy you have to manually insert a \0 if you want to have a properly terminated string.

Upvotes: 0

Related Questions