Я не могу разобрать весь текст из файла .txt. Но когда я запускаю свой код, я не получаю то, что хотел :(

Мой код:

int main()
{
  /* inside "logMsg.txt"
  1/ [111]{1}(text line from 111);
  2/ [222]{2}(text line from 222);
  3/ [333]{3}(text line from 333);
  */

  ifstream textfile("logMsg.txt");

  string log_line;
  string log_time;
  string log_type;
  string log_comment;

  // Get line number
  getline(textfile, log_line, '/');

  // Get Time by unix
  getline(textfile, log_time, '[');
  getline(textfile, log_time, ']');

  // Get type of the function
  getline(textfile, log_type, '{');
  getline(textfile, log_type, '}');

  // Get comment from data_
  getline(textfile, log_comment, '(');
  getline(textfile, log_comment, ')');

  cout << "Line Of the log: " << log_line << "\n";
  cout << "Type of the log: " << log_type << "\n";
  cout << "Time of the log: " << log_time << "\n";
  cout << "Comment of the log :" << log_comment << "\n";
}

Приставка:

Line Of the log: 1
Type of the log: 1
Time of the log: 111
Comment of the log :text line from 111

Я хотел, чтобы парсер прочитал все строки, но результат совсем другой

Я не понимаю, что я делаю неправильно, я пытаюсь получить следующий результат:

Line Of the log: 1, 2, 3,
Type of the log: 1, 2, 3,
Time of the log: 111, 222, 333,
Comment of the log: text line from 111, text line from 222, text line from 333,

Помогите плиз :(

0
ianclever 26 Янв 2022 в 15:28
Getline очищает строку при вызове. Если вы вызовете его дважды, у вас останется только то, что вы прочитали во второй раз, т. е. getline(textfile, log_time, ']'); дает вам последний символ перед], то есть 1. Я также рекомендую отделить получение строк от их разбора.
 – 
Timon van der Berg
26 Янв 2022 в 15:41
Спасибо за совет и рад за комментарий, но я хотел получить весь текст из txt файла, чтобы получить желаемый результат, может вы знаете, как это сделать
 – 
ianclever
26 Янв 2022 в 15:53

1 ответ

Лучший ответ

Я бы рекомендовал использовать для этого регулярные выражения:

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

[Демо ]

#include <fmt/core.h>
#include <iostream>  // cout
#include <regex>
#include <sstream>  // istringstream
#include <string>  // getline

int main() {
    const std::string input{"1/ [111]{1}(text line from 111);\n2/ [222]{2}(text line from 222);\n3/ [333]{3}(text line from 333);"};
    std::istringstream iss{input};

    std::string line{};
    while (std::getline(iss, line))
    {
        const std::regex pattern{R"(([\d+])/\s*\[(\d+)\]\{(\d+)\}\(([^)]+)\);)"};
        std::smatch matches{};
        if (std::regex_match(line, matches, pattern))
        {
            std::cout << fmt::format ("Line: {}, type: {}, time: {}, comment: {}\n",
                matches[1].str(), matches[2].str(), matches[3].str(), matches[4].str());
        }
    }
}

// Outputs:
//
//   Line: 1, type: 111, time: 1, comment: text line from 111
//   Line: 2, type: 222, time: 2, comment: text line from 222
//   Line: 3, type: 333, time: 3, comment: text line from 333
  • Если вам нужен другой вывод (например, как вы предлагаете в своем вопросе, напечатать все номера строк, затем все время и т. д.), вы можете использовать std::vectors для хранения этой информации и печати это в конце.

[Демо ]

#include <algorithm>  // copy
#include <iostream>  // cout
#include <iterator>  // ostream_iterator
#include <regex>
#include <sstream>  // istringstream
#include <string>  // getline

int main() {
    const std::string input{"1/ [111]{1}(text line from 111);\n2/ [222]{2}(text line from 222);\n3/ [333]{3}(text line from 333);"};
    std::istringstream iss{input};

    std::vector<std::string> numbers{};
    std::vector<std::string> types{};
    std::vector<std::string> times{};
    std::vector<std::string> comments{};
    std::string line{};
    while (std::getline(iss, line))
    {
        const std::regex pattern{R"(([\d+])/\s*\[(\d+)\]\{(\d+)\}\(([^)]+)\);)"};
        std::smatch matches{};
        if (std::regex_match(line, matches, pattern))
        {
            numbers.push_back(matches[1]);
            types.push_back(matches[2]);
            times.push_back(matches[3]);
            comments.push_back(matches[4]);
        }
    }
    std::cout << "Line of the log: ";
    std::copy(numbers.cbegin(), numbers.cend(), std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << "\n";
    std::cout << "Type of the log: ";
    std::copy(types.cbegin(), types.cend(), std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << "\n";
    std::cout << "Time of the log: ";
    std::copy(times.cbegin(), times.cend(), std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << "\n";
    std::cout << "Comment of the log: ";
    std::copy(comments.cbegin(), comments.cend(), std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << "\n";
}

// Outputs:
//
//   Line of the log: 1, 2, 3, 
//   Type of the log: 111, 222, 333, 
//   Time of the log: 1, 2, 3, 
//   Comment of the log: text line from 111, text line from 222, text line from 333, 
  • Хотя вам лучше использовать один std::vector из struct с правильными типами для чисел, типов и времени. В этом случае вам нужно будет преобразовать строки из matches в struct int (вы можете сделать это с помощью std::stoi).
struct LineInfo
{
    int number{};
    int type{};
    int time{};
    std::string comment{};
};
std::vector<LineInfo> line_infos{};

[Полная демонстрация кода]

0
rturrado 26 Янв 2022 в 16:53
1
OMG ЧЕЛОВЕК ТЫ СУМАСШЕДШИЙ, СПАСИБО ЗА ВСЕ ИХ
 – 
ianclever
26 Янв 2022 в 16:39
Очень рад быть полезным :)
 – 
rturrado
26 Янв 2022 в 16:40