Reputation: 863
The snprintf
function is perfect when the output buffer may not be big enough to hold the formatted string. But if a call to snprintf
stopped due to insufficient buffer length, how to continue printing to another buffer?
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. I'm not hellbound on snprintf
, any solution confined to the standard C library will do.
Upvotes: 1
Views: 607
Reputation: 3203
You could create a pipe, use fprintf
to write the whole string in there and use a second thread to read from the pipe with as small chunks as you like. This way fprintf
function will block and save the state until you dispatch the data.
The implementation obviously won't fit in your template, but if your data is too big to fit in a single memory buffer, you'll have to generate and dispatch data at the same time. Otherwise, just allocate a single sufficiently large buffer like Mooing Duck suggested.
Upvotes: 0
Reputation: 1
Read documentation of snprintf(3). It returns the total number of needed characters (and you could even invoke it with a NULL
buffer of size 0 to get the number of needed characters first). And on Linux with Gnu glibc, you might also use asprintf(3).
So you might code:
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);
}
In practice, it is better to call snprintf
with a reasonably large enough buffer -to usually avoid calling malloc
then snprintf
a second time- (so 16 bytes is not enough, but in your case 64 bytes would have been reasonable), and redo it only in rare cases. If possible, use asprintf
Upvotes: 2
Reputation: 66951
no. snprintf
is stateless, it can't simply "resume" where it stopped. The closest would be to allocate a bigger buffer, print the entire message to that, then strcpy the desired substring to the target buffer.
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
Upvotes: 3