有很多这样的应用场景:不停的产生一些字符串,并串联在一起,最后一起输出。这种场景的特点是,最终字符串的长度是不确定的。借鉴ngx_poop_t的实现,做一个简单的内存池,代码如下:
typedef struct buf_list_s buf_list_t;
struct buf_list_s {
buf_list_t *next; /* 当一个用满时,重新申请一个,组成链表 */
buf_list_t *current; /* 当前在使用的 */
char *str; /* 内存池 */
int size;
int used;
int resolution; /* 当一个池中所剩的量小于该值时,则重新申请一个使用。该值与size值,可根据具体使用的场景,一次写入的长度来优化选择 */
} ;
buf_list_t* buf_init(int size,int resolution)
{
buf_list_t *buf;
buf = malloc(sizeof(buf_list_t));
buf->next = NULL;
buf->current = NULL;
buf->size = size;
buf->used = 0;
buf->resolution = resolution;
buf->str = malloc(size);
memset(buf->str,'\0',size);
return buf;
}
char *buf_sprintf(buf_list_t *head,char *fmt,...) /* 类似于vsprintf,用起来方便 */
{
buf_list_t *current;
int lr;
va_list args;
current = head->current;
if(current->size-current->used < current->resolution) { /* 使用过程中,自动决定是否要新分配池 */
current->next = buf_init(head->size,head->resolution);
current = current->next;
head->current = current;
}
va_start(args,fmt);
vsprintf(current->str+current->used,fmt,args);
va_end(args);
lr = strlen(current->str+current->used);
current->used += lr;
return current->str+current->used-lr;
}
void buf_print(buf_list_t *head)
{
while(head)
{
printf("%s",head->str);
head = head->next;
}
}
void buf_free(buf_list_t *head)
{
buf_list_t *tmp;
while(head)
{
free(head->str);
tmp = head;
head = tmp->next;
free(tmp);
}
}
这样,使用起来就很快捷方便了:
int main()
{
buf_list_t *head=NULL;
head = buf_init(100,15);
head->current = head;
while(1){
buf_sprintf(head,"%d card(s)\n",cards);
}
buf_print(head);
buf_free(head);
return 0;
}