C++でファイルを読み込むシンプルな例
C++というと、PythonやRubyに比べて、記述が面倒という声をしばしば聞きます。そのような面も否定はできませんが、標準ライブラリSTLやC++11で追加された機能を活用すると、シンプルな書き方ができる場合もあります。今回は、典型的な処理の一つであるテキストファイルの内容すべてをstring型のオブジェクトに読み込む例を紹介します。
概要
次のコードは、あるファイルの全ての内容をstd::string型のオブジェクトに格納する例です。(簡単のためにエラーチェックを省略しています。)
string readFile(const char *filename)
{
ifstream ifs(filename);
return string(istreambuf_iterator<char>(ifs),
istreambuf_iterator<char>());
}
見てわかるように、やっていることは、非常に単純です。ファイルを読み込むためにifstreamのオブジェクトを作成します。stringには、イテレータで範囲を指定するタイプのコンストラクタがあります。ifstreamのストリームをイテレータとして扱うことのできるistreambuf_iteratorで、ファイルの最初から最後までを指定して読み込ませています。
もう少し詳しく
istreambuf_iterator
istreambuf_iteratorは、++演算子を適用するごとにストリームからデータを読み出すイテレータです。例えば、以下のプログラムはファイルの中身を標準出力に表示します。
void showFileContent(const char *filename)
{
ifstream ifs(filename);
istreambuf_iterator<char> it(ifs);
istreambuf_iterator<char> last;
for (; it != last; ++it)
printf("%c", *it);
}
stringの範囲指定コンストラクタ
stringのコンストラクタで、イテレータで範囲を指定するタイプに馴染みがない方もいるかもしれません。このコンストラクタの第一引数は開始イテレータで、第二引数は、終了のイテレータです。よりシンプルな例を以下に示します。
#include <cstdio>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
string s = "This is a book.";
string t(s.begin()+1, s.begin()+6);
printf("t: %s\n", t.c_str());
}
実行結果は以下のとおりです。開始イテレータは、2文字目を指しているのでhであり、終了のs.begin()+6は、isのsを挿していますが、こちらは開始と違って、それ自身を含みません。その直前のiまでとなります。
$ ./string-iter
t: his i