Vai al contenuto

Segnaposti del formato printf

Vai all indice del manuale di programmazione

Nelle funzioni di uscita formattata su stream (Indicate come printf) la formattazione avviene attraverso segnaposti nella stringa di formato. Per esempio, se un programma vuole stampare l’età di una persona, può presentare l’output con il prefisso “Your age is:“. Per specificare che vogliamo che l’integer dell’età venga stampato dopo il messaggio possiamo usare la forma: “Your age is: %d“. La sintassi del segnaposto di formato è %[Flag][Width][. Accuracy] [Length]Type.

Flag, si possono omettere:

  • ‘+’: printf denota sempre il segno ‘+’ o ‘-‘ di un numero (il default è omettere il segno per i numeri positivi). Solo per variabili numeriche.
  • ‘-‘: printf allinea a sinistra l’output di questo segnaposto (il default è a destra).
  • ‘#’: Forma alternata: con ‘g’ e ‘G’, gli zeri finali non sono rimossi; con ‘f’, ‘F’, ‘e’, ‘E’, ‘g’, ‘G’, l’output contiene sempre un punto decimale; con ‘o’, ‘x’, e ‘X’, vengono rispettivamente prefissi uno 0, 0x, o 0X ai numeri diversi da zero.
  • ‘ ‘: Fa inserire a printf spazi sulla sinistra dell’output fino al raggiungimento della lunghezza richiesta. Se combinato con ‘0’ (vedi sotto), farà diventare il segno uno spazio per i numeri positivi, ma gli altri caratteri saranno riempiti da zeri.
  • ‘0’: Fa usare a printf dei caratteri ‘0’ (anziché spazi) a sinistra fino al raggiungimento di una certa lunghezza. Per esempio, assumendo i=3, printf(“%2d”, i) ritorna ” 3″, mentre printf(“%02d”, i) ritorna “03”.

Width, può essere omessa, o essere:

  • ‘un numero’: printf mostra l’output di questo segnaposto con spazi finché è largo almeno ”numero” caratteri.
  • ‘*’: printf espande l’output finché è largo ”n” caratteri, dove n è un valore intero memorizzato nel prossimo argomento. Per esempio printf(“%*d”, 5, 10) risulterà in “10” stampato con una larghezza pari a 5.

Accuracy, può essere omessa, o essere:

  • ‘un numero’: Per i tipi numerici non interi (cioè a virgola mobile), la porzione decimale dell’output viene espressa con esattamente ”numero” cifre. Con le stringhe, taglia l’output a ”numero” caratteri.
  • ‘*’: Come sopra, ma usa un valore intero nell’argomento successivo per determinare il numero di posizioni decimali o la massima lunghezza della stringa. Per esempio, printf(“%.*s”, 3, “abcdef”) risulterà nella stampa di “abc”.

Length, può essere omessa, o essere:

  • ‘hh’: per i tipi interi, printf si attende un argomento lungo quanto un char;
  • ‘h’: per i tipi interi, printf si attende un argomento lungo quanto un intero corto;
  • ‘l’: ‘(elle)’ per i tipi interi, printf si attende un argomento lungo quanto un intero lungo;
  • ‘ll’: ‘(elle elle)’ per i tipi interi, printf si attende un argomento lungo quanto un intero lungo-lungo;
  • ‘L’: per i tipi a virgola mobile, printf si attende un argomento lungo quanto un doppio lungo;
  • ‘z’: per i tipi interi, printf si attende un argomento lungo quanto un intero di tipo size_t;
  • ‘j’: per i tipi interi, printf si attende un argomento lungo quanto un intero di tipo intmax_t;
  • ‘t’: per i tipi interi, printf si attende un argomento lungo quanto un intero di tipo ptrdiff_t.

Type, è obbligatorio:

  • ‘d’, ‘i’: Stampa un intero come [decimale] con segno. ‘%d’ e ‘%i’ sono sinonimi per l’output, ma diversi se usati con scanf() per l’input;
  • ‘u’: Stampa un intero come decimale senza segno;
  • ‘f’, ‘F’: Stampa un valore reale come un numero con virgola;
  • ‘e’, ‘E’: Stampa un valore reale nella forma esponenziale standard ([-]d.ddd e[+/-]ddd); ‘e’ usa la ‘e’ minuscola, ‘E’ usa la maiuscola;
  • ‘g’, ‘G’: Stampa un valore reale con notazione reale o esponenziale, scegliendo quella più adatta alla sua dimensione. ‘g’ usa lettere minuscole, ‘G’ usa lettere maiuscole. Questa notazione è diversa dalla notazione con virgola perché gli zeri superflui alla destra del punto decimale non sono inclusi. Il punto decimale non è incluso nei numeri interi;
  • ‘x’, ‘X’: Stampa un intero senza segno come numero [esadecimale]. ‘x’ usa lettere minuscole e ‘X’ usa maiuscole;
  • ‘o’: Stampa un intero senza segno in base ottale;
  • ‘s’: Stampa una [stringa];
  • ‘c’: Stampa un carattere;
  • ‘p’: Stampa un puntatore a void, in un formato definito dall’implementazione;
  • ‘n’ : Scrivi il numero di caratteri finora scritti correttamente in un parametro puntatore a intero;
  • ‘%’ : stampa un carattere ‘%’ (non accetta flag, precisione, lunghezza o larghezza).

Se la sintassi non è valida, il comportamento non è definito.

Definire caratteri non stampabili

Nella gestione di protocolli di comunicazione quando necessita eseguire l’output di caratteri ascii non stampabili, cioè caratteri con codici inferiori al 16#20 o superiori al 16#7F, occorre anteporre al valore esadecimale del carattere il simbolo $, quindi per il carattere di <STX> 16#02 avremo la definizione ‘$02’, per <ETX> ‘$03’ e così di seguito. Ricordo che alcuni caratteri di controllo come il line feed, codice 16#0A, sia possibile definirli sia come ‘$0A’ che come ‘$l’. Il carriage return, codice 16#0D, è possibile definirlo sia come ‘$0D’ che come ‘$r’, di seguito un elenco:

  • $a: Bell (speaker beeps)
  • $b: Backspace (non-erase)
  • $f: Form feed/clear screen
  • $l: Line feed (Esempio ‘next $l line’)
  • $n: New line
  • $p: New page
  • $r: Carriage return (Esempio ‘Hello$r’)
  • $t: Tab
  • $v: Vertical tab
  • $$: Dollar sign (Esempio ‘I paid $$5 for this’)
  • $’: Single quote (Esempio ‘Enter $’Y$’ for YES’)
  • $”: Double quote
  • $hh: Hexadecimal character code hh (Esempio ‘ABCD=$41$42$43$44’)

Esempi

Come utilizzare gli esempi.
Per meglio comprendere come definire il segnaposto, riportiamo alcuni esempi.

LogicLab (Ptp116, ST_HowToUsePrintf)
PROGRAM ST_HowToUsePrintf
VAR
    Nr : INT; (* Number of returned chars *)
    FPVar : UDINT; (* Fixed point variable *)
    LIVar : LINT; (* Signed long integer variable *)
    ULVar : ULINT; (* Unsigned long integer variable *)
    FLVar : REAL; (* Floating point variable *)
    LRVar : LREAL; (* Long real variable *)
    SVar : STRING[ 32 ]; (* String variable *)
    SOut : STRING[ 32 ]; (* Output string *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_HowToUsePrintf"
// *****************************************************************************
// Here some examples how to use the format field in printf function.
// -----------------------------------------------------------------------------

    // Fixed point variable print.

    FPVar:=12; //Fixed point variable
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%d'), UDINT_TYPE, ADR(FPVar)); //Nr:2, SOut:"12"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%1d'), UDINT_TYPE, ADR(FPVar)); //Nr:2, SOut:"12"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%4d'), UDINT_TYPE, ADR(FPVar)); //Nr:4, SOut:"  12"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('% 4d'), UDINT_TYPE, ADR(FPVar)); //Nr:4, SOut:"  12"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%-4d'), UDINT_TYPE, ADR(FPVar)); //Nr:4, SOut:"12  "

    // Floating point variable print.

    FLVar:=12.543; //Floating point variable
    LRVar:=LREAL#12.543; //Long real variable
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%f'), REAL_TYPE, ADR(FLVar)); //Nr:9, SOut:"12.543000"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%.4f'), REAL_TYPE, ADR(FLVar)); //Nr:7, SOut:"'12.5430"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%4.2f'), REAL_TYPE, ADR(FLVar)); //Nr:5, SOut:"12.54"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%5.2f'), REAL_TYPE, ADR(FLVar)); //Nr:5, SOut:"12.54"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%8.1f'), REAL_TYPE, ADR(FLVar)); //Nr:8, SOut:"    12.5"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%-8.1f'), REAL_TYPE, ADR(FLVar)); //Nr:8, SOut:"    12.5"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%.16lf'), LREAL_TYPE, ADR(LRVar)); //Nr:19, SOut:"'12.5430002212524414"

    // Long integer variable print.

    LIVar:=-1234567890123456789; //Signed long integer variable
    ULVar:=12345678901234567890; //Unsigned long integer variable
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%lld'), LINT_TYPE, ADR(LIVar)); //Nr:20, SOut:"-1234567890123456789"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%llu'), ULINT_TYPE, ADR(ULVar)); //Nr:20, SOut:"12345678901234567890"

    // String variable print.

    SVar:='Hello!'; //String variable
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%s'), STRING_TYPE, ADR(SVar)); //Nr:6, SOut:"Hello!"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%16s'), STRING_TYPE, ADR(SVar)); //Nr:16, SOut:"          Hello!"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%-16s'), STRING_TYPE, ADR(SVar)); //Nr:16, SOut:"Hello!          "
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%.3s'), STRING_TYPE, ADR(SVar)); //Nr:3, SOut:"Hel"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%16.3s'), STRING_TYPE, ADR(SVar)); //Nr:16, SOut:"             Hel"
    Nr:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%-16.3s'), STRING_TYPE, ADR(SVar)); //Nr:16, SOut:"Hel            "

// [End of file]
Was this article helpful?