当输出缓冲区可能不足以容纳格式化字符串时,snprintf
函数是完美的。但是如果由于缓冲区长度不足而导致snprintf
的调用停止,那么如何继续打印到另一个缓冲区?
char buf1[16] = {0};
char buf2[16] = {0};
int n = snprintf(buf1, sizeof buf1, "Lorem ipsum %d dolor sit", 123456);
assert(strcmp(buf1, "Lorem ipsum 123") == 0); // ok
// Insert solution here
assert(strcmp(buf2, "456 dolor sit") == 0); // expected result
P.S。我对snprintf
并不感到沮丧,任何局限于标准C库的解决方案都会这样做。
答案 0 :(得分:3)
没有。 snprintf
是无国籍的,它不能简单地“恢复”它停止的地方。最接近的是分配一个更大的缓冲区,打印整个消息,然后将所需的子字符串strcpy到目标缓冲区。
char buf1[16] = {0};
char buf2[16] = {0};
int n = snprintf(buf1, sizeof(buf1), "Lorem ipsum %d dolor sit", 123456);
if (n > 15) {
char* t = malloc(n+1);
if (t) {
n = snprintf(t, n, "Lorem ipsum %d dolor sit", 123456);
strncpy(buf2, t+sizeof(buf1)-1, sizeof(buf2)-1);
free(t);
}
//might fail the subsequent assert if malloc failed
}
assert(strcmp(buf1, "Lorem ipsum 123") == 0); // ok
assert(strcmp(buf2, "456 dolor sit") == 0); // expected result
答案 1 :(得分:2)
阅读snprintf(3)的文档。它返回所需字符的总数(您甚至可以使用大小为0的NULL
缓冲区调用它来获取所需字符的数量。在使用Gnu glibc的Linux上,您也可以使用asprintf(3)。
所以你可以编码:
int nbc = snprintf(buf1, sizeof(buf1),
"Lorem ipsum %d dolor sit", 123456);
if (nbc<sizeof(buf1))
behappywith(buf1);
else {
memset(buf2, 0, sizeof(buf2));
char* dynbuf = malloc(nbc+1);
if (!dynbuf) { perror("malloc dynbuf"); exit(EXIT_FAILURE); };
snprintf(dynbuf, nbc+1,
"Lorem ipsum %d dolor sit", 123456);
strncpy(buf2, dynbuf+sizeof(buf1), sizeof(buf2));
buf2[sizeof(buf2)-1] = '\0';
free (dynbuf);
behappywithboth(buf1,buf2);
}
在实践中,最好使用足够大的缓冲区调用snprintf
- 通常避免调用malloc
然后调用snprintf
秒 time-(所以16个字节是不够的,但在你的情况下64个字节是合理的),并且只在极少数情况下重做它。如果可能,请使用asprintf
答案 2 :(得分:0)
您可以创建一个管道,使用fprintf
在其中写入整个字符串,并使用第二个线程从管道中读取您喜欢的小块。这种方式fprintf
函数将阻止并保存状态,直到您分派数据。
该实现显然不适合您的模板,但如果您的数据太大而无法放入单个内存缓冲区,则您必须同时生成和分发数据。否则,只需分配一个足够大的缓冲区,如Mooing Duck建议的那样。