C++学习 | 通过正则表达式保证输入格式的正确性

——仅记录个人学习过程——

如果题目中提出了“读入特定输入格式的数据,如果不符合要求则抛出异常、输出错误提示、结束程序”的要求,使用C++的普通输入流无法解决。我使用的方法是逐行读入、结合正则表达式。

题目要求:

  • 从input.txt文件中读入以下内容

  • 首先输入一个正整数n,表示接下来输入的数据总行数。

  • 输入n行数据,每行形如"C 0 1 3"或“L 2 3 5 3”或“S 3 6 4 1”(字符‘C‘后跟三个整数,或字符‘L‘、‘S‘后跟四个整数),如果输入格式不对,或是输入行数过多或过少,则抛出相应异常。

#include <fstream>
#include <sstream>
#include <string>
#include <regex>

const regex Nregex("\\s*(0|([1-9][0-9]*))\\s*"); //首行的n
const regex ENDregex("\\s*"); //文件末尾的空白
const regex THREEregex("(\\s+-?(0|([1-9][0-9]*))){3}\\s*"); //三个整数
const regex FOURregex("(\\s+-?(0|([1-9][0-9]*))){4}\\s*"); //四个整数

ifstream input;
input.open("input.txt", ios::in);
int n;
stringstream inputLineStream;
string nString;

getline(input, nString);
if (!regex_match(nString, Nregex)) {
    //未匹配到文件开始的n,此处的处理操作省略
}
n = stoi(nString); //字符串转整数
for (int i = 0; i < n; i++) {
    inputLineStream.clear();
    string newInputLine;
    string kind;
    input >> kind;
    if (!kind.compare("L") || !kind.compare("S")) {
        getline(input, newInputLine);
        if (!regex_match(newInputLine, FOURregex)) {
            //输入不是四个整数,此处的处理操作省略
        }
        inputLineStream << newInputLine;
        inputLineStream >> int1 >> int2 >> int3 >> int4; //具体处理省略,从这个stream中可以读出这四个整数
    }
    else if (!kind.compare("C")) {
        getline(input, newInputLine);
        if (!regex_match(newInputLine, THREEregex)) {
            //输入不是三个整数,此处的处理操作省略
        }
        inputLineStream << newInputLine;
        inputLineStream >> int1 >> int2 >> int3; //具体处理省略,从这个stream中可以读出这四个整数
    }
    else {
        //读入的并非"C"、"L"、"S",格式显然错误
    }
}
string testEndString;
getline(input, testEndString);
if (!regex_match(testEndString, ENDregex)) {
    //输入未结束,此处的处理操作省略
}
input.close();