How to append strings using sprintf?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP

How to append strings using sprintf?



I am facing a serious issue with sprintf.



Suppose my code snippet is:


sprintf(Buffer,"Hello World");
sprintf(Buffer,"Good Morning");
sprintf(Buffer,"Good Afternoon");
.
.
.



Some hundred sprints....



If I do like this, its getting overwritten.



How can I avoid overwritting using sprintf. If I give a printf at the end I want to see all the lines.





I shall not use sprintf but snprintf, I shall not use printf( str ) but printf( "%s" , str )
– fa.
Apr 20 '10 at 12:59




15 Answers
15



You need:


sprintf(Buffer,"Hello World");
sprintf(Buffer + strlen(Buffer),"Good Morning");
sprintf(Buffer + strlen(Buffer),"Good Afternoon");



and of course you need your buffer to be big enough.





buffer s large enough...i will try...
– user46646
Apr 20 '10 at 10:41





+1 although I like Aeth's solution a bit better, it seems a bit more efficient than recalculating the string length every time.
– extraneon
Apr 20 '10 at 10:47





A trick I've seen along these lines is to #define eos(s) ((s)+strlen(s)), or declare a function if you prefer. Then you can use sprintf(eos(Buffer), "Stuff")
– msandiford
Apr 20 '10 at 10:47


#define eos(s) ((s)+strlen(s))


sprintf(eos(Buffer), "Stuff")





Simpler still, you can just use sprintf(strchr(s, ''), "...").
– Arto Bendiken
Mar 29 '14 at 12:48


sprintf(strchr(s, ''), "...")





What is the + strlen(Buffer) appending to the actual Buffer for?
– bretcj7
Sep 17 '16 at 3:43


int length = 0;
length += sprintf(Buffer+length, "Hello World");
length += sprintf(Buffer+length, "Good Morning");
length += sprintf(Buffer+length, "Good Afternoon");



Here is a version with some resistance to errors. It is useful if you do not care when errors happen so long as you can continue along your merry way when they do.


int bytes_added( int result_of_sprintf )

return (result_of_sprintf > 0) ? result_of_sprintf : 0;


int length = 0;
length += bytes_added(sprintf(Buffer+length, "Hello World"));
length += bytes_added(sprintf(Buffer+length, "Good Morning"));
length += bytes_added(sprintf(Buffer+length, "Good Afternoon"));





But what happens if sprintf experiences a conversion failure?
– anon
Apr 20 '10 at 10:52





Then you have bad things that happen. I omitted the error checking for the sake of brevity.
– Matthew T. Staebler
Apr 20 '10 at 11:21





+1 - Additional error checking should be an exercise for the reader anyway. After all, its their code :)
– Tim Post
Apr 20 '10 at 12:28





I guess make sense to report error and errono in case of negative result of sprintf.
– Boris Ivanov
Oct 23 '14 at 14:32



For safety (buffer overflow) I recommend to use snprintf()





The second argument of snprintf is unsigned (size_t), it means that if length > MAX_BUF, then MAX_BUF-length will underflow and snprintf will happily write outside of the buffer creating a buffer overflow. Note that the return of snprintf is equal to the number of bytes which would have been written if enough space had been available and NOT the number of bytes really written.
– leszek.hanusz
Dec 14 '16 at 17:18



A snprintfcat() wrapper for snprintf():


snprintfcat()


snprintf()


size_t
snprintfcat(
char* buf,
size_t bufSize,
char const* fmt,
...)

size_t result;
va_list args;
size_t len = strnlen( buf, bufSize);

va_start( args, fmt);
result = vsnprintf( buf + len, bufSize - len, fmt, args);
va_end( args);

return result + len;



Why do you want to use sprintf for string concatenation when there are methods intended specifically for what you need such as strcat and strncat?


sprintf


strcat


strncat





It could be that the example was the trivial case only strings are being appended. The problem can be extended to include cases where you are appending other types of formatted data for which strcat would not apply.
– Matthew T. Staebler
Apr 20 '10 at 11:41



strcat



I find the following method works nicely.


sprintf(Buffer,"Hello World");
sprintf(&Buffer[strlen[Buffer]],"Good Morning");
sprintf(&Buffer[strlen[Buffer]],"Good Afternoon");





[...] around strlen? Should it be (...)?
– CodyChan
Jul 8 '15 at 2:42


[...]


strlen


(...)





too much python :D
– Niko
Jul 25 '17 at 7:32



Use the return value of sprintf()


sprintf()


Buffer += sprintf(Buffer,"Hello World");
Buffer += sprintf(Buffer,"Good Morning");
Buffer += sprintf(Buffer,"Good Afternoon");



Are you simply appending string literals? Or are you going to be appending various data types (ints, floats, etc.)?



It might be easier to abstract this out into its own function (the following assumes C99):


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

int appendToStr(char *target, size_t targetSize, const char * restrict format, ...)

va_list args;
char temp[targetSize];
int result;

va_start(args, format);
result = vsnprintf(temp, targetSize, format, args);
if (result != EOF)

if (strlen(temp) + strlen(target) > targetSize)

fprintf(stderr, "appendToStr: target buffer not large enough to hold additional string");
return 0;

strcat(target, temp);

va_end(args);
return result;



And you would use it like so:


char target[100] = 0;
...
appendToStr(target, sizeof target, "%s %d %fn", "This is a test", 42, 3.14159);
appendToStr(target, sizeof target, "blah blah blah");



etc.



The function returns the value from vsprintf, which in most implementations is the number of bytes written to the destination. There are a few holes in this implementation, but it should give you some ideas.


vsprintf





Why don't you put sizeof target inside the function? Why do you need it in parameters?
– valerij vasilcenko
Jul 25 '14 at 8:58





@hellomyfriends: Because in the function, target is a pointer to char, not an array of char, and sizeof will only return the size of the pointer, not the size of the array that it points to.
– John Bode
Jul 25 '14 at 13:54


target


char


char


sizeof



I think you are looking for fmemopen(3):


fmemopen(3)


#include <assert.h>
#include <stdio.h>

int main(void)

char buf[128] = 0 ;
FILE *fp = fmemopen(buf, sizeof(buf), "w");

assert(fp);

fprintf(fp, "Hello World!n");
fprintf(fp, "%s also work, of course.n", "Format specifiers");
fclose(fp);

puts(buf);
return 0;



If dynamic storage is more suitable for you use-case you could follow Liam's excellent suggestion about using open_memstream(3):


open_memstream(3)


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)

char *buf;
size_t size;
FILE *fp = open_memstream(&buf, &size);

assert(fp);

fprintf(fp, "Hello World!n");
fprintf(fp, "%s also work, of course.n", "Format specifiers");
fclose(fp);

puts(buf);
free(buf);
return 0;





This is just what I was looking for. At the suggestion of man fmemopen, I found open_memstream to be a little more suitable for my application. See the GNU manual for an example.
– Liam
Feb 1 '17 at 3:59






@Liam awesome, thanks for the tip about open_memstream. I added an example for that as well.
– wkz
Feb 1 '17 at 17:22


open_memstream





Fantastic, except neither fmemopen nor open_memstream are available on Windows.
– 7vujy0f0hy
Oct 7 '17 at 13:10


fmemopen


open_memstream



You can use the simple line shown below to append strings in one buffer:


sprintf(Buffer,"%s %s %s","Hello World","Good Morning","Good Afternoon");



Use strcat http://www.cplusplus.com/reference/cstring/strcat/


int main ()

char str[80];
strcpy (str,"these ");
strcat (str,"strings ");
strcat (str,"are ");
strcat (str,"concatenated.");
puts (str);
return 0;





Output:


these strings are concatenated.



I write a function support dynamic variable string append, like PHP str append: str . str . ... etc.


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

int str_append(char **json, const char *format, ...)

char *str = NULL;
char *old_json = NULL, *new_json = NULL;

va_list arg_ptr;
va_start(arg_ptr, format);
vasprintf(&str, format, arg_ptr);

// save old json
asprintf(&old_json, "%s", (*json == NULL ? "" : *json));

// calloc new json memory
new_json = (char *)calloc(strlen(old_json) + strlen(str) + 1, sizeof(char));

strcat(new_json, old_json);
strcat(new_json, str);

if (*json) free(*json);
*json = new_json;

free(old_json);
free(str);

return 0;


int main(int argc, char *argv)

char *json = NULL;

/*
str_append(&json, "name: %d, %d, %d", 1, 2, 3);
str_append(&json, "sex: %s", "male");
str_append(&json, "end");
str_append(&json, "");
str_append(&json, ""ret":true");
*/

int i;
for (i = 0; i < 100; i++)
str_append(&json, "id-%d", i);


printf("%sn", json);

if (json) free(json);

return 0;



SMALL FULL CODE EXAMPLE



Using flat plain stdio standard library only



(and no worries about char vector size crash from the "out bounds" of sprintf, cool hun?!!):


#include <stdio.h>
char c="";
int main()

int i=0;
i+=sprintf(c+i,"Sergio ");
i+=sprintf(c+i,"Mcfly ");
i+=sprintf(c+i,"NY-USA ");
i+=sprintf(c+i,"bla bla blahh...455453853;-)");
printf("%s",c);



OUTPUT: Sergio Mcfly NY-USA bla bla blahh...455453853;-)



Using strcat(buffer,"Your new string...here"), as an option.


buffer


Your new string...here





This duplicates a more complete existing answer stackoverflow.com/a/40316229/874188
– tripleee
Feb 17 '17 at 7:10



What about:


char s[100] = "";

sprintf(s, "%s%s", s, "s1");

sprintf(s, "%s%s", s, "s2");

sprintf(s, "%s%s", s, "s3");

printf("%s", s);



But take into account possible buffer ovewflows!





its not appending....
– user46646
Apr 20 '10 at 10:53





It is probably not a safe move to be using s as a source to be read from as well as a destination to be written to. I would liken it to calling strcpy(s, s).
– Matthew T. Staebler
Apr 20 '10 at 11:37



s


strcpy(s, s)






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

Executable numpy error

PySpark count values by condition

Trying to Print Gridster Items to PDF without overlapping contents