wstring (または wchar_t)の出力がうまくいかず困っています。
基本的な質問になるかと思いますがよろしくお願いします。
#include <string>
#include <wchar.h>
using namespace std;
int main() {
wstring str = L"test";
wprintf(L"%s \n", str.c_str());//(1)
wprintf(L"%s \n", L"test");//(2)
wprintf(L"test \n");//(3)
// cout << str <<endl; //(4)
cout << str.c_str() <<endl;//(5)
}
出力結果
(1) t
(2) t
(3) test
(4) コンパイルエラー
(5)
望むのは当然(3)の出力です。
web上で(1)や(4)のような記述はみかけたのですが、(4)に関してはなぜコンパイルエラーになるかもわからず。。
os linux.
gcc 4.1.1
No.1ベストアンサー
- 回答日時:
> wprintf(L"%s \n", str.c_str());//(1)
> wprintf(L"%s \n", L"test");//(2)
c_strはワイド文字列のデータ本体をwchar_t *で返すのみ。"test\0"を返す訳ではない。
この場合、(1)も(2)も
wprintf(L"%s \n", (char *)((wchar_t *)"t\0e\0s\0t\0\0\0"));
に同じ。つまり
wprintf(L"%s \n", "t");
と書いたのと同じである。
書式sにwchar_t型文字列を引数に与える場合は、書式sにl修飾子を付加する事。
(1)、(2)は以下のようにすると正常に動作する筈。
wprintf(L"%ls \n", str.c_str());//(1)
wprintf(L"%ls \n", L"test");//(2)
> wprintf(L"test \n");//(3)
については解説不要。
> // cout << str <<endl; //(4)
#include <iostream>を記述する位置を適切な位置にしない限り、coutの実体であるstreambufの挿入演算子(<<)は、char *しか受けつけず、コンパイルエラーとなる。
> cout << str.c_str() <<endl;//(5)
c_strはワイド文字列のデータ本体をwchar_t *で返すのみ。"test\0"を返す訳ではない。つまり、
cout << "t\0e\0s\0t\0\0\0" <<endl;//(5)
と書いたのと等しく、更に言えば
cout << "t" <<endl;//(5)
と等しい。
この回答への補足
#2さんの補足欄のさらに補足です。
あちこち書く場所が飛んでしまって申し訳ありません。
> 文字化けは、端末のエンコードをEUC-JPに変更したら直りました。
半分嘘でした。
どうやら、/etc/locale.gen の ja_JP.EUC-JP のコメントアウトをはずしてlocale-gen した場合にそうなったようです。
ja_JP.UTF-8 の部分だけコメントアウトしてlocale-genし、
コード中にlocale("japanese") を locale("ja_JP.UTF-8") に変更したところ、例外は発生しなくなりました。が、やはり wcout << L"testテスト" の表示(端末のエンコード UTF8) が
test???
になってしまいます。端末のエンコードの問題ではなさそうです。
詳しいご解説ありがとうございます。
質問のソースコードでうまく行かない理由がよくわかりました。
さっそくwprintfにてフォーマット指定子%lsを使って表示を試みたのですが、日本語を含む場合の出力で文字化けしてしまいました。
ソースコード UTF8
端末のエンコード UTF8
で統一しており、perl で print "testてすと"; 等するとちゃんと端末上に文字化けせずに表示されるのですが・・。
No.2
- 回答日時:
(1)~(3)に関しては、#1の方の回答のとおりです。
(4)がコンパイルエラーになる理由ですが、std::coutすなわちstd::basic_ostream<char, std::char_traits<char> >型に対して多重定義されている<<の右オペランドは、const std::basic_string<char, std::char_traits<char>, std::allocator>&型(cons std::string&)であって、const std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator>&型(const std::wstring&)ではありません。多重定義されていないわけですから、当然エラーになります。
(5)に関しても同様で、右オペランドにconst char*を取る<<演算子は多重定義されていますが、const wchar_t*を取るものは課定義されていないため、const void*に変換されてしまいます。(表示されないのは変です。アドレス値が出るはずです。ただし、変なファセットを持つロケールをimbueしていない場合)
この回答への補足
お礼欄の補足です。
> 再度試してみましたがやはり何も表示されませんでした。
は wprintf した後の cout が表示されないというよく分らない現象のせいで、wprintfを全てコメントアウトしたら表示されました。
文字化けは、端末のエンコードをEUC-JPに変更したら直りました。
本当はUTF-8で吐いてほしいのですが・・
そこで、UNIXの話になってしまうのですが、locale("japanese")を含むプログラムが実行可能であったマシンの、/etc/locale.gen
ja_JP.UTF-8 UTF-8
をコメントアウトし、
# locale-gen
したら
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
Aborted
が表示されるようになってしまいました。現在その原因の調査中です。
ご回答ありがとうございます。
コンパイルエラーの理由、よくわかりました。
> 表示されないのは変です。アドレス値が出るはずです
については再度試してみましたがやはり何も表示されませんでした。
ロケール・imbueをキーワードに色々検索し、以下のページを参考に
#include <string>
#include <iostream>
#include <locale>
using std::wstring;
using std::wcout;
using std::endl;
using std::locale;
int main() {
wstring wstr = L"testテスト";
wprintf(L"%i \n", wstr.length());
wprintf(L"%ls \n", wstr.c_str());
wcout.imbue(locale("japanese"));
wcout << wstr <<endl;
wcout << L"testてすと" << endl;
}
をコンパイルして実行したところ、
7
test???
test???
test???
と文字化けを起こしてしまうのですが、原因がどうもわかりません。
端末の文字エンコードは UTF-8,ソースコードもUTF-8です。
また、このプログラムを異なる計算機(OS,gccのバージョンは同じです)で実行してみたところ、
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
Aborted
という例外を吐いてアボートしてしまいます。
環境がほとんど同じだけに、原因がわからずここでも躓いています。
locale("japanese") が通るように何か(環境の設定,ライブラリ等)他にしなければいけないことがあるのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C++初心者です stirng 2 2022/09/20 20:43
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# C++のcinの動作 5 2023/02/26 00:13
- Visual Basic(VBA) VBAでfunctionを利用しようとしたときに「引数は省略できません」というエラーが出ます 1 2022/10/15 16:30
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- Visual Basic(VBA) ブックのCOPY 4 2023/02/25 20:17
このQ&Aを見た人はこんなQ&Aも見ています
-
10代と話して驚いたこと
先日10代の知り合いと話した際、フロッピーディスクの実物を見たことがない、と言われて驚きました。今後もこういうことが増えてくるのかと思うと不思議な気持ちです。
-
人生最悪の忘れ物
今までの人生での「最悪の忘れ物」を教えてください。 私の「最悪の忘れ物」は「財布」です。
-
2024年に成し遂げたこと
今年も残すところわずか。 皆さんが今年達成したことを教えていただきたいです。 どんな小さなものでも構いません。
-
食べられるかと思ったけど…ダメでした
「この煮物、だいぶ放置しちゃったけど大丈夫かな…」 「食べ物じゃないけど、なんか食べたらすごく美味しそうな気がする」
-
我が家のお雑煮スタイル、教えて下さい
我が家のお雑煮スタイル、教えて下さい! (お汁)味噌汁系? すまし汁系? (お餅)角餅? 丸餅? / プレーンなお餅? あんこ餅?
-
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
「fatal error C1189」を回避するには?
C言語・C++・C#
-
wstringの内容を表示させたい
C言語・C++・C#
-
-
4
CStringをwchar_tに変換したい
C言語・C++・C#
-
5
std::stringからLPCWSTR型への変換
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・「黒歴史」教えて下さい
- ・2024年においていきたいもの
- ・我が家のお雑煮スタイル、教えて下さい
- ・店員も客も斜め上を行くデパートの福袋
- ・食べられるかと思ったけど…ダメでした
- ・【大喜利】【投稿~12/28】こんなおせち料理は嫌だ
- ・前回の年越しの瞬間、何してた?
- ・【お題】マッチョ習字
- ・モテ期を経験した方いらっしゃいますか?
- ・一番最初にネットにつないだのはいつ?
- ・好きな人を振り向かせるためにしたこと
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・2024年に成し遂げたこと
- ・3分あったら何をしますか?
- ・何歳が一番楽しかった?
- ・治せない「クセ」を教えてください
- ・【大喜利】【投稿~12/17】 ありそうだけど絶対に無いことわざ
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
構文エラーが出ているのですが...
-
C++でShowCursorを使いたい。
-
指定した文字を削除したい
-
【C++】複素数で配列を使いたい
-
VHDLのsignedとunsignedの違いは?
-
このプログラミング誰か教えて...
-
findnext();について
-
空ENTERの判別
-
JPEGやPNGが読めるLoadImage関数
-
string型の固定長文字列を配列...
-
C言語 ストリームについて。
-
#include "fstream.h"
-
C++のifstreamの使い方
-
atlbase.h と afxwin.hの同時定義
-
openCVで動画が読み込めないエ...
-
STL string::findで見つからな...
-
ある商品のロス率を5%見込み、...
-
最早開始時間と最遅完了時刻を...
-
信頼区間の1.96や1.65ってどこ...
-
「指定されたキャストは有効で...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
構文エラーが出ているのですが...
-
なぜ、C++の標準ヘッダをインク...
-
VC++で文字列から任意の文字を...
-
enumの値から定義名を文字列化...
-
switch文のエラーについて
-
指定した文字を削除したい
-
std::wstringのメモリリークに...
-
JPEGやPNGが読めるLoadImage関数
-
std::map の const 修飾について
-
#defineの使い方について
-
リモートデスクトップの接続元I...
-
構造体配列のvectorへの変換と...
-
VS2019でofstreamが未定義になる
-
gccでコンパイル時のエラー
-
C言語のポインターで詰まっている
-
C++のifstreamの使い方
-
空ENTERの判別
-
CStringとString
-
C言語のエラーを修正したい
-
VxWorks 6.4ソケット接続につい...
おすすめ情報