Вывод односвязного динамического списка - C (СИ)
Формулировка задачи:
Размер структуры cell - 20 байт. (см. программу ниже). Т.е. при выделении памяти под новый элемент списка к каждому адресу будет прибавляться +20, прим.: 00641730, 00641750, 00641770 и т.д. Пусть список уже сформирован в памяти и нам осталось только вывести его не экран. Тогда, если выполнить операцию rex++; (rex - указатель для перебора адресов элементов списка) то, по аналогии с перебором элементов статического массива, должен произойти переход к адресу следующего элемента, т.е. указатель rex должен бы получить значение адреса следующего звена списка, но этого не проиходит. При выполнении программы он почему-то изменяет значение не на 20, а на 14 и все данные выводятся неправильно.
Что не так в этом примере? В чём моя ошибка? Помогите разобраться.
// ПРИМЕР. Напечатать список
printf("\nСодержимое списка: ");
rex=beg; /* вернули курсор rex к началу - адресу первого элемента списка */
while(rex<=end)
{
printf("\nsign=%s\tweight=%d",rex->sign,rex->weight);
printf(" rex=%p rex->pc=%p beg=%p end=%p ",rex,rex->pc,beg,end);
rex++; /* переход к следующему адресу звена списка */
}// ПРОГРАММА. Односвязный динамический список
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
/* Определение структурного типа "Звено списка" */
struct cell {
char sign[10]; // 10 байт
int weight; // 4 байта
struct cell * pc; // размер 6 байт
}; // общий размер 20 байт
int main()
{
setlocale(LC_ALL,"Rus");
struct cell * rex;
struct cell * beg = NULL; /* начало списка */
struct cell * end = NULL; /* конец списка */
printf("\nВведите значения структур: \n");
/* Цикл ввода и формирования списка */
do
{ /* Выделить память для очередного звена списка */
rex = (struct cell *) malloc (sizeof(struct cell));
printf("rex=%p beg=%p end=%p rex->pc = %p\n",rex,beg,end,rex->pc);
/* Ввести значения элементов звена: */
printf("sign = ");
scanf("%s",&rex->sign);
printf("weight = ");
scanf("%d",&rex->weight);
if (rex->weight == 0)
{
free(rex);
break; /* Выход из цикла ввода списка */
}
/* Включить звено в список */
if (beg==NULL && end==NULL) /* Если список пуст, то */
beg = rex; /* сохранить адрес первого звена списка в beg */
else
end->pc=rex; /* включить звено (2-й элемент и далее) в уже существующий список
указателю pc предыдущего эл-та присвоить адрес на следующий эл-т */
end=rex; /* теперь end указывает на текущий элемент списка */
end->pc=NULL; /* pc последнего звена будет указывать на NULL - признак конца списка */
printf("end->pc = %p rex = %p end = %p rex->pc = %p\n",end->pc,rex,end,rex->pc);
printf("-----------------------------------------------------------\n");
}
while(1); /* Конец цикла ввода списка */
/* Напечатать список */
printf("\nСодержимое списка: ");
rex=beg; /* вернули курсор rex к началу - адресу первого элемента списка */
while(rex!=NULL)
{
printf("\nsign=%s\tweight=%d",rex->sign,rex->weight);
printf(" rex=%p rex->pc=%p beg=%p end=%p ",rex,rex->pc,beg,end);
rex=rex->pc; /* переход к следующему адресу звена списка через указатель pc */
}
rex = beg;
while (rex<end)
{
printf("%p\n",rex++);
}
system("PAUSE");
return EXIT_SUCCESS;
}Решение задачи: «Вывод односвязного динамического списка»
textual
Листинг программы
// Изменение значения указателя на звено списка
struct cell {поля_данных; struct cell *pc;} *beg,*end, *ptr;
. . .
// список сформирован:
// beg==адрес_1-го_звена_готового_списка
// end==адрес_последнего_звена_готового_списка
ptr=beg; // ptr указывает на адрес первого элемента, напр.: FF10
ptr++; // должен произойти переход к следующему значению: значение ptr - FF30
Объяснение кода листинга программы
- Указатель
begинициализируется значениемадрес_1-го_звена_готового_списка. - Указатель
endинициализируется значениемадрес_последнего_звена_готового_списка. - Указатель
ptrинициализируется значениемbeg. - Указатель
ptrинкрементируется на единицу, что должно привести к переходу к следующему звену списка. - Значение
ptrдолжно измениться наадрес_следующего_звена_списка, например,FF30.