你已经被告知std::getline,但他们没有提到你可能会发现有用的一个细节:当你调用getline时,你还可以传递一个参数告诉它要处理什么字符输入结束。要读取您的号码,您可以使用:
std::string number;
std::string name;
std::getline(infile, number, ':');
std::getline(infile, name);
这会将直到“:”的数据放入number,丢弃“:”,并将该行的其余部分读入name。
如果您想使用>> 读取数据,您也可以这样做,但它有点困难,并且深入研究了大多数人从未接触过的标准库区域。流具有关联的locale,用于格式化数字和(重要的是)确定什么构成“空白”。您可以定义自己的语言环境,将“:”定义为空格,将空格 (" ") 定义为 not 空格。告诉流使用该语言环境,它会让您直接读取数据。
#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;
}
现在你知道为什么图书馆的那部分如此被忽视了。从理论上讲,让标准库为您完成工作是很棒的——但实际上,大多数情况下,您自己做这种工作会更容易。