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.