您已经听说过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;
}
现在你知道为什么图书馆的那部分如此被忽视了。从理论上讲,让标准库为您完成工作是很棒的——但实际上,在大多数情况下,您自己做这种工作会更容易。