我正在编写一种将一些数据附加到缓冲区的方法。
缓冲区看起来像:
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将数据放入缓冲区中最后一个字符的内存中;这样我们就可以避免使用终止符。
运行此命令不会附加任何数据,我不确定为什么!
答案 0 :(得分:1)
在C中使用包含任意二进制数据的缓冲区时,您需要存储两个长度字段:分配的缓冲区容量以及当前存储在缓冲区中的数据量。
(与C#/。NET和Java进行比较,就像List<T>
(Java中的ArrayList
)既具有内部T[].Length
又具有单独的Count
)。
我已经重写了您的代码以显示我将如何做。请注意:
Buffer
结构同时存储capacity
和length
。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 );
}