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