についてはすでに説明しましstd::getline
たが、おそらく役立つと思われる詳細については言及されていません。を呼び出すときにgetline
、入力の終わりとして処理する文字を指定するパラメーターを渡すこともできます。あなたの番号を読むために、あなたは使うことができます:
std::string number;
std::string name;
std::getline(infile, number, ':');
std::getline(infile, name);
これにより、「:」までのデータがに入れられ、「:」がnumber
破棄され、残りの行が。に読み込まれname
ます。
データの読み取りに使用したい場合は>>
、それも実行できますが、それは少し難しく、ほとんどの人が決して触れない標準ライブラリの領域を掘り下げます。ストリームには、locale
数値のフォーマットや(重要な)「空白」を構成するものの決定などに使用される関連付けがあります。独自のロケールを定義して、「:」を空白として定義し、スペース( "")を空白ではないものとして定義できます。そのロケールを使用するようにストリームに指示すると、データを直接読み取ることができます。
#include <locale>
#include <vector>
struct colonsep: std::ctype<char> {
colonsep(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::mask());
rc[':'] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
これを使用するために、ストリームにロケールを「注入」します。
#include <fstream>
#include <iterator>
#include <algorithm>
#include <iostream>
typedef std::pair<int, std::string> data;
namespace std {
std::istream &operator>>(std::istream &is, data &d) {
return is >> d.first >> d.second;
}
std::ostream &operator<<(std::ostream &os, data const &d) {
return os << d.first << ":" << d.second;
}
}
int main() {
std::ifstream infile("testfile.txt");
infile.imbue(std::locale(std::locale(), new colonsep));
std::vector<data> d;
std::copy(std::istream_iterator<data>(infile),
std::istream_iterator<data>(),
std::back_inserter(d));
// just for fun, sort the data to show we can manipulate it:
std::sort(d.begin(), d.end());
std::copy(d.begin(), d.end(), std::ostream_iterator<data>(std::cout, "\n"));
return 0;
}
これで、ライブラリのその部分がそれほど無視されている理由がわかりました。理論的には、標準ライブラリを使用して作業を行うことは素晴らしいことですが、実際には、ほとんどの場合、代わりにこの種の作業を自分で行う方が簡単です。