Консультация № 173967
04.11.2009, 17:45
35.00 руб.
0 6 1
Помогите пожалуйста решить задачу :
Целью работы является закрепление практических навыков в работе с указателями, структурами, создание связных списков на базе структур и размещение их в динамической памяти.
Постановка задачи:
1)Параметры прикладной области каждого варианта представить в виде структуры.
2)Подготовить файл исходных данных, содержащий не менее 10 экземпляров конкретных объектов. Имя файла необходимо вводить по запросу с клавиатуры (в отличие от примера программы, в котором имя задается в виде строки символов непосредственно в программе). Допустить возможность ввода списка в динамическую память с клавиатуры.
3)Осуществить ввод и хранение исходных данных из файла в динамическую память в виде связного линейного списка.
4)Предусмотреть сортировку списка по алфавитному и по числовому параметру.
5)Конкретные действия над “базой данных” оформить в виде функций. Приблизительный набор функций для работы со списком представлен в описании примера.
6)Отредактированный список сохранить в файле.
7)Вывод файла на экран выполнить в виде таблицы, столбцы которой соответствуют полям предметной области.
Задание :
Скотоводство
Вид животных, количество особей в стаде в возрасте до 1 года, количество особей 1-3 лет, свыше 3 лет, смертность в каждой группе, рождаемость.

В приложении пример:
Прикладная область – кафедра. Атрибуты:
ФИО преподавателя;
должность;
ученое звание.

Приложение:
/* Для сокращения записи типа структуры введем следующую константу */
#define emlp struct emlp

/* Функция печати списка */
int f_print();

/* Функция ввода списка */
int f_input();

/* Добавление элемента в список */
int f_add();

/* Уничтожение элемента списка */
int f_delete();

/* Изменение значения полей элемента списка */
int f_change() ;

/* Функция сортировки списка */
int f_sort();

/* Функция сохранения списка на диске */
int f_save();

/* Перезапись списка из файла в динамическую память */
int f_restore();


#include <stdio.h>
#include <alloc.h>
/* Описание структуры */
emlp{
char name[25]; /* Ф.И.О. */
int grade; /* Должность */
int hight; /* Звание */
emlp *next; /* Указатель на следующий элемент */
};

emlp *emlph=NULL; /* Начало списка */
char fname[]="D_STRUCT.DA1"; /* Файл для хранения списка */

main() {
char eoj; /* Флаг окончания работы */
int i; /* Вспомогательная переменная */

/* Структура меню */
struct {
int op; /* Номер операции */
(*opf)(); /* Функция обработки */
} m[9] = {
{'1',f_print},{'2',f_input},{'3',f_add},
{'4',f_delete},{'5',f_change},{'6',f_sort},
{'7',f_save},{'8',f_restore},{'0',}
};

int opcode; /* Код операции */

for ( ; ; ) { /* Пока не конец работы */
clrscr(); /* Очистка экрана */
printf("1. Print\n"); /* Вывод пунктов меню на экран */
printf("2. Input\n");
printf("3. Add\n");
printf("4. Delete\n");
printf("5. Change\n");
printf("6. Sort\n");
printf("7. Save\n");
printf("8. Restore\n");
printf("0. Quit\n");
printf("Enter operation code > "); /* Запрос на ввод номера
пункта для выполнения */
opcode=getche(); /* Ввод номера пункта */
putchar('\n');
if (opcode!='0') { /* выход из программы,
если выбран QUIT */
printf("Press any key...");
getch();
exit(0);
}
break;

for (i=0; i<10; i++){ /* Запуск соответствующей функции
обработки */
if (opcode==m[i].op) {
if (m[i].opf()==1) exit(0);
}
}
}

/****************************************************************/
/**************** Функция вывода списка на экран ******************/
/****************************************************************/

f_print() {
emlp *a; /* Указатель на структуру */
int i, j;

/* Если списка нет в памяти, то вывод соответствующего
сообщения */
/* Иначе - вывод всего списка на экран */
if (emlph==NULL) printf("List empty\n");
else {
for (a=emlph,i=1,j=1; a!=NULL; a=a→next,j++,i++) {
printf("#%-2d %-10s %-4d %-4d\n",
i,a→name, a→grade,a→hight);
if (j==20){
printf("Press any key for continue...\n");
getch();
j=1;
}
}
printf("======== end of list ========\n");
}
return 0;
}

/****************************************************************/
/*********** Функция ввода элементов списка ***********************/
/****************************************************************/

f_input() {
int cc;

printf("Enter name=* for end of stream\n");
/* Конец ввода - при вводе '*' вместо имени */
while (!(cc=f_add())); /* Вызов функции добавления */
return cc;
}

/****************************************************************/
/************* Добавление элемента в список ***********************/
/****************************************************************/

int f_add() {
emlp *a, *b;
char ss[40];
int i=1;

/* Если список существует, осуществляем вставку элемента */
if (emlph!=NULL)
for (i++,a=emlph; a→next!=NULL; a=a→next,i++);
/* Приглашение к вводу */
printf("Line #%d. Enter: name grade hight >",i);
scanf("%s",ss);
if (ss[0]=='*') return 2;
/* Выделение памяти под новый элемент */
b=(emlp *)malloc(sizeof(emlp));
strcpy(b→name,ss);
scanf("%d %d",&(b→grade),&(b→hight));
b→next=NULL;
/* Элемент вставляется после головы списка или в начало,
если список пустой */
if (emlph==NULL) emlph=b;
else a→next=b;
return 0;
}

/*****************************************************************/
/************ Функция сохранения списка на диске *******************/
/*****************************************************************/

f_save() {
FILE *dat;
emlp *a;

dat=fopen(fname,"w"); /* Открытие файла на запись */
/* Запись в файл осуществляется полями */
for (a=emlph; a!=NULL; a=a→next)
fprintf(dat,"%s %d %d\n",a→name,a→grade,a→hight);
/* В конце файла - спецкод '***' */
fprintf(dat,"***\n");
fclose(dat); /* Закрытие файла */
return 0;
}

/****************************************************************/
/****** Перезапись списка из файла в динамическую память ***********/
/****************************************************************/

f_restore() {
FILE *dat;
char ss[40];
emlp *a, *b;

/* Открытие файла для чтения, если файл не найден - вывод
соответствующего сообщения */
if ((dat=fopen(fname,"r"))==NULL) {
printf("File not found : %s\n",fname);
return 1;
}
else {
emlph=NULL;
do {
/* Чтение из файла по полям, пока не дошли до
спецкода '* '*/
fscanf(dat,"%s",ss);
if (ss[0]!='*') {
/* Выделение памяти под новый элемент */
b=(emlp *)malloc(sizeof(emlp));
if (emlph==NULL) emlph=b;
else a→next=b;
strcpy(b→name,ss);
fscanf(dat,"%d %d\n",&(b→grade),&(b→hight));
b→next=NULL;
a=b;
}
} while (ss[0]!='*');
fclose(dat); /* Закрытие файла */
}
return 0;
}

/*****************************************************************/
/*************** Функция сортировки списка ************************/
/*****************************************************************/

f_sort() {
int n;
emlp *a, *b, *c;

/* Если список пустой или в нем один элемент,
то выход из функции */
if ((emlph==NULL)||(emlph→next==NULL)) return 0;
/* Сортировка списка методом "пузырька" */
for (n=1; n; ) {
n=0;
for (a=emlph, b=emlph→next; b!=NULL; )
if (strcmp(a→name,b→name)>0) {
a→next=b→next; b→next=a;
if (a==emlph) emlph=b;
else c→next=b;
c=b; b=a→next;
n=1;
}
else {
c=a; a=b; b=b→next;
}
}
return 0;
}

/*****************************************************************/
/************ Ввод номера элемента ********************************/
/*****************************************************************/

int get_ln () {
int ln;

printf("Enter line number >");
do {
/* Ввод номера элемента и проверка его (если он меньше единицы -
выдается сообщение об ошибке) */
scanf("%d",&ln);
if (ln<1) {
printf("Illegial line number. Try again >");
ln=0;
}
} while (!ln);
return ln;
}

/*****************************************************************/
/************* Уничтожение элемента списка ************************/
/*****************************************************************/

f_delete () {
int ln;
emlp *a, *b;

/* Если списка нет в памяти, то вывод соответствующего
сообщения */
if (emlph==NULL) printf("List empty\n");
/* Иначе - ввод номера элемента с помощью функции GET_LN */
else {
ln=get_ln()-1;
if (!ln) {
/* Если номер корректен - переприсваивание указателей
и освобождение памяти */
a=emlph; emlph=a→next; free(a);
}
else {
/* Иначе- ??????? */
for(ln--,a=emlph; ln&&(a!=NULL); a=a→next,ln--);
if (a!=NULL)
if ((b=a→next)!=NULL) {
a→next=b->next; free(b);
}
}
}
return 0;
}

/*****************************************************************/
/********** Изменение значения полей элемента списка ***************/
/*****************************************************************/

f_change() {
char ss[40];
int ln;
emlp *a;

ln=get_ln()-1; /* Ввод номера элемента */
for (a=emlph; ln && a!=NULL; ln--,a=a→next);
if (ln) return 0;
/* Вывод старых и ввод новых значений */
/* Запись новых значений в список */
printf("Old name = %s New name >",a→name);
gets(ss);
if (*ss) strcpy(a→name,ss);
printf("Old grade = %d New grade >",a→grade);
gets(ss);
if (*ss) sscanf(ss,"%d",&(a→grade));
printf("Old hight = %d New hight >",a→hight);
gets(ss);
if (*ss) sscanf(ss,"%d",&(a→hight));
return 0;
}

Обсуждение

Неизвестный
06.11.2009, 10:42
общий
Мне кто-нибудь сможет помочь?
Неизвестный
07.11.2009, 06:00
общий
Ну, вот вариант.
Код:
#include  <stdio.h>
#include <stdlib.h>
#ifndef WIN_32
#define getch getchar
#define getche getchar
#define getch getchar
/*Очищаем ANSI терминал.*/
void clrscr(){fprintf(stderr,"\x1b[2J");};
/*gets очень опасная функция. Никогда не используйте.*/
#define gets(a) fgets(a,40,stdin)
#include <string.h>
#include <termios.h>
#endif
/* Для сокращения записи типа структуры введем следующую константу */
#define emlp struct emlp



/*для разнообразия будем определять типы и наименования полей динамически (всему курсу одно решение, раз такие задачи задают)*/
struct item_definer
{
char type;/* ENUM надо бы, но и так сойдет: s - строка, d - целое, f - float */
char * name;
int width;
char *fmt;
char *name_fmt;
struct item_definer * next;
};

union uitem
{
char * s;
int * d;
float * f;
};

struct item
{
union uitem * data ;
struct item * next;
};



/*Добавить определение поля*/
void add_def(struct item_definer ** definer, char atype,char * aname)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: add_def with invalid definer\n");
exit(1);
};
struct item_definer * ptr= *definer;
if(ptr==NULL)/* нет ни одного поля*/
{
ptr= *definer=calloc(1,sizeof(struct item_definer));
}else{
while(ptr->next != NULL)ptr=ptr->next;/*идем в конец*/
ptr->next=calloc(1,sizeof(struct item_definer));
ptr=ptr->next;
};
ptr->type=atype;
ptr->name=strdup(aname);/*скопируем чтобы не думать, удалять или не удалять - всегда удалять*/
ptr->width=strlen(aname)+1;
ptr->fmt=calloc(1,10);
ptr->name_fmt=calloc(1,10);
snprintf(ptr->fmt,9,"%%-%d%c ",ptr->width,ptr->type);
snprintf(ptr->name_fmt,9,"%%-%ds ",ptr->width);
};

/*Очистить определения полей (так чтобы было, надо убирать за собой)*/
void free_def(struct item_definer ** definer)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: free_def with invalid definer\n");
exit(1);
};
struct item_definer *ptr=* definer;
struct item_definer *free_ptr;
while(ptr != NULL)
{
free_ptr=ptr;
ptr=free_ptr->next;
free(free_ptr->name);
free(free_ptr->fmt);
free(free_ptr->name_fmt);
free(free_ptr);
};
*definer=NULL;
};

/****************************************************************/
/**************** Функция вывода списка на экран ******************/
/****************************************************************/

int f_print(struct item_definer * definer, struct item * list)
{
struct item * ptr=list; /* Указатель на структуру */
struct item_definer * dptr=definer;
fprintf(stderr,"Printing\n");
if (ptr==NULL) fprintf(stderr,"List empty\n");
else {
/*определяем макс ширину столбцов*/
int tmp=0;
while(ptr != NULL)
{
union uitem *data=ptr->data;
dptr=definer;
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
tmp=snprintf(NULL,0,"%s ",data->s);
break;
case 'd':
tmp=snprintf(NULL,0,"%d ",*data->d);
break;
case 'f':
tmp=snprintf(NULL,0,"%f ",*data->f);
break;
};
if(tmp > dptr->width)dptr->width = tmp;
snprintf(dptr->fmt,9,"%%-%d%c ",dptr->width,dptr->type);
snprintf(dptr->name_fmt,9,"%%-%ds ",dptr->width);
dptr = dptr->next;
++data;
};
ptr=ptr->next;
};
/*выводим строки*/
int j=1;
int cnt=0;
ptr=list;
while(ptr != NULL)
{
if(j==1)
{
/*выводим наименования столбцов*/
dptr=definer;
fprintf(stderr,"%5c ",' ');
while(dptr != NULL)
{
fprintf(stderr,dptr->name_fmt,dptr->name);
dptr=dptr->next;
};
fprintf(stderr,"\n");
};
union uitem *data=ptr->data;
dptr=definer;
fprintf(stderr,"%-5d ",cnt++);
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
fprintf(stderr,dptr->fmt,data->s);
break;
case 'd':
fprintf(stderr,dptr->fmt,*data->d);
break;
case 'f':
fprintf(stderr,dptr->fmt,*data->f);
break;
};
dptr = dptr->next;
++data;
};
fprintf(stderr,"\n");
++j;
if (j==20)
{
fprintf(stderr,"Press any key for continue...\n");
getch();
j=1;
};
ptr=ptr->next;
};
}
return 0;
}



/*Создание пустого элемента*/
struct item * create_item(struct item_definer * definer)
{
struct item * created=calloc(1,sizeof(struct item));
struct item_definer * dptr=definer;
int count=0;
while(dptr != NULL)
{
dptr=dptr->next;
++count;
};
created->data=calloc(count,sizeof(union uitem));
return created;
};

/*Удаление элемента*/
void free_item(struct item_definer * definer,struct item ** to_free)
{
struct item_definer * dptr=definer;
union uitem * data=(*to_free)->data;
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
if(data->s!=NULL)free(data->s);
data->s=NULL;
break;
case 'd':
if(data->d!=NULL)free(data->d);
data->d=NULL;
break;
case 'f':
if(data->f!=NULL)free(data->f);
data->f=NULL;
break;
};
dptr=dptr->next;
++data;
};
if((*to_free)->data!=NULL)free((*to_free)->data);
free(*to_free);
*to_free=NULL;
};

/*Удаление всех элементов*/
void free_items(struct item_definer * definer,struct item ** to_free)
{
struct item * del=*to_free;
struct item * ptr=del;
while(ptr !=NULL)
{
del=ptr;
ptr=ptr->next;
free_item(definer,&del);
};
*to_free=NULL;
};

/* Добавляем в конец списка новый элемент */
struct item * add_item(struct item_definer * definer,struct item ** list)
{
struct item * ptr=*list;
if (ptr!=NULL)
{
while(ptr->next !=NULL)ptr=ptr->next;
ptr->next=create_item(definer);
ptr=ptr->next;
}else{
ptr=*list=create_item(definer);
};
return ptr;
};

/****************************************************************/
/************* Добавление элемента в список ***********************/
/****************************************************************/

int f_add(struct item_definer * definer, struct item ** list)
{
char ss[40];
struct item * ptr=NULL;
union uitem * data=NULL;
ptr=add_item(definer,list);
data=ptr->data;
struct item_definer * dptr=definer;
while(dptr != NULL)
{
/* Приглашение к вводу */
fprintf(stderr,"%s: ",dptr->name);
scanf("%s",ss);
switch(dptr->type)
{
case 's':
data->s=strdup(&ss[0]);
break;
case 'd':
data->d=calloc(1,sizeof(int));
*data->d=atoi(&ss[0]);
break;
case 'f':
data->f=calloc(1,sizeof(float));
*data->f=atof(&ss[0]);
break;
};
dptr=dptr->next;
++data;
};
return 0;
}

/*****************************************************************/
/************ Функция сохранения списка на диске *******************/
/*****************************************************************/

f_save(struct item_definer * definer, struct item * list, char * fname)
{
FILE *dat;
struct item_definer * dptr=definer;
struct item * ptr=list;
union uitem * data=NULL;
dat=fopen(fname,"w"); /* Открытие файла на запись */
/* Запись в файл осуществляется полями */
while(ptr != NULL)
{
data=ptr->data;
struct item_definer * dptr=definer;
while(dptr != NULL)
{
char * sp;
switch(dptr->type)
{
case 's':
sp=data->s;
while(*sp !=0)
{
switch(*sp)
{
case ',':
fprintf(dat,"\\,");
break;
case '\\':
fprintf(dat,"\\\");
break;
default:
fprintf(dat,"%c",*sp);
break;
};
++sp;
};
break;
case 'd':
fprintf(dat,"%d",*data->d);
break;
case 'f':
fprintf(dat,"%f",*data->f);
break;
};
dptr=dptr->next;
++data;
if(dptr != NULL)fprintf(dat,",");
};
fprintf(dat,"\n");
ptr=ptr->next;
};
fclose(dat); /* Закрытие файла */
return 0;
}

/****************************************************************/
/****** Перезапись списка из файла в динамическую память ***********/
/****************************************************************/

struct item * f_load(struct item_definer * definer, char * fname)
{
struct item * ptr=NULL;
struct item * delptr=NULL;
struct item * created=NULL;
union uitem * data=NULL;
char buf[40];
char *pb;
FILE *dat;
/* Открытие файла для чтения, если файл не найден - вывод
соответствующего сообщения */
if ((dat=fopen(fname,"r"))==NULL)
{
fprintf(stderr,"File not found : %s\n",fname);
return NULL;
}else {
while(!feof(dat))
{
ptr=add_item(definer,&created);
data=ptr->data;
struct item_definer * dptr=definer;
while(dptr != NULL && ptr != NULL)
{
memset(&buf[0],0,40);
pb=&buf[0];
while(!feof(dat))
{
fread(pb,1,1,dat);
if(*pb=='\\')
{
++pb;
fread(pb,1,1,dat);
++pb;
fread(pb,1,1,dat);
};
if(*pb == ',' || *pb ==10 || feof(dat))break;
++pb;
};
switch(dptr->type)
{
case 's':
data->s=strdup(&buf[0]);
break;
case 'd':
data->d=calloc(1,sizeof(int));
*data->d=atoi(&buf[0]);
break;
case 'f':
data->f=calloc(1,sizeof(float));
*data->f=atof(&buf[0]);
break;
};
dptr=dptr->next;
if(feof(dat) && dptr != NULL)
{
delptr=created;
while( delptr != NULL && delptr->next != ptr)
{
delptr=delptr->next;
};
if(delptr!= NULL)
{
fprintf(stderr,"alive\n");
delptr->next=NULL;
free_item(definer,&ptr);
};
};
++data;
};
if(ptr==NULL)break;
};
fclose(dat); /* Закрытие файла */
}
return created;
}

/*****************************************************************/
/*************** Функция сортировки списка ************************/
/*****************************************************************/

int compare_data(union uitem a, union uitem b,char type)
{
switch(type)
{
case 's':
return strcmp(a.s,b.s);
break;
case 'd':
return (*a.d > *b.d);
break;
case 'f':
return (*a.f > *b.f);
break;
};
fprintf(stderr,"Invalid type in compare_data: %c\n",type);
exit(0);
}

f_sort(struct item_definer * definer,struct item ** list,int sort_by)
{
int n;
struct item *a;
struct item *b;
struct item *c;
struct item_definer * dptr=definer;
int cnt=sort_by;
while(dptr != NULL)
{
if(cnt==0)break;
dptr=dptr->next;
--cnt;
};
if(dptr==NULL)return;

/* Если список пустой или в нем один элемент,
то выход из функции */
if ((*list==NULL)||((*list)->next==NULL)) return 0;
/* Сортировка списка методом "пузырька" */
for (n=1; n; )
{
n=0;
for (a=*list, b=(*list)->next; b!=NULL; )
if (compare_data(a->data[sort_by],b->data[sort_by],dptr->type)>0)
{
a->next=b->next; b->next=a;
if (a==*list) *list=b;
else c->next=b;
c=b; b=a->next;
n=1;
}else{
c=a; a=b; b=b->next;
};
};
return 0;
};




/*****************************************************************/
/************ Ввод номера элемента ********************************/
/*****************************************************************/

int get_ln ()
{
int ln;

fprintf(stderr,"Enter line number >");
do {
/* Ввод номера элемента и проверка его (если он меньше единицы -
выдается сообщение об ошибке) */
scanf("%d",&ln);
if (ln<1)
{
fprintf(stderr,"Illegial line number. Try again >");
ln=0;
}
} while (!ln);
return ln;
}

/*****************************************************************/
/************* Уничтожение элемента списка ************************/
/*****************************************************************/

f_delete (struct item_definer * definer,struct item ** list, int number)
{
int ln=number;
struct item *ptr=*list;
struct item *prev=*list;
if(ptr==NULL)return 0;
while(ln>0 && ptr !=NULL)
{
prev=ptr;
ptr=ptr->next;
--ln;
};
if(ptr==*list)
{
*list=ptr->next;
}else{
prev->next=ptr->next;
};
free_item(definer,&ptr);
return 0;
};

/*****************************************************************/
/********** Изменение значения полей элемента списка ***************/
/*****************************************************************/

f_change(struct item_definer * definer,struct item ** list, int number)
{
char ss[40];
int ln=number;
int field=0;
struct item *ptr=*list;
struct item_definer * dptr=definer;
if(ptr==NULL)return 0;
while(ln>0 && ptr !=NULL)
{
ptr=ptr->next;
--ln;
};
if(ptr==NULL)return;
while(1)
{
/*выводим наименования столбцов*/
dptr=definer;
while(dptr != NULL)
{
fprintf(stderr,dptr->name_fmt,dptr->name);
dptr=dptr->next;
};
fprintf(stderr,"\n");

union uitem *data=ptr->data;
dptr=definer;
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
fprintf(stderr,dptr->fmt,data->s);
break;
case 'd':
fprintf(stderr,dptr->fmt,*data->d);
break;
case 'f':
fprintf(stderr,dptr->fmt,*data->f);
break;
};
dptr = dptr->next;
++data;
};
fprintf(stderr,"\n");
field=ask_field(definer);
if(field==-1)break;
dptr=definer;
int cnt=field;
while(dptr != NULL)
{
if(cnt==0)break;
dptr=dptr->next;
--cnt;
};
fprintf(stderr,"New value for %s: ",dptr->name);
memset(ss,0,40);
scanf("%s",ss);
if(strlen(&ss[0])==0)break;
switch(dptr->type)
{
case 's':
free(ptr->data[field].s);
ptr->data[field].s=strdup(&ss[0]);
break;
case 'd':
*(ptr->data[field].d)=atoi(&ss[0]);
break;
case 'f':
*(ptr->data[field].f)=atof(&ss[0]);
break;
};
};


return 0;
};

int ask_field(struct item_definer * definer)
{
struct item_definer * dptr=definer;
int cnt=0;
char ss[40];
while(dptr != NULL)
{
fprintf(stderr,"%d %s\n",cnt++,dptr->name);
dptr=dptr->next;
};
fprintf(stderr,"\nEnter your choise: ");
int td;
if(scanf("%d",&td))
{
if(td>=0)return td;
else return -1;
}else{
return -1;
};
if(strlen(&ss[0])==1)return -1;
int tmp=atoi(&ss[0]);
if(tmp<0)return -1;
return tmp;
};







void set_input(int i)
{
#ifndef WIN32
/*set up terminal*/

struct termios term,old;
tcgetattr(fileno(stdin),&term);
tcgetattr(fileno(stdin),&old);

if(i)term.c_lflag &= ~ICANON;
else term.c_lflag |= ICANON;
// term.c_lflag &= ~ECHO;
tcsetattr(fileno(stdin),0,&term);
#endif
}





int main()
{
struct item_definer * definer=NULL;
struct item * list=NULL;
/*Создаем описание*/
add_def(&definer, 's',"Animal"); /*Вид животных*/
add_def(&definer, 'd',"Count_lt_1_yo"); /*количество особей в стаде в возрасте до 1 года*/
add_def(&definer, 'd',"Count_1_3_yo"); /*количество особей 1-3 лет*/
add_def(&definer, 'd',"Count_gt_3_yo"); /*свыше 3 лет*/
add_def(&definer, 'f',"Death_rate"); /*смертность в каждой группе*/
add_def(&definer, 'f',"Birth_rate"); /*рождаемость*/



int opcode; /* Код операции */
int row=0;
char file_name[100];
clrscr(); /* Очистка экрана */

for ( ; ; )
{ /* Пока не конец работы */
printf("1. Print\n"); /* Вывод пунктов меню на экран */
printf("2. Add\n");
printf("3. Delete\n");
printf("4. Change\n");
printf("5. Sort\n");
printf("6. Save\n");
printf("7. Restore\n");
printf("0. Quit\n");
printf("Enter operation code > "); /* Запрос на ввод номера
пункта для выполнения */
set_input(1);
opcode=getche(); /* Ввод номера пункта */
set_input(0);
putchar('\n');
if (opcode=='0')
{ /* выход из программы,
если выбран QUIT */
exit(0);
};
switch(opcode)
{
case '1':
f_print(definer,list);
break;
case '2':
f_add(definer,&list);
break;
case '3':
row=0;
fprintf(stderr,"Row to delete: ");
if(scanf("%d",&row))
f_delete(definer,&list,row);
break;
case '4':
row=0;
fprintf(stderr,"Row to change: ");
if(scanf("%d",&row))
f_change(definer,&list,row);
break;
case '5':
row=0;
fprintf(stderr,"Select field:\n");
row=ask_field(definer);
if(row>=0)
f_sort(definer,&list,row);
break;
case '6':
fprintf(stderr,"File name:\n");
if(scanf("%s",file_name))
f_save(definer,list,file_name);
break;
case '7':
fprintf(stderr,"File name:\n");
if(scanf("%s",file_name))
{
free_items(definer,&list);
list=f_load(definer,file_name);
};
break;
};
};
};



Сильно не тестировал, так что при неправильном вводе/недостатке памяти может сегфолтиться. И все переполнения буфера не вылавливал. А так вроде работает.
Исправленный код примера (хотя бы собирается)
Код:
#include  <stdio.h>
#include <stdlib.h>
#ifndef WIN_32
#define getch getchar
#define getche getchar
#define getch getchar
/*Очищаем ANSI терминал.*/
void clrscr(){fprintf(stderr,"\x1b[2J");};
/*gets очень опасная функция. Никогда не используйте.*/
#define gets(a) fgets(a,40,stdin)
#include <string.h>
#endif
/* Для сокращения записи типа структуры введем следующую константу */
#define emlp struct emlp

/* Функция печати списка */
int f_print();

/* Функция ввода списка */
int f_input();

/* Добавление элемента в список */
int f_add();

/* Уничтожение элемента списка */
int f_delete();

/* Изменение значения полей элемента списка */
int f_change() ;

/* Функция сортировки списка */
int f_sort();

/* Функция сохранения списка на диске */
int f_save();

/* Перезапись списка из файла в динамическую память */
int f_restore();


/* Описание структуры */
emlp{
char name[25]; /* Ф.И.О. */
int grade; /* Должность */
int hight; /* Звание */
emlp *next; /* Указатель на следующий элемент */
};

emlp *emlph=NULL; /* Начало списка */
char fname[]="D_STRUCT.DA1"; /* Файл для хранения списка */

main() {
char eoj; /* Флаг окончания работы */
int i; /* Вспомогательная переменная */

/* Структура меню */
struct {
int op; /* Номер операции */
int (*opf)(); /* Функция обработки */
} m[9] = {
{'1',f_print},{'2',f_input},{'3',f_add},
{'4',f_delete},{'5',f_change},{'6',f_sort},
{'7',f_save},{'8',f_restore},{'0',}
};

int opcode; /* Код операции */

for ( ; ; ) { /* Пока не конец работы */
clrscr(); /* Очистка экрана */
printf("1. Print\n"); /* Вывод пунктов меню на экран */
printf("2. Input\n");
printf("3. Add\n");
printf("4. Delete\n");
printf("5. Change\n");
printf("6. Sort\n");
printf("7. Save\n");
printf("8. Restore\n");
printf("0. Quit\n");
printf("Enter operation code > "); /* Запрос на ввод номера
пункта для выполнения */
opcode=getche(); /* Ввод номера пункта */
putchar('\n');
if (opcode!='0') { /* выход из программы,
если выбран QUIT */
printf("Press any key...");
getch();
exit(0);
}
break;

for (i=0; i<10; i++){ /* Запуск соответствующей функции
обработки */
if (opcode==m[i].op) {
if (m[i].opf()==1) exit(0);
}
}
}
}

/****************************************************************/
/**************** Функция вывода списка на экран ******************/
/****************************************************************/

f_print() {
emlp *a; /* Указатель на структуру */
int i, j;

/* Если списка нет в памяти, то вывод соответствующего
сообщения */
/* Иначе - вывод всего списка на экран */
if (emlph==NULL) printf("List empty\n");
else {
for (a=emlph,i=1,j=1; a!=NULL; a=a->next,j++,i++) {
printf("#%-2d %-10s %-4d %-4d\n",
i,a->name, a->grade,a->hight);
if (j==20){
printf("Press any key for continue...\n");
getch();
j=1;
}
}
printf("======== end of list ========\n");
}
return 0;
}

/****************************************************************/
/*********** Функция ввода элементов списка ***********************/
/****************************************************************/

f_input() {
int cc;

printf("Enter name=* for end of stream\n");
/* Конец ввода - при вводе '*' вместо имени */
while (!(cc=f_add())); /* Вызов функции добавления */
return cc;
}

/****************************************************************/
/************* Добавление элемента в список ***********************/
/****************************************************************/

int f_add() {
emlp *a, *b;
char ss[40];
int i=1;

/* Если список существует, осуществляем вставку элемента */
if (emlph!=NULL)
for (i++,a=emlph; a->next!=NULL; a=a->next,i++);
/* Приглашение к вводу */
printf("Line #%d. Enter: name grade hight >",i);
scanf("%s",ss);
if (ss[0]=='*') return 2;
/* Выделение памяти под новый элемент */
b=(emlp *)malloc(sizeof(emlp));
strcpy(b->name,ss);
scanf("%d %d",&(b->grade),&(b->hight));
b->next=NULL;
/* Элемент вставляется после головы списка или в начало,
если список пустой */
if (emlph==NULL) emlph=b;
else a->next=b;
return 0;
}

/*****************************************************************/
/************ Функция сохранения списка на диске *******************/
/*****************************************************************/

f_save() {
FILE *dat;
emlp *a;

dat=fopen(fname,"w"); /* Открытие файла на запись */
/* Запись в файл осуществляется полями */
for (a=emlph; a!=NULL; a=a->next)
fprintf(dat,"%s %d %d\n",a->name,a->grade,a->hight);
/* В конце файла - спецкод '***' */
fprintf(dat,"***\n");
fclose(dat); /* Закрытие файла */
return 0;
}

/****************************************************************/
/****** Перезапись списка из файла в динамическую память ***********/
/****************************************************************/

f_restore() {
FILE *dat;
char ss[40];
emlp *a, *b;

/* Открытие файла для чтения, если файл не найден - вывод
соответствующего сообщения */
if ((dat=fopen(fname,"r"))==NULL) {
printf("File not found : %s\n",fname);
return 1;
}
else {
emlph=NULL;
do {
/* Чтение из файла по полям, пока не дошли до
спецкода '* '*/
fscanf(dat,"%s",ss);
if (ss[0]!='*') {
/* Выделение памяти под новый элемент */
b=(emlp *)malloc(sizeof(emlp));
if (emlph==NULL) emlph=b;
else a->next=b;
strcpy(b->name,ss);
fscanf(dat,"%d %d\n",&(b->grade),&(b->hight));
b->next=NULL;
a=b;
}
} while (ss[0]!='*');
fclose(dat); /* Закрытие файла */
}
return 0;
}

/*****************************************************************/
/*************** Функция сортировки списка ************************/
/*****************************************************************/

f_sort() {
int n;
emlp *a, *b, *c;

/* Если список пустой или в нем один элемент,
то выход из функции */
if ((emlph==NULL)||(emlph->next==NULL)) return 0;
/* Сортировка списка методом "пузырька" */
for (n=1; n; ) {
n=0;
for (a=emlph, b=emlph->next; b!=NULL; )
if (strcmp(a->name,b->name)>0) {
a->next=b->next; b->next=a;
if (a==emlph) emlph=b;
else c->next=b;
c=b; b=a->next;
n=1;
}
else {
c=a; a=b; b=b->next;
}
}
return 0;
}

/*****************************************************************/
/************ Ввод номера элемента ********************************/
/*****************************************************************/

int get_ln () {
int ln;

printf("Enter line number >");
do {
/* Ввод номера элемента и проверка его (если он меньше единицы -
выдается сообщение об ошибке) */
scanf("%d",&ln);
if (ln<1) {
printf("Illegial line number. Try again >");
ln=0;
}
} while (!ln);
return ln;
}

/*****************************************************************/
/************* Уничтожение элемента списка ************************/
/*****************************************************************/

f_delete () {
int ln;
emlp *a, *b;

/* Если списка нет в памяти, то вывод соответствующего
сообщения */
if (emlph==NULL) printf("List empty\n");
/* Иначе - ввод номера элемента с помощью функции GET_LN */
else {
ln=get_ln()-1;
if (!ln) {
/* Если номер корректен - переприсваивание указателей
и освобождение памяти */
a=emlph; emlph=a->next; free(a);
}
else {
/* Иначе- ??????? */
for(ln--,a=emlph; ln&&(a!=NULL); a=a->next,ln--);
if (a!=NULL)
if ((b=a->next)!=NULL) {
a->next=b->next; free(b);
}
}
}
return 0;
}

/*****************************************************************/
/********** Изменение значения полей элемента списка ***************/
/*****************************************************************/

f_change() {
char ss[40];
int ln;
emlp *a;

ln=get_ln()-1; /* Ввод номера элемента */
for (a=emlph; ln && a!=NULL; ln--,a=a->next);
if (ln) return 0;
/* Вывод старых и ввод новых значений */
/* Запись новых значений в список */
printf("Old name = %s New name >",a->name);
gets(ss);
if (*ss) strcpy(a->name,ss);
printf("Old grade = %d New grade >",a->grade);
gets(ss);
if (*ss) sscanf(ss,"%d",&(a->grade));
printf("Old hight = %d New hight >",a->hight);
gets(ss);
if (*ss) sscanf(ss,"%d",&(a->hight));
return 0;
}

Если устраивает, делаю ответ.
Неизвестный
07.11.2009, 22:19
общий
это ответ
Здравствуйте, Faraon.
Добавил чуть побольше проверок на ошибки вызова в функциях.
Переполнение буфера в scanf не исправлял - сами сделайте, если нужно.
Формат файлов - csv, разделитель ',', экранирование в стиле C символом '\' символов '\' , ',', ограничители полей не используются.
Для других заданий поменяйте в начале main() после /*Создаем описание*/ вызовы add_def(struct item_definer ** definer, char atype,char * aname) на те, которые в задании.
Под виндой не проверял (нет ее у меня), но должно работать.


Приложение:
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN_32
#define getch getchar
#define getche getchar
#define getch getchar
/*Очищаем ANSI терминал.*/
void clrscr(){fprintf(stderr,"\x1b[2J");};
/*gets очень опасная функция. Никогда не используйте.*/
#define gets(a) fgets(a,40,stdin)
#include <string.h>
#include <termios.h>
#endif
/* Для сокращения записи типа структуры введем следующую константу */
#define emlp struct emlp



/*для разнообразия будем определять типы и наименования полей динамически (всему курсу одно решение, раз такие задачи задают)*/
struct item_definer
{
char type;/* ENUM надо бы, но и так сойдет: s - строка, d - целое, f - float */
char * name;
int width;
char *fmt;
char *name_fmt;
struct item_definer * next;
};

union uitem
{
char * s;
int * d;
float * f;
};

struct item
{
union uitem * data ;
struct item * next;
};


void * safe_alloc(size_t n,size_t bytes)
{
void *tmp=calloc(n,bytes);
if(tmp==NULL)
{
fprintf(stderr,"Failed to allocate %d blocks %d bytes each.\nExiting.\n");
exit(1);
};
return tmp;
};

/*Добавить определение поля*/
void add_def(struct item_definer ** definer, char atype,char * aname)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: add_def with invalid definer\n");
exit(1);
};
struct item_definer * ptr= *definer;
if(ptr==NULL)/* нет ни одного поля*/
{
ptr= *definer=safe_alloc(1,sizeof(struct item_definer));
}else{
while(ptr->next != NULL)ptr=ptr->next;/*идем в конец*/
ptr->next=safe_alloc(1,sizeof(struct item_definer));
ptr=ptr->next;
};
ptr->type=atype;
ptr->name=strdup(aname);/*скопируем чтобы не думать, удалять или не удалять - всегда удалять*/
ptr->width=strlen(aname)+1;
ptr->fmt=safe_alloc(1,10);
ptr->name_fmt=safe_alloc(1,10);
snprintf(ptr->fmt,9,"%%-%d%c ",ptr->width,ptr->type);
snprintf(ptr->name_fmt,9,"%%-%ds ",ptr->width);
};

/*Очистить определения полей (так чтобы было, надо убирать за собой)*/
void free_def(struct item_definer ** definer)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: free_def with invalid definer\n");
exit(1);
};
struct item_definer *ptr=* definer;
struct item_definer *free_ptr;
while(ptr != NULL)
{
free_ptr=ptr;
ptr=free_ptr->next;
free(free_ptr->name);
free(free_ptr->fmt);
free(free_ptr->name_fmt);
free(free_ptr);
};
*definer=NULL;
};

/****************************************************************/
/**************** Функция вывода списка на экран ******************/
/****************************************************************/

int f_print(struct item_definer * definer, struct item * list)
{
struct item * ptr=list; /* Указатель на структуру */
struct item_definer * dptr=definer;
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
if (ptr==NULL)
fprintf(stderr,"List empty\n");
else {
/*определяем макс ширину столбцов*/
int tmp=0;
while(ptr != NULL)
{
union uitem *data=ptr->data;
dptr=definer;
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
tmp=snprintf(NULL,0,"%s ",data->s);
break;
case 'd':
tmp=snprintf(NULL,0,"%d ",*data->d);
break;
case 'f':
tmp=snprintf(NULL,0,"%f ",*data->f);
break;
};
if(tmp > dptr->width)dptr->width = tmp;
snprintf(dptr->fmt,9,"%%-%d%c ",dptr->width,dptr->type);
snprintf(dptr->name_fmt,9,"%%-%ds ",dptr->width);
dptr = dptr->next;
++data;
};
ptr=ptr->next;
};
/*выводим строки*/
int j=1;
int cnt=0;
ptr=list;
while(ptr != NULL)
{
if(j==1)
{
/*выводим наименования столбцов*/
dptr=definer;
fprintf(stderr,"%5c ",' ');
while(dptr != NULL)
{
fprintf(stderr,dptr->name_fmt,dptr->name);
dptr=dptr->next;
};
fprintf(stderr,"\n");
};
union uitem *data=ptr->data;
dptr=definer;
fprintf(stderr,"%-5d ",cnt++);
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
fprintf(stderr,dptr->fmt,data->s);
break;
case 'd':
fprintf(stderr,dptr->fmt,*data->d);
break;
case 'f':
fprintf(stderr,dptr->fmt,*data->f);
break;
};
dptr = dptr->next;
++data;
};
fprintf(stderr,"\n");
++j;
if (j==20)
{
fprintf(stderr,"Press any key for continue...\n");
getch();
j=1;
};
ptr=ptr->next;
};
}
return 0;
}



/*Создание пустого элемента*/
struct item * create_item(struct item_definer * definer)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
struct item * created=safe_alloc(1,sizeof(struct item));
struct item_definer * dptr=definer;
int count=0;
while(dptr != NULL)
{
dptr=dptr->next;
++count;
};
created->data=safe_alloc(count,sizeof(union uitem));
return created;
};

/*Удаление элемента*/
void free_item(struct item_definer * definer,struct item ** to_free)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
if(to_free==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to free_item() in to_free: may be you forgot '&'.\n");
exit(1);
};
if(*to_free==NULL)return;
struct item_definer * dptr=definer;
union uitem * data=(*to_free)->data;
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
if(data->s!=NULL)free(data->s);
data->s=NULL;
break;
case 'd':
if(data->d!=NULL)free(data->d);
data->d=NULL;
break;
case 'f':
if(data->f!=NULL)free(data->f);
data->f=NULL;
break;
};
dptr=dptr->next;
++data;
};
if((*to_free)->data!=NULL)free((*to_free)->data);
free(*to_free);
*to_free=NULL;
};

/*Удаление всех элементов*/
void free_items(struct item_definer * definer,struct item ** to_free)
{
if(to_free==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to free_items() in to_free: may be you forgot '&'.\n");
exit(1);
};
struct item * del=*to_free;
struct item * ptr=del;
while(ptr !=NULL)
{
del=ptr;
ptr=ptr->next;
free_item(definer,&del);
};
*to_free=NULL;
};

/* Добавляем в конец списка новый элемент */
struct item * add_item(struct item_definer * definer,struct item ** list)
{
if(list==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to add_item() in list: may be you forgot '&'.\n");
exit(1);
};
struct item * ptr=*list;
if (ptr!=NULL)
{
while(ptr->next !=NULL)ptr=ptr->next;
ptr->next=create_item(definer);
ptr=ptr->next;
}else{
ptr=*list=create_item(definer);
};
return ptr;
};

/****************************************************************/
/************* Добавление элемента в список ***********************/
/****************************************************************/

int f_add(struct item_definer * definer, struct item ** list)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
if(list==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to f_add() in list: may be you forgot '&'.\n");
exit(1);
};
char ss[40];
struct item * ptr=NULL;
union uitem * data=NULL;
ptr=add_item(definer,list);
data=ptr->data;
struct item_definer * dptr=definer;
while(dptr != NULL)
{
/* Приглашение к вводу */
fprintf(stderr,"%s: ",dptr->name);
scanf("%s",ss);
switch(dptr->type)
{
case 's':
data->s=strdup(&ss[0]);
break;
case 'd':
data->d=safe_alloc(1,sizeof(int));
*data->d=atoi(&ss[0]);
break;
case 'f':
data->f=safe_alloc(1,sizeof(float));
*data->f=atof(&ss[0]);
break;
};
dptr=dptr->next;
++data;
};
return 0;
}

/*****************************************************************/
/************ Функция сохранения списка на диске *******************/
/*****************************************************************/

f_save(struct item_definer * definer, struct item * list, char * fname)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
FILE *dat;
struct item_definer * dptr=definer;
struct item * ptr=list;
union uitem * data=NULL;
dat=fopen(fname,"w"); /* Открытие файла на запись */
if(dat==NULL)
{
fprintf(stderr,"Faile to write file: %s\n",fname);
return;
};
/* Запись в файл осуществляется полями */
while(ptr != NULL)
{
data=ptr->data;
struct item_definer * dptr=definer;
while(dptr != NULL)
{
char * sp;
switch(dptr->type)
{
case 's':
sp=data->s;
while(*sp !=0)
{
switch(*sp)
{
case ',':
fprintf(dat,"\\,");
break;
case '\\':
fprintf(dat,"\\\");
break;
default:
fprintf(dat,"%c",*sp);
break;
};
++sp;
};
break;
case 'd':
fprintf(dat,"%d",*data->d);
break;
case 'f':
fprintf(dat,"%f",*data->f);
break;
};
dptr=dptr->next;
++data;
if(dptr != NULL)fprintf(dat,",");
};
fprintf(dat,"\n");
ptr=ptr->next;
};
fclose(dat); /* Закрытие файла */
return 0;
}

/****************************************************************/
/****** Перезапись списка из файла в динамическую память ***********/
/****************************************************************/

struct item * f_load(struct item_definer * definer, char * fname)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
struct item * ptr=NULL;
struct item * delptr=NULL;
struct item * created=NULL;
union uitem * data=NULL;
char buf[40];
char *pb;
FILE *dat;
/* Открытие файла для чтения, если файл не найден - вывод
соответствующего сообщения */
if ((dat=fopen(fname,"r"))==NULL)
{
fprintf(stderr,"File not found : %s\n",fname);
return NULL;
}else {
while(!feof(dat))
{
ptr=add_item(definer,&created);
data=ptr->data;
struct item_definer * dptr=definer;
while(dptr != NULL && ptr != NULL)
{
memset(&buf[0],0,40);
pb=&buf[0];
while(!feof(dat))
{
fread(pb,1,1,dat);
if(*pb=='\\')
{
++pb;
fread(pb,1,1,dat);
++pb;
fread(pb,1,1,dat);
};
if(*pb == ',' || *pb ==10 || feof(dat))break;
++pb;
};
switch(dptr->type)
{
case 's':
data->s=strdup(&buf[0]);
break;
case 'd':
data->d=safe_alloc(1,sizeof(int));
*data->d=atoi(&buf[0]);
break;
case 'f':
data->f=safe_alloc(1,sizeof(float));
*data->f=atof(&buf[0]);
break;
};
dptr=dptr->next;
if(feof(dat) && dptr != NULL)
{
delptr=created;
while( delptr != NULL && delptr->next != ptr)
{
delptr=delptr->next;
};
if(delptr!= NULL)
{
fprintf(stderr,"alive\n");
delptr->next=NULL;
free_item(definer,&ptr);
};
};
++data;
};
if(ptr==NULL)break;
};
fclose(dat); /* Закрытие файла */
}
return created;
}

/*****************************************************************/
/*************** Функция сортировки списка ************************/
/*****************************************************************/

int compare_data(union uitem a, union uitem b,char type)
{
switch(type)
{
case 's':
return strcmp(a.s,b.s);
break;
case 'd':
if(a.d==NULL || b.d==NULL)
{
fprintf(stderr,"Invalid data passed to compare_data. Check file load/input functions.\n");
exit(1);
};
return (*a.d > *b.d);
break;
case 'f':
if(a.f==NULL || b.f==NULL)
{
fprintf(stderr,"Invalid data passed to compare_data. Check file load/input functions.\n");
exit(1);
};
return (*a.f > *b.f);
break;
};
fprintf(stderr,"Invalid type in compare_data: %c\n",type);
exit(0);
}

f_sort(struct item_definer * definer,struct item ** list,int sort_by)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
if(list==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to f_sort() in list: may be you forgot '&'.\n");
exit(1);
};
int n;
struct item *a;
struct item *b;
struct item *c;
struct item_definer * dptr=definer;
int cnt=sort_by;
while(dptr != NULL)
{
if(cnt==0)break;
dptr=dptr->next;
--cnt;
};
if(dptr==NULL)return;

/* Если список пустой или в нем один элемент,
то выход из функции */
if ((*list==NULL)||((*list)->next==NULL)) return 0;
/* Сортировка списка методом "пузырька" */
for (n=1; n; )
{
n=0;
for (a=*list, b=(*list)->next; b!=NULL; )
if (compare_data(a->data[sort_by],b->data[sort_by],dptr->type)>0)
{
a->next=b->next; b->next=a;
if (a==*list) *list=b;
else c->next=b;
c=b; b=a->next;
n=1;
}else{
c=a; a=b; b=b->next;
};
};
return 0;
};




/*****************************************************************/
/************ Ввод номера элемента ********************************/
/*****************************************************************/

int get_ln ()
{
int ln;

fprintf(stderr,"Enter line number >");
do {
/* Ввод номера элемента и проверка его (если он меньше единицы -
выдается сообщение об ошибке) */
scanf("%d",&ln);
if (ln<1)
{
fprintf(stderr,"Illegial line number. Try again >");
ln=0;
}
} while (!ln);
return ln;
}

/*****************************************************************/
/************* Уничтожение элемента списка ************************/
/*****************************************************************/

f_delete (struct item_definer * definer,struct item ** list, int number)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
if(list==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to f_delete() in list: may be you forgot '&'.\n");
exit(1);
};
int ln=number;
struct item *ptr=*list;
struct item *prev=*list;
if(ptr==NULL)return 0;
while(ln>0 && ptr !=NULL)
{
prev=ptr;
ptr=ptr->next;
--ln;
};
if(ptr==*list)
{
*list=ptr->next;
}else{
prev->next=ptr->next;
};
free_item(definer,&ptr);
return 0;
};

/*****************************************************************/
/********** Изменение значения полей элемента списка ***************/
/*****************************************************************/

f_change(struct item_definer * definer,struct item ** list, int number)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
if(list==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Invalid pointer passed to f_delete() in list: may be you forgot '&'.\n");
exit(1);
};
char ss[40];
int ln=number;
int field=0;
struct item *ptr=*list;
struct item_definer * dptr=definer;
if(ptr==NULL)
{
fprintf(stderr,"no items.\n");
return 0;
};
while(ln>0 && ptr !=NULL)
{
ptr=ptr->next;
--ln;
};
if(ptr==NULL)
{
fprintf(stderr,"no item %d.\n",number);
return 0;
};
while(1)
{
/*выводим наименования столбцов*/
dptr=definer;
while(dptr != NULL)
{
fprintf(stderr,dptr->name_fmt,dptr->name);
dptr=dptr->next;
};
fprintf(stderr,"\n");

union uitem *data=ptr->data;
dptr=definer;
while(dptr != NULL)
{
switch(dptr->type)
{
case 's':
fprintf(stderr,dptr->fmt,data->s);
break;
case 'd':
fprintf(stderr,dptr->fmt,*data->d);
break;
case 'f':
fprintf(stderr,dptr->fmt,*data->f);
break;
};
dptr = dptr->next;
++data;
};
fprintf(stderr,"\n");
field=ask_field(definer);
if(field==-1)break;
dptr=definer;
int cnt=field;
while(dptr != NULL)
{
if(cnt==0)break;
dptr=dptr->next;
--cnt;
};
fprintf(stderr,"New value for %s: ",dptr->name);
memset(ss,0,40);
scanf("%s",ss);
if(strlen(&ss[0])==0)break;
switch(dptr->type)
{
case 's':
free(ptr->data[field].s);
ptr->data[field].s=strdup(&ss[0]);
break;
case 'd':
*(ptr->data[field].d)=atoi(&ss[0]);
break;
case 'f':
*(ptr->data[field].f)=atof(&ss[0]);
break;
};
};


return 0;
};

int ask_field(struct item_definer * definer)
{
if(definer==NULL)
{
/*защищаемся от null pointer dereference по ошибке*/
fprintf(stderr,"Bug: Definer not set. Check beginning of main().\n");
exit(1);
};
struct item_definer * dptr=definer;
int cnt=0;
char ss[40];
while(dptr != NULL)
{
fprintf(stderr,"%d %s\n",cnt++,dptr->name);
dptr=dptr->next;
};
fprintf(stderr,"\nEnter your choise: ");
int td;
if(scanf("%d",&td))
{
if(td>=0)return td;
else return -1;
}else{
return -1;
};
if(strlen(&ss[0])==1)return -1;
int tmp=atoi(&ss[0]);
if(tmp<0)return -1;
return tmp;
};







void set_input(int i)
{
#ifndef WIN32
/*set up terminal*/

struct termios term,old;
tcgetattr(fileno(stdin),&term);
tcgetattr(fileno(stdin),&old);

if(i)term.c_lflag &= ~ICANON;
else term.c_lflag |= ICANON;
// term.c_lflag &= ~ECHO;
tcsetattr(fileno(stdin),0,&term);
#endif
};





int main()
{
struct item_definer * definer=NULL;
struct item * list=NULL;
/*Создаем описание*/
add_def(&definer, 's',"Animal"); /*Вид животных, строка*/
add_def(&definer, 'd',"Count_lt_1_yo"); /*количество особей в стаде в возрасте до 1 года, целое*/
add_def(&definer, 'd',"Count_1_3_yo"); /*количество особей 1-3 лет, целое*/
add_def(&definer, 'd',"Count_gt_3_yo"); /*свыше 3 лет, целое*/
add_def(&definer, 'f',"Death_rate"); /*смертность в каждой группе, с плавающей точкой*/
add_def(&definer, 'f',"Birth_rate"); /*рождаемость, с плавающей точкой*/



int opcode; /* Код операции */
int row=0;
char file_name[100];
clrscr(); /* Очистка экрана */

for ( ; ; )
{ /* Пока не конец работы */
printf("1. Print\n"); /* Вывод пунктов меню на экран */
printf("2. Add\n");
printf("3. Delete\n");
printf("4. Change\n");
printf("5. Sort\n");
printf("6. Save\n");
printf("7. Restore\n");
printf("0. Quit\n");
printf("Enter operation code > "); /* Запрос на ввод номера
пункта для выполнения */
set_input(1);
opcode=getche(); /* Ввод номера пункта */
set_input(0);
putchar('\n');
if (opcode=='0')
{ /* выход из программы,
если выбран QUIT */
exit(0);
};
switch(opcode)
{
case '1':
f_print(definer,list);
break;
case '2':
f_add(definer,&list);
break;
case '3':
row=0;
fprintf(stderr,"Row to delete: ");
if(scanf("%d",&row))
f_delete(definer,&list,row);
break;
case '4':
row=0;
fprintf(stderr,"Row to change: ");
if(scanf("%d",&row))
f_change(definer,&list,row);
break;
case '5':
row=0;
fprintf(stderr,"Select field:\n");
row=ask_field(definer);
if(row>=0)
f_sort(definer,&list,row);
break;
case '6':
fprintf(stderr,"File name:\n");
if(scanf("%s",file_name))
f_save(definer,list,file_name);
break;
case '7':
fprintf(stderr,"File name:\n");
if(scanf("%s",file_name))
{
free_items(definer,&list);
list=f_load(definer,file_name);
};
break;
};
};
};

Неизвестный
07.11.2009, 22:32
общий
Похоже по заданию надо смертность и рождаемость в каждой группе, а не общую.
Если так, то замените в main() строки
Код:

add_def(&definer, 'f',"Death_rate"); /*смертность в каждой группе, с плавающей точкой*/
add_def(&definer, 'f',"Birth_rate"); /*рождаемость, с плавающей точкой*/

на
Код:

add_def(&definer, 'f',"Death_rate_lt_1_yo"); /*смертность в группе до года, с плавающей точкой*/
add_def(&definer, 'f',"Death_rate_1_3_yo"); /*смертность в группе 1-3 года, с плавающей точкой*/
add_def(&definer, 'f',"Death_rate_gt_3_yo"); /*смертность в группе больше 3 лет, с плавающей точкой*/
add_def(&definer, 'f',"Birth_rate_lt_1_yo"); /*рождаемость в группе до года, с плавающей точкой*/
add_def(&definer, 'f',"Birth_rate_1_3_yo"); /*рождаемость в группе 1-3 года, с плавающей точкой*/
add_def(&definer, 'f',"Birth_rate_gt_3_yo"); /*рождаемость в группе больше 3 лет, с плавающей точкой*/
Неизвестный
09.11.2009, 17:30
общий
Спасибо за ответ, но у меня возникла проблема при компиляции...не находит файл termios.h, я проверил и оказалось что он отсутствует в папке includes это из-за компилятора??каким Вы пользовались?у меня TurboC++
Неизвестный
09.11.2009, 17:46
общий
Faraon:
termios.h это часть стандарта POSIX.1-2001, XSI extension.
Используется для управления работой ANSI-терминала (в досе нужно подгрузить ANSI.SYS), конкретно - отключение канонического ввода для нормальной работы однобуквенных команд.
Я пользовался
Код:
$ gcc --version
gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)
Copyright (C) 2007 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая
коммерческую ценность и применимость для каких-либо целей.

Возможно поможет написать где-нибудь в начале файла
Код:
#define WIN_32

или просто выбросить все, что внутри проверок на не винду.
[offtop]Надо будет собрать toolchain для кросскомпиляции под дос.[/offtop]
Форма ответа