В настоящее время я пытаюсь научить себя C++, и я работаю над файлом IO. Я прочитал через cplusplus.com учебник, и я использую основные методы файла ввода-вывода, я узнал, что:Почему мой сценарий синтаксического анализа текстового файла на C++ намного медленнее, чем мой скрипт Python?
std::ifstream \\using this to open a read-only file
std::ofstream \\using this to create an output file
std::getline \\using this to read each line of the file
outputfile << linecontents \\using this to write to the output file
У меня есть примерно 10MB текстовый файл, содержащий первый миллион простых чисел, разделенных пробелами, 8 простых чисел к линии. Моя цель - написать программу, которая откроет файл, прочитает содержимое и напишет новый файл с одним простым числом на строку. Я использую регулярные выражения, чтобы разбить пробелы на концах каждой строки и заменить пробел между каждым числом одним символом новой строки.
Базовый алгоритм прост: используя регулярные выражения, я обрезаю пробелы в концах каждой строки и заменяю пробел посередине символом новой строки и записываю эту строку в выходной файл. Я написал «тот же самый» алгоритм в C++ и Python (за исключением того, что я использую встроенную функцию strip() для удаления начального и конечного пробелов), а программа Python намного быстрее! Я ожидаю обратное; Я думаю, что (хорошо написанная) программа на C++ должна быть молниеносной, а программа Python в 10-20 раз медленнее. Независимо от того, какая оптимизация выполняется за кадром в Python, хотя она делает это быстрее, чем моя «эквивалентная» программа на C++.
Мои регулярные выражения поиски:
std::tr1::regex rxLeadingTrailingWS("^(\\s)+|(\\s)+$"); //whitespace at beginning or end of string
std::tr1::regex rxWS("(\\s)+"); //whitespace anywhere
Мой файл разбора кода:
void ReWritePrimesFile()
{
std::ifstream readFile("..//primes1.txt");
std::ofstream reducedPrimeList("..//newprimelist.txt");
std::string readout;
std::string tempLine;
std::tr1::regex rxLeadingTrailingWS("^(\\s)+|(\\s)+$"); //whitespace at beginning or end of string
std::tr1::regex rxWS("(\\s)+"); //whitespace anywhere
std::tr1::cmatch res; //the variable which a regex_search writes its results to
while (std::getline(readFile, readout)){
tempLine = std::tr1::regex_replace(readout.c_str(), rxLeadingTrailingWS, ""); //remove leading and trailing whitespace
reducedPrimeList << std::tr1::regex_replace(tempLine.c_str(), rxWS, "\n") << "\n"; //replace all other whitespace with newlines
}
reducedPrimeList.close();
}
Однако этот код занимает минут, чтобы разобрать через 10 Мб файла с. Следующий сценарий Python занимает около 1-3 секунд (не засек):
import re
rxWS = r'\s+'
with open('pythonprimeoutput.txt', 'w') as newfile:
with open('primes1.txt', 'r') as f:
for line in f.readlines():
newfile.write(re.sub(rxWS, "\n", line.strip()) + "\n")
Единственным заметным отличием является то, я использую встроенную функцию в полосе(), чтобы лишить новой строки вместо использования регулярное выражение. (Является ли это источником моего ужасно медленного времени выполнения?)
Я совсем не уверен, откуда исходит ужасная неэффективность моей программы. Файл 10 Мбайт не должен длиться так долго!
* отредактировано: изначально был показан файл размером 20 МБ, это всего лишь 10 МБ.
По предложению Натана Оливера я использовал следующий код, который по-прежнему занимал около 5 минут. Теперь это почти тот же алгоритм, который я использовал в Python. Все еще не уверен, что другое.
void ReWritePrimesFile()
{
std::ifstream readFile("..//primes.txt");
std::ofstream reducedPrimeList("..//newprimelist.txt");
std::string readout;
std::string tempLine;
//std::tr1::regex rxLeadingTrailingWS("^(\\s)+|(\\s)+$"); //whitespace at beginning or end of string
std::tr1::regex rxWS("(\\s)+"); //whitespace anywhere
std::tr1::cmatch res; //the variable which a regex_search writes its results to
while (readFile >> readout){
reducedPrimeList << std::tr1::regex_replace(readout.c_str(), rxWS, "\n") + "\n"; //replace all whitespace with newlines
}
reducedPrimeList.close();
}
второе редактирование: мне пришлось добавить дополнительный символ новой строки в конце строки regex_replace. По-видимому, чтение readFile >> останавливается на каждом символе пробела? Не знаете, как это работает, но он выполняет итерацию цикла while для каждого числа в файле, а не для каждой строки в файле.
Сравнение несправедливо. Вы используете регулярное выражение на C++ дважды, а само регулярное выражение на C++ более сложное, чем python. – deepmax
Более близкий эквивалент C++ к строке.strip() 'будет' boost :: trim (line) '. –
Несколько минут все еще кажется действительно высоким. Попробуйте повторить второе регулярное выражение и время снова, за точку @ deepmax. Мне интересно, есть ли разница в том, как происходит процесс ввода-вывода файлов. Однако, чтобы удалить мой первоначальный ответ, так как неправильно было слишком быстро прочитывать вопрос. Сожалею! –