C++: std::vector
へのCSVデータの読み込み
概要
先日,C++でのテキストデータの一括読み込み方法を整理した。その最後に,昔はCSVファイルの読み込みに挑戦して四苦八苦したが,今ならstd::getline()
を活用すれば簡単に実現できそうだと書いた。
入力データとしてCSVは手軽でよく使われる形式なので,せっかくなので改めてC++でのCSVデータの読み込み方法を整理することにした。
実装
まずは実装例を以下に掲載する。前回同様,GitHubでも公開している。
read-csv-to-vector.cpp
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main(void) {
std::stringstream input("11,12,13\n21,22,23\n31,32,33\n");
std::vector<std::vector<std::string>> vv;
for (std::string value; std::getline(input, value);) {
vv.push_back(std::vector<std::string>());
for (std::stringstream ss(value); std::getline(ss, value, ',');) {
vv[vv.size()-1].push_back(value);
}
}
for (auto& v : vv) {
for (auto& e : v) std::cout << " " << e ;
std::cout << "\n";
}
return 0;
}
このコードをコンパイルして実行すると,以下のようにCSVデータの要素がスペース区切りで表示される。
11 12 13 21 22 23 31 32 33
説明
前回のテキストデータの読み込み同様,std::getline()
を駆使して実装した。
CSVデータを2次元のstd::vector
に格納するために若干工夫した。肝となるのは以下の部分だ。
std::stringstream input("11,12,13\n21,22,23\n31,32,33\n");
std::vector<std::vector<std::string>> vv;
for (std::string value; std::getline(input, value);) {
vv.push_back(std::vector<std::string>());
for (std::stringstream ss(value); std::getline(ss, value, ',');) {
vv[vv.size()-1].push_back(value);
}
}
以下の手順で実装した。
- CSVデータから1行の文字列を
std::string value
に格納 std::vector
に行を追加するため,空のstd::vector
をpush_back()
で追加- 1行文の文字列を格納した
value
から,std::getline()
の入力用文字列ストリームを生成 std::getline()
の区切り文字に','
を指定してコンマ区切りデータをvalue
に格納vv[vv.size()-1].push_back(value);
で最終行に要素 (列) を追加
素直にstd::getline()
を使って実装した。std::vector
への追加方法,要素サイズの拡大方法で少し頭を使った。その他,余計な一時変数が生まれないようにstd::string value
を使いまわした。
わかりやすさを重視するならば,2回目のfor文のvalue
は別の名前の変数にしてもよいかもしれない。
また,前回同様にstd::getline()
の第1引数のオブジェクトを以下のように変更することで,標準入力やファイルにも対応できる。
std::getline()
の第1引数- 標準入力:
std::cin
- ファイル:
std::fstream ifs("file")
- テキスト:
std::stringstream ss("text")
シンプルに実装できて満足だった。
結論
C++でのCSVデータのstd::vector
への読み込み方法を解説した。
CSVデータの読み込みはデータ処理の基本でもあるので,整理できたのはよかった。今回の実装例をベースに,必要に応じて型変換やデータの読み飛ばしなどを行えばよいだろう。
C++を始めたての頃は,変にPythonの知識があった分,Pythonと同じように実装しようとしてライブラリー関数を探し回ったりして遠回りをしていた。
安易に外部ライブラリーなどに頼るのではなく,C言語と同様に,基本的な処理を組み合わせて実装することが,シンプルでわかりやすいのかもしれない。
また何かよくある問題に遭遇したら整理したい。