Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Ада и другие языки _ Файлы (вместо типизированных)

Автор: мисс_граффити 27.10.2006 1:07

есть алгоритм многофазной сортировки, которая работает с файлами. в делфи это был file of integer.
поскольку в с++ абсолютного аналога нет, возник вопрос - что выбрать из имеющихся средств?
Запуталась sad.gif
В чем разница между парами:
fread-fwrite; (для всего подряд?)
fscanf-fprintf; (форматированный ввод/вывод? то есть %d - и будет мне десятичное целое число, как и хочется?)
fgets-fputs; (это вроде для строк.... то есть потом можно сделать IntToStr...)

подскажете?

Автор: volvo 27.10.2006 1:25

Ты забыла еще одну пару:
fgetc/fputc - посимвольное чтение из потока. Как раз то, что тебе нужно, если работаешь с file of byte в терминологии Паскаля... Если же тип более емкий, то я бы выбрал fread/fwrite - аналог blockread/blockwrite, нужно работать с int, тогда

int i;
FILE *f = fopen("file.dat", "rb");
...
fread(&i, sizeof(i), 1, f); // <--- вот и чтение одного int-а
...

Можно вообще выделить это в отдельные функции типа read_int/write_int, и работать именно с бинарным представлением (как и было в file of integer, кстати), а не с текстовым, как в случае fscanf/fprintf

Автор: мисс_граффити 27.10.2006 2:03

спасибо!

Автор: мисс_граффити 29.10.2006 22:36

Пишу:

void MakeFile (void)
{
FILE *f = fopen("vvod.dat", "wb+");
randomize();
int n=random(50)+50;
for (int j=1;j<n;j++)
{
int i=random(500);
fwrite(&i, sizeof(i), 1, f);
Form1->Memo1->Lines->Add(IntToStr(i));
}
fclose(f);
}
//---------------------------------------------------------------------------
void ShowFile (void)
{
FILE *f;
if ((f = fopen("vvod.dat", "rb")))
{
while (!(feof(f)))
{
int i;
fread(&i,sizeof(i), 1, f);
Form1->Memo2->Lines->Add(IntToStr(i));
}
}
else
ShowMessage("!!!");
fclose(f);
}

Все замечательно, но последний элемент выводится дважды... То есть в Memo2 оказывается на строчку больше...
Почему такое может быть?

Автор: volvo 29.10.2006 23:12

Цитата
Почему такое может быть?
Потому, что нужно анализировать результат, возвращаемый fread: если она ничего не прочла из файла, то вернется 0 (ты забыла про #26 - символ конца файла, формально конец файла еще не достигнут, т.е. feof() возвращает "ложь", но при попытке считывания очередного числа происходит считывание #26, и число, естественно, не читаясь заново, остается тем же, что и было прочитано в прошлый раз)...

    while (!(feof(f)))
{
int i;
if( fread(&i,sizeof(i), 1, f) != 0 )
Form1->Memo2->Lines->Add(IntToStr(i));
}

Автор: мисс_граффити 30.10.2006 2:50

tnx.
...и еще вопрос возник: как можно узнать размер файла? то есть нужен аналог SizeOf(F).
на lengthfile ругается, что вообще такого не знает.
GetSizeFile работает, но как-то непонятно.... Что-то совершенно не то возвращает.
Если это повлияет на ответ, конкретизирую задание.
После сортировки у меня получается 3 файла: 2 пустых и 1 с отсортированной последовательностью. Пустые надо удалять, а полный переименовывать. Просто запомнить номер в принципе возможно, но достаточно проблематично...

Автор: volvo 30.10.2006 2:56

Из хелпа Turbo C++ 3.0:

  long filesize(FILE *stream)
{
long curpos, length;

curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET);
return length;
}

Автор: мисс_граффити 30.10.2006 22:17

понимаю, что уже замучала....
но опять с вопросами:

...
fclose(Lenta[TAPE[T-1]]);
Lenta[TAPE[T-1]]=fopen(("L"+IntToStr(TAPE[T-1])+".dat").c_str(),"rb+");
...

Куда устанавливает указатель fopen? В начало файла или в конец?

Автор: мисс_граффити 31.10.2006 2:03

...нашла ошибку. а вот как ее избежать...
как можно указатель "отмотать" на 1 элемент назад?
пробовала

fseek(Lenta[TAPE[i]],-1*sizeof(i),SEEK_CUR); 
- че-то не то.

Автор: volvo 31.10.2006 18:16

Юля, а при чем здесь sizeof(int)? Надо делать sizeof(struct) ...

Автор: мисс_граффити 31.10.2006 20:00

а что есть struct?...
у меня ситуация какая: при некотором условии получается, что я считываю лишний элемент (int). то есть надо вернуться и считать его еще раз... соответственно, возвращаюсь именно на размер int'а.
не так?

Автор: volvo 31.10.2006 20:15

Тогда приведи описания Lenta и TAPE ...

Цитата
при некотором условии получается, что я считываю лишний элемент (int)
Так вот при этом условии НЕ считывай ничего из файла... Как ты хочешь, чтоб тебе подсказали, если ничего не привела, ни ОТКУДА читаешь, ни КУДА, ни СКОЛЬКО...

Автор: мисс_граффити 31.10.2006 20:40

void MergeSort(void)
{
const T=3,p=2;
int suma=0,sumd=0;
int A[T],D[T],TAPE[T];
MakeFile();
Start(T,p,A,D,TAPE,&suma,&sumd);
FILE *Lenta[3];
Lenta[TAPE[T-1]]=fopen("L2.dat","wb+");
for (int j=0;j<T-1;j++)
Lenta[TAPE[j]]=fopen(("L"+IntToStr(j)+".dat").c_str(),"rb");
int Dmax=0, Dost[3];
int sort[3];
while (Dmax<suma)
{
while ( ((fread(&sort[0],sizeof(sort[0]),1,Lenta[TAPE[0]]))!=0)&&((fread(&sort[1],sizeof(sort[1]),1,Lenta[TAPE[1]]))!=0) )
//вот здесь считывается лишнее - одна лента кончилась, а вторая еще нет
{
for (int j=0;j<T;j++)
Dost[j]=D[j];
int zerro=0;
while (zerro<T-1)
{
int min=MaxInt;
int mini;
for (int i=0;i<T-1;i++)
if ((sort[TAPE[i]]<=min)&&(Dost[TAPE[i]]>0))
{
min=sort[TAPE[i]];
mini=i;
}
fwrite(&min,sizeof(min),1,Lenta[TAPE[T-1]]);
Dost[TAPE[mini]]--;
if (Dost[TAPE[mini]]>0)
fread(&sort[TAPE[mini]],sizeof(sort[mini]),1,Lenta[TAPE[mini]]);
else
{
sort[TAPE[mini]]=MaxInt;
zerro++;
}
}
}
for (int i=0;i<T-1;i++)
if (feof(Lenta[TAPE[i]])) //если кончилась лента....
{
D[TAPE[T-1]]=0;
for (int j=0;j<T-1;j++)
D[TAPE[T-1]]+=D[TAPE[j]];
Dmax=D[TAPE[T-1]];
int zap;
fclose(Lenta[TAPE[T-1]]);
Lenta[TAPE[T-1]]=fopen(("L"+IntToStr(TAPE[T-1])+".dat").c_str(),"rb");
int j=TAPE[i];
TAPE[i]=TAPE[T-1];
TAPE[T-1]=j;
fclose(Lenta[TAPE[T-1]]);
Lenta[TAPE[T-1]]=fopen(("L"+IntToStr(TAPE[T-1])+".dat").c_str(),"wb+");
}
else
fseek(Lenta[TAPE[i]],-1*sizeof(i),SEEK_CUR); //а если не кончилась, надо вернуться к предыдущему эл-ту...
}

fcloseall;
}

Автор: volvo 31.10.2006 22:38

Единственное, что приходит в голову - попробуй вот так (нужно привести смещение к типу long):

fseek(Lenta[TAPE[i]], - (long)sizeof(sort[0]), SEEK_CUR);


Кстати, ты уверена, что когда эта операция должна происходить, то есть куда откатываться? Если текущая позиция будет равна 0 (самое начало файла), то будет ошибка и fseek вернет -1...

Автор: мисс_граффити 31.10.2006 23:49

уверена...
0 возвращает.
типа промоталась.
а считывать потом все равно отказывается.

Автор: volvo 1.11.2006 1:03

Юля, присоединить весь проект с данными вместе (в архиве) сможешь? Так, чтобы можно было скомпилировать и пройти пошагово... Просто интересно, что можно сделать в этом случае...

Можно на PM ...

Автор: мисс_граффити 1.11.2006 1:40

вот...
лр4.rar
дубль 1.rar - то же самое на делфи. с маленьким отличием: работает так, как надо....


Прикрепленные файлы
Прикрепленный файл  ______1.rar ( 9.5 килобайт ) Кол-во скачиваний: 180
Прикрепленный файл  __4.rar ( 390.11 килобайт ) Кол-во скачиваний: 175

Автор: volvo 1.11.2006 22:39

Так... Значит, я добил эту программу (в смысле, она теперь работоспособна, единственное что нужно сделать - пройтись по ней, и убрать лишний индекс во всех массивах... Я сделал везде описание int ... [T+1])... Выкладываю только что отработавшую у меня под TC3.0 (Builder-а, к сожалению, не имею...) версию вместе со всей отладочной информацией, может она поможет тебе разобрать что к чему... Работает ТОЧНО так же, как и Дельфийская...

Основная идея (в двух словах) - замени стандартную функцию feof() на вот такую:

int fEOF(FILE *stream)
{
return (ftell(stream) == filesize(stream) || feof(stream));
}
и тот самый проблемный цикл сделай не
while( (!feof(Lenta[TAPE[1]])) && (!feof(Lenta[TAPE[2]])) ) {
...
}

, а
do {
...
} while( (!fEOF(Lenta[TAPE[1]])) && (!fEOF(Lenta[TAPE[2]])) );

smile.gif

P.S. Расширение - PAS, потому что CPP файлы пока нельзя приаттачивать...


Прикрепленные файлы
Прикрепленный файл  __MISS__.PAS ( 7.35 килобайт ) Кол-во скачиваний: 265

Автор: мисс_граффити 2.11.2006 2:08

Супер! Спасибо огромное....
Буду разбираться....