Ошибка в коде из методички. Работа с двусвязным списком - C (СИ)
Формулировка задачи:
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> typedef struct {char data[20]; struct spis *v1; // v1 – указатель на предыдущую структуру struct spis *v2; // v2 – указатель на последующую структуру } spis; void create(void); // создание void list(spis *); // просмотр void del(void); // удаление struct spis *head,*tail; // указатели на начало и конец списка main() { clrscr(); create(); list(head); // просмотр с начала списка list(tail); // просмотр с конца списка del(); list(head); free(head); } void create(void) {spis *p,*pred; pred=NULL; do { p=(spis *)malloc(sizeof(spis)); printf("Фамилия: "); gets(p->data); p->v1=pred; if (pred != NULL) pred->v2=p; else head=p; pred=p; puts(" Закончить - <esc>"); } while (getch()!=27); tail=p; tail->v2=NULL; } void list(spis *p) {if (p==head) while (p != NULL) {puts(p->data); p=p->v2; } else if (p==tail) while ( p!= NULL) {puts(p->data); p=p->v1; } else puts("Неверный адрес "); getch(); } void del(void) {spis *p,*temp;char f[20]; // f[20] – Строка для удаляемой фамилии clrscr(); printf("Фамилия: ");gets(f); p=head; while (p!=NULL) {if (strcmp((p->data),f)==0) // если найдена заданная фамилия {if (p==head) // если найденная запись - первая {head=p->v2; head->v1=NULL; free(p); p=head; } else if (p==tail) // если найденная запись - последняя {tail=p->v1; tail->v2=NULL; free(p); p=tail; } else // удаление из средины списка {p->v2->v1=p->v1; p->v1->v2=p->v2; temp=p; p=p->v2; free(temp); } } else // если заданная фамилия не найдена – продвигаемся по списку p=p->v2; } }
#include <stdio.h> #include <conio.h> #include <alloc.h> #include <string.h> struct spis {char data[20]; struct spis *v1; // v1 – указатель на предыдущую структуру struct spis *v2; // v2 – указатель на последующую структуру }; void create(void); // создание void list(spis *); // просмотр void del(void); // удаление struct spis *head,*tail; // указатели на начало и конец списка main() { clrscr(); create(); list(head); // просмотр с начала списка list(tail); // просмотр с конца списка del(); list(head); free(head); } void create(void) {spis *p,*pred; pred=NULL; do { p=(spis *)malloc(sizeof(spis)); printf("Фамилия: "); gets(p->data); p->v1=pred; if (pred != NULL) pred->v2=p; else head=p; pred=p; puts(" Закончить - <esc>"); } while (getch()!=27); tail=p; tail->v2=NULL; } void list(spis *p) {if (p==head) while (p != NULL) {puts(p->data); p=p->v2; } else if (p==tail) while ( p!= NULL) {puts(p->data); p=p->v1; } else puts("Неверный адрес "); getch(); } void del(void) {spis *p,*temp;char f[20]; // f[20] – Строка для удаляемой фамилии clrscr(); printf("Фамилия: ");gets(f); p=head; while (p!=NULL) {if (strcmp((p->data),f)==0) // если найдена заданная фамилия {if (p==head) // если найденная запись - первая {head=p->v2; head->v1=NULL; free(p); p=head; } else if (p==tail) // если найденная запись - последняя {tail=p->v1; tail->v2=NULL; free(p); p=tail; } else // удаление из средины списка {p->v2->v1=p->v1; p->v1->v2=p->v2; temp=p; p=p->v2; free(temp); } } else // если заданная фамилия не найдена – продвигаемся по списку p=p->v2; } }
Решение задачи: «Ошибка в коде из методички. Работа с двусвязным списком»
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> typedef struct spis {char data[20]; struct spis *v1; // v1 – указатель на предыдущую структуру struct spis *v2; // v2 – указатель на последующую структуру } spis; void create(void); // создание void list(spis *); // просмотр void del(void); // удаление struct spis *head,*tail; // указатели на начало и конец списка int main() { fflush(stdin); fflush(stdout); create(); list(head); // просмотр с начала списка list(tail); // просмотр с конца списка del(); list(head); free(head); } void create(void) {spis *p,*pred; pred=NULL; do { p=(spis *)malloc(sizeof(spis)); printf("Фамилия: "); gets(p->data); p->v1=pred; if (pred != NULL) pred->v2=p; else head=p; pred=p; puts(" Закончить - <esc>"); } while (getch()!=27); tail=p; tail->v2=NULL; } void list(spis *p) {if (p==head) while (p != NULL) {puts(p->data); p=p->v2; } else if (p==tail) while ( p!= NULL) {puts(p->data); p=p->v1; } else puts("Неверный адрес "); getch(); } void del(void) {struct spis *p,*temp; char f[20]; // f[20] – Строка для удаляемой фамилии fflush(stdin); fflush(stdout); printf("Фамилия: ");gets(f); p=head; while (p!=NULL) {if (strcmp((p->data),f)==0) // если найдена заданная фамилия {if (p==head) // если найденная запись - первая {head=p->v2; head->v1=NULL; free(p); p=head; } else if (p==tail) // если найденная запись - последняя {tail=p->v1; tail->v2=NULL; free(p); p=tail; } else // удаление из средины списка {p->v2->v1=p->v1; p->v1->v2=p->v2; temp=p; p=p->v2; free(temp); } } else // если заданная фамилия не найдена – продвигаемся по списку p=p->v2; } }
Объяснение кода листинга программы
В этом коде реализована работа со связанным списком, который используется для хранения информации о фамилиях. Список представлен с помощью структуры spis
, которая содержит строку данных (фамилию), указатель на предыдущую структуру в списке (v1
) и указатель на следующую структуру в списке (v2
).
В функции create
происходит добавление элементов в список. Пользователю предлагается ввести фамилию, после чего создается новый элемент списка, связывается с предыдущим и следующим элементами и добавляется в конец списка.
Функция list
позволяет просмотреть список элементов. Если переданный в функцию указатель на начало списка (head
), то выводятся все элементы списка. Если переданный указатель находится в середине списка, то выводятся элементы, начиная с этого указателя и до конца списка. Если переданный указатель указывает на последний элемент списка (tail
), то выводятся все элементы списка в обратном порядке.
Функция del
предназначена для удаления элемента из списка по заданной фамилии. Если фамилия совпадает с фамилией первого элемента списка, то этот элемент удаляется. Если фамилия совпадает с фамилией последнего элемента списка, то этот элемент удаляется. Если фамилия встречается в середине списка, то элемент удаляется путем разрыва связей между элементами.
В основной функции main
сначала выполняется функция create
для создания списка. Затем функция list
вызывается дважды - сначала с указателем на начало списка (head
), затем с указателем на конец списка (tail
). После этого выполняется функция del
, которая удаляет элемент по заданной фамилии. Затем функция list
вызывается снова с указателем на начало списка (head
), чтобы просмотреть список после удаления элемента. Наконец, память, выделенная под список, освобождается с помощью функции free
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д