Разбор большого текстового файла в переполнении стека

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

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

Проблема в том, что когда я запускаю его, он останавливается после анализа строк от 70 до 92 тыс. Под остановками я подразумеваю, что программа все еще работает, однако она ничего не обрабатывает, и курсор в моем терминале просто остается там и мигает. Используя глупую отладку (используя cout), я проверил, что вокруг строки 92521 она принимает входную строку (правильную строку), однако она не проходит через разделение на токены и восстановление хорошо отформатированной строки и просто останавливается.

Ниже я прилагаю связанный код. Я с нетерпением жду, когда кто-нибудь скажет мне, что происходит, то есть, почему моя программа останавливается и каким образом я могу решить эту проблему. Спасибо за внимание!

#include <iostream>
#include <fstream>
#include <cstring>
#include <sstream>

int main(int argc, char** argv) {
std::ifstream inFile;
std::ofstream outFile;
std::string inDir("/home/marcin/jnp2/proj/data/oceny.txt");
std::string outDir("/home/marcin/jnp2/proj/data/ocenyout.txt");
outFile.open(outDir, std::ios::out | std::ios::app);
inFile.open(inDir, std::ios::in);
std::string line;
int i = 1;
while(std::getline(inFile, line, '\n')) {
//for(int i = 0; i < 251819; i++) { // 197858
//std::string line;
//std::getline(inFile, line, '\n');
//std::cout << "OK1" << std::endl;
if(i == 92520) {
int x;
std::cin >> x;
}
if(!line.empty() && line[0] != '-' && line[0] != 'K' && line[0] != 'S') {
//std::cout << line << std::endl;
std::istringstream iss(line);
std::string code, name, dyd_cycle, term, grade, person, tmp;
iss >> code;
std::size_t found;
do {
if(iss >> tmp) {
//iss >> tmp;
found = tmp.find("20");
if (found == std::string::npos)
if(name.empty())
name = tmp;
else
name = name + " " + tmp;
else
dyd_cycle = tmp;
} else
return 42;
} while (found == std::string::npos);
//std::cout << "OK2" << std::endl;
iss >> term;
iss >> grade >> person;
std::string formattedLine = code + ";" + name + ";" + dyd_cycle + ";" + term + ";" + grade + ";" + person;
outFile << formattedLine << std::endl;
}
//std::cout << "OK3" << std::endl;
std::cout << i++ << std::endl;
}
inFile.close();
outFile.close();
return 0;
}

Редактировать: последний вывод останавливается на
«1000-621MRB; Metody realizacji baz danych; 2004 / TL; 3; 2; LONG_CODE_THAT_IM_NOT_SUPPOSED_TO_SHOW».

Кроме того, я упомяну, что когда я делал это постепенно, то есть сначала по 50 тыс. Строк, а затем велел программе (путем жесткого кодирования пропустить первые 50 тыс. Строк) начинать со строки 50 тыс. + 1 и т. Д. Проблем не было — я Точный вывод я должен был. С другой стороны, когда я сказал, чтобы он закрывал файлы каждые 50 тыс. Строк, снова открывал их и возвращался к правильной строке для входного файла, я все еще сталкивался с той же проблемой.

Edit2: я скомпилировал его в debug и использовал gdb — вокруг критических номеров строк он получил строку правильно (ура), но застрял в коде iss >>. Я использовал отладчик в CLion, поэтому он просто отключился через некоторое время.

1

Решение

Использование cout не всегда лучший способ отладки, так как я нахожу, что это иногда приводит к снижению терминала / общей скорости программы. Вы можете попытаться использовать утверждения или реальный отладчик (такой как GDB) для отладки вашей программы. Отладчик проведет вас по вашему коду и покажет, что именно происходит внутри.

1

Другие решения

У меня действительно была неверная дата — проверка на «20» вызвала программу в вечный цикл. Я хотел бы поблагодарить pm100 и George Sovetov за то, что они указали на этот фрагмент кода как на потенциально опасный. Я использовал отладчик, чтобы найти проблему — я благодарю разработчика и pm100 за предложение сделать это. Благодаря gudok я использовал проверку, чтобы проверить, работает ли iss >> tmp, что помогло мне заметить, что мой цикл станет чрезмерно вечным.

Я исправлю код и буду использовать регулярные выражения, чтобы, надеюсь, избежать любых других форм таких ошибок (согласно предложению knivil). Я также буду использовать ‘\ n’ вместо std :: endl, как предложил kchinger. Спасибо ребята за все комментарии! 🙂

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector