Version 5.10
ifstream をもっと使う!
「この前は、ファイルからデータを読み取る方法を簡単に見てみました」
『 ifstream ってゆーの使ったんだよね』
「そう、こんな感じ」
void CFileTestDlg::OnBtnShow()
{
int i;
std::ifstream cIFStrm;
cIFStrm.open( "Data.txt" );
cIFStrm
>> i;
char chDest[256];
sprintf( chDest, "%d", i );
m_cDataLstBox.AddString( chDest );
}
「この関数には色々問題があるから、その辺を改良していきます」
『ん? ぱっと見問題なさそうだけど』
「まず Data.txt がなかったときの問題」
『え〜? あたしが Data.txt 作ったんだからないわけないでしょ』
「今回はね。でも、このアプリは〈ファイルを指定して読み込む〉機能も着
けるから。ダイアログに【参照】ボタン着けたでしょ」
『そういえば。つまり開いたファイルがあるかどうかチェックしなきゃいけ
ないわけね』
「そこで、 std::ifstream::fail() というメンバ関数を使用します」
『あ、ちょっと待って、 クラス名とメンバ関数の間の :: って、名前空間
の?』
「うーん、微妙なとこだね。基本的には違うけど、使い方は似てるかな。
ま、クラス名が苗字、メンバ関数が名前って考えると似てるでしょ」
『まーねー』
「同じ名前のメンバ関数が違うクラスにあったりするから、こういうふうに
フルネームで書くのがいいかな。さっきの CFileTestDlg::OnBtnShow() み
たいに、定義部はこういうふうに書くし」
『 ifstream::fail() でただひとつのメンバ関数を示せるってことね。じゃ
あ std:: は? これも付けた方がいい?』
「人に寄りけり。 ifstream は有名だから、付けなくても標準 C++ ライブ
ラリのだってことは分かるんだけどね」
『水希ちゃんが付けてる理由は?』
「クセかも」
『クセ、ねぇ……』
「ま、ぱっと見でこっちの方が分かりやすいと思うんだけどね。っと話を戻
して」
『 std::ifstream::fail() だよね。そいや fail って〈失敗〉とかの意味
だよね』
「そう、 std::ifstream::fail() を呼び出すと、ファイル名が開けていた
場合には false が、開けなかった場合には true が返ってきます」
『ん? 前教えてもらったのって TRUE って大文字だったけど』
「そうそう、 Ver 3.11 ( No.036 ) でやった TRUE と FALSE と、ほとんど
同じ。簡単に言えば、 true と false は新しいので、 TRUE と FALSE は古
いの」
『ふと思ったんだけど、大文字ってことは、 なんかの別名なの?』
「当たり! Ver 5.08 ( No.073 ) でやったね。 FALSE は0、 TRUE は
0以外を置き換えたもの」
『な、なにその〈0以外〉って!』
「 if と同じってこと」
『あ、そういえば、 if は0以外だと入って、0だと入らないんだよね』
「それに合わせているんだけど、実は TRUE の値って、決まってないんだよ
ね」
『0以外、だもんね』
「それだと困っちゃうからできたのが、 true と false 。これは 1 と 0
って決まってるから使いやすいわけ」
『でも、2種類あると混乱するなー』
「確かにそうかも。混ぜて使うのはちょっと不安かも。ま、自分でプログラ
ム組むときには true と false がいいかな」
『はーい。で、 std::ifstream::fail() ってどう使うの?』
「 std::ifstream::open() のあとに呼び出せばOK」
cIFStrm.open( "_Data.txt" );
if( cIFStrm.fail() )
{
TRACE( "ファイルがない!\n" );
return;
}
「確認のために _Data.txt ってファイルを開こうとしてみます」
『ないわけだから、 cIFStrm.fail() で……えっと、 true が返ってくるん
だから、それだと1だから if の中に入るんだよね』
「で、ファイルがないってことを知らせて、そのあと何もせずに関数から抜
けます」
『でもちょっと無味簡素よね〜』
「その辺はアイディア次第。実際は TRACE() じゃなくて、ダイアログを表
示したり、もう一度読み直してみたり、とか色々な方法があるから」
『つまり、それをどうするか、あたしが決めなきゃいけないんだ』
「そういうこと。ま、アプリのデザインの部分だね」
『なんかそーゆーのも難しそう……』
「ま、本来はプログラマーの仕事じゃないとは思うんだけどね。さて次。前
回 std::ifstream の >> 演算子は改造されてるって言いました」
『うん、ファイルからデータ取り込んで i に入れてくれるの』
「実は、文字配列にも入れてくれます」
『そういえば、ファイルに入ってるのって文字列そのものなんだから、当然
って言えば当然よね。……って、もしかしてそれって、 sprintf() 要らな
いってことなんじゃない!?』
「その通り!」
void CFileTestDlg::OnBtnShow()
{
std::ifstream cIFStrm;
cIFStrm.open( "Data.txt" );
if( cIFStrm.fail() )
{
TRACE( "ファイルがない!\n" );
return;
}
char chDest[256];
cIFStrm
>> chDest;
m_cDataLstBox.AddString( chDest );
}
「ってすると、 i じゃなく chDest に、文字列として書き込まれます。も
ちろん」
『 sprintf() 必要なし!! むっちゃ無駄骨〜』
「でもこれは問題もあるよ」
『どゆこと?』
「今回の目的は、ファイルから整数値を読み込んで、それをリストボックス
に表示すること。これだと、ファイルに整数値以外が入ってたら?」
『表示しちゃう?』
「そういうこと。だから、ファイルの中に入ってるデータが、整数値かどう
かチェックしないと」
『おー』
「 chDest に入れてから中に整数値が入ってるかどうか調べてもいいんだけ
ど、それより今回は、 cIFStrm の機能を使ってチェックします。なんで、
元に戻します」
『うお、無駄骨!』
「 cIFStrm >> chDest って読み取る場合には、ファイルに何が書かれてて
も読みとれるでしょ」
『テキストファイルの中身は、文字列そのものだもんね』
「 cIFStrm >> i の場合には、文字列として読み取って、それを整数値に変
換しなきゃいけない」
『その変換できない場合を、さっきみたいに if で拾って return すればい
いんじゃない?』
「そういうこと! しかも、さっきと同じ std::ifstream::fail() を使え
ばOK」
cIFStrm
>> i;
if( cIFStrm.fail() )
{
TRACE( "整数値じゃないです\n" );
return;
}
『ホントだ、さっきのファイル開いたときと同じ』
「 std::ifstream::fail() はいろんなエラーチェックができるから。ちな
みに、実際にこれが機能するかどうか調べるときは、 Data.txt の最初に整
数値以外の文字列入れれば確かめられるから」
『〈あ〉とか入れればいーよね。ビルドして実行、うん if の中に入った』
「さて最後。その Data.txt に整数値3つを入れたよね。この3つ全部を読
み取る方法を見ていきましょう」
『あ、3回繰り返せばいいから for 使うんでしょ』
「ぶぶー。確かに今回は3個だけど、ファイルによって違う、ってことにす
ると?」
『3個って決められないんだ。ってことは、ファイルにあるの全部読み取る、
とかできればいいんだよね』
「そういうこと」
cIFStrm
>> i;
cIFStrm
>> i;
if( cIFStrm.fail() ) // 以下略。
「ってするとどうなる?」
『ビルドして実行。あ、 200 って出た。ってことは、 >> を繰り返すと、
どんどん読み取ってくってこと?』
「そういうこと。 cIFStrm の中に〈ファイルを指し示す針〉があって、
>> を使うと、針の位置にあるデータを読み込んでから、針を次のデータの
所まで進める、っていうシステムになってるんです」
『便利ねー。あ、その針が、ファイルの端っことかまで行ったのが分かれば
いいんだよね』
「そういうこと。それを調べるメンバ関数が std::ifstream::eof() 」
『いーおーえふ?』
「 eof は End Of File の略、つまりファイルの最後ってこと」
『おお』
「ファイルの最後に来たら、このメンバ関数が true を返します。というわ
けで、これを while につかうと、こうなります」
void CFileTestDlg::OnBtnShow()
{
int i;
std::ifstream cIFStrm;
cIFStrm.open( "Data.txt" );
if( cIFStrm.fail() )
{
TRACE( "ファイルがない!\n" );
return;
}
while( !cIFStrm.eof() )
{
cIFStrm
>> i;
if( cIFStrm.fail() )
{
TRACE( "整数値じゃないです\n" );
return;
}
char chDest[256];
sprintf( chDest, "%d", i );
m_cDataLstBox.AddString( chDest );
}
}
『ビルドして実行、おー、 100 200 300 全部リストボックスに出た!』
「この辺が、ファイル操作の基本かな」
/*
Preview Next Story!
*/
『ねー、今回のって STL & iostream 入門の iostream のNo.11 と同じ?』
「ほとんど同じ。向こうはやや上級者向けだから解説は簡単だけどね」
『ってことは、こっちは初心者向け?』
「 if の復習とかしてたらやっぱ初心者でしょ」
『う”』
「というわけで次回」
< Version 5.11 ランタイムでファイル操作! >
『につづく!』
「火美ちゃんもちゃんと復習しないとね」
『分かった、ちゃんとする、復讐』
「字が違う!!」