Программа "валится" на методе сортировки файла при записи - C (СИ)
Формулировка задачи:
Доброго времени суток!
Есть вот такая вот программка. Валится на методе сортировки файла при записи в el58.dat. Не найду где.
По условиям задания надо:
1)страна в 1958 выработала больше всех энергии;
2)страны которые в 1955 выработали больше 70 млрд;
3) отсортировать по алфавиту страны которые в 1958 не превысили производство 100 млрд.
Вот на третьем и валится. Можно посмотреть исправленный вариант?
#include "stdafx.h"
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//--------------Прототипы функций------------------
void fileInput(); //Формирование файла
void fileOutput(char*); //Вывод файла
void max58(); //Вывод максимального оборота
void form55(); //Формирование файла со страними с экспортом болеее 900
void form58(); //Формирование файла со страними с импортом менее 1000
void Sort(char*); //Сортировка файла
//------------Глобальные переменные ---------------
struct Record
{ //структуры данных
char country[20]; //Название страны
float el55; //Произведено электроэнергии в 1955
float el58; //в 1958
} a,b;
FILE *fv, *f2; //Файлы прямого доступа
//------------ Основная программа ----------------
int main(void)
{
int f;
printf("Formirovat file? (1 - yes, 0 - no)\n");
scanf("%d",&f);
if(f)
fileInput();
fileOutput("data.dat");
max58();
form55();
printf("Strani, elektri4estdvo v kotorih bolshe 70 mld v 1955\n");
fileOutput("el55.dat");
form58();
Sort("el58.dat");
printf("Strani, elektri4estdvo v kotorih bolshe 100 mld v 1958\n");
fileOutput("el58.dat");
getch();
}
//--------- Реализация функций ---------------------
void fileInput()
{
float f;
if ((fv = fopen("data.dat","w")) == NULL)//Открытие файла для записи
{
printf("Error open file!\n");
exit(-1);
}
strcpy(a.country,"a");
while (strcmp(a.country,"0")!=0) //Ввод записей пока вместо найвания страны не введен 0
{
printf("Enter country <<0 - exit>>\n");
scanf("%s",a.country); //Ввод названия страны
if (strcmp(a.country,"0")!=0)
{
printf("Enter koli4estvo v 1955\n");//Ввод электрических параметров страны
scanf("%f",&f);
a.el55 = f;
printf("Enter koli4estvo v 1958\n");
scanf("%f",&a.el58);
fwrite(&a,sizeof(a),1,fv); //Запись структуры в файл
}
}
printf("Data is writen\n");
fclose(fv); //Закрытие файла
}
void fileOutput(char* name)
{
int uk,i;
if ((fv = fopen(name,"r")) == NULL) //Открытие файла для чтения
{
printf("Error open file!\n");
exit(-1);
}
fseek(fv,0,SEEK_END);
uk = ftell(fv); //Определание размера файла
i = 0; //начальная позиция файла
printf("-----------------------------------\n");
printf("! country !1955 !1958 !\n");
printf("-----------------------------------\n");
while (i<uk) //Пока не достигнут конец файла
{
fseek(fv,i,SEEK_SET); //Установка указателя на текущую позицию
fread(&a,sizeof(a),1,fv); //Чтение текущей структуры из файла
printf("!%20s !%5.1f!%5.1f!\n",
a.country,a.el55,a.el58); //вывод на экран
i += sizeof(a); //Перевод указателя на следующую структуру
}
printf("-----------------------------------\n");
fclose(fv); //Закрытие файла
}
void max58()
{
int uk,i;
float max;
if ((fv = fopen("data.dat","r")) == NULL)//Открытие файла для чтения
{
printf("Error open file!\n");
exit(-1);
}
fseek(fv,0,SEEK_END);
uk = ftell(fv); //Определание размера файла
i = 0; //начальная позиция файла
while (i<uk) //Пока не достигнут конец файла
{
fseek(fv,i,SEEK_SET); //Установка указателя на текущую позицию
fread(&a,sizeof(a),1,fv); //Чтение текущей структуры из файла
if (i==0) //Если тек. структура пермая
max = a.el58-1; //максимуму присваивается заведомо меньшее значение
if (a.el58>max) //количество электроэнерии больше максимального
{
max = a.el58; //Обновление максимального
strcpy(b.country,a.country); //Копирование структуры
b.el55 = a.el55;
b.el58 = a.el58;
}
i += sizeof(a); //Перевод указателя на следующую структуру
}
fclose(fv); //Закрытие файла
printf("max v 1958 - %5.1f (%s)\n",b.el58,b.country);//Вывод результата на экран
}
void form55()
{
int uk,i;
if ((fv = fopen("data.dat","r")) == NULL)//Открытие файла для чтения
{
printf("Error open file!\n");
exit(-1);
}
if ((f2= fopen("el55.dat","w"))== NULL)//Открытие файла для записи
{
printf("Error open file!\n");
exit(-1);
}
fseek(fv,0,SEEK_END);
uk = ftell(fv); //Определание размера файла
i = 0; //начальная позиция файла
while (i<uk) //Пока не достигнут конец файла
{
fseek(fv,i,SEEK_SET); //Установка указателя на текущую позицию
fread(&a,sizeof(a),1,fv); //Чтение текущей структуры из файла
if (a.el55>70) //Если кол-во эл. в 1955 больше 70
{
fwrite(&a,sizeof(a),1,f2); //запись структуры во второй файл
}
i += sizeof(a); //Перевод указателя на следующую структуру
}
fclose(fv); //Закрытие исходного файла
fclose(f2); //Закрытие второго файла
}
void form58()
{
int uk,i;
if ((fv = fopen("data.dat","r")) == NULL)//Открытие файла для чтения
{
printf("Error open file!\n");
exit(-1);
}
if ((f2= fopen("el58.dat","w")) == NULL) //Открытие файла для записи
{
printf("Error open file!\n");
exit(-1);
}
fseek(fv,0,SEEK_END);
uk = ftell(fv); //Определание размера файла
i = 0; //начальная позиция файла
while (i<uk) //Пока не достигнут конец файла
{
fseek(fv,i,SEEK_SET); //Установка указателя на текущую позицию
fread(&a,sizeof(a),1,fv); //Чтение текущей структуры из файла
if (a.el58<100) //Если кол-во эл. в 1958 меньше 100
{
fwrite(&a,sizeof(a),1,f2); //запись структуры во второй файл
}
i += sizeof(a); //Перевод указателя на следующую структуру
}
fclose(fv); //Закрытие исходного файла
fclose(f2); //Закрытие второго файла
}
void Sort(char*name)
{
int i=0, j, pos,n;
if ((fv = fopen(name,"r+w")) == NULL) //Открытие файла для чтения и записи
{
printf("Error open file!\n");
exit(-1);
}
fseek(fv,0,SEEK_SET);
n = ftell(fv)/sizeof(a); //Определение количества записей в файле
while (i<(sizeof(a)*(n-1))) //Пересмотр всех записей кроме последней
{
fseek(fv,i,SEEK_SET);
fread(&a,sizeof(a),1,fv);
j = i+sizeof(a);
while (j<(sizeof(a)*n)) //Просмотр всех записей кроме уже отсортированых
{
fseek(fv,j,SEEK_SET);
fread(&b,sizeof(b),1,fv);
if (strcmp(a.country,b.country)>0)//Сравнение названий стран
{
pos = i;
fseek(fv,pos,SEEK_SET);
fwrite(&b,sizeof(b),1,fv); //Запись структуры b вместо а
pos = j;
fseek(fv,pos,SEEK_SET);
fwrite(&a,sizeof(a),1,fv); //Запись структуры а вместо b
strcpy(a.country,b.country);
a.el55 = b.el55; //Копирование структуры b в а
a.el58 = b.el58;
}
j += sizeof(b);
}
i += sizeof(a);
}
fclose(fv);
}
Иными словами, оно должно выглядеть примерно так:
[404]
а выглядит вот так(падает как раз на моменте сортировки):
[404]
А у самого мозгов не хватает исправить ошибку.
Решение задачи: «Программа "валится" на методе сортировки файла при записи»
textual
Листинг программы
int cmp(const void * a, const void * b) {
return strcmp(((Record*)a)->country,((Record*)b)->country);
}
void Sort(char*name)
{
int i=0, j, pos,n;
if ((fv = fopen(name,"rb+")) == NULL) //Открытие файла для чтения и записи
{
printf("Error open file!\n");
exit(-1);
}
fseek(fv,0,SEEK_END);
n = ftell(fv)/sizeof(a); //Определение количества записей в файле
printf("\n\n\n N = %d \n\n\n",n);
Record * rec = (Record*)calloc(n,sizeof(Record));
puts("\n\nDEBUG:\n\n\n\n");
fseek(fv,0,SEEK_SET);
for (i=0; i<n; i++) {
fread(&rec[i],sizeof(Record),1,fv);
puts(rec[i].country);
}
qsort(rec,n,sizeof(Record),cmp);
fseek(fv,0,SEEK_SET);
puts("\n\nDEBUG SORTED:\n\n\n\n");
for (i=0; i<n; i++) {
puts(rec[i].country);
fwrite(&rec[i],sizeof(Record),1,fv);
}
puts("\n\n");
free(rec);
fclose(fv);
}
Объяснение кода листинга программы
- В функции
Sort(char*name)происходит сортировка содержимого файла, который открывается для чтения и записи. - Сначала определяется количество записей в файле с помощью
fseek(fv,0,SEEK_END)иftell(fv). - Затем выделяется память для массива структур
Recordс помощьюcalloc(n,sizeof(Record)). - Далее, в цикле
forпроисходит чтение записей из файла в массивrecс помощьюfread(&rec[i],sizeof(Record),1,fv). - Каждая запись выводится на экран с помощью
puts(rec[i].country). - Далее, происходит сортировка массива
recс помощьюqsort(rec,n,sizeof(Record),cmp). - После сортировки, записи снова выводятся на экран с помощью
puts(rec[i].country). - Затем, отсортированные записи записываются обратно в файл с помощью
fwrite(&rec[i],sizeof(Record),1,fv). - В конце, память освобождается с помощью
free(rec), файл закрывается с помощьюfclose(fv). - Если в процессе выполнения программы происходит ошибка, то выводится сообщение об ошибке и программа завершается с помощью
printf(Error open file!\n); exit(-1);.