質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

10313閲覧

日本語のテキストファイルを読み込んで出力したい

Parsley_068

総合スコア8

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/12/07 05:28

編集2019/12/07 06:27

##実現したいこと
C++で日本語のテキストファイルを読み込んで画面に出力させようと思っています。fopenでファイルを読み込んでfgetsでchar型の変数に格納するところまではできたのですが、出力結果が文字化けしてしまいます。
少し調べて日本語がマルチバイト文字のせいでアルファベットや数字と仕様が違うところまではわかったのですが、具体的にどうすれば文字化けを防げるかが分かりません。どうすれば文字化けせずに日本語のテキストファイルを読み込めるか教えてください。

##コード

C++

1int main() 2{ 3 FILE* fp; 4 const char fname[] = "text/tutolial.txt"; 5 char s[256]; 6 7 fp = fopen(fname, "r"); 8 9 10 if (fp == NULL)printf("FAILED"); 11 else printf("SUCCESS"); 12 13 while (fgets(s, 256, fp) != NULL) 14 { 15 printf("%s", s); 16 } 17 18 fclose(fp); 19
//tutolial.txt テスト てすと 試用

試したこと

fopen以外にもstd::ifstreamのほうも試してみましたがこちらも文字化けしました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

printfの使い方がぶっ飛んでるのはすでに指摘があるのでこれ以上触れないこととして本題。

C++で、またWindowsで動かすコンソールアプリケーションで適切に文字を取り扱うのは容易ではありません。
これは歴史的経緯もあります。
ref: C++標準化委員会、ついに文字とは何かを理解する: char8_t

Windows のコンソールアプリケーションは何もしないとシステムロケールで動作します。お使いの環境が日本語環境ならcp932(Shift-JIS)という文字コードで表示されます。つまりcp932(Shift-JIS)に含まれない文字(絵文字とかその他多数)を表示しようとすれば表現できませんから文字化けのように見えます。

またそもそもお示しのコードには文字コード変換部分が見受けられません。つまり、読み込んだテキストファイルの文字コードがシステムロケール(多分cp932)と一致しなければ文字化けします。

例えば読み込んだテキストがUTF-8でエンコードされていた場合、cp932とUTF-8でたまたま同じようにエンコードされる範囲(いわゆるASCII)以外は文字化けするでしょう。

読み込んだテキストがUTF-8でエンコードされていた場合にソースコードに手を加えず文字化けを防ぐ方法は最近まではありませんでしたが、Windows 10 1607以降ではchcp 65001とすることでプログラムが動作するロケールをcp932からUTF-8に切り替えられます(正確には昔からあったけどフォントが正しく設定できなかったので実質使えなかった)。chcp 65001の代わりに同等Win32API(SetConsoleCP)を叩いてもいいですが。ただし実行前にフォント設定をお忘れなく。

読み込んだテキストがUTF-8でエンコードされていた場合、こうすれば読み込んだテキストと動作環境のロケールが一致するので文字化けしなくなります。


それ以外のケースでは文字コード変換を行う必要がありますが、これはC/C++標準の範囲ではできず(C++11で追加されたもののC++17でdeprecatedになったため使えない)、Win32APIに頼る必要があります。ただしいかに変換しようともwchar_t系のAPIを叩こうと、コンソールアプリケーションで標準出力から出す限り最終的にシステムロケールの文字コードに内部で変換されますのでcp932で表わせない文字はchcp 65001相当のことをしなければ表現できないことに変わりはありません。

いずれにせよWindowsのコンソールアプリケーションで適切に文字を扱うのは依然として容易ではないのでときには諦めるほうが良かったりします。もしくはコンソールアプリケーションではなくGUIアプリケーションを作るほうが融通がききます。


C++側ではUTF-8でエンコードされた文字を格納することを意図したchar8_t型が追加され、WindowsのいわゆるA系APIもUTF-8に対応するようになりつつあります。あと10年位したらすべてがUTF-8な時代が来てこの辺が楽になるといいですね。

投稿2019/12/07 06:22

yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Parsley_068

2019/12/07 06:45

丁寧補足と解説をありがとうございます! UTF-8だとうまくいかないんですね...htmlは逆にUTF-8じゃないと文字化けしたので盲点でした...
yumetodo

2019/12/07 06:51

いえ、肝は > 読み込んだテキストファイルの文字コードがシステムロケール(多分cp932)と一致しなければ文字化けします です。それ以外では少なくとも常に文字コード変換コードを記述する必要があります。 DxLibを使えるんでしたら、SetUseCharCodeFormat(DX_CHARCODEFORMAT_UTF8);するとUTF-8で文字列を扱えて便利です(漢字異字体シーケンス以外の結合文字列には対応してないですが) ref: https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=4163 https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=view&no=4759
guest

0

printf(100, 100, "FAILED", -1);
printf(100, 100, "SUCCESS", -1);

これは何をしているつもりですか?100-1

こいつがでたらめなものを書くので、文字化けと勘違いしたのでは?

printfの使い方を勉強しましょう。
というか、何がしたいのか不明なので、printfが適当かどうかもわかりません。

とりあえず動かすなら、その2行を削除すればいいです。

投稿2019/12/07 05:41

編集2019/12/07 06:17
otn

総合スコア84555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Parsley_068

2019/12/07 06:31

すみません。引数指定間違えていました…直前までdxlibのdrawstring()関数を使っていたのでそちらと混合してしまいました。
otn

2019/12/07 14:48

ああ、なるほど。座標ですか。
guest

0

文字コードをUTF_8からANSIに変えたら文字化けせずに読み込めました!

投稿2019/12/07 06:41

Parsley_068

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問