【问题标题】:string/char * reallocation exceptionstring/char * 重新分配异常
【发布时间】:2022-01-05 11:45:10
【问题描述】:

我被要求创建一个函数,该函数接受一个字符串并将其添加到另一个字符串中,每个单词之间都带有“#”,末尾带有“@”,末尾没有任何空格。 我已经写了这段代码,但它看起来不起作用,你能帮帮我吗? 重新分配行有一个异常,我相信它是因为最后的 '\0' 或类似的,但我不知道如何解决。

void addStr(char* addTo, char* str,int on)
{
    //on ==1 for nun last string to add
    if (str != NULL) {
        while (str != NULL)
        {
            char* temp = strtok(str, " \0\n");
            if (temp != NULL)
            {
                addTo = (char*)realloc(addTo, strlen(addTo) + strlen(temp) * sizeof(char) + 1);
                strcat(addTo, temp);
                if (str != NULL)
                    strcat(addTo, "#");
            }
        }
        if(on)
            strcat(addTo, "@");
    }
}

【问题讨论】:

  • 有很多问题,但最明显的一个是你的函数的签名。请查看realloc 的签名。它看起来像void realloc(void*, size_t) 吗?不,是void* realloc(void*, size_t)。你能想出一个原因吗?

标签: c string char realloc


【解决方案1】:

重新分配传递给具有单一间接级别的函数的内存是很棘手的,因为这样做会使调用上下文所持有的地址无效。要正确执行此操作,您需要返回新地址并期望调用者在成功时重新分配此地址,或者使用第二级间接来直接更改调用者上下文。

这些函数的两个签名是:

char *addTo(char *, char *, int);
/* or */
void addTo(char **, char *, int);

至于循环本身,您没有正确使用strtok 接口。对该函数的后续调用应将NULL 作为第一个参数传递,以便继续标记原始字符串。否则,您将继续永远循环,因为strtok 将重复返回第一个令牌。

此外,您必须确保您的缓冲区始终有足够的空间用于标记有效 C 字符串的 NUL 终止字节 ('\0')。在这种情况下,缓冲区的大小是现有字符串的长度加上令牌的长度,再加上一个字符('#''@')的大小,再加上一个 NUL 字节。

请注意,sizeof (char)保证1。它的包含是多余的并且容易出错。

这是一个使用前面提到的第二个签名的示例程序。我们可以更巧妙地分配内存,以在tail 为假(或字符串包含单个标记)的情况下节省一个字节,但我不打算这样做这个例子。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SEP " \n"
void edit_string(char **dest, char *src, int tail) {
    char *tok = strtok(src, SEP);

    while (tok) {
        char *resized = realloc(*dest, strlen(*dest) + strlen(tok) + 2);

        if (!resized)
            /* handle failure */;

        strcat(resized, tok);

        if ((tok = strtok(NULL, SEP)))
            strcat(resized, "#");

        *dest = resized;
    }

    if (tail)
        strcat(*dest, "@");
}

int main(int argc, char **argv) {
    char *dest = calloc(1, 1);
    char input[] = "hello world";

    edit_string(&dest, input, argc > 1);

    printf("%s\n", dest);
    free(dest);
}

【讨论】:

    猜你喜欢
    • 2014-08-28
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多