2014-11-08 16 views
10

considerare questo programma di esempio:Qual è la differenza tra printf ("% s"), printf ("% ls"), wprintf ("% s") e wprintf ("% ls")?

#include <cstdio> 
#include <cwchar> 
#include <string> 

int main() 
{ 
    std::string narrowstr = "narrow"; 
    std::wstring widestr = L"wide"; 
    printf("1 %s \n", narrowstr.c_str()); 
    printf("2 %ls \n", widestr.c_str()); 
    wprintf(L"3 %s \n", narrowstr.c_str()); 
    wprintf(L"4 %ls \n", widestr.c_str()); 

    return 0; 
} 

L'output di questo è:

1 narrow 
2 wide 

mi chiedo:

  1. perché 3 & 4 non è stato stampato
  2. cosa le differenze sono comprese tra 1 & 3 e 2 & 4.
  3. fa alcuna differenza se narrowstr è in utf8 e widestr è in utf16?
+1

Hai letto il documentazione? In particolare di [cstdio] (http://www.cplusplus.com/reference/cstdio/)? –

+0

"widestr is in utf16" implica che stai usando Windows (più sistemi Unicode utilizzano UTF-32 come predefinito per le stringhe larghe). Ci sono molti arcani cerchi da saltare se vuoi fare qualcosa oltre l'ASCII su un sistema Windows usando standard C++ o C. Potresti anche cedere e usare WinAPI. – Cubbi

+0

NON DARE A MICROSOFT STUPIDITY. Salva te stesso il dolore e scrivi la tua libreria di stringhe. Per l'amore di dio NON usare le conversioni di windows e altre follia, fidati di me, è orrendo e nella confusione si insinuano tutti i tipi di errori. – Owl

risposta

0

Le risposte a 1 e 2 sono nella domanda sono nella documentazione. Qualsiasi buon set di documentazione funzionerà. Dicono che cppreference è molto buono.

Come per 3, lo standard di lingua non specifica alcuna codifica particolare per le stringhe o qualsiasi dimensione particolare di wchar_t. È necessario consultare la documentazione per la propria implementazione, piuttosto che per il linguaggio corretto (sebbene la scrittura di codice dipendente dall'implementazione sia raramente consigliabile).

5

Hai bisogno di fare:

wprintf(L"3 %hs \n", narrowstr.c_str()); 
wprintf(L"4 %s \n", widestr.c_str()); 

Perché? Perché per printf, % s si dice string-stringa stretta. Per wprintf, % ls dice largo.

Ma, per wprintf, % s implica ampia, % ls significherebbe ampia stessa. % hs significherebbe stretto (per entrambi). Per printf, % s, in questo modo significherebbe semplicemente % hs

On VC++/Windows, %S (S maiuscola), sarebbe invertire l'effetto. Pertanto per printf("%S") significherebbe largo e wprintf("%S") significherebbe stretto. Questo è utile per _tprintf.

+0

Anche questo non stampa nulla. [collegamento] (http://ideone.com/ZCiDb1) –

+0

Aspetta! Perché non sta nemmeno stampando i numeri ?? Hai controllato che wprintf funzioni? – Ajay

5

Nota che stai utilizzando flussi C. I flussi C hanno una qualità molto speciale chiamata "orientamento". Un flusso è o non orientato, largo o stretto. L'orientamento è deciso dalla prima uscita fatto per qualsiasi flusso particolare (v http://en.cppreference.com/w/cpp/io/c per una sintesi dei flussi CI/O)

Nel tuo caso, stdout inizia non orientato, e eseguendo il primo printf, si sta impostando lo stretto . Una volta stretto, è bloccato stretto e wprintf non riesce (controllare il suo codice di ritorno!). L'unico modo per cambiare un flusso C è freopen, che non funziona abbastanza con stdout. Ecco perché 3 e 4 non hanno stampato.

Le differenze tra 1 e 3 è che 1 è una funzione di uscita stretta che utilizza l'identificatore di conversione stringhe strette% s: legge byte dall'array di caratteri e invia byte in un flusso di byte.3 è una funzione di uscita ampia con un identificatore di conversione stringhe strette% s: prima legge i byte dal char array e mbtowc s in wchar_t s, quindi invia wchar_t s in un flusso ampio, che quindi wctomb s in byte o sequenze multibyte che vengono poi spinti nello standard con un write

Infine, se widestr è in utf16, è necessario utilizzare Windows e tutte le scommesse sono disattivate; c'è molto poco supporto per qualsiasi cosa al di fuori di ASCII su quella piattaforma. Puoi anche cedere e usare WinAPI (puoi cavartela con lo standard C++ 11 per alcune cose Unicode, e persino fare questo output C, con le parole magiche _setmode(_fileno(stdout), _O_U16TEXT);, che è stato discusso abbastanza volte)

Problemi correlati