web-dev-qa-db-fra.com

sprintf () sans espace nul de fin dans C

Existe-t-il un moyen d'utiliser la fonction C sprintf () sans qu'elle ajoute un caractère '\ 0' à la fin de sa sortie? J'ai besoin d'écrire du texte formaté au milieu d'une chaîne de largeur fixe.

40
zaratustra

Il n'y a aucun moyen de dire à sprintf() de ne pas écrire de null final. Ce que vous pouvez faire est d'utiliser sprintf() pour écrire dans une chaîne temporaire, puis quelque chose comme strncpy() pour copier uniquement les octets souhaités.

42
Greg Hewgill

sprintf renvoie la longueur de la chaîne écrite (sans compter le terminal nul), vous pouvez l'utiliser pour savoir où était le terminal nul et changer le caractère du terminal nul en autre chose (c'est-à-dire un espace). Ce serait plus efficace que d'utiliser strncpy.

 unsigned int len = sprintf(str, ...);
 str[len] = '<your char here>';
25
Doug T.

Vous ne pouvez pas faire cela avec sprintf (), mais vous pouvez pouvoir avec snprintf (), en fonction de votre plate-forme.

Vous devez savoir combien de caractères vous remplacez (mais comme vous les placez au milieu d'une chaîne, vous le savez probablement de toute façon).

Cela fonctionne car certaines implémentations de snprintf () NE garantissent PAS l'écriture d'un caractère de fin - probablement pour des raisons de compatibilité avec des fonctions comme stncpy ().

char message[32] = "Hello 123, it's good to see you.";

snprintf(&message[6],3,"Joe");

Après cela, "123" est remplacé par "Joe".

Sur les implémentations où snprintf () garantit une terminaison nulle même si la chaîne est tronquée, cela ne fonctionnera pas. Donc, si la portabilité du code est un problème, vous devez éviter cela.

La plupart versions Windows de snprintf () présentent ce comportement.

Mais, MacOS et BSD (et peut-être Linux) semblent toujours se terminer par null.

4
Roddy

Vous pouvez également utiliser votre chaîne de largeur fixe comme une chaîne de format comme ceci:

char my_fixed_width_string_format[] = "need 10 chars starting here: %10s";
char my_fixed_width_string[40];
char string_to_print[] = "abcdefghijklmnop";
sprintf(my_fixed_width_string, my_fixed_width_string_format, string_to_print;
printf(my_fixed_width_string);

devrait céder

besoin de 10 caractères commençant ici: abcdefghij

1
Nathan Fellman

Puisque vous écrivez dans une zone fixe, vous pouvez le faire comme ceci:

// pointer to fixed area we want to write to
char* s;

// number of bytes needed, not including the null
int r = snprintf(0, 0, <your va_args here>);

// char following the last char we will write - null goes here
char c = s[r + 1];

// do the formatted write
snprintf(s, r + 1, <your_va_args here>);

// replace what was overwritten
s[r + 1] = c;
0
Todd Freed

En fait, cet exemple n'ajoutera pas de valeur null si vous utilisez snprintf:

char name[9] = "QQ40dude";  
unsigned int i0To100 = 63;  
_snprintf(&name[2],2,"%d",i0To100);  
printf(name);// output will be: QQ63dude  
0
yan bellavance