C语言 Example for strncpy()



如果我对字符串使用strncpy函数catdog.我不明白字符是否算在内,所以我想知道最终结果是否会catdo?还是会像catdo

strncpy("cat", "dog", 2);

正如 torstenvl 提到的,"cat""dog"是字符串文字,所以你在这里没有正确使用该函数。第一个参数是目标,第二个参数是源,第三个参数是要复制的字节数。

char *strncpy(char *restrict s1, const char *restrict s2, size_t n)

来源:开放组基本规范 - strncpy

要回答您的特定问题:是;空终止符将复制到目标字符串。 写入n字节,如果源字符串s2短于n个字节,则填充NULL,直到写入n个字节。

在您的问题中,您似乎正在尝试附加两个字符串。若要在 C 中执行此操作,需要首先分配一个源字符串缓冲区,复制第一个字符串,然后从第二个字符串的末尾开始复制第二个字符串。根据您从何处开始最后一步,您可能会以"catdog\0"或"cat\0dog\0"结束。这是典型的"一分之一"错误的另一个例子。

首先,您必须计算要附加的两个字符串的长度。您可以使用strlenstring.h来执行此操作。strlen不会将 null 终止符计为长度的一部分,因此请记住,要获取最终字符串的长度,您必须执行strlen(s1) + strlen(s2) + 1

然后,您可以像往常一样复制第一个字符串。执行第二个副本的一个简单方法是执行以下操作:

char* s2start = finalString[strlen(s1) + 1];

然后你可以做strncpy(s2start, s2, [the size of s2])这样你就知道你是在s1 null终止符上开始,避免"cat\0dog"错误。

希望这有帮助,祝你好运。

你根本不应该使用strncpystrncat函数。

它们的名字以str开头,但实际上并不适用于字符串。在 C 中,字符串定义为"以''结尾的字符序列"。这些函数不保证生成的字符数组始终以 null 结尾。

更好的选择是strlcpystrlcat,但这些并非无处不在。

更好的是单独的字符串库,其中确定字符串的长度是一个常量时间操作。但这会分散注意力。

当你在c中写出像"cat""dog"这样的字符串时,数组无法更改,如果你尝试这样做将导致未定义的行为。只有当函数需要const char * input时,您才能使用这些函数,const告诉您它不能/不会在函数中更改。当您写入"dog"字符数组中的数据将如下所示:

{'d','o','g',''}

请注意,它以 NUL 终止。

您正在使用的功能:

char *strncpy(char *dest, const char *src, size_t n)

src复制到dst,最大长度为n您无法复制到"cat"如上所述,您可以看到char *dest不是恒定的,而是const char * src恒定的。所以来源可能是"cat""dog"

如果要为字符串分配空间,则可以对其进行修改:

char cat_str[] = "cat";

现在字符数组cat_str初始化为"cat"但我们可以随时更改它,请注意它的长度将为 4(每个字母一个加上一个 NUL),因为我们没有指定长度。所以请确保不要更改超过 cat_str[3] 的任何内容,您可以将其索引为 0 到 3

一些静态分析工具有一个常见的误解,认为strncpy是更安全的strcpy版本。不是,它有不同的目的。 如果我们坚持使用它来防止缓冲区溢出,您需要认识到这样一个事实,即它的签名

char * strncpy ( char * destination, const char * source, size_t num );

如果source长于num,则不会在destination末尾隐式附加空字符。因此,在这种情况下,destination不应被视为以空结尾的 C 字符串(这样读取它会溢出)。

因此,如果您知道您的源是以空结尾的 C 字符串,那么您可以执行以下操作:

#include <stdio.h>
#include <string.h>
int main()
{
const char* source = "dog";
char destination[4] = "cat";
printf("source is %sn", source);
printf("destination is %sn", destination);
/* the strlen+1 accounts for null termination on source */
/* but you need to be sure that source can fit into destination */
/* and still be null terminated - (that's on you the programmer) */
strncpy(destination, source, strlen(source) + 1);
printf("source is still %sn", source);
printf("destination is now %sn", destination);
return 0;
}

最新更新