Взять n строк из файла, содержащего m строк, при необходимости повторить файл (лениво) - PullRequest
3 голосов
/ 14 июля 2020

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

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

Но в C ++ Я мало понимаю, с чего начать, за исключением того, что почти уверен, что Boost Hana предлагает множество инструментов, которые мне нужны для разработки решения.

Вот пример входного файла,

line 1
line 2
line 3

и, если я попрошу 7 строк, вот что я хотел бы поместить в переменную (например, в один std::string со встроенным '\n' s),

line 1
line 2
line 3
line 1
line 2
line 3
line 1

I думаю, функция может иметь такое объявление:

std::string function(std::string s, int n);

Ответы [ 2 ]

7 голосов
/ 15 июля 2020

Предполагая, что file - это некоторый входной поток, и вы хотите повторить строки в file для n строк, вы можете использовать библиотеку range-v3 следующим образом:

namespace rv = ranges::views;

auto lines = ranges::getlines(file) 
           | ranges::to<std::vector<std::string>>;
  
auto result = lines 
            | rv::cycle
            | rv::take(n) 
            | rv::join('\n') 
            | ranges::to<std::string>;

Вот a демонстрация .

1 голос
/ 15 июля 2020

Чтобы сделать это в C ++, вам потребуется l oop аналогично следующему:

std::string readLines(std::string filename, int nlines)
{
    std::ifstream in(filename);
    std::string line, result;

    while (nlines > 0)
    {
        while (std::getline(in, line))
        {
            result += line;
            result += '\n';
            if (--nlines == 0)
                return result;
        }

        if (!in) // an error occurred...
            break; // or throw...

        // must be eof, rewind and start over...

        in.clear(); // <-- seekg() clears eofbit in C++11 and later...

        if (!in.seekg(0)) // an error occurred...
            break; // or throw...
    }

    return result;
}
...