最近做一个C语言的嵌入式项目,需要分段向指定内存调用vsnprintf输出不定长度的格式化输出,因为是分段输出,而且长度不定,所以一开始就不能分配固定长度内存,每次输出都要从输出到上次的结尾开始,所以还要记录每次的输出长度。还是Java开发方便,有现成的StringBuffer可以用,不停的向StringBuffer调用 append添加就好了,哪有这么麻烦。
为了解决这个麻烦,我参照Java中的StringBuffer对象,实现了一个 stringbuffer,并基于它实现bufprintf函数可以向stringbuffer格式化输出,调用时就不需要再考虑自动分配内存和偏移量的问题了。
以下是可以直接运行的完整代码:
stringbuffer_test.c
#include#include #include #include #include #include #include typedef struct { char *buffer; size_t length; size_t offset; } stringbuffer; / return NULL; } if (needed > INT_MAX) { return NULL; } needed += p->offset + 1; if (needed <= p->length) { return p->buffer + p->offset; } if (needed > (INT_MAX / 2)) { if (needed <= INT_MAX) { newsize = INT_MAX; } else { return NULL; } } else { newsize = ((needed + 256 - 1) >> 8 << 8); } newbuffer = (char*)realloc(p->buffer, newsize); if (newbuffer == NULL) { free(p->buffer); p->length = 0; p->buffer = NULL; return NULL; } p->length = newsize; p->buffer = newbuffer; return newbuffer + p->offset; } / va_list args; va_start(args, fmt); size_t bufsz = pbuf->length - pbuf->offset; int wsz = vsnprintf(pbuf->buffer + pbuf->offset, bufsz, fmt, args); va_end(args); if (wsz < 0) { if (errno == ERANGE) { va_list args1; va_start(args1, fmt); wsz = vsnprintf(NULL, 0, fmt, args1); char *output = ensure(pbuf, wsz); va_end(args1); if(!output) { printf("MEM ERRORn"); return -1; } bufsz = pbuf->length - pbuf->offset; va_list args2; va_start(args2, fmt); wsz = vsnprintf(output, bufsz, fmt, args2); va_end(args2); assert(wsz < bufsz); } else { printf("vsnprintf ERROR %d:%s for fmt:[%s]n", errno, strerror(errno), fmt); return -1; } } else if (wsz >= bufsz) { char *output = ensure(pbuf, wsz); if(!output) { printf("MEM ERRORn"); return -1; } bufsz = pbuf->length - pbuf->offset; va_list args; va_start(args, fmt); wsz = vsnprintf(output, bufsz, fmt, args); va_end(args); assert(wsz < bufsz); } pbuf->offset += wsz; return 0; } / printf("MEM ERRORn"); return -1; } pbuf->buffer = (char*)p; pbuf->length = length; pbuf->offset = 0; return 0; } / int main() { stringbuffer sbuf; int c = stringbuffer_init(&sbuf, 0); if (c == 0) { bufprintf(&sbuf, "hello %sn", "jerry"); bufprintf(&sbuf, "welcome to my partyn", "jerry"); printf("sbuf content:n%sn", sbuf.buffer); stringbuffer_uninit(&sbuf, false); } else { printf("stringbuffer init failn"); } }
如果使用MSVC编译器,如在VS 开发人员提示(CMD)下执行 cl stringbuffer_test.c就可以直接编译出stringbuffer_test.exe,运行就能看到效果。
gcc下编译也很简单:
>gcc stringbuffer_test.c >a.exe sbuf content: hello jerry welcome to my party



