Какой идиоматический способ анализа текста с использованием ifstream? - PullRequest
1 голос
/ 21 января 2011

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

    std::ifstream f("/file/on/disk");
    while (!f.eof()) {
        char buf[256];
        f.getline(buf, sizeof(buf));
        std::string str(buf);
        if (str.find(pattern) != std::string::npos)
        {
            // further processing, then break out of the while loop and return.
        }
    }

Ответы [ 3 ]

5 голосов
/ 21 января 2011

Вот один из возможных вариантов переписывания:

std::ifstream f("/file/on/disk");
char buffer[256];
while (f.getline(buffer, sizeof(buf))) { // Use the read operation as the test in the loop.
    if (strstr(buffer, pattern) != NULL) { // Don't cast to string; costs time
        // further processing, then break out of the while loop and return.
    }
}

Основные изменения помечены как встроенные, но для суммирования:

  1. Используйте операцию чтения в качестве теста в цикле while.Это делает код намного короче и понятнее.
  2. Не приводите строку в стиле C к std::string;просто используйте strstr для сканирования.

В качестве дальнейшего примечания вы, вероятно, не захотите использовать здесь строку в стиле C, если вы не уверены, что это то, что вам нужно.C ++ string, вероятно, лучше:

std::ifstream f("/file/on/disk");
std::string buffer;
while (std::getline(f, buffer)) { // Use the read operation as the test in the loop.
    if (buffer.find(pattern) != std::string::npos) {
        // further processing, then break out of the while loop and return.
    }
}
3 голосов
/ 21 января 2011

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

Далее вы создаете std::string из заполненного вами массива.Опять ненужно.Если вам нужна строка, скопируйте ее из потока прямо в строку.

std::ifstream f("/file/on/disk");
for( std::string line; std::getline(f, line); ) {
    if (str.find(pattern) != std::string::npos) {
        // further processing, then break out of the while loop and return.
    }
}
1 голос
/ 21 января 2011

Вам вообще не нужно char[].

string line;
std::getline(f, line);
if (line.find(pattern) != std::string::npos)
{
    ....
}
...