web-dev-qa-db-ja.com

printf( "%s")、printf( "%ls")、wprintf( "%s")、および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;
}

この出力は次のとおりです。

1 narrow 
2 wide 

不思議なんだけど:

  1. 3と4が印刷されなかった理由
  2. 1&3と2&4の違いは何ですか?.
  3. narrowstrがutf8にあり、widestrがutf16にある場合、違いはありますか?
16
Display Name

あなたがする必要があります:

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

どうして? printfの場合、%sは、narrow-char-stringを表します。 wprintfの場合、%lsは広いと言います。

ただし、wprintfの場合、%sは広いことを意味し、-%lsはそれ自体が広いことを意味します。 %hsは狭くなります(両方とも)。 printfの場合、%sは、この方法では単に%hsを意味します

VC++/Windowsでは、_%S_(大文字のS)を使用すると、効果が逆になります。したがって、printf("%S")は幅が広く、wprintf("%S")は幅が狭いことを意味します。これは__tprintf_に役立ちます。

9
Ajay

Cストリームを使用していることに注意してください。 Cストリームには、「向き」と呼ばれる非常に特殊な品質があります。ストリームは、無指向、ワイド、ナローのいずれかです。方向は、特定のストリームに対して行われる最初の出力によって決定されます(C I/Oストリームの概要については http://en.cppreference.com/w/cpp/io/c を参照)

あなたの場合、stdoutは無指向で始まり、最初のprintfを実行することで、それを狭く設定しています。狭くなったら狭くなり、wprintfは失敗します(戻りコードを確認してください!)。 Cストリームを変更する唯一の方法は、それをfreopenすることです。これはstdoutでは十分に機能しません。そのため、3と4は印刷されませんでした。

1と3の違いは、1はナロー文字列変換指定子%sを使用するナロー出力関数です。char配列からバイトを読み取り、バイトストリームにバイトを送信します。 3は、幅の狭い文字列変換指定子%sを持つワイド出力関数です。最初に文字配列からバイトを読み取り、mbtowcsバイトを_wchar_t_ sに読み込み、次に_wchar_t_ sをワイドストリームに送信します。次に、それらをwctombsバイトまたはマルチバイトシーケンスに変換し、writeを使用して標準出力にプッシュします。

最後に、widestrがutf16にある場合、Windowsを使用している必要があり、すべてのベットがオフになっています。 ASCIIを超えるものに対するサポートはほとんどありません。WinAPIを提供して使用することもできます(Unicodeについては、標準のC++ 11を使用して、さらにはマジックワード_setmode(_fileno(stdout), _O_U16TEXT);を含むこのC出力、十分に議論されています)

6
Cubbi

質問の1と2に対する回答はドキュメントにあります。ドキュメントの適切なセットで十分です。 cppreference はとても良いと彼らは言う。

3に関しては、言語標準は文字列の特定のエンコーディング、または特定のサイズのwchar_tを指定していません。適切な言語ではなく、実装のドキュメントを参照する必要があります(実装に依存するコードを記述することはほとんどお勧めできません)。

0