Не работает копирование в списке - C (СИ)
Формулировка задачи:
Добрый день! Нужно реализовать копирование указанного элемента . Но почему то не работает . Подскажи в чем дело.
#include <stdio.h> #include <stdlib.h> typedef struct L { int value; char name[10]; struct L *next, *prev; } ListItem; int main() { static ListItem base; static ListItem *current; static ListItem *pos; static int a,b,c,k,g; static int num; current = &base; base.next = base.prev = &base; num=0; /*Создание и добавления нового элемента до предыдущего*/ do{ pos = (ListItem*)malloc(sizeof(ListItem)); printf("\nWhat is your name? \t"); scanf("%s",&pos->name); printf("\nHow tall are you? \t"); scanf("%d",&pos->value); if(pos->value==0){ free(pos); break; } pos->next = current->next; pos->prev = current; current->next->prev = pos; current->next = pos; num++; } while(1); /*Печать всего списка*/ pos=current->prev; while(pos!=&base) { printf("\nname=%s\ttall=%d\n",pos->name,pos->value); pos=pos->prev; } /*Копирование указанной ячейки и вставить до нее*/ printf("\nVvedite do kakoi vstavit\t"); scanf("%d",&k); pos=current->prev; for(c=1;c<k;c++){ pos=pos->prev; } current->next=pos; pos = (ListItem*)malloc(sizeof(ListItem)); pos->name=current->next->name; pos->value=current->next->value; pos->prev=current->next; pos->next=current->next->next; current->next->next->prev=pos; current->next->next=pos; num++; for(c=1;c<=num-k;c++){ current->next=pos->prev; } pos=current->prev; while(pos!=&base) { printf("\nname=%s\ttall=%d\n",pos->name,pos->value); pos=pos->prev; }
Решение задачи: «Не работает копирование в списке»
textual
Листинг программы
#include <stdio.h> #include <string.h> #include <malloc.h> typedef struct node { int value; char name[10]; struct node* next; struct node* prev; } node_t; typedef struct { node_t* head; node_t* tail; } list_t; void list_init(list_t* l); int list_add_front(list_t* l, const char* s, int n); int list_add_back(list_t* l, const char* s, int n); node_t* list_insert(list_t* l, node_t* p, const char* s, int n); node_t* list_delete(list_t* l, node_t* p); void list_clear(list_t* l); int main(void){ node_t* p; list_t l; list_init(&l); list_add_back(&l, "Uran", 1); list_add_back(&l, "Mars", 2); list_add_back(&l, "Venus", 3); list_add_front(&l, "Erath", 4); list_add_front(&l, "Saturn", 5); list_add_front(&l, "Neptun", 8); //вставить копию у чётных for(p = l.head; p != NULL; p = p->next){ if(! (p->value % 2)) p = list_insert(&l, p, p->name, p->value); } //вывести с начало for(p = l.head; p != NULL; p = p->next) printf("%s\t%d\n", p->name, p->value); putchar('\n'); // вывести с конца for(p = l.tail; p != NULL; p = p->prev) printf("%s\t%d\n", p->name, p->value); putchar('\n'); //удалить все чётные p = l.head; while(p != NULL){ if(!(p->value % 2)){ p = list_delete(&l, p); continue; } p = p->next; } //вывести с начало for(p = l.head; p != NULL; p = p->next) printf("%s\t%d\n", p->name, p->value); putchar('\n'); // вывести с конца for(p = l.tail; p != NULL; p = p->prev) printf("%s\t%d\n", p->name, p->value); putchar('\n'); list_clear(&l); return 0; } //инициализация void list_init(list_t* l){ l->head = l->tail = NULL; } //вставка в начало списка int list_add_front(list_t* l, const char* s, int n){ node_t* p = (node_t*)malloc(sizeof(node_t)); if(p != NULL){ p->next = p->prev = NULL; p->value = n; strcpy(p->name, s); if(l->head == NULL) l->head = l->tail = p; else { p->next = l->head; l->head->prev = p; l->head = p; } } return (p != NULL); } //вставка в конец списка int list_add_back(list_t* l, const char* s, int n){ node_t* p = (node_t*)malloc(sizeof(node_t)); if(p != NULL){ p->next = p->prev = NULL; p->value = n; strcpy(p->name, s); if(l->head == NULL) l->head = l->tail = p; else { l->tail->next = p; p->prev = l->tail; l->tail = p; } } return (p != NULL); } //вставка перед элементом node_t* list_insert(list_t* l, node_t* p, const char* s, int n){ node_t* t; if(p == NULL) return NULL; else if(p == l->head){ if(list_add_front(l, s, n)) return l->head->next; return NULL; } t = (node_t*)malloc(sizeof(node_t)); if(t != NULL){ strcpy(t->name, s); t->value = n; t->next = p; t->prev = p->prev; p->prev->next = t; p->prev = t; } return p; } //удаление элемента node_t* list_delete(list_t* l, node_t* p){ node_t* t; if(p == NULL) return NULL; else if(p == l->head){ l->head = l->head->next; if(l->head != NULL) l->head->prev = NULL; t = l->head; } else if(p == l->tail){ l->tail = l->tail->prev; if(l->tail != NULL) l->tail->next = NULL; t = l->tail; } else { p->prev->next = p->next; p->next->prev = p->prev; t = p->next; } if(l->head == NULL) l->tail = NULL; free(p); return t; } //удаление всего списка void list_clear(list_t* l){ node_t* t; while(l->head != NULL){ t = l->head; l->head = l->head->next; free(t); } l->tail = NULL; }
Объяснение кода листинга программы
В данном коде реализована работа со связанным списком. Список содержит узлы, каждый из которых включает в себя значение типа int и строку типа char, а также указатели на следующий и предыдущий узлы.
- Переменные и типы данных:
node_t
- структура, представляющая один узел спискаlist_t
- структура, представляющая весь списокint
- тип данных для значения в узлеchar
- тип данных для строки в узлеnode_t*
- указатель на узелlist_t*
- указатель на списокconst char*
- указатель на строкуint*
- указатель на значениеvoid*
- указатель на любое значениеFILE*
- указатель на файл (используется для отладки)
- Функции:
list_init
- инициализирует список пустымlist_add_front
- добавляет новый узел в начало спискаlist_add_back
- добавляет новый узел в конец спискаlist_insert
- вставляет новый узел перед указанным узломlist_delete
- удаляет узел из спискаlist_clear
- очищает список, освобождая память
- Основная часть программы:
- Создается список и инициализируется пустым
- В список добавляются узлы в произвольном порядке
- Пытаются вставить копию каждого узла перед четными узлами
- Выводят список с начала и с конца
- Удаляют все четные узлы
- Выводят список с начала и с конца
- Очищают список
- Возвращается 0, завершая программу Возможные проблемы и их решения:
- При использовании функции
strcpy
для копирования строк, всегда выделяется 10 символов для строкиname
, даже если строкаs
короче. Это может привести к переполнению буфера, что является серьезной проблемой безопасности. Чтобы избежать этого, необходимо проверять длину строкиs
перед вызовомstrcpy
. - В коде нет обработки ошибок для операций с памятью (например, если
malloc
возвращаетNULL
). Хорошей практикой является обработка таких ошибок с помощьюifdef
илиtry-catch
конструкции. - Код не содержит комментариев, что затрудняет понимание его работы. Добавление комментариев к коду поможет другим разработчикам легче понять его структуру и функциональность.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д