strncpy没有按预期工作

时间:2012-12-25 03:45:21

标签: c++ string strncpy

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

我的输出是:some random string。但我希望它是:some。任何人都可以解释为什么它会这样吗?

4 个答案:

答案 0 :(得分:6)

strncpy does not necessarily null-terminate the string正在努力工作。当你这样做时:

strncpy(c, token, 5);

它将token的前5个字节复制到c 中,但不会终止结果。此外,这条线是没用的:

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

strlen(c)查找现有的null终止符,一旦找到,就会用另一个null终止符覆盖它,这是没有意义的。

在新代码中,strncpy应该很少,如果使用的话。它的预期用途(固定长度的缓冲区,不一定是空终止的)长期以来一直被人们所使用。更喜欢像strlcpy这样的函数(注意:strlcpy不是标准的;它仅在类似BSD的系统中可用。)

或者,如果您使用C ++而不是纯C进行编码,只需使用std::string并完全避免棘手的问题。

答案 1 :(得分:4)

我认为你的输出应该是“一些随机字符串”,因为你的两行代码什么都不做,请看评论。

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

如果你想输出“some”,你可以这样做:

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

strncpy()不会自动向dest字符串添加尾部'\ 0'。如果源字符串长度大于len(strncpy的第3个参数),则len字符复制到dest而不尾随'\ 0'。所以你必须通过代码明确地给出一个尾随的'\ 0'。

答案 2 :(得分:1)

在整个字符串之后,您需要在单词“some”后面的null终止,而不是null。 strncpy会将“some”复制到c中,但它不一定是null终止你的字符串(参见strncpy的手册页)

c[4] = '\0'

答案 3 :(得分:0)

正如其他人所提到的,与snprintfsprintf不同,strncpy不是strcpy的更安全版本。它只是确保“确切的N个字符被复制到目的地(如果源字符串短于N则使用NUL)”。 (手册页)

但我认为你已经注意到了这一行

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

这意味着确保c的空终止。但它实际上没有意义,因为strlen使用NUL来确定c的长度。所以这条线几乎没有“找到NUL并将NUL写入该位置”。

strncpy的重要性是复制字符串的certian部分。它不是strcpy的修复程序,并且在引入snprintf函数之前就已存在。