我只是在学习使用C语言进行编程。 今天,我正在尝试编写自己的strlcpy函数,但遇到了问题。
为了测试我的功能,我将结果与“正式”功能的结果进行了比较。一切正常,除了...当我将0设为len arg时。 strcpy函数似乎在目标字符串中放入了垃圾字符,我真的不明白为什么。
这是函数的原型: size_t strlcpy(char *限制dst,const char *限制src,size_t dstsize);
感谢您的帮助!
好的。我想进行很多测试,这就是为什么要在循环内调用该函数的原因。
这是我主要功能的一部分,测试该功能:
do
{
/* Ask for first string */
printf("\nGive me a string (0 to stop): ");
gets(str);
/* Ask for a number */
printf("Now, give me a number please: ");
scanf("%d", &i);
while (getchar() != '\n');
/* I test with the "official function */
j = strlcpy(str2, str, i);
printf("Here is the expected result: %s\n", str2);
printf("Num returned: %d\n", j);
/* Now I test using my function */
j = ft_strlcpy(str3, str, i);
printf("Here is my result: %s\n", str3);
printf("Num returned: %d\n", j);
}while (str[0] != '0');
这是我编写的函数:
unsigned int ft_strlcpy(char *dest, char *src, unsigned int size)
{
unsigned int cpt;
unsigned int i;
cpt = 0;
i = 0;
while (src[cpt] != '\0')
cpt++;
if (size == 0)
return (0);
while (i < cpt && i < (size - 1))
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (cpt);
}
在函数中,我不应该从标准库中调用任何函数。我的主要对象是在这里进行测试。 函数原型是由我的老师给出的,这就是为什么我不尊重原始函数的原因。
抱歉,我需要在这里放置代码的时间,并感谢您的帮助。
答案 0 :(得分:2)
您能解释一下“垃圾字符”的来源吗?函数如何查找该字符并将其放入字符串?即使不应使用0 len值调用它。
手册没有说strlcpy
不应以0 len值调用,它只是说如果 NUL终止结果,则不会dstsize
是 0,即e。完全不复制任何字符到dst
。
您可能会在目标字符串中放入“垃圾字符”的印象很可能是由于dst
从一开始就未初始化,而您看到的是未初始化的dst
。
答案 1 :(得分:1)
首先,我想您在“ ... strlen函数似乎会造成垃圾...”( strlcpy 而不是 strlen strlen不给字符串添加任何内容-size_t strlen( const char * s);)。
所以您对strlcpy有疑问。
正如references所说的,关于strlcpy(以及strncpy)的第三个参数确定要从 src 复制到 dst 的字符数。因此,如果大小为0,则不应复制任何数据。仔细阅读文档-原型为:
strlcpy(char *dst, const char *src, size_t size);
和 size 的解释为:
只要大小大于0
答案 2 :(得分:0)
程序中有几个问题。
首先不要使用gets()
。这是不安全的,而且已经过时了。选中this。
而是使用fgets()
。选中this。
在此声明中
printf("\nGive me a string (0 to stop): ");
0 to stop
实际上不会停止任何操作并执行其下的所有语句,直到while
循环检查条件为止。可能需要放置if
的情况,像这样:
if (str[0] != '0') {
.....
.....
}
}while (str[0] != '0');
在此声明中
printf("Now, give me a number please: ");
scanf("%d", &i);
....
....
j = ft_strlcpy(str3, str, i);
您正在将此数字作为目标大小传递给ft_strlcpy()
函数。假设您的源字符串包含"123456789"
字符串,目标字符串大小为5
,并且用户输入的数字为100
。在函数ft_strlcpy()
中,对于给定的输入
//cpt variable value would be 9
//size variable value would be 100
//initial value of i is 0
while (i < 9 && i < (100 - 1))
{
dest[i] = src[i]; //buffer overflow!!!!, this statement will execute 9 times and dest buffer size is 5
i++;
}
因此,您应该提供目标缓冲区的大小,而不是将要复制的字符数作为用户的输入。像这样
j = ft_strlcpy(str3, str, sizeof(str3));
来自strlcpy
strlcpy()最多将dstsize-1个字符从字符串src复制到dst, 如果dstsize不为0,则NUL终止结果。
这意味着如果目标缓冲区大小为0
,则不会执行任何复制。
还要选中this。
将所有内容放在一起,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
unsigned int ft_strlcpy(char *dest, const char *src, unsigned int size) {
unsigned int i = 0, j = 0;
while (src[i] != '\0') {
if (size && (i < (size - 1))) {
dest[i] = src[i];
j++;
}
i++;
}
dest[j] = '\0';
return (i);
}
int main() {
char str[100], str3[100];
unsigned int j;
do {
/* Ask for first string */
printf("\nEnter a string (press only enter key to stop): ");
if (fgets(str, sizeof(str), stdin) == NULL) {
fprintf (stderr, "Failed to read input");
break;
}
/* If input is bigger than the size of buffer, discard the rest of input characters */
if (strchr(str, '\n') == NULL) {
int c;
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
else {
/* Remove the trailing newline character */
str[strcspn(str, "\n")] = 0;
}
if (str[0] != '\0') {
j = ft_strlcpy(str3, str, sizeof(str3));
printf("Here is my result: %s\n", str3);
printf("Num returned: %d\n", j);
}
}while (str[0] != '\0');
return 0;
}