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

C++ c++;ifstream函数和字段分隔符,c++,file-io,ifstream,C++,File Io,Ifstream,对于这个程序,我只使用了shell脚本中数据文件的字段分隔符。但是我尝试使用标准库函数ifstream()来读取数据文件。唯一的问题是我得到的数据是这样的 A:KT5:14:行政台: 这是一个哈希表,我需要为数据结构和事务类型分离行中的值。我一直在网上搜索,没有发现太多关于字段分隔符的内容,我发现的内容相当混乱 接下来的问题是,有没有一种方法可以使用ifstream函数设置字段分隔符,还是应该使用另一个标准库i/o函数 谢谢。提供了指定分隔符的选项。然后,您可以从流中读取由\u Delim分隔的

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

A:KT5:14:行政台:

这是一个哈希表,我需要为数据结构和事务类型分离行中的值。我一直在网上搜索,没有发现太多关于字段分隔符的内容,我发现的内容相当混乱

接下来的问题是,有没有一种方法可以使用ifstream函数设置字段分隔符,还是应该使用另一个标准库i/o函数

谢谢。

提供了指定分隔符的选项。然后,您可以从流中读取由
\u 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
   );
模板
基本信息流&getline(
基本istream<图表类型,特征>&Istr,
基本字符串&\u Str,
图型
);
如果这是统一结构的数据,那么定义一个包含它的结构并实现
operator>
从流中加载每个实例(使用上述运算符代码内部的函数)可能会很有用


如果您必须处理多行(因此newline是一个记录分隔符和:一个字段分隔符),请使用
basic\u istream::getline
将每行依次加载到
stringstream
,然后将该行后处理为字段,如图所示。

@Steve Townsend已经指出了一种可能性。如果您喜欢使用
operator>
而不是
std::getline
,您也可以这样做。
istream
始终将空白视为分隔符。每个流都有一个关联的区域设置,每个区域设置都包含一个
ctype
facet。
ctype
facet是
istream
用来确定哪些输入字符是空白的

在您的例子中,您显然希望流仅将换行符和冒号视为“空白”(即分隔符),而实际的空格字符仅视为“普通”字符,而不是分隔符

为此,您可以创建一个ctype方面,如下所示:

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];
    }
};
struct字段\u读取器:std::ctype{
字段_reader():std::ctype(get_table()){}
静态std::ctype_base::mask const*get_table(){
静态std::vector
rc(表大小,std::ctype_base::mask());
rc['\n']=std::ctype_base::space;
rc[':']=std::ctype_base::space;
返回&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;
}
intmain(){
std::stringstream输入(“A:KT5:14:行政台:”);
//让流使用我们的ctype方面:
imbue(std::locale(std::locale(),newfield_reader());
//将字段从流复制到标准输出,每行一个:
std::copy(std::istream_迭代器(输入),
std::istream_迭代器(),
std::ostream_迭代器(std::cout,“\n”);
返回0;
}
然而,我是第一个承认这有一些缺点的人。首先,语言环境和方面通常都是很差的文档,所以大多数C++程序员很难理解这一点(尤其是当所有的真实工作都在“覆盖”下发生时)。
另一种可能性是使用。老实说,这需要做更多的工作——它需要你做一些事情,比如读一个字符串,然后把它分开。同时,它有很好的文档记录,非常广为人知,并且更符合人们关于如何做这样的事情的先入之见,尽管有额外的复杂性,但很多人可能会发现它更容易遵循。

@onemasse,erm:声明实际上看起来像:
istream&getline(istream&is,string&str,char-delim);
,现在还不错吧?:),更不用说
std::getline
在等效的C:)上给了你什么了@onemasse-编码时看起来并不那么糟糕。第一个参数是
ifstream&
,第二个参数是
string&
,最后一个参数只是一个
char
@Nim Ok,这还不错。我可能会在某个时候尝试C++。Nim在C语言中,std::getline给了你什么?我很好奇,我不想开始一个语言抨击战争。@ OnMease-问这个问题并得到一些要点(如果还没有开始)。我同意很多C++开发人员都很难理解地方/方面。但这是因为实际上很少有人会费心去学习他们的代码,因此他们从来不会费心去学习这些东西。但是,这是另一个原因,要尽可能经常地提出它,以表明正确使用它可以使主代码更易于编写和理解。这是我从facets中学到的另一个技巧,我打算尽快使用它。