好吧,strncpy
不适用于NULL终止字符串 - 它不是为NULL终止字符串设计的(如果dest太短,它不会被NULL终止,如果dest更长,它将被填充零())。
所以,这是一个简单的代码:
const char *src = ....; // NULL terminated string of unknown length
char dest[30];
如何 src 到 dest ? strcpy
不安全,strncpy
也是不好的选择。所以我离开了 strlen ,然后是memcpy
?
我想解决方案会有所不同,每当我关心 dest 不会被截断( dest 小于 src 的长度)时。
一些限制:
strlcpy
- gcc不提供它。 strncpy
那样用零 dest 来浪费CPU时间填充。但是,我不是在谈论过早优化,而是用C语言执行字符串复制的愚蠢方式。修改
Oopps,我的意思是strncpy
而不是snprintf
。我的错误
答案 0 :(得分:4)
使用strncpy:
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';
这个填充零,但格式化工作比snprintf
少得多。如果你真的必须让计算机做得尽可能少,请自己描述一下:
char* last = dest + sizeof(dest) - 1;
char* curr = dest; /* assuming we must not alter 'dest' */
while (curr != last && *src) { *curr++ = *src++; }
*last = '\0'; /* avoids a branch, but always writes.
If branch prediction is working well and the text normally fits:
if (curr == last) { *curr = '\0'; } */
答案 1 :(得分:4)
我认为你在谈论strncpy()
,它可能不会终止字符串并用零填充缓冲区的其余部分。
snprintf()
总是终止目标字符串(只要缓冲区的大小至少为1),并且不用零填充缓冲区的剩余部分。
总之,snprintf()
是你想要的,除非你非常关心性能。由于snprintf()
需要解释格式字符串(即使它最终完成的是复制字符串),对于有界字符串复制操作,最好使用strlcpy()
之类的东西。
(如果你想要strlcpy()
但没有它,你可以得到相当简单的source here。为了完整性,strlcat()
is here)
答案 2 :(得分:3)
如果您不关心截断,可以使用strncat()
:
dest[0] = 0;
strncat(dest, src, sizeof dest - 1);
答案 3 :(得分:1)
我只是自己动手:
for (int i = 0; i < (sizeof(dest) - 1) && src[i] != NULL; i++)
{
dest[i] = src[i];
}
dest[i] = NULL;
这可确保dest
以空值终止,但绝不会添加超出必要的空值。如果您确实对性能敏感,可以将其声明为公共标头中的宏或内联函数。
答案 4 :(得分:1)
使用snprintf
。它始终为null终止,并且不执行任何空填充。不知道你对它有什么误解......
答案 5 :(得分:0)
std::copy(src, src+strlen(src)+1, dest)
答案 6 :(得分:0)
我不确定我是否完全理解你的问题,但如果你担心零填充,如果你像这样初始化你的数组,通常可以非常有效地完成。
char dest[30] = { 0 };
如果你初始化它就像你不必关心额外的逻辑来将'\ 0'添加到字符串的末尾,它甚至可能更快。
但是,如果您要进行优化,请记住在优化之前和之后测量性能。否则始终会考虑可读性和可维护性。