MFC CStringの中身をファイルに書き出したいのですが。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
かなたん
記事: 50
登録日時: 12年前
連絡を取る:

MFC CStringの中身をファイルに書き出したいのですが。

#1

投稿記事 by かなたん » 12年前

Windows7でVisual Studio 2008を使ってMFCプログラミングをしています。
マインスイーパーのハイスコアを記録させたいと思い、CString型を含むデータをファイルに書き込みたいと思っています。
データは以下のようなものです。
[hr]初級
プレイ回数0 クリア回数0 クリア率0% 連勝数0 連敗数0 現在0
1. 999 名無し 0000/00/00 00:00:00
2. 999 名無し 0000/00/00 00:00:00
3. 999 名無し 0000/00/00 00:00:00
4. 999 名無し 0000/00/00 00:00:00
5. 999 名無し 0000/00/00 00:00:00
6. 999 名無し 0000/00/00 00:00:00
7. 999 名無し 0000/00/00 00:00:00
8. 999 名無し 0000/00/00 00:00:00
9. 999 名無し 0000/00/00 00:00:00
10. 999 名無し 0000/00/00 00:00:00
中級
―以下略―
[hr]
見てわかるとおり、全角と半角が混ざっています。
スペースはすべて全角です。
それが原因なのか、書き込みがうまくいきません。

コード:

CStdioFile fout(L"time.score",CFile::modeCreate | CFile::modeWrite );
for(int n=0;n<3;n++){
	fout.WriteString((CString)grade[n]+L"\n"); //char grade[3][5]
	fout.WriteString((CString)numbers[n]+L"\n"); //char numbers[3][100]
	for(int m=0;m<10;m++){
		fout.WriteString(recordsc[n][m]+L"\n"); //CString recordsc[3][11]
	}
}
fout.Close();
とすると
[hr]1.2.3.4.5.6.7.8.9.10.1.2.3.4.5.6.7.8.9.10.1.2.3.4.5.6.7.8.9.10.
[hr]
となり、全角だけでなくそれ以降全てが無視され、改行もされません。

コード:

CStdioFile fout(L"time.score",CFile::modeCreate | CFile::modeWrite );
for(int n=0;n<3;n++){
	str=L"";
	str=(CString)grade[n]+L"\n";
	fout.Write(str.GetBuffer(),str.GetLength());
	str=L"";
	str=(CString)numbers[n]+L"\n";
	fout.Write(str.GetBuffer(),str.GetLength());
	for(int m=0;m<10;m++){
		str=L"";
		str=recordsc[n][m]+L"\n";
		fout.Write(str.GetBuffer(),str.GetLength());
	}
}
fout.Close();
とすると、
[hr]Rラ0・0゙Vpe1 00・0゙Vpe0 00・0s1 . 09 9 9 0
T!qW0 00 0 0 0 /2 . 09 9 9 0
T!qW0 00 0 0 0 /3 . 09 9 9 0
T!qW0 00 0 0 0 /4 . 09 9 9 0
T!qW0 00 0 0 0 /5 . 09 9 9 0
T!qW0 00 0 0 0 /6 . 09 9 9 0
T!qW0 00 0 0 0 /7 . 09 9 9 0
T!qW0 00 0 0 0 /8 . 09 9 9 0
T!qW0 00 0 0 0 /9 . 09 9 9 0
T!qW0 00 0 0 0 /1 0 . 09 9 9 0
T!qW0 00 0 0 0 -Nラ0・0゙Vpe0 00・0゙Vpe0 00・01 . 09 9 9 0
T!qW0 00 0 0 0 /2 . 09 9 9 0
T!qW0 00 0 0 0 /3 . 09 9 9 0
T!qW0 00 0 0 0 /4 . 09 9 9 0
T!qW0 00 0 0 0 /5 . 09 9 9 0
T!qW0 00 0 0 0 /6 . 09 9 9 0
T!qW0 00 0 0 0 /7 . 09 9 9 0
T!qW0 00 0 0 0 /8 . 09 9 9 0
T!qW0 00 0 0 0 /9 . 09 9 9 0
T!qW0 00 0 0 0 /1 0 . 09 9 9 0
T!qW0 00 0 0 0
Nラ0・0゙Vpe0 00・0゙Vpe0 00・01 . 09 9 9 0
T!qW0 00 0 0 0 /2 . 09 9 9 0
T!qW0 00 0 0 0 /3 . 09 9 9 0
T!qW0 00 0 0 0 /4 . 09 9 9 0
T!qW0 00 0 0 0 /5 . 09 9 9 0
T!qW0 00 0 0 0 /6 . 09 9 9 0
T!qW0 00 0 0 0 /7 . 09 9 9 0
T!qW0 00 0 0 0 /8 . 09 9 9 0
T!qW0 00 0 0 0 /9 . 09 9 9 0
T!qW0 00 0 0 0 /1 0 . 09 9 9 0
T!qW0 00 0 0 0
[hr]
となり、文字化けでうまくいきません。
改行位置も思っていたものと違いますし・・・

どのように書けばCString型などの全角を含む文字列を正しい改行で書き込むことができるでしょうか?
プログラミングにおいて全角と半角が混じっていたら文字化けを起こす可能性があるのは知っていますが、この場合もあきらめないといけないでしょうか?
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: MFC CStringの中身をファイルに書き出したいのですが。

#2

投稿記事 by へにっくす » 12年前

コード:

str=(CString)grade[n]+L"\n";
char[]をそのままCStringにキャストしようとしているのがそもそもの間違い。
以下を参考にしましょう。
方法 : さまざまな文字列型間で変換する
written by へにっくす

かなたん
記事: 50
登録日時: 12年前
連絡を取る:

Re: MFC CStringの中身をファイルに書き出したいのですが。

#3

投稿記事 by かなたん » 12年前

へにっくす さんが書きました: char[]をそのままCStringにキャストしようとしているのがそもそもの間違い。
間違いなんですね。
今はじめて知りました。
デバッグでCStringの中身を見てみると正しい内容が入っていたので、問題ないと思っていました。
紹介してもらったページを参考に以下のように変えてみました。

コード:

CStdioFile fout(L"time.score",CFile::modeCreate | CFile::modeWrite );
for(int n=0;n<3;n++){
	CString cg(grade[n]);
	cg+=L"\n";
	fout.Write(cg.GetBuffer(),cg.GetLength());
	CString cn(numbers[n]);
	cn+=L"\n";
	fout.Write(cn.GetBuffer(),cn.GetLength());
	for(int m=0;m<10;m++){
		recordsc[n][m]+=L"\n";
		fout.Write(recordsc[n][m].GetBuffer(),recordsc[n][m].GetLength());
	}
}
fout.Close();
でも、出力結果に変わりはないようでした。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: MFC CStringの中身をファイルに書き出したいのですが。

#4

投稿記事 by へにっくす » 12年前

コードを見るにWCHARの文字列を使用している(文字列にLを使用している)ようですが、grade、numbersの定義がchar[]なのはおかしいと思いませんか。
以下を参考にしましょう。
char *文字列とwchar_t *文字列の相互変換
またCStdioFileは基本MBCSの出力のようですね
以下のページはVS2005ですが2008でも当てはまると思います。
CStdioFileにて全角がファイルに書けない?
written by へにっくす

かなたん
記事: 50
登録日時: 12年前
連絡を取る:

Re: MFC CStringの中身をファイルに書き出したいのですが。

#5

投稿記事 by かなたん » 12年前

へにっくす さんが書きました:コードを見るにWCHARの文字列を使用している(文字列にLを使用している)ようですが、grade、numbersの定義がchar[]なのはおかしいと思いませんか。
それもダメですか?
やっぱり今回ファイルからの読み込みをfscanfでやっていることもよくないんでしょうね・・・
初めにfscanfでgrade・numbers・recordsというcharの配列に読み込んでいます。
gradeは書き換えないのでそのまま、numbersは書き変わりますが数値をいじるだけなので分解していじってくっつけるで型はそのまま、recordsだけはクリアーしたときにタイムを記録させるときにCTimeのFormatを使うとCStringが帰ってくることなどからrecordscというCStringに入れています。

C++はC言語と同じ書き方ができると教わり、MFCやっていてもベースはC言語で・・・
WCHARって単語も今初めて知りました。
UNICODE使ってるからよ_Tマクロを使うようにと教わり、どこかでLを先頭に書けばいいというのを見て、私はマクロの代わりにそっちを使ってます。

教えてもらったページを参考に書き込み部分を_wsetlocale(LC_ALL, _T("jpn"));と_wsetlocale(LC_ALL, _T(""));で囲ってみました。
CStdioFileとWriteの組み合わせでは相変わらずでしたが、以下のようにCStdioFileとWriteStringの組み合わせでは文字化けになることなく正しい位置で改行されました。
ありがとうございました。

コード:

_wsetlocale(LC_ALL, _T("jpn"));
CStdioFile fout(L"time.score",CFile::modeCreate | CFile::modeWrite );
for(int n=0;n<3;n++){
	CString cg(grade[n]);
	cg+=L"\n";
	fout.WriteString(cg);
	CString cn(numbers[n]);
	cn+=L"\n";
	fout.WriteString(cn);
	for(int m=0;m<10;m++){
		fout.WriteString(recordsc[n][m]+L"\n");
	}
}
fout.Close();
_wsetlocale(LC_ALL, _T(""));
MFC編 - テキストファイルの入出力を見てUNICODEを使っているからWriteのほうがいいんだと思っていました。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

アバター
バグ
記事: 130
登録日時: 14年前
住所: 愛媛県
連絡を取る:

Re: MFC CStringの中身をファイルに書き出したいのですが。

#6

投稿記事 by バグ » 12年前

解決はしているようなので、あくまで個人的な趣味の話ですが・・・。
数値→文字列変換はCStringクラスのメンバであるFormat関数を使うと非常に楽です。

閉鎖

“C言語何でも質問掲示板” へ戻る