お世話になります。
VC++6.0ダイアログベースで作成中ですが、forの使い方について伺いたいと思っており
ます。
ファイルから1行ずつ読み込む際に、
for( i=0; i<100; i++){
file.ReadString( ss );
}
としていますが、この時ssに入るのは1行目、2行目・・・
となるのか、
1行目をループし続けるのか、いまいちわかりません。
どなたかアドバイスを頂けないでしょうか。
宜しくお願いします。
えーと。
fileがどんなクラスのインスタンスなのか明記されていません。
コードを書き込むにしてもそこに出てくる変数がどんなクラス、
または型なのかがわかるように提示してください。
で、多分CStdioFileクラスだろうと言う仮定で書きますが、
ファイルを操作する場合、その時点のファイル上の現在位置を保持する
用になっていて、基本的にこの手のファイルを読み込んだり、
書き込んだりする関数はその操作を行った分だけ現在位置を動かします。
ですから、ReadStringを実行すると読み込んだ分だけ現在位置を動かし、
次のReadStringは移動後の現在位置から読み込みを行ないます。
多分、わかっていると思いますが、
上記の処理だとファイルの行数に関わりなく、100行分読み込む処理に
なっているので途中でファイルの終端に達しても100回関数の呼び出しが
行なわれる事になりますね。
あと、この手の疑問はまずは自分で動かしてみて確認した方が早いです。
特に今回の処理は読み込みなのでファイルを壊す可能性も低いですしね。
ファイルの書き込みとかファイルを削除してしまうような操作だと
大事なファイルを書き換えてしまったり、消してしまったりしないように
注意しないといけませんけれど。
なんか、バラバラ書き込んでいますが、
今回の内容ならforの使い方ではなくてCStdioFile::ReadStringの使い方と
言うべきだと思いますよ。
この手の処理はこれで無いと駄目と言うのは無いと思いますけれど、
定番の処理方法と言うのはあるのでその辺はWeb上で調べてみると
出てくると思います。
指定されたファイルを最後まで読みたいのであれば、
forループよりもwhileループの方が向いているような気もします。
ご回答ありがとうございます。
書き込むのは初めてなもんで、色々お手数をかけて申し訳ないです。
ちなみに今作っているのは、csvファイルよりデータを読んで各行3列目の数字により、
別ファイルにアルファベットを書き込むということを考えてます。
ofstream fout;
char ch[2];
CString str;
int i;
CStdioFile file( test.csv, CFile::modeRead );
fout.open( test.DAT, ios::out );
for( i=0; i<100; i++ ){
file.Seek( 6, CFile::current );
file.ReadString( ch, 2 );
str = ch;
if( str = 0 ){
fout << A;
}
if( str = 1 ){
fout << B;
}
}
file.Close();
fout.close();
としたのですが、書き込みファイルには5つくらいしかデータがなかったです。
Seekの使い方が間違っている気がしますが、原因がわかりません。
宜しくお願いします。
話の内容からして、CSVファイルのフォーマットが分からないと何とも答えよう
がないかも。
> file.Seek( 6, CFile::current );
6バイト先がいったいどういうフォーマットなのか?
> ちなみに今作っているのは、csvファイルよりデータを読んで各行3列目の数字によ
り、
各行3列目の数字がどういうフォーマットなのか?
> 別ファイルにアルファベットを書き込むということを考えてます。
どういうフォーマットで何を書き込むのか?
あと、分からないときは、複数の問題を一気に片付けようとしない方が良いです。
今は CStdioFile と ofstream の双方を同時に検証しようとしているようですが、
まずは、CStdioFileのカタをつけましょう。
出力先を cout とか TRACE にして、正しくファイルを読み込めていることを確認
してから、改めて ofstream に再チャレンジしましょう(^-^)
0,0,1,0,0,0
0,0,0,0,0,0
11,0,0,0,0,0
↑
ここを読み込みたい
という仕様にするつもりなのですが、例えば途中が2桁になってるとこの方法では対応で
きないことに気づきました。
もう少し考えてみようと思います。
CString strLine;
file.ReadString( strLine);
CString strNum;
AfxExtractSubString( strNum, strLine, 2, _T(',')); // , で区切られた3番目の値
int nValue = ::_tstoi( strNum);
という方法もある。
私もFlatWestさんの考え方の方がやりやすいと思いますよ。
読み込みのところでコントロールするより、
毎回一行分読み込んで、後の処理はメモリ上で行った方が
デバッガで確認したりもしやすいですし。
処理をうまく分割して各処理を独立させる感じで組み上げると
後から見た時に処理が分かりやすくなりますし、
問題がある部分の特定もやりやすくなります。
今回のケースなら、読み込み部分で細工をするより、
読み込みは単純に一行分読み込む。
読み込んだら、次の処理でカンマで分解する。
分解した情報から必要な情報を参照して処理をする。
という風に処理を分けてしまった方が分かりやすいです。
また、カンマで分解する部分の処理は関数化しておくと
他の時に流用できたりしますしね。
他の人に見せるつもりが無いとしても
コメントを処理ごとに入れるように癖をつけておくと
後々、自分で自分のソースを読むハメになった時に
かなり役に立ちます。
今回のソースは短いようですけれど、
長いソースになると自分で書いたソースでも
後で見た時は他人のソース(良く分からない)なんて事も
ありますからね。
あと、デバッガを活用しましょう。
うまく使うとおかしな動きをしている所を
早く見つける事が出来ます。
せっかくデバッガが使える環境なんですから
どんどん活用しましょう。
PATIOさん,bunさん,FlatWestさん,ありがとうございます。
おかげさまで解決できました!
質問内容以外のところでもアドバイスを頂いて,大変助かりました。
またお世話になると思いますが,宜しくお願いします。