Ваш компилятор должен предупреждать вас о неизвестном типе n
in:
struct n { //The definition of Linked List
int x;
n * next;
};
Над типом n
неизвестно в то время, когда вы объявляете n * next;
.Чтобы исправить это, вам необходимо включить struct
перед n
, например
struct n { //The definition of Linked List
int x;
struct n * next;
};
Эта проблема также присутствует в вашем typedef
, например
typedef n node;
Снова n
неизвестно в это время.Вместо этого вам нужно.
typedef struct n node;
Как указывает Бруно, вы вызываете Неопределенное поведение , используя x
в counter
, когда оно не инициализировано, например:
int counter(node *r){ //Counting the node.
int x;
while(r != NULL){
x++; /* what is the value of x on the first iteration? */
...
Инициализируйте int x = 0
для исправления.
Проблемы со списком копирования
Сначала не ставьте пробелы вокруг ->
в r = r->next;
Оператор со стрелкой должен непосредственноподключите структуру и член.
Ваша cpyLl()
функция ничего не копирует.Чтобы скопировать список, вам нужна функция, которая возвращает указатель на вновь скопированный список.Например, имеет смысл сделать:
/* cpyL1 should return a pointer to the head of the newly copied list */
node *cpyLl (node *r) {
Внутри вашей функции вам нужно выделить / создать новый первый узел и назначить первое значение данных для копии, а затем, по существу, повторить для остальных узлов, циклически повторяющихсявсе узлы создают новый выделенный узел для копирования и копирования значения.Вам нужно будет сохранить указатель на начало скопированного списка для возврата.Вам не нужно counter
вообще в cpyL1
.У вас есть связанный список, вы можете перебирать список, используя указатели next
.например,
/* cpyL1 should return a pointer to the head of the newly copied list */
node *cpyLl (node *r) {
node *copy = NULL, *p; /* pointers for new list - initialized NULL */
if (!r) { /* validate r is not NULL */
fputs ("error: list to copy is empty.\n", stderr);
return NULL;
}
copy = malloc (sizeof *copy); /* allocate 1st node of copy */
if (!copy) {
perror ("malloc-copy");
return NULL;
}
p = copy;
p->x = r->x;
while (r->next) { /* copy all nodes from r to copy */
p->next = malloc (sizeof *p->next); /* allocate each node */
if (!p->next) { /* validate the allocation */
perror ("malloc-p->next");
return copy; /* return partial copy of list */
}
r = r->next; /* advance to next node */
p = p->next;
p->x = r->x; /* set node value */
p->next = NULL;
}
return copy; /* return pointer to newly copied list */
}
( примечание: вы должны ПРОВЕРЯТЬ каждое выделение.)
Теперь, если вы просто хотите скопировать определенный узел, вы можете выполнять итерацию, пока не найдетезначение или адрес и просто скопируйте один узел.
Поместив его целиком и добавив список печати и функцию свободного списка, вы можете сделать что-то похожее на:
#include <stdio.h>
#include <stdlib.h>
struct n { //The definition of Linked List
int x;
struct n *next;
};
typedef struct n node;
int counter (node *r) //Counting the node.
{
int y = 0;
while (r != NULL) {
y++;
r = r->next;
}
return y;
}
/* cpyL1 should return a pointer to the head of the newly copied list */
node *cpyLl (node *r) {
node *copy = NULL, *p; /* pointers for new list - initialized NULL */
if (!r) { /* validate r is not NULL */
fputs ("error: list to copy is empty.\n", stderr);
return NULL;
}
copy = malloc (sizeof *copy); /* allocate 1st node of copy */
if (!copy) {
perror ("malloc-copy");
return NULL;
}
p = copy;
p->x = r->x;
while (r->next) { /* copy all nodes from r to copy */
p->next = malloc (sizeof *p->next); /* allocate each node */
if (!p->next) { /* validate the allocation */
perror ("malloc-p->next");
return copy; /* return partial copy of list */
}
r = r->next; /* advance to next node */
p = p->next;
p->x = r->x; /* set node value */
p->next = NULL;
}
return copy; /* return pointer to newly copied list */
}
void prnlist (node *l)
{
while (l) {
printf (" %d", l->x);
l = l->next;
}
putchar ('\n');
}
void freelist (node *l)
{
while (l) {
node *victim = l;
l = l->next;
free (victim);
}
}
int main (void) {
node *root, *p, *copy = NULL;
root = malloc (sizeof *root);
/* first node */
if (!root) { /* validate EVERY allocation */
perror ("malloc-root");
return 1;
}
root->x = 10;
p = root; /* assign pointer to root */
/* second node */
p->next = malloc (sizeof *p->next);
if (!p->next) { /* validate EVERY allocation */
perror ("malloc-p->next");
return 1;
}
p = p->next;
p->x = 20;
/* third node */
p->next = malloc (sizeof *p->next);
if (!p->next) { /* validate EVERY allocation */
perror ("malloc-p->next");
return 1;
}
p = p->next;
p->x = 30;
p->next = NULL; /* set p->next to NULL */
copy = cpyLl(root); /* copy root list to copy */
if (!copy) {
fputs ("error: copy is NULL\n", stderr);
return 1;
}
puts ("\noriginal list:\n");
prnlist (root);
puts ("\ncopy of list:\n");
prnlist (copy);
freelist (root); /* don't forget to free what you allocate */
freelist (copy);
return 0;
}
ПримерИспользование / Вывод
$ ./bin/structfwd
original list:
10 20 30
copy of list:
10 20 30
Использование памяти / проверка ошибок
Не забудьте проверить использование памяти для любых ошибок.
$ valgrind ./bin/structfwd
==12148== Memcheck, a memory error detector
==12148== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==12148== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==12148== Command: ./bin/structfwd
==12148==
original list:
10 20 30
copy of list:
10 20 30
==12148==
==12148== HEAP SUMMARY:
==12148== in use at exit: 0 bytes in 0 blocks
==12148== total heap usage: 6 allocs, 6 frees, 96 bytes allocated
==12148==
==12148== All heap blocks were freed -- no leaks are possible
==12148==
==12148== For counts of detected and suppressed errors, rerun with: -v
==12148== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)