0k
Гость
|
|
« : 19-04-2008 09:39 » |
|
Доброго времени суток! Есть текстовый файл размером ~65 Мб, ~605000 строк. Из этих строк необходимо выделить строки, котрые содержат подстроки "10077" и "Новая запись:" и сохранить их в другой текстовый файл. Написал следующий код: #include <stdio.h> #include <string.h>
int main(void) { FILE* log_file; FILE* result_file; char current_str[1000];
if(!(log_file=fopen("log.txt", "r"))) { printf("Open log_file failed.\n"); return 0; }
result_file=fopen("result.txt", "w");
fin: while(!(feof(log_file))) { fgets(current_str, 1000, log_file);
if (ferror(log_file)) { printf("error"); return 0; }
if (((strstr(current_str,"10077"))!=NULL)&&((strstr(c urrent_str,"Новая запись:"))!=NULL)) { fputs(current_str, stdout); fputs(current_str, result_file); } else goto fin; }
fclose(log_file); fclose(result_file);
return 0; }
код работает, но обрабатывает файл не до конца: только 750 строк. В чем ошибка?
|
|
« Последнее редактирование: 19-04-2008 09:56 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 19-04-2008 09:48 » |
|
0k, для на чала исправь код так, чтобы там не использовалось GOTO
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #2 : 19-04-2008 10:27 » |
|
Тоже не понял, к чему там goto. 65мегабайтных текстовых файлов у меня нет, поэтому испытал на 1,2 МБ - проходит до конца. Из этих строк необходимо выделить строки, котрые содержат подстроки "10077" и "Новая запись:" Содержат обе подстроки одновременно? Ещё смущает return из цикла без закрытия дескрипторов файлов - если будет ошибка, можешь потерять данные, по идее.
|
|
« Последнее редактирование: 19-04-2008 10:30 от Вад »
|
Записан
|
|
|
|
0k
Гость
|
|
« Ответ #3 : 20-04-2008 05:25 » |
|
0k, для на чала исправь код так, чтобы там не использовалось GOTO сорри. конечно, это нафик здесь не надо. сказывается бейсиковское детство) Исправил: #include <stdio.h> #include <string.h>
int main(void) { FILE* log_file; FILE* result_file; char current_str[500];
/*if(!(log_file=fopen("log.txt", "r"))) { printf("Open log_file failed.\n"); return 0; } */ log_file=fopen("log.txt", "r"); result_file=fopen("result.txt", "w"); while(!(feof(log_file))) { fgets(current_str, 500, log_file); if (ferror(log_file)) { printf("error"); return 0; }
if (((strchr(current_str, '+'))==NULL)&&((strchr(current_str, '*'))==NULL)) { if (((strstr(current_str,"10077"))!=NULL)&&((strstr(current_str,"Новая запись:"))!=NULL)) { fputs(current_str, stdout); fputs(current_str, result_file); } } } fclose(log_file); fclose(result_file); return 0; }
Вад, нужно выделить строку, в которой содержатся обе эти строки одновременно. Здесь еще один момент... файл кроме символов, содержит бинарные данные, перед которыми стоят символы "+" или "*". Может из-за этого затыкается?
|
|
« Последнее редактирование: 20-04-2008 07:49 от Вад »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #4 : 20-04-2008 05:52 » |
|
файл кроме символов, содержит бинарные данные, перед которыми стоят символы "+" или "*". А после них что стоит? Или какова их длина? И считать ли их за одну строчку (несмотря на возможные в них символы перевода строки и нулевые символы)? f (((strstr(current_str,"10077"))!=NULL)&&((strstr(current_str,"Новая запись:"))!=NULL)) Ещё полезно бы знать алгоритм поиска подстроки в строке, чтобы адаптировать его и искать всё нужное за один проход. Впрочем, это не необходимость, а пожелание.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Антон (LogRus)
|
|
« Ответ #5 : 21-04-2008 04:37 » |
|
int _tmain(int argc, _TCHAR* argv[]) { std::ifstream inf("input.txt"); std::ofstream outf("output.txt");
while (!inf.eof()) { std::string tmp_str; std::getline(inf, tmp_str);
if ((std::string::npos != tmp_str.find("10077")) && (std::string::npos != tmp_str.find("Новая запись:"))) outf << tmp_str << "\n"; }
return 0; }
|
|
|
Записан
|
Странно всё это....
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #6 : 21-04-2008 05:16 » |
|
std::getline(inf, tmp_str); Это с бинарными данными может обломиться, если в бинарных данных найдётся \n. Хотя если искать сами вхождения, а не строки, их содержащие, то не важно.
|
|
« Последнее редактирование: 21-04-2008 05:18 от dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
0k
Гость
|
|
« Ответ #7 : 22-04-2008 04:37 » |
|
Всем спасибо за помощь! Заработало. Изменил метод доступа с текстового на бинарный и еще кой-чего поправил: void __fastcall TForm1::Button1Click(TObject *Sender) { FILE* log_file; FILE* result_file; char current_str[500]; unsigned long n,i=0; unsigned long k=0;
log_file=fopen("e:\\log_080421.txt", "rb");
if (log_file==NULL) { printf("Open log_file failed.\n"); return; }
result_file=fopen("e:\\77777_210408.txt","w");
ProgressBar1->Max=500;
while(!(feof(log_file))) { Application->ProcessMessages(); if(f==1)return; n=fread(¤t_str[i],1,1,log_file); i++; ProgressBar1->Position++; if((current_str[i-1]==0x0A)&&(current_str[i-2]==0x0D)) { if(((strstr(current_str,"10077"))!=NULL)&&((strstr(current_str,"Новая запись:"))!=NULL)) { fputs(current_str, result_file); } for (k=0;k<500;k++)current_str[k]=0x00; i=0; ProgressBar1->Position=0; } }
fclose(log_file); fclose(result_file);
return; }
|
|
« Последнее редактирование: 22-04-2008 05:07 от Вад »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #8 : 22-04-2008 05:16 » |
|
я бы лучше сделал break вместо return - так хотя бы точно закроются дескрипторы файлов, да и одна точка выхода в таких случаях, имхо, лучше, чем две, при том, что во втором случае одна - в теле цикла Побайтовое чтение сделал? Имхо, не самый лучший вариант. Тогда уж реализация через iostreem выглядела бы логичнее, наверное. Ты говорил что-то о бинарных данных - ты их сейчас просто пропускаешь через поиск наравне с остальными данными, выходит. Ну и заполнение строки нулями - насколько оно вообще имеет смысл? Может, стоит просто делать if((current_str[i-1]==0x0A)&&(current_str[i-2]==0x0D)) { current_str[i]=0; // ... }
?
|
|
|
Записан
|
|
|
|
0k
Гость
|
|
« Ответ #9 : 23-04-2008 11:44 » |
|
Ну и заполнение строки нулями - насколько оно вообще имеет смысл? Может, стоит просто делать if((current_str[i-1]==0x0A)&&(current_str[i-2]==0x0D)) { current_str[i]=0; // ... }
? мне нужно очистить массив. Сделал так: for (k=0;k<=i;k++)current_str[k]=0x00;
заработало быстрее
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #10 : 23-04-2008 12:16 » |
|
0k, просто я не увидел смысла в очистке строки - зануление у тебя используется только для того, чтобы на следующей итерации строка после посимвольного чтения была NULL-terminated, чтобы можно было корректно с ней дальше работать. Вот и предложил оптимизацию
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 23-04-2008 13:54 » |
|
>>заработало быстрее а вот так ещё быстрее будет memset(current_str,0,i); а всё таки воот так - ещёёёё быстрее current_str[0]=0;
|
|
|
Записан
|
|
|
|
0k
Гость
|
|
« Ответ #12 : 26-04-2008 10:01 » |
|
Всем спасибо. Оффтопик, но все же... Как в C Builder передавать пути к файлам из OpenDialog и SaveDialog (AnsiString) в fopen (char*) и задавать строки для поиска в Edit? Т.е. нужно преобразовать AnsiString в char.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #13 : 26-04-2008 10:14 » |
|
ְAnsiString по идее говоря хранит строку как массив чаров. Можно попробовать (char *)string или &string[0], а лучше почитать хелп.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #14 : 26-04-2008 10:37 » |
|
в классе ansistring есть метод c_str(). возвращает char*
|
|
|
Записан
|
|
|
|
0k
Гость
|
|
« Ответ #15 : 29-04-2008 04:34 » |
|
в классе ansistring есть метод c_str(). возвращает char*
Спасибо, все получилось
|
|
|
Записан
|
|
|
|
marat_
Шеф-повар
Опытный
Offline
|
|
« Ответ #16 : 29-04-2008 11:09 » |
|
не за что, обращайся
|
|
|
Записан
|
|
|
|
|