@Steve Townsend 已经指出了一种可能性。如果您更喜欢使用operator>> 而不是std::getline,您也可以这样做。 istream 始终将空格视为分隔符。每个流都有一个关联的语言环境,每个语言环境都包含一个ctype 方面。 ctype facet 是 istream 用来确定哪些输入字符是空格的。
在您的情况下,您显然希望流仅将换行符和冒号视为“空白”(即分隔符),而实际的空格字符仅被视为“普通”字符,而不是分隔符。
为此,您可以像这样创建一个 ctype facet:
struct field_reader: std::ctype<char> {
field_reader(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(table_size, std::ctype_base::mask());
rc['\n'] = std::ctype_base::space;
rc[':'] = std::ctype_base::space;
return &rc[0];
}
};
要使用这个,你必须使用这个方面给流“灌输”一个语言环境:
int main() {
std::stringstream input("A:KT5:14:executive desk:");
// have the stream use our ctype facet:
input.imbue(std::locale(std::locale(), new field_reader()));
// copy fields from the stream to standard output, one per line:
std::copy(std::istream_iterator<std::string>(input),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
然而,我是第一个承认这有一些缺点的人。首先,语言环境和方面的文档通常很差,因此大多数 C++ 程序员可能会发现这相当难以理解(尤其是当所有实际工作都发生在“幕后”时,可以这么说)。
另一种可能性是使用Boost Tokenizer。老实说,这是一个更多的工作——它需要你做一些事情,比如读取一个字符串,然后单独分解它。同时,它有据可查,广为人知,并且更符合人们对如何做这样的事情的先入之见,尽管有额外的复杂性,但仍有相当多的人可能会发现它更容易遵循。