使用流C ++读取换行符

时间:2015-08-28 17:21:45

标签: c++ stl

如何使用C ++>>读取新行?操作

ifstream input("doc.txt".c_str());
vector<string> contents;
while (input >> word) {
    contents.push_back(word);
}

对于文件:

hello 
world
C++ is the best tool

应该返回

hello
\n
world
\n
C++
is
the
best
tool
P / S:这是一个较大问题的减少问题。我解析文件的方式导致了这个问题。

4 个答案:

答案 0 :(得分:2)

getline提及您jaggedSpirepush_back "\n"自己{/ 3}}:

ifstream input("doc.txt");
vector<string> contents;
for (string line; getline(input, line);) {
    istringstream str(line);
    for (string word; str >> word;) {
        contents.push_back(word);
    }
    contents.push_back("\n");
}

答案 1 :(得分:1)

如果您希望专门使用operator>>并且您在技术上不需要专门使用字符串,那么您可以简单地创建一个自定义类,其中包含从{{1}读入时所需的行为}。它甚至可以(大部分)是字符串的包装器,在读取初始空格时具有自定义行为。

istream

字符串read in运算符会自动忽略所有preceding whitespace到一系列非空白字符,如当前语言环境所定义。这是你想要改变的行为,事实证明这样做非常简单。

初始空格的处理通常由称为sentry对象的东西执行,该对象还检查流是否有效,并设置流的class StringAndNewline{ std::string str_; friend std::istream& operator>>(std::istream& in, StringAndNewline& str); public: StringAndNewline() : str_(){} StringAndNewline(std::string str) : str_(str){} const std::string& str() const noexcept {return str_;} std::string release() {return std::move(str_);} }; (如果它位于文件的末尾)。虽然它的默认行为是消耗空白,直到遇到非空白字符,但它由构造函数中的标志控制,因此我们可以使用它提供的非常好的封装流有效性检查。

failbit的字符串重载会生成并检查一个哨兵,然后读取,直到遇到空格,流的结尾或读取失败。我们可以简单地确保它的哨兵不会通过自己处理它来遇到空白。

因此,我们的自定义类'custom operator>>的最终读入结构将如下所示:

  • 让非白人吃哨兵
  • 检查哨兵,如果失败的流无效则返回
  • 处理空白
  • 将数据读入包裹的字符串
  • 返回流

由于我们只关注我们的空白中的'\ n'字符,这也很简单:只要在流有效时循环(如果在达到我们的任一条件之前它用完了空格,则设置{{1}就像我们想要的那样)并且如果两个条件之一是net,则退出循环:我们得到一个换行符,或者我们得到一个非空白字符。再次,简单易懂:

operator>>

完成后,我们设置了一个ostream运算符,以便于打印:

failbit

并测试我们的代码:

std::istream& operator>>(std::istream& in, StringAndNewline& str){
    std::istream::sentry sentry{in, true}; // make a sentry that doesn't eat whitespace
    if(!sentry){return in;} // check the sentry
    std::locale
        presentLocale{}; // get the present locale
    char presentChar;
    while(in.get(presentChar)){ // while the stream is valid
        if(presentChar == '\n'){ // if we get a newline
            str.str_ = "\\n"; // set the string to an escaped newline
            break; // exit the loop
        }
        // if we get a non-whitespace character
        else if(!std::isspace(presentChar, presentLocale)){
            in.unget(); // replace the character in the stream
            in >> str.str_; // take advantage of the existing string operator
            break; // done with loop
        }
    }
    return in; // return the istream, whatever state it might be in
}

打印出来:

std::ostream& operator<<(std::ostream& out, const StringAndNewline& str){
    return out << str.str();
}

就像我们想要的一样! Live on Coliru

如果你真的想轻松地将包装类转换为字符串,你甚至可以编写一个字符串运算符,但我会把它留给你。

答案 2 :(得分:0)

尝试使用getline(http://www.cplusplus.com/reference/istream/istream/getline/)。 getline将遍历每一行(直到它看到新行字符)并在到达文件末尾时返回0。因此,在每次调用getline并打印之后,它也会打印\ n。以下是您的问题的示例,randFile是一个随机文件,其中包含文本。

  1 #include <iostream>
  2 #include <fstream>
  3 int main(){
  4 
  5   std::ifstream myFile("randFile", std::ifstream::in);
  6   char s[BUFSIZ];
  7 
  8   while(myFile.getline(s, BUFSIZ)){
  9     std::cout << s << std::endl;
 10     std::cout << "\\n"<< std::endl;
 11   }
 12 
 13   return 0;
 14 }

答案 3 :(得分:-1)

首先,您已经在流的构造函数中作为const char *传递。 其次,流读取器读取字符而不是空格,这就是它知道何时切割成字符串的方式。

通常我们读取一个二进制文件,读者知道有一个字符告诉我们什么时候跳过一行着名的\ n但它与平台的不同之处(Win,Unix)。