Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция "переворачиваня" текстового файла, не работает с большими файлами 
:(
    Опции темы
Code Magister
  Дата 5.6.2005, 02:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



Код

#include <conio.h>
#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <stdlib.h>

void main()
{
    FILE *f;
    FILE *f2;
    char str[100], *way;
    unsigned long int c=0;  //счетчик строк

    clrscr();
    cout<<"FileReverser v1.0 beta\n\n";
    cout<<"Input the name of file: ";
    cin>>way;
    f=fopen(way,"r");
    if (!f) { printf("File does not exist...",f); getch(); abort(); }
    f2=fopen("reverse.txt","w");
    if (!f2) { printf("Can't create output file...",f); getch(); abort(); }

    while(!feof(f))       //тут мы считаем сколько всего строк в файле
    {
        fscanf(f,"%s",str); //это нужно только для перемещения курсора
        c++;                         
    }
    while(c>0)           //тут переходим  на последнюю строку, преносим ее в 2 файл, затем на предпоследюю и т. д.
    {
        rewind(f);
        for(int i=1; i<c; i++) fscanf(f,"%s",str);   
        fscanf(f,"%s",str);
        fprintf(f2,"%s\n",str);
        c--;
    }
    cout<<"done!\nPress any key...";
    getch();
    fclose(f);
    fclose(f2);
}

Вот она эта функция, написаная мной.
С небольшими файлами работает безотказно, НО если в файле (насколько я заметил) больше, чем 32786 строки, то прога сначала дуплится, а потом начинает выводить эту самую 32786 строку ХЗ сколько раз.
В чем тут дело?
Добавлено @ 02:12
И еще, если файл меньше, то она хоть и правильно, но как-то очень медленно работает.
Я пытался откомпилировать это в билдере, так там вобще ошибку на стадии выполнения выдает.

Это сообщение отредактировал(а) _Slipknot - 5.6.2005, 02:19
--------------------
PM MAIL WWW ICQ   Вверх
Mayk
Дата 5.6.2005, 07:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Можно сделать так: перемотать файл в конец, потом считывать с конца в буфер n-ное кол-во байт, строки из буфера в обратном порядке пихать в выходной файл. Только тут надо учитывать то, что на начало буфера выпадает середина строки. Поэтому приходится отматывать вперед, чтобы при следующем заходе прочитать всю строку.
И еще один момент - в DOS'е строка оканчивается не так как в Linux. Это может повлиять на результат.

800 килобайтный Фауст(20427 строк) перевернулся за ~0.1 секунду
3 метровый Эмбер(60895 строк) перевернулся за ~0.66 секунды.

Код

#include <stdio.h>
int main(int argc, char** argv)
{
        FILE* fin, *fout;
        long pos;char buf[1024];int len;
        fin = fopen( argv[1], "r" );
        fout = fopen( argv[2], "w" );
        fseek(fin, 0, SEEK_END);
        pos = ftell(fin);
        while( pos > 0 ){
                char* ptr;
                len = ( pos < sizeof(buf) ) ? pos : sizeof(buf);
                fseek(fin, -len, SEEK_CUR);
                printf("%x\n", pos);
                fread(buf, len, 1, fin);
                buf[len]=0;
                while( ptr = strrchr(buf, '\n') ){
                        *ptr++=0;
                        fprintf(fout,"%s\n",ptr);
                }
                if( pos < sizeof(buf) ){
                        fputs(buf, fout);
                        break;
                }
                fseek(fin, strlen( buf )-len, SEEK_CUR);
                pos += strlen( buf ) - len;
        }
        fclose(fin);
        fclose(fout);
}


Цитата(_Slipknot @ 5.6.2005, 02:09)
И еще, если файл меньше, то она хоть и правильно, но как-то очень медленно работает.

Ну так, посмотри как ты много читаешь: допустим в файле 5 строк.
Ты прочитаешь 5 строк, чтобы узнать их кол-во,
затем прочитаешь 4 строки, чтобы прочитать и вывести пятую,
потом три строки, чтобы вывести четвертую.
В общем кол-во чтений строк - сумма арифмитической прогрессии от 1 до n, где n - кол-во строк. И это будет что-то типа
S=n*((1+n)/2)=(n^2+n)/2;
если я не попутал. В примере S = (25+5) / 2 = 15; да еще +5 = 20 чтений строк.
А теперь пусть n=1000=10^3. S=(10^6+10^3) / 2 = 10 * (10^5 + 10^2) / 2 = 5 * 10^ 5 + 5 * 10^2 = 50500 чтений. Это много.





--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Code Magister
Дата 5.6.2005, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



спасибо конечно за прогу, но я хочу разобратъся со своей.
Цитата
А теперь пусть n=1000=10^3. S=(10^6+10^3) / 2 = 10 * (10^5 + 10^2) / 2 = 5 * 10^ 5 + 5 * 10^2 = 50500 чтений. Это много.

можно попроще обьяснить? и как это исправить?
--------------------
PM MAIL WWW ICQ   Вверх
Mayk
Дата 5.6.2005, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(_Slipknot @ 5.6.2005, 19:33)
и как это исправить?

Я привел пример как это делать быстрее.

Цитата(_Slipknot @ 5.6.2005, 19:33)

можно попроще обьяснить


[в прошлом посте недоквотил "в чем тут дело?"]

По-проще это будет "функция fscanf вызывается СЛИШКОМ много раз, этого можно избежать". Или "алгоритм не годится для решения задачи".

Те вычисления показывают что значит слово "СЛИШКОМ" и объясняют почему
алгоритм не годится:
Большую часть времени программа из первого листинга бегает по файлу туда-сюда, хотя этого можно избежать. Медленная работа вызвана выбором далеко не лучшего алгоритма.
Кол-во fscanfов(кстати fgets() подошел бы больше) есть квадратичная функция
(это показано в вычислениях).
Программа из второго листинга бегает гораздо реже(и там кол-во вызовов fseek() есть линейная функция, которая кстати от кол-ва строк зависит лишь косвенно).


Графики функций ax^2 и kx представляешь?








--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
__Sergey__
Дата 6.6.2005, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 21.1.2005

Репутация: нет
Всего: 4



Пример от Рихтера

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  17_FileRev.rar 5,32 Kb
PM MAIL   Вверх
Code Magister
Дата 6.6.2005, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



Mayk а что от того, что она много бегает по файлу,она зависает чтоли?
--------------------
PM MAIL WWW ICQ   Вверх
Mayk
Дата 6.6.2005, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(_Slipknot @ 6.6.2005, 18:15)
Mayk а что от того, что она много бегает по файлу,она зависает чтоли?

Она от этого медленно работает. А зависает от... (копаюсь)... Хм, по-моему она не зависает. Просто медленно работает, можно делать printf("%d",c); чтоб не скучно было.

Теперь к дупам:
Вот в 30 строчке есть
Код

for(int i=1; i<c; i++) fscanf(f,"%s",str);

Ну если особо не вдаваться в подробности - вот здесь int заменить на unsigned long int.

Кстати, только сейчас заметил, прога переворачивает слова, а не строки, а в комментариях указаны строки... И еще - cin >> way; куда указывает way?

Это сообщение отредактировал(а) Mayk - 6.6.2005, 20:45


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Code Magister
Дата 6.6.2005, 23:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



Цитата(Mayk @ 6.6.2005, 20:42)
Она от этого медленно работает. А зависает от... (копаюсь)... Хм, по-моему она не зависает.

Зависает, зацикливается на 32768 строчке. Если б проблема была только в быстродействии - для меня это не была б проблема.
Цитата(Mayk @ 6.6.2005, 20:42)
Ну если особо не вдаваться в подробности - вот здесь int заменить на unsigned long int.

Точно, с long, а i int - ща исправим.
Цитата(Mayk @ 6.6.2005, 20:42)
Кстати, только сейчас заметил, прога переворачивает слова, а не строки, а в комментариях указаны строки...

Прога переворачивает строки. 1-я строчка станет последней, а последняя первой. Сами строчки при этом не изменятся
Цитата(Mayk @ 6.6.2005, 20:42)
И еще - cin >> way; куда указывает way?

way - это путь файла, который мы будем переворачивать.
Добавлено @ 23:38
Mayk да, проблема была именно в типе i. Кажется теперь работает, хоть и медленно.
Спасибо за помощь!
--------------------
PM MAIL WWW ICQ   Вверх
Code Magister
Дата 7.6.2005, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



А насчет твоей проги. Так она переворачивает только первые 128 строк.
Как я понял она считывает файл в оперативу.
Я увеличил размер
Цитата(Mayk @ 5.6.2005, 07:32)
char buf[1024]
и она прочитала больше строк. Тогда я увеличил его до char buf[65535]. И она уже продолжительное время работает... Или я не так понял принцип ее работы?
--------------------
PM MAIL WWW ICQ   Вверх
ManiaK
Дата 7.6.2005, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



Цитата(_Slipknot @ 6.6.2005, 23:31)
Зависает, зацикливается на 32768 строчке.

Помножте число на двое и вычтете единицу. Получите 0xFFFF. Это значит, что в какой-то функции происходит переполнение двухбайтовой знаковой переменной.
PM MAIL WWW   Вверх
Mayk
Дата 7.6.2005, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Судя по всему не понял. Приницип я уже пояснял.
Теперь проиллюстрирую работу:
входной файл:
--- a.txt ---
AAAAAA`\n`
BBBBBB`\n`
CCCCCC`\n`
-- eof ---
Размер буфера = 10.
Теперь посмотрим что прочтется из файла.
--- a.txt --
AAAAAA`\n`
BBBB[BB`\n`
CCCCCC`\n`
]
--- eof ---
в квадратных скобках выделено жирным то, что содержится в буфере.
Теперь прочтенные строки пихаем в обратном порядку:
1) \n в конце. Все что справа пихаем в выходной файл и \n. Так как правее нет ничего, то в выходной файл идет только \n (багофича). Заменяем '\n' на 0
2) '\n' после BB. Все что правее пихаем в выходной файл + '\n'. Туда добавляется "CCCCCC\n"
'\n' меняем на 0.
EOL'ов больше нет.

Считываем следующий блок.
Так как в буфере есть два байта то теперь мы считываем не 10 байт, а только 8(таким образом мы прочитаем эту строчку полностью)
--- a.txt --
AAA[AAA`\n`
BBBBBB
]`\n`
CCCCCC`\n`
--- eof ---

В выходной файл идет все что правее '\n'. то есть BBBBBB. Плюс перевод строки.
(кстати, теперь в выходном файле три строки: пустая, CCCCCC, BBBBBB)

В буфере остается 3 байта.
Мы не можем полностью заполнить весь буфер, поэтому считываем так:

--- a.txt --
[AAAAAA]`\n`
BBBBBB`\n`
CCCCCC`\n`
--- eof ---

Выкидываем эту строку в выходной файл. Теперь файл перевернут










--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Code Magister
Дата 7.6.2005, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



Mayk тогда хз че она у меня не работает.
А моя уже 2-й час переворачивает 6-ти метровый файлик. Тише едешь - дальше будешь smile
--------------------
PM MAIL WWW ICQ   Вверх
ManiaK
Дата 7.6.2005, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



Цитата(_Slipknot @ 5.6.2005, 02:09)
for(int i=1; i<c; i++) fscanf(f,"%s",str);


Вот это место. Похоже в вашем компиляторе int - двухбайтовый. Тогда, разумеется, цикл будет вечным. Замените на unsigned long int или, лучше, просто unsigned long (насколько знаю, разницы никакой).
PM MAIL WWW   Вверх
Mayk
Дата 7.6.2005, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



_Slipknot
Какой компилятор используешь?


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Code Magister
Дата 7.6.2005, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Magister of Code
*


Профиль
Группа: Участник
Сообщений: 155
Регистрация: 9.7.2004
Где: Kiev

Репутация: 1
Всего: 1



ManiaK почитай посты выше. Я уже нашел ошибку и исправил ее.
А говорим мы сейчас о программе, которую написал Mayk
Добавлено @ 16:04
Mayk BC++ 3.1
--------------------
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0682 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.