对于这个程序,我只使用shell脚本中的数据文件中的字段分隔符。但我试图使用标准库函数ifstream()从数据文件读入。唯一的问题是我得到的数据是这样的
答:KT5:14:执行委员会:
这是针对哈希表的,我需要分离数据结构行中的值以及事务类型。我一直在寻找网络,并没有找到很多关于现场分离器和我发现的相当混乱。
那么问题是,有没有办法用ifstream函数设置字段分隔符,还是我应该使用另一个标准库i / o函数?
感谢。
答案 0 :(得分:5)
operator>>
而不是std::getline
,那么您也可以这样做。 istream
始终将空格视为分隔符。每个流都有一个关联的区域设置,每个区域设置都包含ctype
方面。 ctype
方面是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。老实说,这是一个更多工作 - 它需要你做一些事情,比如阅读一个字符串,然后单独分解它。与此同时,它有很好的文档记录,广为人知,并且与人们对如何做这类事情的先入之见相比更适合,尽管有更多的复杂性,但很多人可能会发现它更容易理解。
答案 1 :(得分:4)
getline为您提供了指定分隔符的选项。然后,您可以将来自流的输入读取为由string
分隔的_Delim
序列:
template<class CharType, class Traits, class Allocator>
basic_istream< CharType, Traits >& getline(
basic_istream< CharType, Traits >& _Istr,
basic_string< CharType, Traits, Allocator >& _Str,
CharType _Delim
);
如果这是统一结构化的数据,那么定义一个包含它的结构并实现operator>>
从流中加载每个实例可能是有用的,使用操作符代码内部的上述函数。
如果必须处理多行(以便换行是记录分隔符和:字段分隔符),请使用stringstream
依次将每一行加载到basic_istream::getline
,然后将该行后处理字段如图所示。