実現したいこと
MSVCコンソールプログラムで、標準入力からUTF-8エンコードされた文字列を入力したいです。
標準出力であれば、コードページを65001(UTF-8)にすることで対処できることが周知されています。
しかし、入力の場合にはそれでは正しく入力することが出来ませんでした。
どうすれば期待した動作にすることが出来るでしょうか。ご教授の程お願いいたします。
追記:「リダイレクトを使う」という回答を頂きましたが、あくまで標準入力にこだわる解決法もお願いいたします。
環境・前提
Windows 10 20H2
Visual Studio Community 2019 16.9.4
言語標準はC++17(/std:c++17
)です。
追加のオプションで/utf-8
を指定しています。
Windows 10のシステムロケールをUTF-8にする機能は使用していません。
症状
以下のことを行うコードを用意しました。
cmd.exe
のコードページを65001にする- 標準入力から
s
に入力をする s
の各バイトについて、ビットごとに出力するs
をそのまま標準出力に出力する
cpp
1#include <iostream> 2#include <string> 3#include <bitset> 4 5int main() 6{ 7 system("chcp 65001"); 8 9 std::string s; 10 std::cin >> s; 11 for (auto&& ele : s) { 12 std::cout << " " << std::bitset<8>(ele) << std::endl; 13 } 14 std::cout << s; 15}
実行結果です。a
に関しては問題ありませんでした。
しかし、あ
と思われる部分はデタラメかつ1バイトの値で、実行するごとに値が変わります。
cmd
1Active code page: 65001 2aあ 3 01100001 4 00110000 5a0
試したこと
疑ったのはロケールです。CRTの記事ですが、MSVCは".utf8"
で、utf8をコードページに出来るようです。
setlocale, _wsetlocale | Microsoft Docs
以下のコードを用い、std::cin
のロケールを変更して症状
と同じことを行いました。
が、実行結果では症状
と同様、あ
の部分がデタラメな1バイトの値になってしまっています。
cpp
1#include <iostream> 2#include <sstream> 3#include <string> 4#include <bitset> 5 6int main() 7{ 8 system("chcp 65001"); 9 10 std::cin.imbue(std::locale(".utf8")); 11 12 std::string s; 13 std::cin >> s; 14 for (auto&& ele : s) { 15 std::cout << " " << std::bitset<8>(ele) << std::endl; 16 } 17 std::cout << s; 18}
cmd
1Active code page: 65001 2aあ 3 01100001 4 11110000 5a
確認したこと
ところがstd::ifstream
やstd::istringstream
においては、正常に動作することが確認できました。
ですから、std::istream
が壊れていることは考えづらいです。ということは、cmd.exe
のUTF-8サポートが完全ではないのでしょうか。
以下のコードと、UTF-8エンコードのファイル(utf8_test.txt
、BOMなし)を用意して検証しました。
cpp
1// cmd.cpp 2 3#include <iostream> 4#include <sstream> 5#include <string> 6#include <fstream> 7#include <filesystem> 8 9int main() 10{ 11 system("chcp 65001"); 12 13 std::string s; 14 15 std::ifstream ifs(std::filesystem::path("D:/utf8_test.txt")); 16 ifs >> s; 17 std::cout << s << std::endl; 18 19 std::stringstream ss(u8"aあ"); 20 ss >> s; 21 std::cout << s << std::endl; 22}
txt
1aあ
cmd
1Active code page: 65001 2aあ 3aあ