2017-06-27 2 views
4

Je sais que %% est utilisé pour échapper réelle % signes dans une chaîne, donc %%%ds se terminera avec %10s dans la chaîne de format suivant, mais je ne sais pas pourquoi je dois %%5s dans cette chaîne?Chaîne de format avec des signes multiples pour cent

Après tout, il n'y a que deux arguments supplémentaires (BUFFSIZE/10).

#define BUFFSIZE 100 
char buf[100]={0} 
sprintf(buf, "%%5s %%%ds %%%ds", BUFFSIZE/10, BUFFSIZE/10); 

Après avoir exécuté le code ci-dessus, le buf contiendra la chaîne,

%10s %10s 
+5

Je reçois '% 5s% 10s% 10s' dans' buf', démo ici http://ideone.com/c8MhN6. Qu'est-ce que vous attendiez? –

+2

Cela signifie que quelqu'un est trop intelligent ou ne connaît pas ['% * s'] (https://stackoverflow.com/questions/7105890/set-variable-text-column-width-in-printf). –

+1

@ n.m. ou, n'a pas peur du mainteneur (_Ref: le psychopathe violent_) –

Répondre

5

Le but est d'obtenir une chaîne de format pour l'utiliser dans une autre fonction qui a besoin d'une chaîne de format comme sscanf().

Avec votre code, vous obtenez: %5s %10s %10s écrit sur votre buf, see online, ce qui signifie qu'il accepte trois chaînes avec un identificateur de longueur.

%%5s   --> %5s 
%%%ds with 10 --> %10s (read it that way: {%%}{%d}{s}) 

Ce tampon %5s %10s %10s pourrait maintenant être utilisé dans un appel sscanf() comme montré here. Mais il existe une meilleure pratique pour éviter un dépassement de tampon causé par sscanf() qui est également décrit par Kernighan et Pike dans leur livre The Practice of Programming, voir here on SO.


La raison pour laquelle vous pouvez peut-être pas utiliser %*s peut être, voir here on SO:

Pour printf, le * vous permet de spécifier la largeur de champ minimale par un paramètre supplémentaire, c.-à-printf("%*d", 4, 100); spécifie une Pour scanf, le * indique que le champ doit être lu mais ignoré, de sorte que scanf("%*d %d", &i) pour l'entrée "12 34" ignorera 12 et lira 34 dans l'entier i.

2

% en lui-même est un spécificateur de conversion valide. La syntaxe est prescrite, tel que mentionné dans C11, chapitre §7.21.6.1/P2, (souligné dans)

Chaque spécification de conversion est introduit par le caractère %. Après la %, les éléments suivants apparaissent dans l'ordre:

  • Zéro ou plusieurs drapeaux [...]

  • Une largeur de champ minimale en option.

  • Une option précision [...]

  • Un modificateur de longueur optionnelle [...]

  • Un caractère de spécification de conversion qui spécifie le type de conversion à appliquer.

Puis, à partir P8, pour spécificateurs de conversion

Les indicateurs de conversion et leurs significations sont:

......

%

A % le caractère est écrit. Aucun argument n'est converti. La spécification de conversion complète doit être %%.

Ainsi, basé sur une approche avide, compilateur groupe une syntaxe comme

.... %%%ds, BUFFSIZE/10 .... 

comme

{%%}{%d}{s} 
    ^^--------------------------Replaced as % 
     ^^----------------------Actual conversion specification happens, argument is used 
     ^^------------------just part of final output 

qui produit finalement

%Xs //where X is the value of (BUFFSIZE/10) 

qui est un format valide chaîne (%, largeur de champ minimum, spécificateur de conversion, tous dans l'ordre), à nouveau, à utiliser ultérieurement.

+0

vous avez tout expliqué, mon erreur –

+0

@VishwajeetVishu Nevermind, c'est OK.J'ai également mis à jour la réponse en attendant. :) –

0

L'OP calcule une chaîne de format à partir de tailles paramétriques. Compte tenu des arguments, la chaîne contiendra %5s %10s %10s, qui peut être utilisé avec printf ou scanf:

printf("%5s %10s %10s", "A", "B", "C"); 

sorties:

A   B   C 

char a[6], b[11], c[11]; 
scanf("%5s %10s %10s", a, b, c); 

lira 3 cordes en a, b, c mais limite le nombre de caractères lus pour chaque chaîne pour empêcher le débordement de la mémoire tampon.

Notez cependant que pour le printf cas, il est nécessaire de calculer la chaîne telle que publiée, puisque vous auriez pu utiliser:

printf("%5s %*s %*s", "A", BUFFSIZE/10, "B", BUFFSIZE/10, "C"); 

Malheureusement, scanf() attache une sémantique différente au modificateur de format * et il est impossible de spécifier le nombre maximal de caractères à stocker avec un argument, uniquement avec des chiffres dans la chaîne de format, d'où la nécessité d'une étape de mise en forme distincte.