Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;istream、getline、二进制文件、正则表达式和字符串的意外行为_C++ - Fatal编程技术网

C++ C++;istream、getline、二进制文件、正则表达式和字符串的意外行为

C++ C++;istream、getline、二进制文件、正则表达式和字符串的意外行为,c++,C++,我正在使用一个结合了文本和二进制格式(有时只是纯文本)的文件。所以我决定以二进制文件的形式打开文件,并尝试一下。但是,当我以后使用正则表达式时,我会遇到意想不到的行为(这类问题表明内存损坏): (经过编辑以获得最少的示例) (即使例外文本也被打断,并且只有最后一部分: “不是可识别的Fortran格式。”) 因此,更多的是出于好奇,而非无所事事:我是否在做一些根本错误的事情,破坏了某些内在的东西?这是否可以归因于编译器(VS2015) 仅供参考,我将尝试一种“在格式之间跳转”的方法来解决这个问题

我正在使用一个结合了文本和二进制格式(有时只是纯文本)的文件。所以我决定以二进制文件的形式打开文件,并尝试一下。但是,当我以后使用正则表达式时,我会遇到意想不到的行为(这类问题表明内存损坏):

(经过编辑以获得最少的示例)

(即使例外文本也被打断,并且只有最后一部分: “不是可识别的Fortran格式。”)

因此,更多的是出于好奇,而非无所事事:我是否在做一些根本错误的事情,破坏了某些内在的东西?这是否可以归因于编译器(VS2015)


仅供参考,我将尝试一种“在格式之间跳转”的方法来解决这个问题(保存当前位置,根据需要以文本或二进制形式关闭和打开,恢复位置),但我只想了解我当前的方法可能有什么问题。

有两件事需要考虑:

在文本模式下,
\n
作为本机EOL组合处理(因此在Windows上是
\r\n
)。在二进制模式下,不会执行此类操作,因此
\n
始终是换行符,而不是其他字符。您要求阅读尽可能多的文本,直到
\n
,在Windows上,这会使您在字符串的末尾保留
\r

然后,需要整个字符串与正则表达式匹配。您的正则表达式不允许在字符串末尾添加额外的空格,因此它不匹配。将在该输入上返回
true
,因为没有最后一个字符的子字符串与模式匹配


Protip:使正则表达式更容易,因为您不必转义文本(现在在regex101中调试起来很容易!):


如果在行尾没有一个回车符,你真的什么都说不出来吗?调试器将是验证的最佳工具。这在Windows上吗?文本文件需要以文本模式打开,才能正确映射换行符。更新:刚刚看到您正在使用VS 2015。什么样的文件包含文本和二进制的混合?我将尝试创建一个最小的可复制示例来回答这个问题:它是一个旧的内部格式感谢专业提示。正则表达式没有捕获结尾处的\r,甚至没有在结尾处使用。*。但我所做的是在获得“\r”时将其从行中删除,这就成功了。
#include <string>
#include <iostream>
#include <fstream>
#include <regex>
#include <ios>

struct FortranFormat {
    std::string itemsPerRow;
    std::string type;
    std::string numberOfCharacters;
};

class XXXParserException: virtual public std::runtime_error {
    using runtime_error::runtime_error;
};


std::string parseSection(const std::string &line) {
    return  line.substr(16, std::string::npos );
}


FortranFormat parse(const std::string& expression) {
    const std::regex getItemsExpr("\\(([0-9]+)([A|a|I|i|F|f|E|e])([0-9]+)\\)");

    std::cout << "expression: " << expression << std::endl;

    std::smatch elements;
    if (std::regex_match(expression, elements, getItemsExpr)) {
        
        return {elements[1].str(),elements[2].str(),elements[3].str()};
    } else {
        throw XXXParserException("The expression " + expression + " is not a recognized Fortran Format.");
    }
}

void main() {

    std::ifstream fb;
    fb.open("example.txt", std::ios::binary); // remove the binary flag, and it works
    std::string line;
    getline(fb, line);
    std::cout << "line: " << line << std::endl;
    std::string formula = parseSection(line);
  
    auto format = parse(formula);
    
    std::cout << "format: " << format.type << std::endl;
}
line: *VALUES        6(5E16.8)
expression: (5E16.8)
const std::regex getItemsExpr(R"eos(\(([0-9]+)([A|a|I|i|F|f|E|e])([0-9]+)\))eos");