Reputation: 91
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
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
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
Reputation: 3990
strncpy has limitations, see above. have a look at sprintf like
sprintf( string2, "%.*s", sizeof(string2)-1, string1 );
Upvotes: 0
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
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
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