|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Двухсвязанный список на Си. |
|
Двухсвязанный список на Си.
|
Пользователь Сообщения: 79 |
Профиль | Отправить PM | Цитировать
1. Постановка вопроса.
- В данную задачу необходимо реализовать средствами языка Си. - Необходимо организовать двухсвязанный список, т.е. создать его и загрузить в оперативную память, а затем производить различные манипуляции с элементами этого списка (всё сводится к поиску и сортировке). - Полностью код выкладывать не буду (считаю будет только загромождать), покажу только, то с чем проблема. #include <stdio.h> #include <conio.h> #include <alloc.h> #define TRUE 1 #define FALSE 0 struct expt{int expert; //char fam[20]; //int mesto; }; struct record{expt sps; record *prior, *next;}; void main (){ record *begin=NULL, /*Указатель начала списка*/ *last=NULL, /*Указатель на очередную запись*/ *list; /*Указатель на элементы списка*/ char c; while(1){clrscr(); printf(" 2 - Input data \n3 - View\n Selection item: "); scanf("%s",&c); switch(c){ case '2':{ int b=TRUE; while(b!=FALSE){ //цикл ввода данных last=(struct record*)malloc(sizeof(struct record)); if(last==NULL){printf("\n Error !\n No find memory\n Press any key...");getch();return;} /*проверка, выделена ли память?*/ clrscr(); printf("\n Input namber expert (0-9): "); scanf("%d",&(*last).sps.expert); if(begin==NULL){last->prior=NULL;begin=last;last->next=NULL;} //списка ещё нет else{list=begin; //cписок уже существует while(list){ /*цикл просмотра списка-поиск места для новой записи*/ if(list->next==NULL){ /*Включить запись в конец списка*/ last->next=NULL; last->prior=list; list->next=last; break; /*выход из списка просмотра цикла*/ } list=list->next; } //конец цикла просмотра while } //конец else список уже существует printf("\n Next input? 1 - Yes\\0 - No\n"); //ввод нового эксперта scanf("%d",&b); getch(); } //конец цикла ввода данных while(b!=FALSE) break;} case '3':{ clrscr(); printf("\n Out spicok:\n"); list=begin; while(list){ printf("(list->sps.expert)=%d\n",list->sps.expert); list=list->next; } getch(); break;} default:{printf("\n Error !\n Can't no right selection item\n Press any key...");getch();break;} } } } (record *prior, *next;), и структуру (sps) типа expt. Создаем и загружаем в оперативную память список в операторе switch{case '2':.........}. Здесь, я думаю, что сделал всё верно. Прикреплю блок-схему http://forum.oszone.net/attachment.p...tid=1976&stc=1. 2. Вопрос. - В операторе switch{case '3':.........} хочу вывести все элементы списка на экран, но не выходит аленький цветочек. Всё компилируется, ошибок никаких не выдается, только одно предупреждение (" 'last' is assigned a value that is never used"),запускаем *.exe файл, ввожу в список записи, затем пытаюсь просмотреть, выползает окошко с ошибкой ("Thread stopped D:\BC5\bin\cs.c Fault: access violation at ..... read of address ........"), и всё на этом, программа останавливается. Убираю цикл while по крайней мере выводит правильно первый элемент. В чём моя ошибка? Где собака зарыта? |
|
Отправлено: 12:05, 27-04-2006 |
Ночной странник Сообщения: 4050
|
Профиль | Сайт | Отправить PM | Цитировать Hemp
а почему не использовать STL-левский шаблон для списков? |
------- Отправлено: 20:36, 30-04-2006 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Пользователь Сообщения: 79
|
Профиль | Отправить PM | Цитировать Vlad Drakula
Потому, что сессия не за горами, потому, что требуют на языке Си использовать списки, С++ нельзя использовать, шаблоны здесь не пойдут. Задачу решил следующим образом, функция views() правильно отображает данные из списка. #include <stdio.h> #include <conio.h> #include <alloc.h> #define TRUE 1 #define FALSE 0 #define FILE_DB "db1.dat" struct expt{int expert;char sport[20];int mesto;}; struct record{expt sps; record *prior;record *next;}; void clr (char a[]); void printmenu(void); void views(void); void save(char a[],record *begin); void load(char a[],record *begin); void clr (char a[]){ FILE *f; if((f=fopen(a,"w"))==NULL)printf("\n Error !\nFile could not be create\\opened.\n Press any key..."); else printf(" \n Data base clear successfully!\n Press any key..."); getch(); fclose(f); } void printmenu(){ clrscr(); printf("|----------------------------------|\n| Menu:\t\t\t\t |\n|------------\ ----------------------|\n| 1 - Clear file data base \t |\n| 2 - Input data\t\t |\n| 3 - View db data\t\t\t |\n| 4 - Form file \ expert questioning |\n| 5 - Form file best sportsmans |\n| 0 - Exit\t\t\t |\n|-------\ ---------------------------|\n\n Selection item: "); } void views(record *begin){ clrscr(); printf("\n Out spicok bd:\n"); while(begin){ printf("(expert%d---%s---mesto-%d\n",begin->sps.expert,begin->sps.sport,begin->sps.mesto); begin=begin->next; } getch(); } void save(char a[],record *begin){ FILE *f; if((f=fopen(a,"w"))==NULL){printf("File could not be opened\n Press any key..."); getch();return;}else{ while(begin!=NULL){ fprintf(f,"%d",begin->sps.expert); fprintf(f,"%s",begin->sps.sport); fprintf(f,"%d",begin->sps.mesto); begin=begin->next; } } fclose(f); } void main (){ record *begin=NULL, /*Указатель начала списка*/ *last=NULL, /*Указатель на очередную запись*/ *list; /*Указатель на элементы списка*/ char c; FILE *f; if((f=fopen("db1.dat","a+"))==NULL){printf("File could not be opened\n Press any key..."); getch();return;}else{ while(fgetc(f)!=EOF){ last=(struct record*)malloc(sizeof(struct record)); if(last==NULL){printf("\n Error !\n No find memory\n Press any key...");getch();return;} fscanf(f,"%d",&last->sps.expert); fscanf(f,"%s",&last->sps.sport); fscanf(f,"%d",&last->sps.mesto); if(begin==NULL){last->prior=NULL;begin=last;last->next=NULL;} else{list=begin; while(list){ if(list->next==NULL){ last->next=NULL; last->prior=list; list->next=last; break; } list=list->next; } } } } fclose(f); while(1){printmenu(); scanf("%s",&c); switch(c){ case '1':{clr("db1.dat");break;} case '2':{ int b=TRUE,extemp,count,c; while(b!=FALSE){ //цикл ввода данных clrscr(); printf("\n Input namber expert (1-10): "); scanf("%d",&extemp); for(count=3;count>0;count--){ last=(struct record*)malloc(sizeof(struct record)); if(last==NULL){printf("\n Error !\n No find memory\n Press any key...");getch();return;} /*проверка, выделена ли память?*/ (*last).sps.expert=extemp; (*last).sps.mesto=count; printf("\n Input family srortsmen: "); scanf("%s",&(*last).sps.sport); if(begin==NULL){last->prior=NULL;begin=last;last->next=NULL;} //списка ещё нет else{list=begin; /*cписок уже существует*/ while(list){ /*цикл просмотра списка-поиск места для новой записи*/ if(list->next==NULL){ /*Включить запись в конец списка*/ last->next=NULL; last->prior=list; list->next=last; break; /*выход из списка просмотра цикла*/ } list=list->next; } } } printf("\n Next input? 1 - Yes \\ 0 - No\n"); //ввод нового эксперта scanf("%d",&b); } printf("\n Data save? 1 - Yes \\ 0 - No\n"); /*записать данные в db.dat?*/ scanf("%d",&c); if(c==TRUE)save(FILE_DB,begin); else ; break;} case '3':{views(begin);break;} case '4':break; case '0':return; default:{printf("\n Error !\n Can't no right selection item\n Press any key...");getch();break;} } } } При запуске программы, данные из файла db1.dat (конечно, если, они на этот момент существуют), должны должны загружаться в оперативную память. Вот участок кода: FILE *f; if((f=fopen("db1.dat","a+"))==NULL){printf("File could not be opened\n Press any key..."); getch();return;}else{ while(fgetc(f)!=EOF){ last=(struct record*)malloc(sizeof(struct record)); if(last==NULL){printf("\n Error !\n No find memory\n Press any key...");getch();return;} fscanf(f,"%d",&last->sps.expert); fscanf(f,"%s",&last->sps.sport); fscanf(f,"%d",&last->sps.mesto); if(begin==NULL){last->prior=NULL;begin=last;last->next=NULL;} else{list=begin; while(list){ if(list->next==NULL){ last->next=NULL; last->prior=list; list->next=last; break; } list=list->next; } } } } fclose(f); В чём заключается ошибка? Как это реализовать? |
Отправлено: 13:49, 02-05-2006 | #3 |
Старый параноик Сообщения: 2423
|
Профиль | Отправить PM | Цитировать -> fscanf(f,"%s",&last->sps.sport);
По-моему, нужно очень осторожно работать с fscanf. Вот данный конкретный - он считает что? Всё до символа конца строки? Слово до пробела? До некоего разделителя? Или вообще всё до конца файла? |
Отправлено: 11:23, 05-05-2006 | #4 |
Пользователь Сообщения: 79
|
Профиль | Отправить PM | Цитировать hasherfrog
Всё верно. разделители нужны.... Считать данные из файла в двухсвязанный список получилось. Функция views() отображает на экран данные из памяти. Функция save() -- записывает в фаил из списка. Перед каждым элементом структуры record, переходим на новую сторку (т.е.разграничиваем --- fprintf(f,"\n%1d",list->sps.expert). функия load() -- считывает из файла в список. Вот код: ...... struct expt{int expert;char sport[20];int mesto;}; struct record{expt sps; record *prior;record *next;}*begin,*last,*list; ....... void views(){ clrscr(); printf("\n Out spicok bd:\n"); list=begin; while(list){ printf("expert %d: %s -- mesto %d\n",list->sps.expert,list->sps.sport,list->sps.mesto); list=list->next; } getch(); } void save(char a[]){ FILE *f; if((f=fopen(a,"w"))==NULL){printf("File could not be opened\n Press any key..."); getch();return;}else{ list=begin; while(list!=NULL){ fprintf(f,"\n%1d",list->sps.expert); fprintf(f,"%20s\n",list->sps.sport); fprintf(f,"%1d",list->sps.mesto); list=list->next; } } fclose(f); } void load(char a[]) { FILE *f; if((f=fopen(a,"r+"))==NULL){printf("File could not be opened\n Press any key..."); getch();return;}else{ while(1){if((fgetc(f))==EOF)break; else{ last=(struct record*)malloc(sizeof(struct record)); if(last==NULL){printf("\n Error !\n No find memory\n Press any key...");getch();return;} fscanf(f,"%1d",&last->sps.expert); fscanf(f,"%20s",last->sps.sport); fscanf(f,"%1d",&last->sps.mesto); if(begin==NULL){last->prior=NULL;begin=last;last->next=NULL;} else{list=begin; while(list){ if(list->next==NULL){ last->next=NULL; last->prior=list; list->next=last; break; } list=list->next; } } } } } fclose(f); } main() { ...... } |
|
Отправлено: 12:38, 12-05-2006 | #5 |
Пользователь Сообщения: 79
|
Профиль | Отправить PM | Цитировать Ещё вопрос, теперь по сортировке.
Необходимо отсортировать двухсвязанный список в порядке возрастания по элементу sps->expert с помощью функции form1(). Допустим есть изначально следующий список (функция views()): | expert | family | ochki | |--------------------------------| | 7 | krotov | 3 | | 7 | popov | 2 | | 7 | sidopov | 1 | | 2 | semenov | 3 | | 2 | sidopov | 2 | | 2 | ivanov | 1 | | 4 | sidorov | 3 | | 4 | chein | 2 | | 4 | petrov | 1 | |--------------------------------| Необходимо получить вот такой следующий: expert | family | ochki | |--------------------------------| | 2 | semenov | 3 | | 2 | sidopov | 2 | | 2 | ivanov | 1 | | 4 | sidorov | 3 | | 4 | chein | 2 | | 4 | petrov | 1 | | 7 | krotov | 3 | | 7 | popov | 2 | | 7 | sidopov | 1 | |--------------------------------| Получается такой: expert | family | ochki | |--------------------------------| | 7 | krotov | 3 | | 7 | popov | 2 | | 7 | sidopov | 1 | |--------------------------------| В чём моя ошибка? Помогите разобраться. #define TRUE 1 #define FALSE 0 ...... struct expt{int expert;char sport[20];int mesto;}; struct record{expt sps; record *prior;record *next;}*begin,*last,*list; ....... void form1() { int is_sort=FALSE; if(begin==NULL){clrscr();printf("Spisok not avialible.\n Press any key... ");getch();return;} //если списка не существует, выходим if(begin->next==NULL){clrscr();printf("One element of spisok.\n Press any key... ");getch();return;}//если один элемент списка, //зачем ,сортировать? while(!is_sort){ //выход из цикла -- is_sort==TRUE. "Пробегаем" в цакле по списку, пока не отсортируем is_sort=TRUE; // предпологаем, что список уже отсортирован for(last=begin;last->next!=NULL;){ //цикл существует, пока есть за указателем last есть следующий элемент list=last; last=last->next; if(list->sps.expert>last->sps.expert){ //если предыдущий элемент списка больше последующего // то меняем указатели местами list->next=last->next; if(last->next==NULL); else last->next->prior=list; if(list->prior==NULL); else list->prior->next=last; last->prior=list->prior; last->next=list; list->prior=last; is_sort=FALSE; // чтобы ещё раз просмотреть список и отсортировать, если, он не отсортирован } } } } ....... void main(){ begin=NULL; last=NULL; char c; load(FILE_DB); while(1){printmenu(); scanf("%s",&c); switch(c){ case '1':{clr("db1.dat");break;} case '2':{edit();break;} case '3':{views();break;} //просматриваем содержимое списка в памяти case '4':{form1();break;} //сортируем содержимое списка по элементу expert структуры expt case '0':return; default:{printf("\n Error !\n Can't no right selection item\n Press any key...");getch();break;} } } } |
Отправлено: 15:21, 18-05-2006 | #6 |
Старый параноик Сообщения: 2423
|
Профиль | Отправить PM | Цитировать Ух, какой кошмарный swap двух елементов :-E
Затираете где-то указатель, имхо, сразу тут: last->next->prior=list; Кто такой last->next->prior? Это ведь last? Получаем last = list; Брррррррррррр... Мозги скрутились... Last, List... Может last->next.prior? |
Отправлено: 19:17, 18-05-2006 | #7 |
Пользователь Сообщения: 79
|
Профиль | Отправить PM | Цитировать hasherfrog
если делаем вот так: то можно проследить, что происходит после кождой итерации цикла while(!is_sort). Перед последней итерацией данного цикла список выглядит так: |--------------------------------| | expert | family | ochki | |--------------------------------| | 7 | krotov | 3 | | 2 | semenov | 3 | | 2 | sidopov | 2 | | 2 | ivanov | 1 | | 4 | sidorov | 3 | | 4 | chein | 2 | | 4 | petrov | 1 | | 7 | popov | 2 | | 7 | sidopov | 1 | |--------------------------------| т.е. два наибольших элемента переместились в конец списка (значит до этого момента всё работает верно), а при перемещении третьего наибольшего элемента получается вся ерунда. Т.е. иными словами, когда один из замещаемых элементов является началом списка. Цитата:
------------------------------------------------------------------------------------------------------------ Цитата:
last->next->prior -- это указатель prior этого следующего за last элемента, т.е. last->next->prior=list; указатель prior следующего за last элемента, теперь будет указывать на тот же участок памяти, что и list. |
||
Отправлено: 10:35, 19-05-2006 | #8 |
Пользователь Сообщения: 79
|
Профиль | Отправить PM | Цитировать Перестановка двух элементов списка получилась.
for(last=begin;last->next!=NULL;){ list=last; last=last->next; if(list->sps.expert>last->sps.expert){ list->next=last->next; if(last->next==NULL); else last->next->prior=list; if(list==begin){last->prior=NULL;begin=last;} // вот в этих else{list->prior->next=last;last->prior=list->prior;} // строках были сделаны изменения last->next=list; list->prior=last; is_sort=FALSE; } |
Отправлено: 09:16, 24-05-2006 | #9 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
2008 - Список сайтов | Alex_Fox | Windows Server 2008/2008 R2 | 2 | 01-07-2009 13:22 | |
Список Dl | Scorpion666 | Вебмастеру | 4 | 20-11-2007 21:42 | |
Список компов в сети? Список открытых папок на компе? | DANTIST | Программирование и базы данных | 3 | 12-06-2003 10:05 | |
Список команд | Trojn | Хочу все знать | 13 | 17-05-2003 15:41 | |
Список серверов | CyMpak | Сетевые технологии | 9 | 05-02-2003 09:19 |
|