Cosa significa "%. * S" in printf?


Risposte:


121

Puoi usare un asterisco ( *) per passare lo specificatore di larghezza / precisione a printf(), invece di codificarlo in modo rigido nella stringa di formato, ad es.

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

4
Va notato che l' str_lenargomento deve avere tipo int(o tipo integrale più stretto, che verrebbe promosso a int). Sarebbe un errore di passare long, size_te così via
MM

10
Vale la pena ricordare che il probabile scopo di questo codice, specialmente se usato con %s, è stampare una sottostringa della stringa originale. In questo caso d'uso, strpunta a un punto all'interno della stringa originale (possibilmente all'inizio) e str_lenspecifica la lunghezza della sottostringa da stampare.
Sonic Atom

2
Specificando una lunghezza, possiamo aggirare la stampa (o sprintf) di una stringa che non ha terminatore nullo, ad esempio una stringa che viene immessa da qualsiasi flusso o sorgente basata su file. Che è molto più spesso il caso d'uso che ho riscontrato, rispetto alla semplice stampa di prettine.
Conrad B

23

Maggiori dettagli qui .

valore intero o *che specifica la larghezza minima del campo. Il risultato viene riempito con caratteri di spazio (per impostazione predefinita), se necessario, a sinistra se giustificato a destra oa destra se giustificato a sinistra. Nel caso in cui venga utilizzato *, la larghezza è specificata da un argomento aggiuntivo di tipo int. Se il valore dell'argomento è negativo, risulta con il flag specificato e larghezza del campo positiva. (Nota: questa è la larghezza minima: il valore non viene mai troncato.)

.seguito da un numero intero o * o nessuno dei due che specifica la precisione della conversione. Nel caso in cui venga utilizzato *, la precisione è specificata da un argomento aggiuntivo di tipo int. Se il valore di questo argomento è negativo, viene ignorato. Se non viene utilizzato né un numero né un *, la precisione viene considerata zero. Vedere la tabella seguente per gli effetti esatti della precisione.

Quindi, se proviamo entrambe le specifiche di conversione

#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;
}

otteniamo l'output:

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

12

Non penso che il codice sopra sia corretto ma (secondo questa descrizione di printf()) i .*mezzi

La larghezza non è specificata nella stringa di formato, ma come argomento di un valore intero aggiuntivo che precede l'argomento che deve essere formattato. '

Quindi è una stringa con una larghezza passabile come argomento.


2
Ho aggiunto il riferimento incrociato all'URL in modo da evitare addebiti per plagio. Naturalmente, la citazione corretta dice "La precisione non è ..." invece di "La larghezza non è ...".
Jonathan Leffler

Come ha sottolineato @MattMcNabb, ogni riferimento a quella pagina deve evidenziare che " un valore intero " è esattamente int(o un sottoinsieme di esso) - non solo un valore integrale come più intuitivo size_to i suoi possibili alias, come std::string::size_type. Ciò crea ancora più confusione, tenendo conto che la pagina di riferimento menziona size_tcome uno degli specificatori di tipo supportati.
Anton Samsonov

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.