[英]Recreating strlcat function in C "invalid operands to binary expression ('size_t' (aka 'unsigned long') and 'char *')"
I'm trying to recreate my strlcat
function from the C function library.我正在尝试从 C 函数库中重新创建我的
strlcat
函数。 I was looking around on the internet how it works.我在互联网上环顾四周,它是如何工作的。 Basically,
strlcat
allows appending your source string into destination string with a NUL-terminated.基本上,
strlcat
允许将源字符串附加到目标字符串中,并以 NUL 结尾。 The return value must be the size value after appending.返回值必须是追加后的大小值。
To make it short, I am pulling my strlen
function into strlcat
to have the size of my destination and source in the same time.简而言之,我将我的
strlen
函数拉入strlcat
以同时拥有目标和源的大小。 I iterate through my new destination to have the length of my new string for my source string to fit.我遍历我的新目的地,以获得适合我的源字符串的新字符串的长度。 To do this, I copy the memory by using
memcpy
.为此,我使用
memcpy
复制内存。
This is what I have (assuming we have the necessary headers):这就是我所拥有的(假设我们有必要的标题):
char my_strlcat(char *dst, const char *src, size_t n)
{
size_t dsize;
size_t len;
size_t res;
dsize = my_strlen(dst) - dst;
len = my_strlen(src) - src;
res = dsize + len;
if(dsize < n)
{
dst+= dsize;
n-=dsize;
if(n <= len)
len = n - 1;
dst[len] = '\0';
my_memcpy(dst,src,len);
}
return (res);
}
void *my_memcpy(void *dst, const void *src, size_t num)
{
size_t i;
i = -1;
while (i++ != num)
((unsigned char *)dst)[i] = ((unsigned char *)src)[i];
return (dst);
}
size_t my_strlen(const char *str)
{
int len;
len = 0;
while (str[len] != '\0')
len++;
return (len);
}
int main()
{
char my_strlcat_src[7] = "banana";
char my_strlcat_dst[12] = "good";
printf("my_strlcat => 'banana', 'good', 12 expected: 10 => %c\n", my_strlcat(my_strlcat_dst, my_strlcat_src, 12));
char my_strlcat_src2[6] = "whatt";
char my_strlcat_dst2[15] ="he said.";
printf("my_strlcat => 'he said.', 'whatt', 15 expected: 13 => %c\n",my_strlcat(my_strlcat_dst2, my_strlcat_src2, 15));
}
After I execute this program, I'm getting this error saying "invalid operands to binary expression ('size_t' (aka 'unsigned long') and 'char *')" which I quite don't really understand what is causing trouble.执行此程序后,我收到此错误消息,提示“二进制表达式的操作数无效('size_t'(又名'unsigned long')和'char *')” ,我不太明白是什么导致了问题。 Is it because I am doing unsigned char in my
memcpy
function?是因为我在
memcpy
函数中做 unsigned char 吗? What do you guys think?你们有什么感想?
I apologize for not understanding your constrains more fully.我很抱歉没有更充分地理解你的限制。 After checking:
检查后:
$ man strlcat
No manual entry for strlcat
I thought you were making a new strlcat
up and prepared one accordingly that would self allocate, etc. I have now found a man page for strlcat
and can now offer a bit more help on how a strlcat
could be written我以为你正在制作一个新的
strlcat
并相应地准备了一个可以自我分配的,等等。我现在找到了一个strlcat
的手册页,现在可以提供更多关于如何编写strlcat
帮助
strlcat
concatenates both strings taking the maximum size of the dst
buffer as the third argument ( size meaning it must include space for the terminating nul-character as opposed to the length of both strings) strlcat
will append at most size - strlen(dst) - 1 bytes
, NUL-terminating the result. strlcat
连接两个字符串,将dst
缓冲区的最大大小作为第三个参数(大小意味着它必须包含终止空字符的空间,而不是两个字符串的长度) strlcat
将最多附加size - strlen(dst) - 1 bytes
,NUL 终止结果。 strlcat
returns the total length of the string it tried to create. strlcat
返回它尝试创建的字符串的总长度。
With those constraints, you could write the strlcat
function something like the following (using string indexes rather than pointers since that may be a bit more familiar to you)有了这些约束,您可以编写如下所示的
strlcat
函数(使用字符串索引而不是指针,因为您可能会更熟悉)
size_t strlcat (char *dst, const char *src, size_t size)
{
/* dst length and general variable i */
size_t dlen = strlen (dst), i;
if (!src || !*src) /* validate src not NULL or empty */
return dlen;
/* concatenate at most size - 1 bytes & nul-terminate */
for (i = 0; i < size - dlen - 1 && src[i]; i++)
dst[i + dlen] = src[i];
dst[i + dlen] = 0;
return i + dlen; /* dest + bytes of src concatenated */
}
Putting it together in a short example, you could do something like the following:将其放在一个简短的示例中,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
#define MAXS 32
size_t strlcat (char *dst, const char *src, size_t size)
{
/* dst length and general variable i */
size_t dlen = strlen (dst), i;
if (!src || !*src) /* validate src not NULL or empty */
return dlen;
/* concatenate at most size - 1 bytes & nul-terminate */
for (i = 0; i < size - dlen - 1 && src[i]; i++)
dst[i + dlen] = src[i];
dst[i + dlen] = 0;
return i + dlen; /* dest + bytes of src concatenated */
}
int main (int argc, char **argv) {
size_t n = 0, sz1 = 0; /* length variables, total and 1st string */
char str[MAXS] = "",
*s1 = argc > 1 ? argv[1] : "hello", /* string 1 */
*s2 = argc > 2 ? argv[2] : "world"; /* string 2 */
printf ("\nconcatenating empty src with\ns1: %s\ns2: %s\n\n", s1, s2);
sz1 = strlcat (str, s1, MAXS); /* concatenate s1 -> str */
printf ("after 'strlcat (str, s1, n)', str : %s (%zu chars)\n", str, sz1);
n = strlcat (str, s2, MAXS); /* concatenate s2 -> str */
printf ("after 'strlcat (str, s2, n)', str : %s (%zu chars)\n", str, n);
return 0;
}
Example Use/Output示例使用/输出
$ ./bin/strlcat
concatenating empty src with
s1: hello
s2: world
after 'strlcat (str, s1, n)', str : hello (5 chars)
after 'strlcat (str, s2, n)', str : helloworld (10 chars)
$ ./bin/strlcat strlcat _works
concatenating empty src with
s1: strlcat
s2: _works
after 'strlcat (str, s1, n)', str : strlcat (7 chars)
after 'strlcat (str, s2, n)', str : strlcat_works (13 chars)
Testing MAXS length restriction (attempting to concatenate a total of 33-chars (2-more than allowed):测试 MAXS 长度限制(尝试连接总共 33 个字符(超过允许的 2 个):
$ ./bin/strlcat 12345678901234567890 1234567890123
concatenating emptr sry with
s1: 12345678901234567890
s2: 1234567890123
after 'strlcat (str, s1, n)', str : 12345678901234567890 (20 chars)
after 'strlcat (str, s2, n)', str : 1234567890123456789012345678901 (31 chars)
Custom Self Allocating Version (before finding man strlcat
)自定义自分配版本(在找到
man strlcat
之前)
There is learning to be had in this version as well, so I will leave it as originally posted.在这个版本中也有学习内容,所以我将保留它最初发布的内容。
It is hard to tell what all your constraints are as you are writing a strcat
function, but using memcpy
.在编写
strcat
函数但使用memcpy
,很难说出所有约束是什么。 Regardless, the following code provides a working strlcat
in my best understanding of what you are trying to achieve.无论如何,以下代码在我对您要实现的目标的最佳理解中提供了一个有效的
strlcat
。
As you have hinted at in your code, there are two cases to cover (1) where dst
is empty where you essentially just allocate for dst
and copy src -> dst
and then (2) where both src
and dst
contain strings and you need to concatenate the strings (presumably placing a space
in between the words).正如您在代码中所暗示的那样,有两种情况可以涵盖(1)
dst
为空的情况,您实际上只是为dst
分配并复制src -> dst
,然后(2) src
和dst
都包含字符串并且您需要连接字符串(大概在单词之间放置一个space
)。 You are free to use your own my_strlen
function in your code, I simply use strlen
below as that didn't appear to be an area that was the source of your problem.您可以在代码中自由使用自己的
my_strlen
函数,我只是在下面使用strlen
,因为这似乎不是问题的根源所在。
Putting the pieces together, you could do something similar to the following:将各个部分放在一起,您可以执行类似于以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *strlcat (char **dst, const char *src, size_t *n)
{
size_t dlen, slen; /* dst & src lengths */
void *tmp = NULL; /* realloc variable */
if (!src) /* validate src not NULL */
return *dst;
if (!*dst) /* realloc dst (1) if empty; (2) extending current length */
tmp = realloc (*dst, (dlen = 0) + (slen = strlen (src)) + 2);
else
tmp = realloc (*dst, (dlen = strlen (*dst)) + (slen = strlen (src)) + 2);
if (!tmp) /* validate realloc */
return *dst;
*dst = tmp; /* assign reallocated block to dst */
if (!dlen) { /* if no *dst, just copy src to *dst */
strcpy (*dst, src);
*n = slen; /* update total length */
}
else { /* if *dst non-empty */
(*dst)[dlen] = ' '; /* add ' ' between *src/dst */
strcpy (*dst + dlen + 1, src); /* copy src to end (after ' ') */
*n = dlen + slen + 1; /* update total length */
}
return *dst; /* return pointer to new string */
}
int main (int argc, char **argv) {
size_t n = 0; /* length variaale */
char *s1 = argc > 1 ? argv[1] : "hello", /* string 1 */
*s2 = argc > 2 ? argv[2] : "world", /* string 2 */
*str = NULL; /* string to hold concatenated result */
strlcat (&str, s1, &n); /* concatenate s1 -> str */
strlcat (&str, s2, &n); /* concatenate s2 -> str */
printf ("src: %s\ndst: %s\nstr: %s\n", s1, s2, str);
printf ("len: %zu chars.\n", n);
free (str); /* don't forget to free allocated memory */
return 0;
}
( note: I pass the address of dst
to strlcat
which will allow the new address for dst
to be set within the function. As you currently have your code, you would have to change the function return type to char *
and assign the return to a character pointer variable in main()
, otherwise your changes to dst
in strlcat
would never be reflected back in main()
) (注意:我将
dst
的地址传递给strlcat
,这将允许在函数内设置dst
的新地址。由于您目前拥有代码,您必须将函数返回类型更改为char *
并将返回分配给main()
的字符指针变量,否则您在strlcat
对dst
的更改将永远不会反映在main()
)
Example Use/Output示例使用/输出
$ ./bin/strlcat
src: hello
dst: world
str: hello world
len: 11 chars.
$ ./bin/strlcat C-Programming can-do
src: C-Programming
dst: can-do
str: C-Programming can-do
len: 20 chars.
Always run any program you dynamically allocate memory in through a memory error checking program .始终运行通过内存错误检查程序动态分配内存的任何程序。 For Linux,
valgrind
is the normal choice, but there are similar tools for all platforms,对于Linux,
valgrind
是正常的选择,但是所有平台都有类似的工具,
Memory Use/Error Check内存使用/错误检查
$ valgrind ./bin/strlcat C-Programming can-do
==15976== Memcheck, a memory error detector
==15976== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==15976== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==15976== Command: ./bin/strlcat C-Programming can-do
==15976==
src: C-Programming
dst: can-do
str: C-Programming can-do
len: 20 chars.
==15976==
==15976== HEAP SUMMARY:
==15976== in use at exit: 0 bytes in 0 blocks
==15976== total heap usage: 2 allocs, 2 frees, 36 bytes allocated
==15976==
==15976== All heap blocks were freed -- no leaks are possible
==15976==
==15976== For counts of detected and suppressed errors, rerun with: -v
==15976== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always make sure there are no errors and that you have freed all memory you have allocated.始终确保没有错误并且您已经释放了您分配的所有内存。
Look things over and let me know if I understood where you problem area was and whether or not you have further questions.仔细检查一下,让我知道我是否理解您的问题所在以及您是否还有其他问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.