1
votes

Ambiguïté dans le sprintf concernant le retour du caractère '%'

Je dois sortir une chaîne qui commence par% character (% EE # WD ...) et j'utilise sprintf. Dans plusieurs références, j'ai lu qu'en utilisant un spécificateur% après%, la fonction sprintf renvoie le caractère%.

Mais pour moi, dans différents compilateurs (comme DEV C ++, JDOODLE), le résultat n'est pas ce à quoi je m'attendais et enfin j'ai obtenu le caractère% en répétant le spécificateur% 4 fois!

Quelle est la raison?

Voici le code et les sorties:

#include <stdio.h>
int main()
{
    static char Command[10]     ;
    sprintf (Command,"%%%%EE#") ;
    printf  (Command)           ;    
    return 0                    ;
}


3 commentaires

@xing - ce serait en effet le problème, si vous expliquez un peu plus, cela ferait une excellente réponse


premier sprintf "%%%% EE #" -> "%% EE #" . Le deuxième printf car il s'agit de la chaîne de format "%% EE #" -> "% EE #" . Pour imprimer la chaîne, utilisez à la place. C'est de toute façon beaucoup plus rapide.


@xing merci beaucoup. J'ai compris


4 Réponses :


1
votes
sprintf (Command,"%%%%EE#") ;
printf  (Command)           ;  

3 commentaires

En effet, mais ce n'est pas ce qui est imprimé par la ligne next pour la raison expliquée par @xing


oui, bien sûr, printf (commande) obtient le résultat précédent sous forme de format


@ChrisStratton j'ai édité ma réponse, quand quelque chose est sous-entendu j'ai la mauvaise habitude de ne pas le dire dans ma réponse, j'ai du mal à me corriger



0
votes

%% vous donnera % le % E fait en fait référence à la notation scientifique, c'est pourquoi vous obtenez un nombre et avez besoin de plus % pour imprimer %E


1 commentaires

Seulement parce qu'il est interprété deux fois pour la raison indiquée par @xing. Ce que vous proposez n'est pas vraiment la bonne solution, sauf si l'objectif est de générer par programme une chaîne de format, ce qui, bien que possible , n'est pas ce que l'on souhaite ici, et n'est généralement pas une bonne idée.



4
votes

Après sprintf (Command, "%% EE #") , la Command contiendra % EE # . Si vous passez maintenant ce contenu à printf en tant que chaîne de format, le (maintenant) unique % sera interprété comme un spécificateur de format, recherchant alors un argument flottant. Ceci n'est pas fourni et conduit en fait à un comportement indéfini. Avec sprintf (Command, "%%%% EE #") , vous "surmontez" ce problème car Command contiendra %% EE # alors.

Mais en fait, vous devriez écrire ...

static char Command[10];
strcpy(Command,"%EE#");
printf  ("%s",Command);    

Ou ...

static char Command[10] = "%EE#";
printf  ("%s",Command);    


4 commentaires

... ou utilisez put () ou fputs () si vous voulez sortir une chaîne telle quelle, sans engager la machine de formatage.


@JohnBollinger Un bon compilateur émettra le même code efficace pour printf ("% s", Command); et fputs (Command, stdout); . IMO, codez pour plus de clarté et laissez le compilateur gérer ces optimisations linéaires.


@chux, je soumets que l'utilisation de fputs (Command, stdout) au lieu de printf ("% s", Command) est codant pour plus de clarté. C'est, en fait, mon point.


@JohnBollinger J'ai lu le commentaire en tant que point sur l'efficacité du code, pas la clarté. Ce qui semble le plus clair dans un contexte diffère et dépend du code voisin. IAC, nous convenons que la clarté est un problème déterminant. En général, je trouve aussi fputs () meilleur, mais près de nombreuses lignes de code printf () non triviales, je trouve printf ("% s ", Command) plus clair. ... Et attendez-vous à ce que mon compilateur fasse du bon travail.



3
votes

La transmission du résultat de sprintf comme premier argument à printf entraîne sa réinterprétation en tant que chaîne de format. Ainsi, votre chaîne est interprétée comme une chaîne de format une fois pour sprintf et de nouveau pour printf . Ne faites pas cela.

Si vous n'avez pas besoin de formatage, imprimez simplement une chaîne avec fputs , comme dans fputs ("% EE #", stdout); . ( met est similaire, mais il ajoute un caractère de nouvelle ligne. fputs imprime simplement les caractères qui lui sont donnés.)

Si vous avez besoin d'un formatage et pouvez imprimer directement (sans tampon intermédiaire), utilisez printf ; n'utilisez pas sprintf au préalable.

Si vous avez besoin d'un formatage et que le résultat doit être écrit dans un tampon, utilisez sprintf et imprimez le tampon avec fputs , pas printf .


0 commentaires