텍스트와 이진 형식 (때로는 일반 텍스트)을 결합한 파일로 작업하고 있습니다. 그래서 파일을 바이너리로 열고 시도해보기로 결정했습니다. 그러나 나중에 정규식 (메모리 손상을 나타내는 종류의 문제)을 사용할 때 예기치 않은 동작이 발생합니다.
(최소한의 예를 갖도록 편집)
#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)
(예외 텍스트도 깨지고 마지막 부분 만 있습니다 : "은 인식 된 Fortran 형식이 아닙니다.")
그래서, 아무것도 아닌 것보다 호기심에서 더 나옵니다. 제가 내부적으로 무언가를 깨뜨리는 근본적으로 잘못된 일을하고 있습니까? 이것이 컴파일러 (VS2015) 때문일 수 있습니까?
참고로, 문제를 해결하기 위해 "형식 간 이동 접근 방식"을 시도해 보겠습니다 (현재 위치 저장, 필요에 따라 텍스트 또는 바이너리로 닫고 열기, 위치 복원).하지만 현재 내 문제가 무엇인지 이해하고 싶습니다. 접근하다.
고려해야 할 두 가지 사항이 있습니다.
텍스트 모드에서는 \n
기본 EOL 조합으로 처리됩니다 (따라서 \r\n
Windows에서). 바이너리 모드에서는 그러한 작업이 수행되지 않으므로 \n
항상 개행 문자 만 사용됩니다. 까지 가능한 한 많은 텍스트를 읽도록 요청합니다 \n
. Windows \r
에서는 문자열 끝에 남습니다 .
그런 다음 std::regex_match
정규식과 일치하는 전체 문자열이 필요합니다. 정규식은 문자열 끝에 추가 공백을 허용하지 않으므로 일치하지 않습니다. 마지막 문자가없는 하위 문자열이 패턴과 일치하기 때문에 해당 입력을 std::regex_search
반환 true
합니다.
Protip : 원시 문자열 리터럴 은 리터럴 을 이스케이프 할 필요가 없기 때문에 정규식을 훨씬 쉽게 만듭니다 (지금 regex101에서 디버그하기 쉽습니다!).
const std::regex getItemsExpr(R"eos(\(([0-9]+)([A|a|I|i|F|f|E|e])([0-9]+)\))eos");
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다