简体   繁体   中英

strncpy is not working as expected

#include <iostream>
using namespace std 
#include <string.h>
int main(){
    char token[] = "some random string";
    char c[23];  
    strcpy( c, token);
    strncpy(c, token, 5); 
    c[strlen(c)] = '\0';
    cout<<c;
    return 0 ;
}

My output is: some random string . But I expect it to be: some . Can anyone please explain why it is behaving like this?

It's working just fine—bear in mind that strncpy does not necessarily null-terminate the string . When you do this:

strncpy(c, token, 5);

It copies the first 5 bytes of token into c but does not null-terminate the result . Furthermore, this line is useless:

c[strlen(c)] = '\0';

strlen(c) looks for an existing null terminator, and as soon as you find one, you overwrite it with another null terminator, which is pointless.

In new code, strncpy should seldom, if ever be used. Its intended use (fixed-length buffers which are not necessarily null-terminated) have long been obseleted. Prefer instead a function like strlcpy (note: strlcpy is not standard; it's only available in BSD-like systems).

Or, if you're coding in C++ instead of pure C, just use std::string and avoid tricky issues like this altogether.

I think your output should be "some random string", because your two lines of code do nothing, see the comment.

int main(){
   char token[] = "some random string";
   char c[23];  
   strcpy( c, token);
   strncpy(c, token, 5);  // Does nothing
   c[strlen(c)] = '\0';   // Does nothing
   cout<<c;
   return 0 ;
}

If you want to output "some", you could do this:

strncpy(c, token, 5);
c[5] = '\0';

strncpy() doesn't automatically add trailing '\\0' to dest string. If the source string length is bigger than len (3rd argument of strncpy), then len characters copied to dest without trailing '\\0'. So you have to give a trailing '\\0' explicitly by code.

You need to null terminate after the word "some" instead of null terminating after the entire string. strncpy will copy "some " into c, but it does not necessarily null terminate your string (see man page for strncpy )

c[4] = '\0'

As others have mentioned, unlike snprintf to sprintf , strncpy is not a safer version of strcpy . It merely ensures that "exactly N characters are copied to destination (use NUL if source string is shorter than N)". (man page)

But I think you've already noticed that by the line

c[strlen(c)] = '\0';

It meant to ensure the null termination of c . But it is actually pointless since strlen uses NUL to determine the length of c . So this line barely means "find NUL and write NUL to that location".

The importance of strncpy is to copy a certian part of string. It is not a fix to strcpy , and existed before the introduction of snprintf functions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM