Разбор файла двух форматов и разбор строки тоже - PullRequest
2 голосов
/ 04 апреля 2019

У меня есть огромный файл, который может иметь строки в следующих двух форматах:

формат 1:

*1 <int_1/string_1>:<int/string> <int_2/string_2>:<int/string> <float>

ФОРМАТ2:

*1 <int/string>:<int/string> <float>

Итак, возможные варианты для вышеуказанного формата:

*1 1:2 3:4 2.3
*1 1:foo 3:bar 2.3
*1 foo:1 bar:4 2.3
*1 foo:foo bar:bar 2.3
*1 foo:foo 2.3

Из обеих приведенных выше строк формата мне нужно учитывать только «Формат1» для моего кода. Читая этот огромный файл, пропустите строки, соответствующие «Format2». В возможных случаях я рассмотрю первые 4 случая, а не последний, так как он соответствует «Format2». Итак, регулярное выражение должно быть примерно таким:

(\d+)(\s+)(\\*\S+:\S+)(\s+)(\\*\S+:\S+)(\s+)(\d+)

, где

\d is any digit. \d+ is more than 1 digit.
\s is space. \s+ is more than 1 space.
\S is anything non-space. \S+ is anything more than 1 non-space.

После рассмотрения строки 'Format1' мне нужно взять из нее два значения:

int_1/string_1
int_2/string_2

Что вы могли бы сделать оптимально, чтобы справиться с этим?

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

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

struct Field {
    int start, stop;
};
Field fields[4];
int i = 0, nf = 0;
while (s[i]) {
    while (s[i] && isspace(s[i])) i++;
    if (!s[i]) break;
    int start = i;
    while (s[i] && !isspace(s[i])) i++;
    nf++;
    if (nf == 5) break; // Too many fields
    fields[nf-1].start = start;
    fields[nf-1].stop = i;
}
if (nf == 4) {
    // We got 4 fields, line could be acceptable
    ...
}

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

0 голосов
/ 04 апреля 2019

Использование повышение

#include <iostream>
#include <array>
#include <vector>
#include <string>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

int main() {
    std::array<std::string, 5> x = { "*1 1:2 3:4 2.3",
        "*1 1:foo 3:bar 2.3",
        "*1 foo:1 bar:4 2.3",
        "*1 foo:foo bar:bar 2.3",
        "*1 foo:foo 2.3"
    };

    for (const auto& item : x) {

        std::vector<std::string> Words;
        // split based on <space> and :

        boost::split(Words,item, boost::is_any_of(L" :"));
        std::cout << item << std::endl;

       // Only consider the Format1
        if (Words.size() > 4) {
            std::cout << Words[1] << ":" << Words[2] << std::endl;
            std::cout << Words[3] << ":" << Words[4] << std::endl;
        }
        std::cout << std::endl;
    }
    return 0;
}

Использование std::regex

int main() {
    std::array<std::string, 5> x = { "*1 1:2 3:4 2.3",
        "*1 1:foo 3:bar 2.3",
        "*1 foo:1 bar:4 2.3",
        "*1 foo:foo bar:bar 2.3",
        "*1 foo:foo 2.3"
    };

    std::regex re(R"(\*1\s+(\w+):(\w+)\s+(\w+):(\w+).*)");

    for (const auto& item : x) {
        std::smatch sm;
        if (std::regex_match(item, sm, re)) {
            std::cout << sm[1] << ":" << sm[2] << std::endl;
            std::cout << sm[3] << ":" << sm[4] << std::endl;
        }
    }

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...