提问者:小点点

为什么C++的文件I/O在读取文本文件时忽略初始空行? 我怎么才能让它不这样做呢?


我正在尝试用自己定制的正则表达式和抽象语法树解析库“srl.h”(又名“字符串和正则表达式库”)为自己构建一种迷你编程语言,我发现了一个我似乎不太清楚的问题。

问题是这样的:当我的自定义代码遇到错误时,它显然会抛出一个错误消息,而这个错误消息包含有关错误的信息,其中一位是抛出错误的行号。

问题在于C++似乎只是完全忽略不包含字符的行的存在(即仅为CRLF的行),直到它找到一个包含字符的行,在这一点之后它停止忽略空行并正确地处理它们,从而给所有抛出的错误提供一个不正确的行号,它们都以相同的偏移量不正确。

基本上,如果给出一个包含内容“(crlf)(crlf)abc(crlf)def”的文件,它将被当作内容“abc(crlf)def”来读取,忽略初始的新行,从而为抛出的任何和所有错误报告错误的行号。

这里是我用来获取文本文件文本的(vary messily coded)函数的副本。 如果你们中有人能告诉我这里发生了什么,那就太好了。

template<class charT> inline std::pair<bool, std::basic_string<charT>> load_text_file(const std::wstring& file_path, const char delimiter = '\n') {


    std::ifstream fs(file_path);

    
    std::string _nl = srl::get_nlp_string<char>(srl::newline_policy);


    if (fs.is_open()) {


        std::string s;


        char b[SRL_TEXT_FILE_MAX_CHARS_PER_LINE];


        while (!fs.eof()) {


            if (s.length() > 0)
                s += _nl;


            fs.getline(b, SRL_TEXT_FILE_MAX_CHARS_PER_LINE, delimiter);


            s += std::string(b);
        }


        fs.close();


        return std::pair<bool, std::basic_string<charT>>(true, srl::string_cast<char, charT>(s));
    }
    else
        return std::pair<bool, std::basic_string<charT>>(false, std::basic_string<charT>());
}

共1个答案

匿名用户

std::ifStream::getLine()不将分隔符(在本例中为'\n')输入到字符串中,还将其从流中刷新,这就是为什么文件中的所有换行(包括前导行)在读取时被丢弃的原因。

程序似乎没有忽略其他行之间的换行是因为:

if (s.length() > 0)
     s += _nl;

所有的换行实际上都是从这里来的,但是这不能在最开始的时候发生,因为字符串是空的。

这可以用一个小的测试程序来验证:

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream inFile{ "test.txt" }; //(crlf)(crlf)(abc)(crlf)(def) inside

    char line[80]{};
    int lineCount{ 0 };

    std::string script;

    while (inFile.peek() != EOF) {
        inFile.getline(line, 80, '\n');
        lineCount++;

        script += line;
    }

    std::cout << "***Captured via getline()***" << std::endl;
    std::cout << script << std::endl; //prints "abcdef"
    std::cout << "***End***" << std::endl << std::endl;

    std::cout << "Number of lines: " << lineCount; //result: 5, so leading /n processed

}

如果删除了If条件,那么程序只需:

s += _nl;

,将从文件中插入换行,而不是丢弃的行,但是只要'\n'是分隔符,std::ifStream::getLine()将继续丢弃原始行。

最后,我建议使用

while (fs.peek() != EOF){};

而不是

while(fs){};while(!fs.eof()){};

如果查看int linecount在测试程序中的最终值,后两者给出的是6而不是5,因为它们最终会进行一次冗余迭代。

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|文件|i|o|读取|文本文件|忽略|初始|空行|能让|它不|做)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?