CStringやCTimeがうまく使えていない?

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

CStringやCTimeがうまく使えていない?

#1

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

Visual Studio 2008を使ってMFCで30秒の間に4,1,3,2,4という数字の列を何回打つことができるかというプログラムを作っています。
30秒たった後に何回打つことができたのか(int clear)・何回失敗してしまったのか(int miss)・いつ開始したか(CTime cTime)を表示させるとともに、その結果をテキストファイルに出力させようとしています。
画面に表示させる結果はすべて1つのCString型変数に格納させたものを表示させるようにしています。
-------------------------
clear:クリア回数
miss:失敗回数
%Y/%m/%d %H:%M:%S
-------------------------
となるように書いたつもりなのですが、
-------------------------
clear:クリア回数↑miss:失敗回数↑
-------------------------
と表示されています。
なぜか"\n"が"↑"になって、cTime.Format("%Y/%m/%d %H:%M:%S")の部分は一切表示されていないようです。
テキストファイルにはまだいつ開始したかしか書き込むようにしていませんが、出来上がったファイルを見るとサイズが0バイトであり、何か書かれているように見えません。
何が原因なのでしょうか?

画面描画部分

コード:

CString str;
str.Format(L"clear:%d\nmiss:%d\n",clear,miss);
str=str+cTime.Format("%Y/%m/%d %H:%M:%S");
pDC->SetTextColor(RGB(0,0,0));
pDC->TextOutW(0,0,str);
テキスト出力部分

コード:

CStdioFile fout(L"practis.txt",CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate);
fout.SeekToEnd();
CString str;
str=cTime.Format("%Y/%m/%d %H:%M:%S");
fout.WriteString(str);
fout.Close();
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: CStringやCTimeがうまく使えていない?

#2

投稿記事 by みけCAT » 10年前

"clear:%d\nmiss:%d\n"や"practis.txt"の前にはLがついているのに、"%Y/%m/%d %H:%M:%S"の前にはついていません。
これはこういう書き方で大丈夫なのでしょうか?

"\n"が"↑"になる問題は、とりあえず\nを\r\nにしてみてください。
それでダメなら、表示の方法が改行に対応していないので、別の方法で表示することを考えましょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: CStringやCTimeがうまく使えていない?

#3

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

みけCAT さんが書きました:"clear:%d\nmiss:%d\n"や"practis.txt"の前にはLがついているのに、"%Y/%m/%d %H:%M:%S"の前にはついていません。
これはこういう書き方で大丈夫なのでしょうか?
参考にしたstr.Formatのサンプルでは_T("")を使っていた、L""を使うことにしました。
CTime.Formatのサンプルではそういうたぐいがなかったので特につけていません。
という理由でしかありません。
CTimeのほうは以前別のプログラムでこのような書き方をしていて、その時は特に問題なく出力ができたので、(たぶん)その書き方で大丈夫だと思っています。
str.Formatのほうは初めて使うのでまったく確信がないです。

{quote="\n"="みけCAT"]が"↑"になる問題は、とりあえず\nを\r\nにしてみてください。
それでダメなら、表示の方法が改行に対応していないので、別の方法で表示することを考えましょう。[/quote]


\r\nに変えてみたところ、↑ではなく見たことない記号(串刺しおでんみたいなやつ)が表示されました。
たぶん改行コードとしては認識されずにそういった記号として認識されたようです。
そこできちんと各行個別に描画するように書き換えてみました。

コード:

pDC->SetTextColor(RGB(0,0,0));
CString str;
str.Format(L"clear:%d",clear);
pDC->TextOutW(0,0,str);
str.Format(L"miss:%d",miss);
pDC->TextOutW(0,20,str);
str=cTime.Format("%Y/%m/%d %H:%M:%S");
pDC->TextOutW(0,40,str);
改行されているようには見えるようになりましたが、結局日時は表示されていませんでした。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: CStringやCTimeがうまく使えていない?

#4

投稿記事 by みけCAT » 10年前

かなたん さんが書きました:参考にしたstr.Formatのサンプルでは_T("")を使っていた、L""を使うことにしました。
CTime.Formatのサンプルではそういうたぐいがなかったので特につけていません。
という理由でしかありません。
CTimeのほうは以前別のプログラムでこのような書き方をしていて、その時は特に問題なく出力ができたので、(たぶん)その書き方で大丈夫だと思っています。
str.Formatのほうは初めて使うのでまったく確信がないです。
混ぜるのは良くないと思います。CTime.Format、str.Format共にこのプログラムではLをつけてみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: CStringやCTimeがうまく使えていない?

#5

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

みけCAT さんが書きました:混ぜるのは良くないと思います。CTime.Format、str.Format共にこのプログラムではLをつけてみてください。
CTime.FormatのほうにもLをつけてみましたが、それでも日時は表示されませんでした。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

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

Re: CStringやCTimeがうまく使えていない?

#6

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

CStringはTCHARを基に構成されているので、Unicode/MBCSで特に分ける必要がないのならば、必ず_T()を使うべきだと思います。
CTime.Formatについても同様です。
Unicode とマルチバイト文字セット (MBCS: Multibyte Character Set) のサポート
CTime::Format

コード:

pDC->SetTextColor(RGB(0,0,0));
CString str;
str.Format(_T("clear:%d"),clear);
pDC->TextOut(0,0,str);
str.Format(_T("miss:%d"),miss);
pDC->TextOut(0,20,str);
str=cTime.Format(_T("%Y/%m/%d %H:%M:%S"));
pDC->TextOut(0,40,str);
ちなみにTextOutは、改行などの文字は認識しません。認識させたいのならば、DrawTextを使用してください。
このことは、Win32APIのヘルプを見ればわかります。
DrawText関数
TextOut関数
written by へにっくす

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

Re: CStringやCTimeがうまく使えていない?

#7

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

へにっくす さんが書きました:CStringはTCHARを基に構成されているので、Unicode/MBCSで特に分ける必要がないのならば、必ず_T()を使うべきだと思います。
CTime.Formatについても同様です。
_T()やLを使う理由については知りませんでした。
最初_T()を習い、そのあとどこかでLを見てから_T()ではなくLを使っていました。
へにっくす さんが書きました:ちなみにTextOutは、改行などの文字は認識しません。認識させたいのならば、DrawTextを使用してください。
そうだったんですね。
これから改行付き文字列を描画させたい時はDrawTextを使うことにします。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: CStringやCTimeがうまく使えていない?

#8

投稿記事 by softya(ソフト屋) » 10年前

TCHARはマルチバイトとユニコードの文字列処理をコンパイル・オプションだけで切り替えるために必要な仕組みとしてマイクロソフトから提供されています。
で、マルチバイトとユニコードが混在すると文字コードの化けなどややこしいバグを発生させるので、_T()とLと""だけを混在させるのは危険です。
デバッグでもややこしくなります(デバッガで見ると一見問題がないように見えます)。

_T("") ... コンパイルオプションでマルチバイトとユニコードが切り替わるマクロ。
L"" ユニコード文字専用
"" マルチバイト文字専用

となっています。
使い分ける必然がないなら_T()で統一をしましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: CStringやCTimeがうまく使えていない?

#9

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

softya(ソフト屋) さんが書きました: 使い分ける必然がないなら_T()で統一をしましょう。
はい。
今まで文字列関連でビルドエラーになったら「Lつけないとだめか・・・」というスタンスでやってきてしまっていましたが、これからはどちらにせよきちんと_T()を使うことにします。
授業でLを教わらなかったのもこういうことのためなんでしょうね。

日時が表示できないことについてデバッグして調べてみました。

コード:

str=cTime.Format(_T("%Y/%m/%d %H:%M:%S"));
のときのstrを見てみると、str = ""と表示されました。
どうやらフォーマットした日時を取得できずにいるのかもしれません。
そこで、cTimeについても見てみました。
cTimeはCTime型の変数としてとりあえずでグローバル変数として定義してしまっています。
0秒目の時点で

コード:

cTime=CTime::GetCurrentTime();
として日時を取得しています。
その一行が実行される前はcTime = {m_time=0 }と表示され、実行された後はcTime = {m_time=1390028937 }と表示されたので、たぶん何かしらのデータは入っているのだと思います。
フォーマットの書き方は_Tマクロを使うことにした以外以前使ったものそのままなのですが、何が問題なのでしょうか?
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: CStringやCTimeがうまく使えていない?

#10

投稿記事 by ISLe » 10年前

ロケール(LC_TIME)を設定する必要があるのでは?

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

Re: CStringやCTimeがうまく使えていない?

#11

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

ISLe さんが書きました:ロケール(LC_TIME)を設定する必要があるのでは?
ISLeさんの指摘の通りでした。

コード:

_wsetlocale(LC_ALL, _T("jpn"));
等を追加したらうまくいきました。
しかも元のソースにはきちんとそれも書いてありました。
ありがとうございました。
わからないことも、ブログに書いているうちにひらめくこともある。
本当に行き詰ったら、考え直すのも1つの手かな。

閉鎖

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