Version 5.09
ファイルから読み取る!
「さて今回からはファイル編」
『うお、なんかすごーく難しそう!!』
「ま、これまでに比べればそれなりにはね。でも少しずつ見ていけば、そん
なに難しくないと思うよ」
『分かってる人はみんなそう言うのよッ!!』
「う”、まーそうかもしんないけど。さて、今回はファイルからデータを読
み取ってみましょう」
『はーい』
「まず、前回言ったけど〈何かの機能を使う〉場合には、色々なライブラリ
から色々な関数やクラスを探して、それを使うっていう方法になります」
『ってことは、ファイルから読み取る関数やクラスがどっかにあるんだ。も
しかしてランタイムにある?』
「うん、ランタイムにあるよ。それ以外にも API や MFC 、それに iostream
っていうのにも入ってるし」
『でたっ、別のメルマガでやってるのでしょ』
「そうそう。〈 STL & iostream 入門〉でもやってるけど、今回はこの
iostream を使って読み込んでみましょう」
『おお! でもそんだけいっぱい方法があって、なんで iostream なの?』
「簡単だからね、使うだけなら。ただし、他のも次回以降に見ていくから」
『それって、水希ちゃんお得意の〈いろんなライブラリを使い比べてみよう〉
戦法でしょ』
「戦法……まあそういうこと。そうすることで選択肢が広がるし、プログラ
ミングのことがよく分かるようになると思うよ」
『そーゆーもんなんだ』
「さてまず、データファイルを用意しましょう」
『データファイル? あ、読み取るためのファイルね』
「そう、今回は整数値を読み取って表示するから、整数値を書き込んだファ
イルを用意します。メニューの【ファイル】−【新規作成】選んで」
『いつもプロジェクト作るときに使うのだよね』
【新規作成】ダイアログが表示される。【ファイル】ページが表示されて
いる。
『あ、いつもの MFC App なんとかとかがない』
「それは【プロジェクト】のページ。今回はその左の【ファイル】のページ
を見て」
『ヘッダーファイルとかソースファイルとか、これで作れるんだ』
「今回は【テキスト ファイル】を選んで」
『テキストファイルってよく聞くね』
「ただ文字が入ってるだけのファイルを〈テキストファイル〉っていいます。
拡張子が .txt のファイルがそう」
『フリーウェアの readme.txt とかもそう?』
「そう。その他に HTML ファイルもそうだし、プログラムが書かれてるソー
スファイルやヘッダーファイルもそう」
『あ、じゃあ今開いてる FileTestDlg.cpp なんかもそうなんだ』
「そういうこと。ちなみに〈ただ文字が入ってる〉ってどういうことだと思
う?」
『へ? うーん……』
「バイナリー表示したらどうなってると思う?」
『あそっか、 A って文字だったら 0x41 って数字が入ってるんだ』
「そういうこと。テキストファイルにはそういう値が入ってて、テキストエ
ディタの方で〈 0x41 だから A を表示しよう〉っていうことをしてるわけ」
『なんか複雑よねー』
「まーね。ま、基本は〈ファイルの中に入ってるのは整数〉っていうイメー
ジを持つ方が大事かも」
『で、ファイル作らないといけないんでしょ?』
「そうそう。【テキスト ファイル】を選んで、【ファイル名】は Data.txt
にして」
『ベタベタねー。んで OK ?』
「そ。【位置】とかは、このファイルはプロジェクトの中に置くからそのま
までね」
『んじゃ OK !』
VC のウィンドウがまっさらになり、タイトルバーに [Data.txt] と表示
される。
『今作ったファイルがテキストエディタに表示されてるんだよね』
「そう、ここで読み取るための整数値を書き込みます」
100
200
300
「って入れて閉じて」
『保存して閉じるっと』
「なんだったらプロジェクトのあるフォルダ開いて、ファイルあるの確認し
た方がいいかも」
『うん、 Data.txt あるよ』
「テキストファイルはメモ帳でも見られるから」
『ホントだ、ちゃんと書き込まれてるね』
「そしたらこれを読み込みましょう。まず、これから使う iostream につい
て」
『おお、他でも解説してるのに。相変わらず親切丁寧ねー』
「そゆこと言わないで。 iostream は、標準 C++ ライブラリのなかのカテ
ゴリーのひとつ」
『標準 C++ ライブラリって、ランタイムのこと?』
「ランタイムは標準 C ライブラリ。これは C 言語時代、つまり古いライブ
ラリだから、 C++ ができたときにライブラリも新しくしよう、ってことに
なって」
『それで作られたのが標準 C++ ライブラリなんだ』
「そういうこと。で、 iostream はその中の〈入出力〉を専門にするクラス
のカテゴリー」
『ファイルと入出力するんだ』
「ファイルとは限らないけどね。ま、ファイルがメインかな。 io は in out
、つまり入出力のこと。 stream は、川の流れみたいなの」
『川??』
「データをファイルに入出力するのがそういうイメージなのかも」
『そういえばインターネットライブとかのって〈ストリーミング〉って言う
もんね』
「それと同じ感じだね。それでは、実際に使ってみましょう。普通、あるラ
イブラリを使う時には、そのライブラリのヘッダーファイルをインクルード
します」
『インクルード?』
「前にちょっとやったけど忘れちゃったか。 FileTestDlg.cpp の上の方に
こういうのがあるでしょ」
#include "stdafx.h"
#include "FileTest.h"
#include "FileTestDlg.h"
『あ、なんかおぼろげに記憶が……』
「 Ver 2.12 ( No.023 ) でやったでしょ。あるクラスや関数を使いたい!
っていうときには」
『その宣言部が入ってるヘッダーをインクルードする!!』
「そう、 FileTestDlg.cpp の中で CFileTestDlg のメンバ関数を作れるの
は、 FileTestDlg.h をインクルードしているから。このヘッダーファイル
に CFileTestDlg の本体が入ってるからね」
『ってことは、 iostream のもこんなふうにインクルードすれば使えるよう
になるんだ』
「そういうこと。で、ホントはちょっと違うんだけど、今回は簡単にするた
めにここで iostream をインクルードしちゃおうか」
『ホントは別のとこでするの?』
「ホントはね。というわけで、今の3行に、こんな感じに1行を挿入して」
#include "stdafx.h"
#include <fstream>
#include "FileTest.h"
#include "FileTestDlg.h"
『上から2行目の <fstream> がそうだよね。あれ、なんでダブルクォーテー
ションじゃないの?』
「 "" で囲むと、プロジェクト内のファイルしかインクルードしてくれない
から。ライブラリはプロジェクトの外に置いてあって、そういうファイルを
インクルードするときには <> で囲みます」
『外って言うと、この前の API みたいに?』
「そういうこと。ここには書いてないけど、 API も <> で囲んでインクルー
ドしてるから」
『へー。あ、あと、なんで fstream って .h がついてないの?』
「標準 C++ ライブラリのヘッダーファイルは、全部拡張子がついてないん
だよね。ま、そうなってるってことで」
『なんで?』
「新しく作られたライブラリだから、これまでに作られた他のヘッダーファ
イルとファイル名が重ならないように、ってことでそうなったみたいだね」
『へ〜』
「さてこれで準備は完了。実際に iostream を使って読み込んでみます」
『いつも使ってる CFileTestDlg::OnBtnShow() に?』
「そう、今こうなってるでしょ」
void CFileTestDlg::OnBtnShow()
{
const int i = 100;
char chDest[256];
sprintf( chDest, "%d", i );
m_cDataLstBox.AddString( chDest );
}
『前回こう書いたんだよね』
「それをこう書き換えて」
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 );
}
『うお難しそう! あ、でも最後の3行は同じなんだね』
「他もそんなに難しくないよ。1行目は分かるでしょ」
『変数 i を作ってるね。2行目の std:: って、もしかして名前空間?』
「そう、 Ver 4.01 ( No.051 ) でやったよね。標準 C++ ライブラリのクラ
スや関数は、全部この std っていう名前空間で囲まれてます」
『もしかして、これもさっきの .h 付けないってのと同じ理由?』
「同じ理由。同じ名前のクラスや関数がもう作られてても、名前空間に囲ま
れていれば別の名前ってことになるからね」
『なんかデリケートなのねー。で、 std::ifstream って? ぱっと見型で、
cIFStrm って変数作ってるみたいだけど』
「その通り。 std::ifstream は iostream の中にある〈ファイルからデー
タを読み取る〉ためのクラス。ちゃんと MSDN にも載ってるよ」
『そのクラスの変数が cIFStrm なんだね。次のは open() ってメンバ関数
読んでるんだよね。 "Data.txt" ってことは、ここでファイル開いてる
の?』
「そう、このメンバ関数で Data.txt ってファイルを開いて、 cIFStrm を
使ってデータを読み取る準備をしてます。ちなみにこれちょっと省略してる
から」
『省略?』
「ホントは、 Data.txt があるかどうかのチェックする必要あるから。それ
は次回」
『でも今作ったんだからないはずはないと思うけど……』
「4行目の cIFStrm >> i; で、実際にデータをファイルから読み込んでま
す」
『はれ? >> ってビットシフトする演算子でしょ。 Ver 4.05 ( No.055 )
でやったよ』 std::ifstream
「実は、ここでは全然違う機能。 std::ifstream は >> 演算子を〈改造〉
してて」
『かっ、改造!?』
「 >> に〈ファイルからデータを読み取る〉っていう機能を着けたわけ。
そのおかげで、 cIFStrm >> i ってすると、ファイルから整数値が読み取ら
れて i の中に入れられるんです」
『な、なんかすごい……』
「仕組みは難しいから無視するとして、使い方はどう?」
『つまり、 std::ifstream の変数使って、 open() で目的のファイルを開
いて、 >> で右側に値を入れたい変数置けば勝手に入ってくれるってことだ
よね』
「そういうこと」
『あ、試してなかった。ビルドして実行。おお!! ちゃんと 100 が表示
されてる!』
/*
Preview Next Story!
*/
『使うだけなら簡単だけど、 STL(略)入門読むと理解は大変そう』
「ま、とりあえずは使えることが大事だからね」
『理解はあと?』
「ずっとあと。あと1回くらい、 iostream になれてみましょー」
『というわけで次回』
< Version 5.10 ifstream をもっと使う! >
「につづく!」
『ずっとあとって、5年後とかじゃないでしょーね』
「はははははははは……………………」