6

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

A:KT5:14:行政台:

这是针对哈希表的,我需要为数据结构和事务类型分隔行中的值。我一直在网上四处寻找,并没有在字段分隔符上找到太多内容,而且我发现的内容非常令人困惑。

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

谢谢。

4

2 回答 2

6

@Steve Townsend 已经指出了一种可能性。如果您更喜欢使用operator>>而不是std::getline,您也可以这样做。Anistream始终将空格视为分隔符。每个流都有一个关联的语言环境,每个语言环境都包含一个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。老实说,这需要做更多的工作——它需要你做一些事情,比如读取一个字符串,然后单独分解它。同时,它有据可查,广为人知,并且更符合人们对如何做这样的事情的先入之见,尽管有额外的复杂性,但仍有相当多的人可能会发现它更容易遵循。

于 2010-11-16T19:13:29.737 回答
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
   );

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

如果您必须处理多行(因此换行符是记录分隔符和 : 字段分隔符),请将每一行依次加载到stringstreamusingbasic_istream::getline中,然后将该行后处理为字段,如图所示。

于 2010-11-16T18:40:01.523 回答