Win32のCSV読み取りで文字化けする理由が分かりません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

トピックに返信する


答えを正確にご入力ください。答えられるかどうかでスパムボットか否かを判定します。

BBCode: ON
[img]: ON
[flash]: OFF
[url]: ON
スマイリー: OFF

トピックのレビュー
   

展開ビュー トピックのレビュー: Win32のCSV読み取りで文字化けする理由が分かりません

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#32

by かずま » 5年前

wbuf と n2 の値を尋ねているに、返事がありませんね。
かずま さんが書きました:
5年前
ステップ実行も知らずに、やれ表示できないとか、文字化けするとか
言っているプログラマのなんと多いことか。
sujiniku さんが書きました:
5年前
いろいろと知らないから不具合が起きるので質問を聞いてるんですけど?
質問サイトで質問して、何が悪いんですか?
「日本語を表示できないとか、文字化けするとかいう問題はステップ
実行によって、理由が分かりますよ」という意味で言っているのに、
「質問サイトで質問することは悪い」という意味だと邪推するのは
飛躍が過ぎます。
sujiniku さんが書きました:
5年前
ステップ実行を使いこなして、文字化けの原因を特定できてバグ修正できるなら、そもそも質問をしないと思うですが?
そうですね。ステップ実行を使いこなして、文字化けの原因を特定
できてバグ修正できた人が質問をしないのは当然です。

ところが、ステップ実行をして、文字化けの原因となる場所を特定
できても、バグ修正できないこともあります。

例えば、fgets(str1, 100, fp); を実行して、str1 が
<文字列中に無効な文字があります。> と表示されたら、
「文字化けの原因となる場所はここだ」と特定できますよね。

でも、「なぜ fgets が失敗するのか」は分からないことがあります。
そんな時、質問するのを悪いという人は誰もいないと思います。

ただ、質問をする時は、十分な情報を付けてください。
読んでいるファイルの内容と、読み込んだ後の str[0], str[1], ...
fgets に至るまでの、ソースコード。

できればプログラム全体のソースをつけることが望ましいのですが、
それができないのであれば、そのバグに無関係な部分を削除しても
バグが再現できるようなコードを付けてもらえると
回答が得られやすくなるでしょう。

何もソースがないと、
str1 のサイズが 100 より小さいんじゃないの?
オープンに失敗して fp が NULL なんじゃないの?
ぐらいしか言えなくて、正しい回答が得られなくなります。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#31

by かずま » 5年前

オフトピック
#14 の毒舌の元ネタは NHK の番組「チコちゃんに叱られる!」です。
好奇心旺盛でなんでも知っている5歳の少女・チコちゃんが、岡村隆史をはじめとする大人の解答者たちに、「いってらっしゃーいってお別れするとき、手を振るのはなぜ?」「かんぱーいってするときにグラスをカチンとするのはなぜ?」といった、素朴かつ当たり前過ぎてかえって答えられないような疑問を投げ掛ける。正解できなかった大人は、顔を真っ赤にして目から黄色い炎を出し、頭から白い湯気を汽笛音とともに噴き出すチコちゃんに「ボーっと生きてんじゃねえよ!」と叱られてしまうという雑学番組。
森田美由紀(NHKアナウンサー) - ナレーション。「そんなことも知らずに、やれ○○だとか、○○などと言っている日本人のなんと多いことか」「今こそ全ての日本国民に問います!」と“全国民”に対して上から目線で淡々と毒を吐くスタイルだが、これは「NHKスペシャル風にやってほしい」とのリクエストに応じたもので、水高満NHKチーフプロデューサーによると「おちゃらけたバラエティーのナレーションではなくて、真面目に淡々と読む、だけど言っていることは変、という方が面白いというのがあって、“ザ・NHK”に読んでもらった方が、その面白さが増すと思い、森田アナにお願いすることになった」とのこと。
今夜 19:57 から、または明日の朝 8:15 から見てください。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#30

by usao » 5年前

#む? 貼ったコード内の改行がいくつか失われた模様
オフトピック
プロジェクトの設定を「マルチバイト文字セットを使う」側にして
「文字列をcharの配列で表す」という世界でやるという選択肢だってありだと思うけど,いかんのかな.
OpenCV使ってるとファイル名とかにconst char*を求められるから,そうすることが多いんだけど.

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#29

by usao » 5年前

(1)VisualStudioでWin32プロジェクトを新規に作る → ビルドするとウィンドウが出るコードが生成される
(2)てきとーに外部変数に wchar_t WStr[100]; とか追加
(3)_tWinMain()のど頭に以下を記述

コード:

{
    setlocale(LC_ALL, "");
    FILE *fp = fopen( "Test.txt", "r" );        char Buff[100];
    fgets( Buff, 100, fp );     mbstowcs(WStr, Buff, 100);
    fclose( fp );
}
(4)ファイル Test.txt は メモ帳 でANSIで保存.内容はとりあえず

コード:

コボルト,12,6,10,5
(4)ウィンドウプロシージャのWM_PAINTにTextOutW()を記述

コード:

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    // TODO: 描画コードをここに追加してください...
    TextOutW( hdc, 30,30, WStr, 4 );    //Add this line only
    EndPaint(hWnd, &ps);
    break;
私の環境では,これでとりあえずウィンドウに「コボルト」と表示される.
日本語だからどうのという問題は発生していないように見える.

#「勝手な絞り込み」はしません.

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#28

by かずま » 5年前

かずま さんが書きました:
5年前
wbuf と n2 の値だけを教えてください。
wbuf の値の表示が変になっているかもしれないので、
「自動」の「名前」の wbuf の左の三角をクリックして、
wbuf[0], wbuf[1], ... を n2 の個数まで、教えてください。
値が 10進表示の場合は、右クリックで「16進数で表示」を選んでください。
str1 も同様に str1[0], str1[1], ... があったほうが望ましい。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#27

by かずま » 5年前

#14 で、ふざけたことを書いて、そのせいで、
炎上してしまったことをお詫びいたします。

さて、#14 ですが、ふざけたこと「だけ」を書いているのではありません。

「なんで、TextOut にブレークポイントを置いて、
wbuf や n2 の値を確認しないの?」

これが私の回答の主旨です。

sujinikuさんが、wbuf と n2 の値はこれこれですよ、
と返事してくれれば、問題の解決に近づけたと思います。

前のトピックでは、

1. fgets で char str[100] に読み込むときは、ファイルの
 文字コードが ANSI(Shift-JIS) でないといけない。
2. mbstowcs で文字コードの変換を行うためには setlocale が必要。

この 2点で日本語の文字化けの問題は解決しました。

それを前提に、新たな文字化け問題として、このトピックが立てられました。

タイトルに「理由が分かりません」とあるので、
#3 で、「文字化けの理由」を詳しく説明しました。
そして、修正案も付けました。

#6 で sujiniku さんは、一番知りたかった文字化けの理由に
納得したのかどうか全く返事していません。

返事をする代わりに、修正案で文字化けすると言っています。

文字化けしないはずの修正版で文字化けするのなら
その「理由」を調べて回答しなければならないでしょう。

そのためには、こちらの知りえない情報が必要です。
情報というのは変数の値の変化です。

そこで、『今初めて「シングルステップ実行」という言葉を知りました。
具体的な方法が分かりません。』という言葉に応えて、
#7 で、変数の値の変化を知る方法を詳しく説明しました。

実は、「ステップ実行」という言葉は「初めて」ではありません。
前のトピックの #14 で Yuo さんが「ステップ実行と合わせて,
IDEでの開発の基本知識になります。」と言っているのです。

sujiniku さんは、理由が知りたいのであって、デバッグの仕方を
知りたいのではないと思ったのかこれを無視されたようです。

「ステップ実行」が分からなければググってみてください。

1. その1 デバッグの超基本「ステップ実行」
2. ステップ実行とは「分かりそう」で「分からない」でも「分かった」気になれる
3. シングルステップ実行とは - IT用語辞典 Weblio辞書

などと出てきます。どれも分かりやすい説明になっています。

#10 で、ステップインを繰り返した sujiniku さんは、
なぜか kanma_pos の情報しか教えてくれません。

そこで、#11 で、「すべての変数の値の変化を見ていますか?
konma_pos だけ見て、str1 は見ていないのではありませんか?」
と質問しました。

#13 で sujiniku さんは、入力ファイルが Unicode であることを告白しました。
解決したはずの文字化けの起こる理由の一つです。

ここで質問です。
入力ファイルの文字コードが ANSI でないと気付いたのは str1 の値を
見たからではないのですか?

さらに、文字コードを ANSI に戻したのに『日本語の文字表示ができません』
という怪現象。

そこで、#14 で、wbuf や n2 の値を問いました。しかし、
私がふざけたことを付け加えたせいか、返事はもらえませんでした。

『皮肉に付き合うつもりはありません』という言葉に反して、
長大な文章で皮肉に付き合っているではありませんか。

皮肉に付き合わずに、wbuf と n2 の値を提示するだけでいいのに、
それをしないのはなぜですか?

『あなたが、もし、回答されないつもりの質問を返事を保留されると、
私がほかの掲示板サイトで同じ内容の質問をしづらくなりますので、
もしメンドウで回答したくなら、即座にハッキリとそういってください。』

これは意味がよく分かりません。

『「絞り込んでください」とは言っておらず、私は最初から、
「理由が分かりません」ので理由を「教えてください」と頼んでいます。』

理由を教えるには、どこに文字化けの原因があるのかを調べるための
絞り込みが必要です。
「理由を教えてください」と要求することは
「絞り込んでください」と言っているのと同じです。

『もし理由が分からないなら、まず先に、「私には理由が分からないので、
こういう方法で原因を探ってください」というような回答をすべきだと思います。』

ブレークポイントを設定したり、ステップ実行をして、変数の値の変化を
見てください、と回答してるのがそれにあたりませんか?

長くなるのは嫌なので、
wbuf と n2 の値だけを教えてください。
よろしくお願いいたします。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#26

by usao » 5年前

オフトピック
これは完全に善意のアドバイス.

他の場でこの内容の質問を行う際には,
「答えが欲しいのであって,答えにたどり着くための方法を教えてもらいたいわけではない」旨を最初に断った方がよい.
(個人的な偏見(?)では,プログラム系の質問では,このような場合にはデバッグ方法に関する回答がなされる率が高いので,同じことになることが危惧される)

また,同一の内容を複数の個所で質問すると
「マルチポスト」とだけ指摘されて終わってしまうことになりがちなので,
ここのURLを提示して「別の箇所で質問したけども,らちがあかなかった」旨を述べた方がよい.

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#25

by 結城紬 » 5年前

sujiniku さん

あくまで自分の行動には一点の瑕疵もないという主張で押し通すおつもりのようですが、
冷静になって考えていただきたいのですが、それで sujiniku さんは得をしますか?
目の前の問題は解決しますか? 自分のスキルは向上しますか? しませんよね

ご自分の主張をされるのは結構ですが、まずは暴言を吐いたことを謝罪すべきではないでしょうか。
sujiniku さんは社会人だと思いますが、多分学生であろうかずまさんに対してする態度ではないでしょう。
かずまさんは、教え方は拙いですが、この掲示板では教える意欲がある方です。
親しくない人に通じるかどうかわからない冗談を言ったのは悪かったと思いますが、それを責め立ててご自分の正当性を訴えたところで、
sujiniku さんとかずまさんのやり取りを見て、この掲示板で sujiniku さんの質問に答えようという人は、もう誰もいないでしょうね。
それで損をするのは、sujiniku さんであって、我々ではありません。

名を変え場所を変えれば逃げおおせると思っているかもしれませんが、心を入れ替えなければ何度でも同じ過ちを繰り返しますよ。
はっきり言って、日本のサイトでC言語の質問に答えてくれる場所なんて数えるほどしかありません。
「初心者」への心からのアドバイスです。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#24

by たいちう » 5年前

> 何故あなたの考えるところの良いログを実現するための努力を,回答を書く側だけに求めるのか?

初心者にとってとっつきにくいということは、我々経験者の怠慢であるとお考えなのでしょう。
この推測があってても間違ってても、私では意思の疎通は無理なようです。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#23

by usao » 5年前

そのような考えをお持ちなのであれば,
自身のコードを提示する時点で,コードの各所に関して「何でこのように書いているのか」の理由を明記した方がよろしいのでは?
あなたのコードを見た人が
> なんで mbstowcs が 3つもあるの?
とかならないように.

また,掲示板を見る他の初心者のことまで気に掛けるのであれば,
回答に不明瞭な点がある場合には,推測とか察するとかで終わらせずに,
その時々でその回答をした相手に不明瞭な点を問うとよいのでは.
(あなたの推測が正しくて話がそのまますんなり終わってしまったとしたら,まさにあなたが危惧する「初心者に理解できないログ」だけが残る事態になるのだから)

何故あなたの考えるところの良いログを実現するための努力を,回答を書く側だけに求めるのか?

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#22

by sujiniku » 5年前

そもそも初心者には、
Unicode などの文字コードやwchar_tなどのワイド型などを意識してプログラムすべきと、ある回答者たちが言ったあとで、
なぜ、ANSIコードでエンコードしたテキストファイルの読み取りソースコードでchar型で型宣言したコードを提示するのかさえ、
初心者には、理解できないでしょう。

なぜ、char型で宣言するのかさえ、
理由がまともに説明されておりません。


私は勝手に推測して、
「おそらく、初心者むけのC言語入門書にはchar型のコードが書いてあるし、
Windowsでは標準設定ではchar型でANSIの読み取りをできるから、
なるべく、それを使ってコードを書くのが、初心者には書きやすいだろう。」と回答者が配慮したと推測し、

そして回答者に、「char型に対応してない関数を呼び出す場合には、その都度、型変換を使ってchar型からwchar_tなどに変換させるように、初心者には、やらせよう。」
という考えがあるのだろうと、私は勝手に察しました。


ですが、私以外の初心者には、そこまで事情を察せないかもしれません。


すると、せっかく掲示板を読みにきた初心者には理解できず、役立たないかもしれません。

質問掲示板だから、初心者が読みにくるわけです。
初心者がコードの仕組みを理解できるように、回答文に理由を書かなければなりません。

だから、私は、私以外の今後の質問書にも役立つようにと「理由を教えてほしい」と、言ってるわけです。


理由がないコードは、応用が聞きません。仕組みが説明されておらず分からないと、ちょっとでも使用条件が変わると、そのままでは使えなくなってしまいます。

プログラマー業界で「デバッグされてないコードは負債である」という格言がありますが、
さしずめ、「理由の説明のないコードも、負債である」と感じます。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#21

by usao » 5年前

要するに,
【自分ではデバッグ作業とか一切やりたくないんだからお前ら勝手にバグ見つけて俺に教えやがれ.無料で.】
という主張ですよね.

理由を見つける方法の話とかいらねーから,最初から理由だけをよこせ と.
じゃあ,他者はあなたにその理由を教えるために,どうやってその理由を見つけるんだろうね?
バグの理由を見つけるのには一般に絞り込み作業が必要だと思う.
理由だけをよこせ という主張は,他人に絞り込み作業をやらせていることに他ならないと思うんだが.
でもそれは相手が勝手にやったことだ!と.

ぐだぐだ言っているけど,ただのクレクレ君ですやん.くだらねぇ.

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#20

by sujiniku » 5年前

絞り込んでいく作業すら他人にやらせるの?

やらせてもませんよ?
あなた方が、自発的に絞り込んだんですよ?

「絞り込んでください」とは言っておらず、私は最初から、「理由が分かりません」ので理由を「教えてください」と頼んでいます

私から言えば、「理由を教えて」と言ってるのにかかわらず、理由以外の回答をされており、ハッキリいうと、質問内容を無視されてるような感じさえ受けます。

もし理由が分からないなら、まず先に、「私には理由が分からないので、こういう方法で原因を探ってください」というような回答をすべきだと思います。

自発的にボランティア(絞込み)をすること自体は結構なことですが、
感謝を強制されるのは、
恩着せがましいと思います。
そういうのは、偽善者です。

まるで、発展途上国とかに行くと、観光客目当ての現地人が、頼んでないのに荷物を持ち運んだあとに、観光客に代金をせびるような人たちがいますが、
そういう人種と同レベルです。

あなたがたの偽善性に失望しました。


もしかしたら、「バグ原因の絞込みをすべき」という、そのような自主規制がこの掲示板にあるのかもしれませんが、しかし、そのような自主規制があるとすれば、その自主規制を設置した人はあなたがたであり、私ではないのです。私に、自主規制の責任はないのです。

もし自主規制の負担への不満を、質問者に不満をぶつけるべきではないと思います。
自主規制がツライなら、自主規制を改訂すべきだし、それはあなたがた運営ボランティア自身が決定すべきです。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#19

by usao » 5年前

オフトピック
> CSVファイル読み取りなどの仕事でも使う機会の多いコードの解説サイトとか

個人的には,「C言語でCSV読む」機会とかまず存在しない感だが……

仮に,世間一般に於いてはそのような機会がすこぶる多いのだとしても,
「よーし,CSVファイル読んじゃうぞー」となった時点でやるべきことは明らかだし,何か特別難しいアルゴリズムとかが必要な話でもないので,解説に値する事柄が乏しい題材なんじゃないかな.
(Stateパターンの話で例としてCSV読込を取り上げているものは見かけたことはある)

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#18

by たいちう » 5年前

#14は、かずまさんの悪ふざけだったと思いますが、
それ以前は、すごく丁寧に回答してくれていましたよね?
ソースコードも書いてくれているし、デバッガの使い方も説明してくれている。
繰り返し変数の値を確認するように書いてくれています。
なぜ無視するのですか?

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#17

by usao » 5年前

#14の言い回しは,あれっすよ.TV番組ネタ.

そもそもプログラマは教育者じゃないし,ましてボランティアで教育活動をすること求められる筋合いは無いんじゃないかなぁ.
(何か,東京オリンピック的な考えですね.)


まぁそれはそれとして……

苦言的な(?)ことを言えば,
ステップ実行という調査手段が得られたなら
「TextOutの出力結果を見て異常だったら,真っ先にTextOut時点でのデータの中身をチェックするっしょ」
というのは,なんというか,一般に期待される事柄だとは思うのですよね.
(そして,当然ながら,中身がおかしいならばその原因追及を行うことも)
要するに,
> 変数の値の変化を丁寧に見ないのはなぜですか?
これなんですよね.
デバッグ方法を教わった後でもまだ
【どうやら問題はこの行の処理による.
 直前まではデータが真っ当なのだが,ここでイカれた結果になる.
 しかし,なぜこの行の記述でそのような結果が生じるのか,その理由は……】
とかなんとか,絞り込んでいく作業すら他人にやらせるの?

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#16

by sujiniku » 5年前

ステップ実行も知らずに、やれ表示できないとか、文字化けするとか
いろいろと知らないから不具合が起きるので質問を聞いてるんですけど?
質問サイトで質問して、何が悪いんですか?

ステップ実行を使いこなして、文字化けの原因を特定できてバグ修正できるなら、そもそも質問をしないと思うですが?

あ、皮肉だろうとは思いますけど、皮肉につきあうつもりはありません。


私がわからないことは、私だけが分からないんじゃなくって、私と同様に分からない初心者が多いと思うから、あえて質問を繰り返しています。

いちおう私の手元にソフトバンク「やさしいC」とか、実教出版「プログラミング技術」とか書籍があって、それらでC言語の文法を確認しながら、書籍に書いてないことや解説不足の箇所を質問をしています。



もし、質問が多すぎて回答がめんどくさいなら、私に「ここから先はしらべるとか、ほかのサイトで質問してください」とか言ってください。

私はひとことも即日回答してくれ、なんて頼んでないし、「あなただけに質問したい」とも言ってません。

あなたが、もし、回答されないつもりの質問を返事を保留されると、
私がほかの掲示板サイトで同じ内容の質問をしづらくなりますので、
もしメンドウで回答したくなら、即座にハッキリとそういってください。


また、このため、もし回答しないまま数日が過ぎれば、回答の拒否と受け取らせていただきます。(そして2ちゃんねる等のほかの掲示板で質問をします。)

もし回答したくない旨を伝えられえば、2ちゃんねる掲示板など他のwebサイトで質問しますので。



書店で売られてる一般的なC言語の入門書に書いてない専門的な質問をその専門の掲示板で質問して、
「悪い」とは思いませんし、
もし、それを悪いとする文化が、この掲示板にあるなら、それは間違っていると思います。

「質問サイトで質問に答えるのが嫌なら、なんで、回答してるんですか?」というのが、私の感想です。


たとえるなら、教育では、大人が当然に知ってることだって子供は知らないから、教育ではそれを教えるのが仕事なように、
初心者が知らないだろうことを教えるのが教育でしょう?

Win32APIとかVisual Studio とかは、それらの入門書に書いてないので、質問をしてるんですよ?


私の感想は、短刀直入にいえば、「もとをただせば、既存のプログラマが、Win32APIや初心者むけのVisual Studioの使い方の情報共有や教育活動をサボッテるんでしょ?」ってのが、率直な私の感想です。


例えば書店でWin32APIの本を買おうにも、そもそも、その本自体が出版点数が少なく、マイクロソフト公式ヘルプの内容を写しただけの内容になってて、初心者の分からないところを何もおしえてなかったり・・・


本来なら、既存のプログラマが、ネットでWin32APIの教育サイトを作ったり、90年代くらいの古くなったWin32APIのサイト内容を更新したり、
C言語の解説サイトでもCSVファイル読み取りなどの仕事でも使う機会の多いコードの解説サイトとかを作るべきだと思いますが・・・・

そういう教育活動を日本のプログラマがサボって来てるんだと思います。


「じゃあ、お前がやれよ」っていわれるかもしれないけど、だから私は既に自分でC言語やWin32APIの教育サイトを作るために質問していますし、実際、某所の教育ボランティアwebサイトでC言語の教育サイトを作成しています。(プログラム以外の数学や理科の教科書は、すでに作成しております。それらが終わったので、プログラム教育の教材の作成に入りました。)

私が2018年のいままでプログラムをしてなかったのは、そもそも職業がプログラマではないからです。(前職はアナログ電気機械の技術者です。)

私は、2018年の6月くらいにWin32APIのプログラミングを初めたばかりの初心者です。

あなたがたが職業外の半導体造装置のガスパネル制御とかの仕組みとかを詳しく知らないように、
私にも職業外のWindowsプログラミングの知識が、ほとんどありません。

私は「半導体製造装置の仕組みをしらないのに、パソコンの質問をするな。」とか言いません。
私にかぎらず、日本のアナログ技術者や理系の科学者は、そういうことを言いません。

なのに、なんでプログラミング業界では「〇〇の仕組みをしらないのに、プログラミングの質問をするな」とかという回答が、まかり通ってるんでしょうか?


そもそも、私のようなGUIアプリを作り始めたばかりの初心者でも、出版市場にWin32の解説書が少ないことに気づいたりするのに、
なのに職業プログラマがWin32API解説の普及活動をサボってきたんだろうと思います。


あと、TextOutのブレークポイントは、しらべてないんじゃなくって、ブレークポイントのステップ実行をおしえて貰ったときに、ついでに調べたけど、そのときの質問内容とは違うので、そのときは報告しませんでした。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#15

by usao » 5年前

職場で笑っちゃったじゃないですか…

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#14

by かずま » 5年前

今こそ、すべてのプログラマに問います!

なんで、TextOut にブレークポイントを置いて、
wbuf や n2 の値を確認しないの?

ボーっとデバッグしてんじゃねーよ。

ステップ実行も知らずに、やれ表示できないとか、文字化けするとか
言っているプログラマのなんと多いことか。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#13

by sujiniku » 5年前

テキストファイルの文字コードを Unicode に変えたままだったので、読み込みできてなかったようです。
ANSIに戻したところ、自動ペインで下記のように値を読み込みました。

kanma_pos 0x0046f81c ",2,2,1,2\n"
str1 0x0046f814 "スライム,2,2,1,2"

しかし、相変わらず、TextOutによる日本語の文字表示ができません。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#12

by かずま » 5年前

かずま さんが書きました:
5年前
str1 は最後に '\n' を含んでいますから、
konma_pos が NULL になるはずがありません。

そのコードでデバッグしていますか?
その前に、'\n' を削除するコードを残したままではありませんか?
ちょっと勘違いしていました。次のように訂正します。

str1 が ',' を含んでいたら、
kanma_pos が NULL になるはずがありません。

すべての変数の値の変化を見ていますか?
kanma_pos だけ見て、str1 は見ていないのではありませんか?

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#11

by かずま » 5年前

sujiniku さんが書きました:
5年前
このとき、自動ペインのkanma_pos の値は赤く変わりますが、値は

コード:

0x00000000 <NULL>
です。
「次のように修正すると改善するでしょう」の
ソースでは、fgets(str1, 100, fp); で取得した
str1 を処理するのは、

コード:

	char *kanma_pos = strchr(str1, ',');
	if (kanma_pos) *kanma_pos = '\0';  // erase first ','
	n2 = mbstowcs(wbuf, str1, 100);
の 3行だけです。
str1 は最後に '\n' を含んでいますから、
konma_pos が NULL になるはずがありません。

そのコードでデバッグしていますか?
その前に、'\n' を削除するコードを残したままではありませんか?
すべての変数の値の変化を見ていますか?
konma_pos だけ見て、str1 は見ていないのではありませんか?

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#10

by sujiniku » 5年前

ステップインをクリックしてください。
現在の行を 1ステップだけ実行し、次の行で停止します。
kanma_pos が変化し、",2,2,1,2\n" と赤く表示されます。
ステップインを1回クリックすると、次の行としてか, string.h が表示されます。

コード:

_Check_return_
    inline char* __CRTDECL strchr(_In_z_ char* const _String, _In_ int const _Ch)
    { 4ミリ秒経過
        return const_cast<char*>(strchr(static_cast<char const*>(_String), _Ch));
    }
のように表示されます。そして、4ミリ秒のところに赤い枠の白抜きの矢印カーソルが合わさっています。
この時点では、自動、ローカル、ウォッチをみても、kanma_pos がありません。

つづけて3回、さらにステップインを押すと、もとのソースの行に戻り、

コード:

char *kanma_pos = strchr(str1, ','); ≦3ミリ秒経過
の行に矢印が合わさります。この時点では、自動ペインにある kanma_pos は、まだ赤くなっていません。

このときの kanma_pos の値は

コード:

0xcccccccc <文字列の読み取り中にエラーが発生しました。>
です。

もう1回、ステップインすると、

コード:

if (kanma_pos) *kanma_pos = '\0';  // erase first ','
の行に赤白の矢印が移ります。
このとき、自動ペインのkanma_pos の値は赤く変わりますが、値は

コード:

0x00000000 <NULL>
です。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#9

by かずま » 5年前

かずま さんが書きました:
5年前
ブレークポイントをたくさん置いて、複数の行を実行することを
マルチステップ実行というかどうかは知りません。
ブレークポイントで停止した後、数行先を右クリックすると、
「カーソル行の前まで実行」というのが出てきますね。
これがマルチステップ実行かもしれません。

また、ソースのペインと、「自動」のペインの配置は、左右でも
上下でもなんでも構いません。自分の好みで配置しましょう。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#8

by かずま » 5年前

かずま さんが書きました:
5年前
ツールバーの「緑色の右ボタン」をクリックして、実行を開始します。
「緑色の右向き▶ボタン」です。

ツールバーのボタンをクリックする代わりに、
F5 や F11 などのファンクションキーを使ってもいいし、
「デバッグ」メニューから選択することもできます。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#7

by かずま » 5年前

sujiniku さんが書きました:
5年前
今初めて「シングルステップ実行」という言葉を知りました。具体的な方法が分かりません。

コード:

	char *kanma_pos = strchr(str1, ',');
	if (kanma_pos) *kanma_pos = '\0';  // erase first ','
	n2 = mbstowcs(wbuf, str1, 100);
}
char *kanma_pos = strchr(str1, ','); の行にブレークポイントを設定し、
ツールバーの「緑色の右ボタン」をクリックして、実行を開始します。

停止したところで、タブをドラッグしたりして、真ん中のペインに
ソース、右側のペインに「自動」が表示されるようにしましょう。
str1 の値が分かりますね。"スライム,2,2,1,2\n" となっていませんか?

ツールバーの「茶色の■」の右の方に、矢印が 4つありますね。
そこにマウスカーソルを持っていくと、
「ステップイン(F11)」や「ステップオーバー(F10)」などが表示されます。

ステップインをクリックしてください。
現在の行を 1ステップだけ実行し、次の行で停止します。
kanma_pos が変化し、",2,2,1,2\n" と赤く表示されます。

ステップインをクリックすると、
現在の行を 1ステップだけ実行し、次の行で停止します。
*kanma_ps は '\0'、kanma_ps は "" になり、
str1 は "スライム" になりました。

ステップインをクリックすると、mbstowcs() が実行され、
n2 が 4 に、wbuf が L"スライム" になります。

このように 1行ずつ実行することをシングルステップ実行と言います。
ブレークポイントをたくさん置いて、複数の行を実行することを
マルチステップ実行というかどうかは知りません。

ステップインとステップオーバーの違いは自分で調べてください。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#6

by sujiniku » 5年前

次のように修正すると改善するでしょう。
試してみましたが、相変わらず日本語だけ文字化けします。

テキストファイルの文字コードはANSIで試しています。
なおテキストファイルの文字コードをUnicodeにすると、TextOutしても何も表示されません。

プロジェクトのプロパティの文字コードは、Visual Studioの標準設定のまま、Unicodeにしています。

シングルステップ実行で、
変数の値の変化を丁寧に見ないのはなぜですか?
今初めて「シングルステップ実行」という言葉を知りました。具体的な方法が分かりません。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#5

by かずま » 5年前

これからも質問が続きそうなので。

コード:

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h> // wsprintf
#include <stdio.h>   // fopen_s, fclose, fgets
#include <stdlib.h>  // mbstowcs
#include <string.h>  // strchr
#include <locale.h>  // setlocale

#include <string>    // wstring
#include <list>
using namespace std;

struct Entry {
	wstring name;                // 名前
	int hp, quick, gold, value;  // 最大HP, 素早さ, ゴールド, 経験値
};
list<Entry> data2;

void onCreate(HWND hwnd)
{
	FILE *fp;
	if (fopen_s(&fp, "test.txt", "r")) return;

	char str1[100];
	fgets(str1, 100, fp);

	while (fgets(str1, 100, fp)) {
		char *p = strchr(str1, ',');
		if (!p) break;
		*p = '\0';  // erase first ','
		wchar_t wbuf[100];
		size_t n2 = mbstowcs(wbuf, str1, 100);
		Entry e;
		e.name = wstring(wbuf, wbuf + n2);
		sscanf(p + 1, "%d,%d,%d,%d", &e.hp, &e.quick, &e.gold, &e.value);
		data2.push_back(move(e));
	}
	fclose(fp);
}

void onPaint(HWND hwnd)
{
	PAINTSTRUCT ps;
	HDC hdc = BeginPaint(hwnd, &ps);
	int i = 0;
	for (auto& e : data2) {
		wchar_t wbuf[100];
		size_t n2 = wsprintf(wbuf, L"%s: 最大HP = %d, 経験値 = %d", e.name.c_str(), e.hp, e.value);
		TextOut(hdc, 30, 80 + 30 * i++, wbuf, n2);
	}
	EndPaint(hwnd, &ps);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
	switch (msg) {
	case WM_CREATE:  onCreate(hwnd); break;
	case WM_PAINT:   onPaint(hwnd); break;
	case WM_DESTROY: PostQuitMessage(0); break;
	default: return DefWindowProc(hwnd, msg, wp, lp);
	}
	return 0;
}

int WINAPI wWinMain(HINSTANCE h, HINSTANCE p, LPWSTR cl, int cs)
{
	setlocale(LC_ALL, "");  // for mbstowcs 
	WNDCLASS wc = { 0, WindowProc, 0, 0, h, NULL,
		LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, L"wc" };
	if (!RegisterClass(&wc)) return 0;
	if (!CreateWindowEx(WS_EX_COMPOSITED, L"wc", L"Title",
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		80, 60, 640, 480, NULL, NULL, h, NULL)) return 0;
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#4

by かずま » 5年前

かずま さんが書きました:
5年前
strncpy を実行すると、
wordsss は、先頭「4バイト」が置き換えられて、
"スライムフフフフフフ..." になります。
すみません。先頭「8バイト」に訂正します。

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#3

by かずま » 5年前

sujiniku さんが書きました:
5年前

コード:

	char *n_pos = strchr(str1, '\n');
	if (n_pos) *n_pos = '\0';  // erase '\n'
	n2 = mbstowcs(wbuf, str1, 100);

	mbstowcs(wbuf, str1, 100);
	
	char wordsss[100]; // 一時的な変数
	char *kanma_pos = strchr(str1, ',');
	//	if (kanma_pos) *kanma_pos = '\0';  // erase '\n'
	strncpy(wordsss, str1, kanma_pos - str1);
	//
	n2 = mbstowcs(wbuf, wordsss, (kanma_pos - str1) / sizeof(char));
なんで mbstowcs が 3つもあるの?
wbuf には、L"スライム" を入れたいんじゃないの?

最初の mbtowcs で、
wbuf には、L"スライム,2,2,1,2" が入り、
n2 には、12 が入ります。

次の mbtowcs で
wbuf に、L"スライム,2,2,1,2" を入れなおします。

strncpy を実行するとき、
wordsss は、"フフフフフフ..." です。
デバッグビルドでは未初期化の変数の各バイトには
0xcc が入るからです。
str1 は、"スライム,2,2,1,2" です。
kanma_pos - str1 は、8 です。

strncpy を実行すると、
wordsss は、先頭「4バイト」が置き換えられて、
"スライムフフフフフフ..." になります。

n2 = mbstowcs(wbuf, wordsss, (kanma_pos - str1) / sizeof(char));
を実行するとき、
wbuf は、L"スライム,2,2,1,2" です。
wordsss は、"スライムフフフフフフ..." です。
(kanma_pos - str1) / sizeof(char) は 8 です。

n2 = mbstowcs(wbuf, wordsss, (kanma_pos - str1) / sizeof(char));
を実行すると、
wbuf は、先頭「8文字」が置き換えられて、
L"スライムフフフフ,1,2" になります。

文字化けするのは当然です。

次のように修正すると改善するでしょう。

コード:

	fopen_s(&fp, "test.txt", "r");

	fgets(str1, 100, fp);
	fgets(str1, 100, fp);
	fclose(fp);

	char *kanma_pos = strchr(str1, ',');
	if (kanma_pos) *kanma_pos = '\0';  // erase first ','
	n2 = mbstowcs(wbuf, str1, 100);
ブレークポイントで停止した後、シングルステップ実行で、
変数の値の変化を丁寧に見ないのはなぜですか?

Re: Win32のCSV読み取りで文字化けする理由が分かりません

#2

by Bull » 5年前

Visual Studio のプロジェクトには“Unicode 文字セットを使用する”と“マルチ バイト文字セットを使用する”があります。
プロジェクトのプロパティーの[全般]→[文字セット]で設定できます。

“Unicode”にすると、プリプロセッサで "UNICODE" が定義され、“マルチ バイト”にすると、プリプロセッサで "_MBCS" が定義されます。

詳細は今さら聞けない、教えてもらえない!! Unicode /マルチバイト文字対応 国際化VC ++ プログラミングの基礎!!などを参照してください。

その他に大事なこととして、Win API の関数が切り替わるということです。
API には ANSI 文字バージョンとワイド文字バージョンがある関数が多数あります。
TextOut 関数も "UNICODE" が定義されているか否かによって、TextOutW と TextOutA のどちらかが呼ばれます。
TextOutA にワイド文字列を渡しても、文字化けしてしまいます。
プログラムを作るときは文字セットを常に意識する必要があります。

プログラムの内部の文字列や関数はこれらのマクロによって切り替えが可能ですが、外部のデータ (テキストファイルなど) はそうはいません。データを読込んで、プログラムで文字コードを判断するのが一番いいのでしょうが、Shift_JIS とか UTF-8 とか決めてしまってもいいのかもしれません。

Windows の内部コードは UNICODE ですし、「プログラム内部では、常に文字列は wchar_t (UNIDOE) で扱う。読込んだデーはその時点で変換して、wchar_t に格納する」としてしまった方が、楽かもしれません。

ちなみに、マルチバイト (Shift_JIS/UTF-8) のファイルを読込んで、wchar_t (の配列) に格納する方法はいくつかあります。

下記のプログラムは UTF-8 で書かれたテキストファイルを読込みます。

コード:

#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <stdlib.h>

int main(void)
{
	setlocale(LC_ALL, "");

	char file_name[260] = "test.txt";
	FILE *fp;
		
	if (fopen_s(&fp, file_name, "r,ccs=UTF-8") == 0) {
		wchar_t buff[256];
		while (fgetws(buff, _countof(buff), fp)) {
			wchar_t *p;
			wchar_t *context;

			for (p = wcstok(buff, L",\n", &context); p; p = wcstok(NULL, L",\n", &context)) {
				wprintf(L"%ls ", p);
			}
			wprintf(L"\n");
		}
		fclose(fp);
	} else {
		perror(file_name);
	}

	return 0;
}

Win32のCSV読み取りで文字化けする理由が分かりません

#1

by sujiniku » 5年前

結論から言うと、CSVの英数字を読み取れるファイルを作りましたが、しかし日本語が読み取れず、(私が)困っており、私に教えてください。

なお、ReadFileは用いていないので、前トピックのReadFileのトピックとは別に、新規のトピックを作成しました。

下記のようなCSVファイルを作成しました。

test.txt

コード:

名前,最大HP,素早さ,ゴールド,経験値
slime,2,2,1,2
コボルト,12,6,10,5

これを読み取ろうと、まず、2行目1列目のモンスター名「slime」を読み取るつもりのプログラムを書きました。(slimeだけモンスター名が英語なのは、日本語にすると表示がバグるから。このバグを解決したい。)


まず、インクルードやグローバル変数の宣言は

コード:

#include <stdio.h>   // fopen_s, fclose, fgets
#include <stdlib.h>  // mbstowcs
#include <string.h>  // strchr
#include <locale.h>  // setlocale

#pragma warning(disable:4996)


wchar_t wbuf[100];
size_t n2;
となっており、

wWinMain では

コード:

 // TODO: ここにコードを挿入してください。

	FILE *fp;
	char str1[100];
	// char str2[100];


	fopen_s(&fp, "test.txt", "r");

	fgets(str1, 100, fp);
	fgets(str1, 100, fp);
	fclose(fp);

	char *n_pos = strchr(str1, '\n');
	if (n_pos) *n_pos = '\0';  // erase '\n'
	n2 = mbstowcs(wbuf, str1, 100);

	mbstowcs(wbuf, str1, 100);



	char wordsss[100]; // 一時的な変数
	char *kanma_pos = strchr(str1, ',');
	//	if (kanma_pos) *kanma_pos = '\0';  // erase '\n'
	strncpy(wordsss, str1, kanma_pos - str1);
	//
	n2 = mbstowcs(wbuf, wordsss, (kanma_pos - str1) / sizeof(char));
としました。

WM_PAINT では

コード:

// TODO: HDC を使用する描画コードをここに追加してください...
            
				TextOut(hdc, 30, 80, wbuf, n2);
を作成しました。

テストした結果、英数字は読み取りできて「slime」と座標 (30,80) の位置に表示できるのですが、
しかしテキストファイルの「slime」を「スライム」と日本語にすると、文字化けをします。

最終的に、日本語が表示できないと、日本人向けのアプリケーションにならないので、なんとかしたいのです。

ページトップ