Вывод односвязного динамического списка - 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

Объяснение кода листинга программы

  1. Указатель beg инициализируется значением адрес_1-го_звена_готового_списка.
  2. Указатель end инициализируется значением адрес_последнего_звена_готового_списка.
  3. Указатель ptr инициализируется значением beg.
  4. Указатель ptr инкрементируется на единицу, что должно привести к переходу к следующему звену списка.
  5. Значение ptr должно измениться на адрес_следующего_звена_списка, например, FF30.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 3.929 из 5
Похожие ответы