使用Memcpy将某些Char *追加到包含Char *的缓冲区中

时间:2019-09-17 00:25:42

标签: c

我正在编写一种将一些数据附加到缓冲区的方法。

缓冲区看起来像:

coerce

我想将数据追加到缓冲区,我编写的方法如下:

Buffer *new_buffer(size_t reserved) {
    Buffer* buffer = malloc(sizeof(Buffer));
    buffer->data   = (char*)calloc(reserved, sizeof(char));
    buffer->length = reserved;
    return buffer;
}

请注意,size参数只是要附加的数组的大小。

void append_buffer(Buffer *buffer, char *data, size_t length) {
    if( buffer->length <= length ) {
        buffer->length = buffer->length + length;
        buffer->data   = realloc( buffer->data, buffer->length * 2 );
    }
    memcpy( &buffer->data[ strlen( buffer->data ) - 1 ], data, length );

}

我认为我的memcpy存在错误;

思考过程是使用memcpy将数据放入缓冲区中最后一个字符的内存中;这样我们就可以避免使用终止符。

运行此命令不会附加任何数据,我不确定为什么!

1 个答案:

答案 0 :(得分:1)

在C中使用包含任意二进制数据的缓冲区时,您需要存储两个长度字段:分配的缓冲区容量以及当前存储在缓冲区中的数据量。

(与C#/。NET和Java进行比较,就像List<T>(Java中的ArrayList)既具有内部T[].Length又具有单独的Count )。

我已经重写了您的代码以显示我将如何做。请注意:

  • Buffer结构同时存储capacitylength
  • 代码使用assert()来验证参数并验证分配是否成功。这仅出于演示目的,因为如果assert被捍卫,则会从程序中删除NDEBUG,而应该始终验证内存分配。
  • 我将用于追加(append_buffer)的逻辑与用于重新分配缓冲区(expand_buffer)的逻辑分开。

像这样:

#undef NDEBUG // So `assert` is always compiled.

struct Buffer {
    char*  data;
    size_t capacity; // Size of the actual allocated space
    size_t length;   // Amount of space currently used
};

struct Buffer* new_buffer( size_t initialCapacity ) {
    struct Buffer* info = malloc( sizeof(Buffer) ); // Allocate space for the metadata
    assert( info ); // Always ensure allocation succeeded!
    info->data = calloc( initialCapacity, sizeof(char) );
    assert( info->data );
    info->capacity = initialCapacity;
    info->length   = 0;
    return info;
}

void append_buffer( struct Buffer* buffer, char* data, size_t dataLength ) {
    assert( buffer ); // Parameter argument validation
    assert( data );
    if( dataLength == 0 ) return;

    size_t remainingCapacity = buffer->capacity - buffer->length;
    if( remainingCapacity < dataLength ) {
        size_t desiredCapacity = buffer->capacity + dataLength; // You might want to add a growth factor here
        expand_buffer( buffer, desiredCapacity );
    }

    char* start = buffer->data + buffer->length;
    memcpy( start, data, dataLength );
    buffer->length += dataLength;
}

void expand_buffer( struct Buffer* buffer, size_t desiredCapacity ) {
    assert( buffer );
    assert( buffer->data );
    char* newData = realloc( buffer->data, desiredCapacity );
    assert( newData );
    buffer->data     = newData;
    buffer->capacity = desiredCapacity;
    // buffer->length remains unchanged
}

void destroy_buffer( struct Buffer* buffer ) {
    assert( buffer );

    if( buffer-> data ) {
        free( buffer->data );
        buffer->data = NULL;
    }

    free( buffer );
}