Заставляем getline проверять вторую и третью строки входного файла

#c #regex #ifstream #getline

#c #регулярное выражение #ifstream #getline

Вопрос:

Я проверил большинство вопросов stackoverflow по этой теме, но, похоже, я не получил правильного ответа.

Я считываю строки из текстового файла, затем я проверяю, содержит ли каждая строка текстового файла правильные строки, используя регулярное выражение.

Мой код проверяет первую строку входного файла и выводит «bad», если первая строка входного файла не является «#FIRST». Я пытаюсь сделать то же самое для следующих двух строк, однако я не знаю, как сказать getline проверять только вторую строку после того, как первая строка в порядке.

Вторая строка должна быть «это комментарий». Третья строка должна быть «#SECOND».

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

int main (){



    std::ifstream input( "test.txt" );
    for( std::string line; getline( input, line ); )
{   std::regex e("#FIRST");
  std::regex b("#this is a comment");
   //std::regex c("#SECOND");

    if(std::regex_match(line,e))
    std::cout << "good." << std::endl;

else
  std::cout << "bad." << std::endl;

    if(std::regex_match(line,b))
    std::cout << "good." << std::endl;

else
  std::cout << "bad." << std::endl;
break;

}

    return 0;
}
  

входной файл

 #FIRST
#this is a comment
#SECOND
  

Комментарии:

1. Похоже, ваша проблема на самом деле не в использовании getline , а в том, как выполнить несколько похожих (но немного отличающихся) проверок подряд, я прав? Нужно ли выполнять какие-либо другие проверки для последующих строк в файле?

2. аналогичные проверки в разных строках. Да, мне нужно это сделать

3. Проводится ли проверка для каждой строки или некоторые строки вообще не проверяются?

4. для каждой строки, но я хочу сначала проверить первые три и добавить другие строки позже

Ответ №1:

Одним из решений является сохранение списка проверок, которые вы хотите выполнить, а затем циклическое их выполнение. Для каждой проверки прочитайте строку и посмотрите, соответствует ли она:

 #include <iostream>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::string> validLines {
        "#FIRST",
        "this is a comment",
        "#SECOND"
    };

    std::istringstream fileStream { // pretend it's a file!
            "#FIRSTn" 
            "this is a commentn" 
            "this line should failn"};

    std::string fileLine;
    for (auto constamp; validLine : validLines) {
        // for every validity check, read a line from the file and check it
        if (!std::getline(fileStream, fileLine)) {
            std::cerr << "Failed to read from file!n";
            return 1;
        }
        if (validLine == fileLine) { // could be a regex check
            std::cout << "goodn";
        }
        else {
            std::cout << "badn";
        }
    }
}
  

При этом будут считываться только те строки, для которых у вас есть проверка. Если в файле больше строк, они вообще не будут прочитаны.

Также обратите внимание, я сделал пару упрощений, используя строку вместо файла и используя простое совпадение вместо регулярного выражения, но это не имеет никакого значения для того, что вас интересует.


Просто для развлечения, вот другой подход, если вам нужно проверить только определенные номера строк:

 #include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>

int main()
{
    using LineCheckMap = std::unordered_map<std::size_t, std::string>;
    LineCheckMap validLines {
        {3, "#SECOND"}
    };

    std::istringstream fileStream { // pretend it's a file!
            "#FIRSTn" 
            "this is a commentn" 
            "this line should failn"};

    std::string fileLine;
    std::size_t lineCount {0};
    while (std::getline(fileStream, fileLine)) {
        // for every line in the file, add to a counter and check
        // if there is a rule for that line
          lineCount;
        LineCheckMap::const_iterator checkIter = validLines.find(lineCount);
        if (std::end(validLines) != checkIter) {
            if (checkIter->second == fileLine) {
                std::cout << "goodn";
            }
            else {
                std::cout << "badn";
            }
        }
    }
}
  

Комментарии:

1. большое спасибо 🙂 У меня есть еще один вопрос, если я хочу добавить допустимую строку «SIZE 40 11» и я хочу извлечь целые числа из строки, нужно ли мне вносить изменения в if (validLine == fileLine) условие или мне следует создать отдельную векторную строку, которая будет сравнивать входные данные с векторной строкой и добавлять условие в if (validLine == fileLine) строку?

2. Я не совсем понимаю вопрос, но ничто не мешает вам сохранять регулярные выражения в map и сверять их со строкой из файла. Я просто изменил ваш исходный пример, чтобы использовать точное совпадение строк, чтобы упростить задачу.