Que signifie «%. * S» dans printf?


Réponses:


121

Vous pouvez utiliser un astérisque ( *) pour passer le spécificateur / précision de largeur à printf(), plutôt que de le coder en dur dans la chaîne de format, c.-à-d.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}

4
Il convient de noter que l' str_lenargument doit avoir un type int(ou un type intégral plus étroit, qui serait promu en int). Ce serait un bug à passer long, size_tetc.
MM

10
Il convient de mentionner que le but probable de ce code, en particulier lorsqu'il est utilisé avec %s, est d'imprimer une sous-chaîne de la chaîne d'origine. Dans ce cas d'utilisation, strpointerait vers quelque part à l'intérieur de la chaîne d'origine (éventuellement au début), et str_lenspécifierait la longueur de la sous-chaîne à imprimer.
Sonic Atom

2
En spécifiant une longueur, nous pouvons contourner l'impression (ou sprintf) d'une chaîne qui n'a pas de terminateur nul, par exemple une chaîne qui est entrée à partir de n'importe quelle source basée sur un flux ou un fichier. Ce qui est beaucoup plus souvent le cas d'utilisation que j'ai rencontré, que de simples jolies impressions.
Conrad B

23

Plus de détails ici .

valeur entière ou *qui spécifie la largeur minimale du champ. Le résultat est complété par des espaces (par défaut), si nécessaire, à gauche lorsqu'il est justifié à droite, ou à droite s'il est justifié à gauche. Dans le cas où * est utilisé, la largeur est spécifiée par un argument supplémentaire de type int. Si la valeur de l'argument est négative, il en résulte avec l'indicateur - spécifié et une largeur de champ positive. (Remarque: il s'agit de la largeur minimale: la valeur n'est jamais tronquée.)

.suivi d'un nombre entier ou *, ou ni l'un ni l'autre qui spécifie la précision de la conversion. Dans le cas où * est utilisé, la précision est spécifiée par un argument supplémentaire de type int. Si la valeur de cet argument est négative, il est ignoré. Si ni un nombre ni * ne sont utilisés, la précision est considérée comme zéro. Voir le tableau ci-dessous pour les effets exacts de la précision.

Donc, si nous essayons les deux spécifications de conversion

#include <stdio.h>

int main() {
    int precision = 8;
    int biggerPrecision = 16;
    const char *greetings = "Hello world";

    printf("|%.8s|\n", greetings);
    printf("|%.*s|\n", precision , greetings);
    printf("|%16s|\n", greetings);
    printf("|%*s|\n", biggerPrecision , greetings);

    return 0;
}

nous obtenons la sortie:

|Hello wo|
|Hello wo|
|     Hello world|
|     Hello world|

12

Je ne pense pas que le code ci-dessus soit correct mais (selon cette description de printf()) les .*moyens

La largeur n'est pas spécifiée dans la chaîne de formatage, mais comme argument de valeur entière supplémentaire précédant l'argument à mettre en forme. '

C'est donc une chaîne avec une largeur passable comme argument.


2
J'ai ajouté la référence croisée d'URL afin que vous puissiez éviter des accusations de plagiat. Bien sûr, la citation correcte dit "La précision n'est pas…" plutôt que "La largeur n'est pas…".
Jonathan Leffler

Comme l'a souligné @MattMcNabb, chaque référence à cette page doit mettre en évidence qu'une « valeur entière » est exactement int(ou un sous-ensemble de celle-ci) - pas simplement n'importe quelle valeur intégrale comme plus intuitive size_tou ses alias possibles, comme std::string::size_type. Ceci est encore plus déroutant, en tenant compte du fait que la page référencée mentionne size_tcomme l'un des spécificateurs de type pris en charge.
Anton Samsonov

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.