c ++ ifstream函数和字段分隔符

raj*_*504 5 c++ file-io ifstream

对于这个程序,我只使用shell脚本中的数据文件中的字段分隔符.但我试图使用标准库函数ifstream()从数据文件读入.唯一的问题是我得到的数据是这样的

答:KT5:14:执行委员会:

这是一个哈希表,我需要分离数据结构的行中的值以及事务类型.我一直在寻找网络,并没有找到很多关于现场分离器和我发现的相当混乱.

那么问题是,有没有办法用ifstream函数设置字段分隔符,或者我应该使用另一个标准库i/o函数?

谢谢.

Ste*_*end 5

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
   );
Run Code Online (Sandbox Code Playgroud)

如果这是统一结构化的数据,那么定义一个结构来包含它并operator>>使用操作符代码内部的上述函数实现从流中加载每个实例可能会很有用。

如果您必须处理多行(以便换行符是记录分隔符,而 : 是字段分隔符),请依次将每行加载到 using 中stringstreambasic_istream::getline然后将行后处理到字段中,如图所示。


Jer*_*fin 5

@Steve Townsend已经指出了一种可能性.如果你喜欢用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];
    }
};
Run Code Online (Sandbox Code Playgroud)

要使用此功能,您必须使用此方面使用语言环境"灌输"流:

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;
}
Run Code Online (Sandbox Code Playgroud)

然而,我是第一个承认这有一些缺点的人.首先,语言环境和方面通常记录很差,因此大多数 C++程序员可能会发现这很难理解(特别是当所有实际工作都发生在"幕后"时),可以这么说.

另一种可能性是使用Boost Tokenizer.说实话,这是一个更多的工作 - 它需要你做一些事情,如读一个字符串,然后分开.同时,它有很好的文档记录,广为人知,并且与人们对如何做这样的事情的先入为主的理解足够好,尽管有额外的复杂性,但很多人可能会发现它更容易理解.