Я пытаюсь прочитать случайную строку из текстового файла.
Мой код до сих пор выбирает первую строку, но мне нужна случайная строка.
Как бы я получить случайную строку?
string line;
if(infile.good()){
getline(infile, line);
}
Вы можете прочитать в строках вашего файла в std::vector<std::string>
а также случайным образом получить доступ к определенной строке в диапазоне размеров векторов:
std::string line;
std::vector<std::string> lines;
while(getline(infile, line)) {
lines.push_back(line);
}
if(lines.size() >= 4) {
std::cout << "Line number 5: " << lines[4] << std::endl;
}
Другой вариант — сначала установить случайное число и считать прочитанные строки:
int lineno = 5;
int linecount = 0;
std::string line;
while(getline(infile, line)) {
++linecount;
if(linecount == lineno) {
std::cout << "Line number " << lineno << ": " << line << std::endl;
}
}
Вызов getline
случайное число раз и обязательно остановите цикл, если вы достигнете конца файла.
Пока вы не знаете, какова длина строк в вашем файле, невозможно каким-либо образом вычислить начало любой строки (кроме самой первой строки, конечно) и искать непосредственно в этой точке.
Вы можете использовать подход «Отбор проб резервуаров», как описано в следующих публикациях:
Как мы узнали из статьи в Википедии о взятии проб из резервуара:
Выборка из резервуара — это семейство рандомизированных алгоритмов для случайного выбора выборки из k элементов из списка S, содержащего n элементов, где n — очень большое или неизвестное число. Обычно n достаточно велико, чтобы список не помещался в основную память.
Используя такой алгоритм, можно выбрать случайные элементы из серии неизвестной длины за один проход, без необходимости хранить их все в памяти.
Вот (непроверенный) пример:
#include <cstdlib>
#include <iostream>
#include <random>
#include <string>
int main() {
std::random_device seed;
std::mt19937 prng(seed());
std::string line, result;
for(std::size_t n = 0; std::getline(std::cin, line); n++) {
std::uniform_int_distribution<> dist(0, n);
if (dist(prng) < 1)
result = line;
}
std::cout << "random line: '" << result << "'\n";
}
Пример вывода:
$ g++ test.cc -std=c++11 && ./a.out < test.cc
random line: '#include <iostream>'
Для справки:
Вы можете сохранить смещения файлов начала строки в std::vector
, Затем сгенерируйте ваше случайное число. Используйте номер в качестве индекса в std::vector
и получите начальную позицию линии. Найдите эту позицию и найдите строку.
std::vector<std::streampos> line_offsets;
line_offsets.push_back(0); // The first line.
std::string text_line;
while (getline(text_file, text_line))
{
std::streampos file_offset = text_file.tellg();
line_offsets.push_back(file_offset);
}
//...
std::streampos offset = line_offsets[Get_Random_Line_Number()];
text_file.seekg(offset);
std::string random_text_line;
getline(text_file, random_text_line);
Этот метод не использует столько памяти, сколько сохраняет каждую текстовую строку в векторе.