How to get the last characters of formatted output when snprintf returns more than its size argument?












0















I have a buffer that is 65536 characters long. I need to print formatted output to the buffer. Problem is: If the formatted output size turns out to be bigger than 65535, I would like to have the last characters of it in the buffer, discarding the first ones, and not the remaining ones, as snprintf does.



I thought about implementing the snprintf logic, but starting from the end of the string instead of the beginning.



Is there any easier way to accomplish this?










share|improve this question

























  • What are you doing that could possibly need more than 65535 characters in a single formatted output?

    – Barmar
    Jan 18 at 21:48






  • 1





    Consider dynamically allocating if you're unsure of how much storage you need. If you guess wrong you can reallocate.

    – tadman
    Jan 18 at 21:49








  • 1





    Can you show an example of the format string? I assume it must be printing a potentially long string. So you could split it up into separate calls, for everything before the string, and everything after the string. Then you add the lengths of each of these to the length of the string, and see whether it's longer than 65535.

    – Barmar
    Jan 18 at 21:52











  • @Barmar I'm writing my own terminal. I haven't thought about examples of my program where that could happen. Currently, I'm writing a function that sends data to be printed to the terminal, and can be formatted. What if the buffer size was smaller? "Declare bigger buffers" can't be a solution to every instance of this problem :P

    – Yuri J
    Jan 18 at 22:01






  • 2





    @Barmar By doing that, you're formatting the entirety of the data anyway. At that point you might as well do it the easy way and just use something like asprintf() to start.

    – Andrew Henle
    Jan 18 at 22:02
















0















I have a buffer that is 65536 characters long. I need to print formatted output to the buffer. Problem is: If the formatted output size turns out to be bigger than 65535, I would like to have the last characters of it in the buffer, discarding the first ones, and not the remaining ones, as snprintf does.



I thought about implementing the snprintf logic, but starting from the end of the string instead of the beginning.



Is there any easier way to accomplish this?










share|improve this question

























  • What are you doing that could possibly need more than 65535 characters in a single formatted output?

    – Barmar
    Jan 18 at 21:48






  • 1





    Consider dynamically allocating if you're unsure of how much storage you need. If you guess wrong you can reallocate.

    – tadman
    Jan 18 at 21:49








  • 1





    Can you show an example of the format string? I assume it must be printing a potentially long string. So you could split it up into separate calls, for everything before the string, and everything after the string. Then you add the lengths of each of these to the length of the string, and see whether it's longer than 65535.

    – Barmar
    Jan 18 at 21:52











  • @Barmar I'm writing my own terminal. I haven't thought about examples of my program where that could happen. Currently, I'm writing a function that sends data to be printed to the terminal, and can be formatted. What if the buffer size was smaller? "Declare bigger buffers" can't be a solution to every instance of this problem :P

    – Yuri J
    Jan 18 at 22:01






  • 2





    @Barmar By doing that, you're formatting the entirety of the data anyway. At that point you might as well do it the easy way and just use something like asprintf() to start.

    – Andrew Henle
    Jan 18 at 22:02














0












0








0








I have a buffer that is 65536 characters long. I need to print formatted output to the buffer. Problem is: If the formatted output size turns out to be bigger than 65535, I would like to have the last characters of it in the buffer, discarding the first ones, and not the remaining ones, as snprintf does.



I thought about implementing the snprintf logic, but starting from the end of the string instead of the beginning.



Is there any easier way to accomplish this?










share|improve this question
















I have a buffer that is 65536 characters long. I need to print formatted output to the buffer. Problem is: If the formatted output size turns out to be bigger than 65535, I would like to have the last characters of it in the buffer, discarding the first ones, and not the remaining ones, as snprintf does.



I thought about implementing the snprintf logic, but starting from the end of the string instead of the beginning.



Is there any easier way to accomplish this?







c printf






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 18 at 22:37







Yuri J

















asked Jan 18 at 21:46









Yuri JYuri J

947




947













  • What are you doing that could possibly need more than 65535 characters in a single formatted output?

    – Barmar
    Jan 18 at 21:48






  • 1





    Consider dynamically allocating if you're unsure of how much storage you need. If you guess wrong you can reallocate.

    – tadman
    Jan 18 at 21:49








  • 1





    Can you show an example of the format string? I assume it must be printing a potentially long string. So you could split it up into separate calls, for everything before the string, and everything after the string. Then you add the lengths of each of these to the length of the string, and see whether it's longer than 65535.

    – Barmar
    Jan 18 at 21:52











  • @Barmar I'm writing my own terminal. I haven't thought about examples of my program where that could happen. Currently, I'm writing a function that sends data to be printed to the terminal, and can be formatted. What if the buffer size was smaller? "Declare bigger buffers" can't be a solution to every instance of this problem :P

    – Yuri J
    Jan 18 at 22:01






  • 2





    @Barmar By doing that, you're formatting the entirety of the data anyway. At that point you might as well do it the easy way and just use something like asprintf() to start.

    – Andrew Henle
    Jan 18 at 22:02



















  • What are you doing that could possibly need more than 65535 characters in a single formatted output?

    – Barmar
    Jan 18 at 21:48






  • 1





    Consider dynamically allocating if you're unsure of how much storage you need. If you guess wrong you can reallocate.

    – tadman
    Jan 18 at 21:49








  • 1





    Can you show an example of the format string? I assume it must be printing a potentially long string. So you could split it up into separate calls, for everything before the string, and everything after the string. Then you add the lengths of each of these to the length of the string, and see whether it's longer than 65535.

    – Barmar
    Jan 18 at 21:52











  • @Barmar I'm writing my own terminal. I haven't thought about examples of my program where that could happen. Currently, I'm writing a function that sends data to be printed to the terminal, and can be formatted. What if the buffer size was smaller? "Declare bigger buffers" can't be a solution to every instance of this problem :P

    – Yuri J
    Jan 18 at 22:01






  • 2





    @Barmar By doing that, you're formatting the entirety of the data anyway. At that point you might as well do it the easy way and just use something like asprintf() to start.

    – Andrew Henle
    Jan 18 at 22:02

















What are you doing that could possibly need more than 65535 characters in a single formatted output?

– Barmar
Jan 18 at 21:48





What are you doing that could possibly need more than 65535 characters in a single formatted output?

– Barmar
Jan 18 at 21:48




1




1





Consider dynamically allocating if you're unsure of how much storage you need. If you guess wrong you can reallocate.

– tadman
Jan 18 at 21:49







Consider dynamically allocating if you're unsure of how much storage you need. If you guess wrong you can reallocate.

– tadman
Jan 18 at 21:49






1




1





Can you show an example of the format string? I assume it must be printing a potentially long string. So you could split it up into separate calls, for everything before the string, and everything after the string. Then you add the lengths of each of these to the length of the string, and see whether it's longer than 65535.

– Barmar
Jan 18 at 21:52





Can you show an example of the format string? I assume it must be printing a potentially long string. So you could split it up into separate calls, for everything before the string, and everything after the string. Then you add the lengths of each of these to the length of the string, and see whether it's longer than 65535.

– Barmar
Jan 18 at 21:52













@Barmar I'm writing my own terminal. I haven't thought about examples of my program where that could happen. Currently, I'm writing a function that sends data to be printed to the terminal, and can be formatted. What if the buffer size was smaller? "Declare bigger buffers" can't be a solution to every instance of this problem :P

– Yuri J
Jan 18 at 22:01





@Barmar I'm writing my own terminal. I haven't thought about examples of my program where that could happen. Currently, I'm writing a function that sends data to be printed to the terminal, and can be formatted. What if the buffer size was smaller? "Declare bigger buffers" can't be a solution to every instance of this problem :P

– Yuri J
Jan 18 at 22:01




2




2





@Barmar By doing that, you're formatting the entirety of the data anyway. At that point you might as well do it the easy way and just use something like asprintf() to start.

– Andrew Henle
Jan 18 at 22:02





@Barmar By doing that, you're formatting the entirety of the data anyway. At that point you might as well do it the easy way and just use something like asprintf() to start.

– Andrew Henle
Jan 18 at 22:02












1 Answer
1






active

oldest

votes


















1














A solution is :



#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

int snprintfEnd(char *str, size_t size, const char *format, ...)
{
va_list ap1, ap2;

va_start(ap1, format);
va_copy(ap2, ap1);

/* get length of all */
int sz = vsnprintf(0, 0, format, ap2);

va_end(ap2);

/* get all */
char * all = malloc(sz + 1);

vsprintf(all, format, ap1);
va_end(ap1);

/* copy the expected part */
int r;

if (sz < size) {
strcpy(str, all);
r = sz;
}
else {
strcpy(str, all + sz - size);
r = size;
}

free(all);
return r;
}

int main()
{
char s[6];

int ln = snprintfEnd(s, 5, "%d %d %d", 1, 234, 567);

printf("%d : '%s'n", ln, s);

return 0;
}


Execution :



5 : '4 567'





share|improve this answer
























  • size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

    – chux
    Jan 18 at 23:57













  • Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

    – chux
    Jan 19 at 0:07











  • @chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

    – bruno
    Jan 19 at 8:32











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54261854%2fhow-to-get-the-last-characters-of-formatted-output-when-snprintf-returns-more-th%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














A solution is :



#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

int snprintfEnd(char *str, size_t size, const char *format, ...)
{
va_list ap1, ap2;

va_start(ap1, format);
va_copy(ap2, ap1);

/* get length of all */
int sz = vsnprintf(0, 0, format, ap2);

va_end(ap2);

/* get all */
char * all = malloc(sz + 1);

vsprintf(all, format, ap1);
va_end(ap1);

/* copy the expected part */
int r;

if (sz < size) {
strcpy(str, all);
r = sz;
}
else {
strcpy(str, all + sz - size);
r = size;
}

free(all);
return r;
}

int main()
{
char s[6];

int ln = snprintfEnd(s, 5, "%d %d %d", 1, 234, 567);

printf("%d : '%s'n", ln, s);

return 0;
}


Execution :



5 : '4 567'





share|improve this answer
























  • size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

    – chux
    Jan 18 at 23:57













  • Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

    – chux
    Jan 19 at 0:07











  • @chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

    – bruno
    Jan 19 at 8:32
















1














A solution is :



#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

int snprintfEnd(char *str, size_t size, const char *format, ...)
{
va_list ap1, ap2;

va_start(ap1, format);
va_copy(ap2, ap1);

/* get length of all */
int sz = vsnprintf(0, 0, format, ap2);

va_end(ap2);

/* get all */
char * all = malloc(sz + 1);

vsprintf(all, format, ap1);
va_end(ap1);

/* copy the expected part */
int r;

if (sz < size) {
strcpy(str, all);
r = sz;
}
else {
strcpy(str, all + sz - size);
r = size;
}

free(all);
return r;
}

int main()
{
char s[6];

int ln = snprintfEnd(s, 5, "%d %d %d", 1, 234, 567);

printf("%d : '%s'n", ln, s);

return 0;
}


Execution :



5 : '4 567'





share|improve this answer
























  • size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

    – chux
    Jan 18 at 23:57













  • Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

    – chux
    Jan 19 at 0:07











  • @chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

    – bruno
    Jan 19 at 8:32














1












1








1







A solution is :



#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

int snprintfEnd(char *str, size_t size, const char *format, ...)
{
va_list ap1, ap2;

va_start(ap1, format);
va_copy(ap2, ap1);

/* get length of all */
int sz = vsnprintf(0, 0, format, ap2);

va_end(ap2);

/* get all */
char * all = malloc(sz + 1);

vsprintf(all, format, ap1);
va_end(ap1);

/* copy the expected part */
int r;

if (sz < size) {
strcpy(str, all);
r = sz;
}
else {
strcpy(str, all + sz - size);
r = size;
}

free(all);
return r;
}

int main()
{
char s[6];

int ln = snprintfEnd(s, 5, "%d %d %d", 1, 234, 567);

printf("%d : '%s'n", ln, s);

return 0;
}


Execution :



5 : '4 567'





share|improve this answer













A solution is :



#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

int snprintfEnd(char *str, size_t size, const char *format, ...)
{
va_list ap1, ap2;

va_start(ap1, format);
va_copy(ap2, ap1);

/* get length of all */
int sz = vsnprintf(0, 0, format, ap2);

va_end(ap2);

/* get all */
char * all = malloc(sz + 1);

vsprintf(all, format, ap1);
va_end(ap1);

/* copy the expected part */
int r;

if (sz < size) {
strcpy(str, all);
r = sz;
}
else {
strcpy(str, all + sz - size);
r = size;
}

free(all);
return r;
}

int main()
{
char s[6];

int ln = snprintfEnd(s, 5, "%d %d %d", 1, 234, 567);

printf("%d : '%s'n", ln, s);

return 0;
}


Execution :



5 : '4 567'






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 18 at 22:22









brunobruno

4,7111921




4,7111921













  • size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

    – chux
    Jan 18 at 23:57













  • Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

    – chux
    Jan 19 at 0:07











  • @chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

    – bruno
    Jan 19 at 8:32



















  • size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

    – chux
    Jan 18 at 23:57













  • Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

    – chux
    Jan 19 at 0:07











  • @chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

    – bruno
    Jan 19 at 8:32

















size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

– chux
Jan 18 at 23:57







size_t size in snprintfEnd() is begin used as the max string length (without the null character). IMO, snprintfEnd(s, 5, "%d %d %d", 1, 234, 567) should use size as the size of the destination allowed including the null character and then s becomes "4 56" that needs 5 char.

– chux
Jan 18 at 23:57















Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

– chux
Jan 19 at 0:07





Such excessively long uses of *print() are prone to Environmental limits. C11 §7.21.6.1 15. This may be a case where "fprintf function returns the number of characters transmitted, or a negative value if an output or encoding error occurred.". So checking for that from int sz = vsnprintf() would be prudent.

– chux
Jan 19 at 0:07













@chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

– bruno
Jan 19 at 8:32





@chux yes I do not follow the same rule for size, but whatever because without news from the OP I will probably destruct that wasted answer

– bruno
Jan 19 at 8:32


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54261854%2fhow-to-get-the-last-characters-of-formatted-output-when-snprintf-returns-more-th%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Liquibase includeAll doesn't find base path

How to use setInterval in EJS file?

Petrus Granier-Deferre