Je suis confronté à un problème sérieux avec sprintf.
Supposons que mon extrait de code est:
sprintf(Buffer,"Hello World");
sprintf(Buffer,"Good Morning");
sprintf(Buffer,"Good Afternoon");
.
.
.
Une centaine de sprints ....
Si j'aime ça, ça va être écrasé.
Comment puis-je éviter d'écraser en utilisant sprintf. Si je donne un printf à la fin, je veux voir toutes les lignes.
Vous avez besoin:
sprintf(Buffer,"Hello World");
sprintf(Buffer + strlen(Buffer),"Good Morning");
sprintf(Buffer + strlen(Buffer),"Good Afternoon");
et bien sûr, vous avez besoin que votre tampon soit suffisamment grand.
int length = 0;
length += sprintf(Buffer+length, "Hello World");
length += sprintf(Buffer+length, "Good Morning");
length += sprintf(Buffer+length, "Good Afternoon");
Voici une version avec une certaine résistance aux erreurs. Il est utile si vous ne vous souciez pas des erreurs si vous pouvez continuer dans la bonne voie quand elles se produisent.
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"));
Pour la sécurité (débordement de tampon), je recommande d'utiliser snprintf ()
const int MAX_BUF = 1000; char * Buffer = malloc (MAX_BUF); int longueur = 0; longueur + = snprintf ( Buffer + length, MAX_BUF-length, "Hello World"); Length + = snprintf (Buffer + length, MAX_BUF-length, "Good Morning"); Length + = snprintf (Buffer + longueur, MAX_BUF-longueur, "bon après-midi");
Un wrapper snprintfcat()
pour 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;
}
Utilisez la valeur de retour de sprintf()
Buffer += sprintf(Buffer,"Hello World");
Buffer += sprintf(Buffer,"Good Morning");
Buffer += sprintf(Buffer,"Good Afternoon");
Est-ce que vous ajoutez simplement des littéraux de chaîne? Ou allez-vous ajouter différents types de données (ints, floats, etc.)?
Il serait peut-être plus facile d’abréger cela dans sa propre fonction (ce qui suit suppose 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;
}
Et vous l'utiliseriez comme ceci:
char target[100] = {0};
...
appendToStr(target, sizeof target, "%s %d %f\n", "This is a test", 42, 3.14159);
appendToStr(target, sizeof target, "blah blah blah");
etc.
La fonction renvoie la valeur de vsprintf
, qui dans la plupart des implémentations correspond au nombre d'octets écrits dans la destination. Il y a quelques trous dans cette implémentation, mais cela devrait vous donner quelques idées.
Je pense que vous cherchez 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;
}
Si le stockage dynamique vous convient mieux, vous pouvez suivre l'excellente suggestion de Liam concernant l'utilisation de 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;
}
Je trouve que la méthode suivante fonctionne bien.
sprintf(Buffer,"Hello World");
sprintf(&Buffer[strlen[Buffer]],"Good Morning");
sprintf(&Buffer[strlen[Buffer]],"Good Afternoon");
Utilisez 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.
Vous pouvez utiliser la simple ligne illustrée ci-dessous pour ajouter des chaînes dans un tampon:
sprintf(Buffer,"%s %s %s","Hello World","Good Morning","Good Afternoon");
Petit exemple de code complet
Utilisation de la bibliothèque plate stdio standard uniquement
#include <stdio.h>
int main()
{
char c[1024];
int i=0;
i+=sprintf(c+i,"We " );
i+=sprintf(c+i,"Love " );
sprintf(c+i,"Coding");
printf("%s",c);
}
SORTIE: Nous aimons coder
J'écris une chaîne de variable dynamique supportant les fonctions append, comme 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("%s\n", json);
if (json) free(json);
return 0;
}