0
#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

4 回答 4

6

它工作得很好 - 请记住,strncpy不一定会以空值终止 string。当你这样做时:

strncpy(c, token, 5);

它复制tokeninto的前 5 个字节,c 但不以空值终止 result。此外,这条线是无用的:

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

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

在新代码中,strncpy应该很少使用,如果曾经使用过。它的预期用途(不一定是空终止的固定长度缓冲区)早已过时。更喜欢类似的功能strlcpy(注意:strlcpy不是标准的;它仅在类似 BSD 的系统中可用)。

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

于 2012-12-25T03:51:28.430 回答
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 ;
}

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

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

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

于 2012-12-25T03:51:32.427 回答
1

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

c[4] = '\0'
于 2012-12-25T03:51:18.500 回答
0

正如其他人所提到的,与snprintfto不同sprintfstrncpy它不是更安全的strcpy. 它只是确保“恰好 N 个字符被复制到目标(如果源字符串短于 N,则使用 NUL)”。(手册页)

但我想你已经注意到了

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

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

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

于 2012-12-25T07:26:53.750 回答