2

由于我保证存在的原因,我正在逐个字符地读取输入,如果一个字符符合某些条件,我会将其写入动态分配的缓冲区。此函数将指定字符添加到指定字符串的“结尾”。读取缓冲区时,我读取了第一个“大小”字符。

void append(char c, char *str, int size)
{
 if(size + 1 > strlen(str))
        str = (char*)realloc(str,sizeof(char)*(size + 1));
 str[size] = c;
}

该功能经过多次迭代开发,产生了“损坏的双链表”、“双重释放或损坏”等错误。下面是应该如何使用 append 的示例:

// buffer is a string
// bufSize is the number of non-garbage characters at the beginning of buffer
char *buft = buffer;
int bufLoc=0;
while((buft-buffer)/sizeof(char) < bufSize)
    append(*(buft==),destination,bufLoc++);

它通常适用于一些看似任意数量的字符,然后因错误而中止。如果不清楚第二个代码片段在做什么,它只是从缓冲区复制到某个目标字符串。我知道有用于此的库方法,但有时我需要更好地控制确切复制的内容。

提前感谢您的任何见解。我难住了。

4

2 回答 2

4

此函数不会将字符附加到缓冲区。

void append(char c, char *str, int size)
{
    if(size + 1 > strlen(str))
        str = realloc(str, size + 1);
    str[size] = c;
}

首先,什么是strlen(str)?你可以说“它的长度str”,但这忽略了一些非常重要的细节。它是如何计算长度的?简单——str必须以 NUL 结尾,并找到其中第一个字节strlen的偏移量。NUL如果您的缓冲区末尾没有 NUL 字节,则您无法使用strlen它来查找其长度。

通常,您需要跟踪缓冲区的长度。为了减少重新分配的次数,请分别跟踪缓冲区大小和其中的数据量。

struct buf {
    char *buf;
    size_t buflen;
    size_t bufalloc;
};

void buf_init(struct buf *b)
{
    buf->buf = NULL;
    buf->buflen = 0;
    buf->bufalloc = 0;
}

void buf_append(struct buf *b, int c)
{
    if (buf->buflen >= buf->bufalloc) {
        size_t newalloc = buf->bufalloc ? buf->bufalloc * 2 : 16;
        char *newbuf = realloc(buf->buf, newalloc);
        if (!newbuf)
            abort();
        buf->buf = newbuf;
        buf->bufalloc = newalloc;
    }
    buf->buf[buf->buflen++] = c;
}

另一个问题

这段代码:

str = realloc(str, size + 1);

它只会改变strin的值append——它不会改变str调用函数中的值。函数参数是函数的本地参数,更改它们不会影响函数之外的任何内容。

小问题

这有点奇怪:

// Weird
x = (char*)realloc(str,sizeof(char)*(size + 1));

强制(char *)转换不仅是不必要的,而且它实际上可以掩盖错误——如果你忘记包含<stdlib.h>,强制转换将允许代码编译。真可惜。

并且sizeof(char)是 1,根据定义。所以不要打扰。

// Fixed
x = realloc(str, size + 1);
于 2012-11-11T11:32:54.437 回答
0

当您执行以下操作时:

str = (char*)realloc(str,sizeof(char)*(size + 1));

str 中的更改不会反映在调用函数中,换句话说,更改是函数本地的,因为指针是按值传递的。要解决此问题,您可以返回 str 的值:

char * append(char c, char *str, int size)
{
 if(size + 1 > strlen(str))
        str = (char*)realloc(str,sizeof(char)*(size + 1));
 str[size] = c;

 return str;
}

或者您可以通过地址传递指针:

void append(char c, char **str, int size)
{
 if(size + 1 > strlen(str))
        *str = (char*)realloc(*str,sizeof(char)*(size + 1));
 (*str)[size] = c;
}
于 2012-11-11T11:34:48.873 回答