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

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

    while (!(feof(f)))
{
int i;
if( fread(&i,sizeof(i), 1, f) != 0 )
Form1->Memo2->Lines->Add(IntToStr(i));
}
мисс_граффити
tnx.
...и еще вопрос возник: как можно узнать размер файла? то есть нужен аналог SizeOf(F).
на lengthfile ругается, что вообще такого не знает.
GetSizeFile работает, но как-то непонятно.... Что-то совершенно не то возвращает.
Если это повлияет на ответ, конкретизирую задание.
После сортировки у меня получается 3 файла: 2 пустых и 1 с отсортированной последовательностью. Пустые надо удалять, а полный переименовывать. Просто запомнить номер в принципе возможно, но достаточно проблематично...
volvo
Из хелпа 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;
}
мисс_граффити
понимаю, что уже замучала....
но опять с вопросами:
...
fclose(Lenta[TAPE[T-1]]);
Lenta[TAPE[T-1]]=fopen(("L"+IntToStr(TAPE[T-1])+".dat").c_str(),"rb+");
...

Куда устанавливает указатель fopen? В начало файла или в конец?
мисс_граффити
...нашла ошибку. а вот как ее избежать...
как можно указатель "отмотать" на 1 элемент назад?
пробовала
fseek(Lenta[TAPE[i]],-1*sizeof(i),SEEK_CUR); 
- че-то не то.
volvo
Юля, а при чем здесь sizeof(int)? Надо делать sizeof(struct) ...
мисс_граффити
а что есть struct?...
у меня ситуация какая: при некотором условии получается, что я считываю лишний элемент (int). то есть надо вернуться и считать его еще раз... соответственно, возвращаюсь именно на размер int'а.
не так?
volvo
Тогда приведи описания Lenta и TAPE ...

Цитата
при некотором условии получается, что я считываю лишний элемент (int)
Так вот при этом условии НЕ считывай ничего из файла... Как ты хочешь, чтоб тебе подсказали, если ничего не привела, ни ОТКУДА читаешь, ни КУДА, ни СКОЛЬКО...
мисс_граффити
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
Единственное, что приходит в голову - попробуй вот так (нужно привести смещение к типу long):
fseek(Lenta[TAPE[i]], - (long)sizeof(sort[0]), SEEK_CUR);


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

Можно на PM ...
мисс_граффити
вот...
лр4.rar
дубль 1.rar - то же самое на делфи. с маленьким отличием: работает так, как надо....
volvo
Так... Значит, я добил эту программу (в смысле, она теперь работоспособна, единственное что нужно сделать - пройтись по ней, и убрать лишний индекс во всех массивах... Я сделал везде описание 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 файлы пока нельзя приаттачивать...
мисс_граффити
Супер! Спасибо огромное....
Буду разбираться....
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.