Не работает копирование в списке - 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
конструкции. - Код не содержит комментариев, что затрудняет понимание его работы. Добавление комментариев к коду поможет другим разработчикам легче понять его структуру и функциональность.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д