简体   繁体   English

在 C 中重新创建 strlcat 函数“二进制表达式的无效操作数('size_t'(又名'unsigned long')和'char *')”

[英]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) srcdst都包含字符串并且您需要连接字符串(大概在单词之间放置一个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()的字符指针变量,否则您在strlcatdst的更改将永远不会反映在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.

相关问题 c中二进制表达式的无效操作数('const char *'和'const char *') - invalid operands to binary expression ('const char *' and 'const char *') in c 二进制表达式的操作数无效,C - Invalid Operands to binary Expression, C 如何在 c 中执行此操作:错误:二进制表达式的操作数无效('char [3]' 和 'int') - how to do this in c: error: invalid operands to binary expression ('char [3]' and 'int') C 编程错误 二进制 int 和 long long 无符号操作数无效 integer - C Programmıng Error invalid operands to binary int and long long unsigned integer 警告:字段宽度说明符 &#39;*&#39; 需要类型为 &#39;int&#39; 的参数,但参数 2 的类型为 &#39;size_t&#39; {aka &#39;long unsigned int&#39;} - warning: field width specifier '*' expects argument of type 'int', but argument 2 has type 'size_t' {aka 'long unsigned int'} 我在C代码中遇到错误:二进制表达式的操作数无效(&#39;long long(int)&#39;和&#39;int&#39;)我不知道如何修复 - I am getting an error in C code: invalid operands to binary expression ('long long (int)' and 'int') and I don't know how to fix 二进制错误的无效操作数(有&#39;long unsigned int *&#39;和&#39;int&#39;) - Invalid operands to binary errors (have 'long unsigned int *' and 'int') 错误:从&#39;void *&#39;到&#39;test :: apr_size_t * {aka long unsigned int *}&#39;的无效转换&#39;[-fpermissive] - error: invalid conversion from ‘void*’ to ‘test::apr_size_t* {aka long unsigned int*}’ [-fpermissive] 类型&#39;int *&#39;和&#39;long unsigned int&#39;类型的无效操作数到C中的二进制&#39;operator *&#39;错误 - invalid operands of types ‘int*’ and ‘long unsigned int’ to binary ‘operator*’ error in C 将size_t转换为unsigned long int是否安全? - Is it safe to cast size_t to unsigned long int?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM