it-swarm.com.de

Was ist der Unterschied zwischen printf ("% s"), printf ("% ls"), wprintf ("% s") und wprintf ("% ls")?

Betrachten Sie dieses Beispielprogramm:

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

Die Ausgabe davon ist:

1 narrow 
2 wide 

Ich frage mich:

  1. warum 3 & 4 nicht gedruckt hat
  2. was sind die Unterschiede zwischen 1 & 3 und 2 & 4.
  3. macht es einen Unterschied, ob narrowstr in utf8 und widestr in utf16 ist?
14
Display Name

Sie müssen tun:

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

Warum? Denn für printf sagt% s / schmale Zeichenfolge. Für wprintf sagt% ls weit.

Für wprintf bedeutet% s wide,% ls würde weit bedeuten.% hs würde eng (für beide) bedeuten. Für printf,% s bedeutet auf diese Weise einfach% hs

Unter VC++/Windows würde %S (Großbuchstabe S) den Effekt umkehren. Für printf("%S") würde das also wide bedeuten, und wprintf("%S") würde eng bedeuten. Dies ist nützlich für _tprintf.

9
Ajay

Beachten Sie, dass Sie C-Streams verwenden. C-Streams haben eine ganz besondere Qualität, die "Orientierung" genannt wird. Ein Stream ist entweder unorientiert, breit oder schmal. Die Orientierung wird durch die erste Ausgabe bestimmt, die für einen bestimmten Stream erstellt wurde (eine Übersicht über C I/O-Streams finden Sie unter http://en.cppreference.com/w/cpp/io/c - ).

In Ihrem Fall beginnt stdout unorientiert, und wenn Sie den ersten printf ausführen, setzen Sie ihn eng. Sobald es eng ist, bleibt es eng und wprintf schlägt fehl (überprüfen Sie den Rückkehrcode!). Die einzige Möglichkeit, einen C-Stream zu ändern, ist freopen it, was mit stdout nicht ganz funktioniert. Deshalb haben 3 und 4 nicht gedruckt.

Der Unterschied zwischen 1 und 3 besteht darin, dass 1 eine schmale Ausgabefunktion ist, die den engen String-Konvertierungsspezifizierer% s verwendet: Er liest Bytes aus dem Char-Array und sendet Bytes in einen Bytestrom. 3 ist eine Wide-Ausgabefunktion mit einem schmalen String-Konvertierungsspezifizierer% s: Sie liest zuerst Bytes aus dem Char-Array und mbtowcs in wchar_ts und sendet dann wchar_ts in einen Wide-Stream, in den sie dann wctombs eingebettet werden Bytes oder Multibyte-Sequenzen, die dann mit einem write in den Standardout verschoben werden

Wenn widestr in utf16 ist, müssen Sie Windows verwenden und alle Wetten sind deaktiviert. Über ASCII auf dieser Plattform hinaus wird kaum etwas unterstützt. Sie können auch WinAPI nachgeben und verwenden (Sie können mit Standard-C++ 11 für einige Unicode-Dinge auskommen und sogar diese C-Ausgabe mit den magischen Wörtern _setmode(_fileno(stdout), _O_U16TEXT); ausführen, das wurde oft genug diskutiert.)

5
Cubbi

Die Antworten zu 1 und 2 sind in der Frage in der Dokumentation. Jede gute Dokumentation wird ausreichen. Sie sagen, dass cppreference sehr gut ist.

Wie bei 3 gibt der Sprachstandard keine bestimmte Codierung für Zeichenfolgen oder eine bestimmte Größe von wchar_t an. Sie müssen die Dokumentation für Ihre Implementierung und nicht für die richtige Sprache konsultieren (obwohl das Schreiben von implementierungsabhängigem Code selten ratsam ist).

0
n.m.