Как в C двусвязном списке присваивать указатель основной вопрос - PullRequest
0 голосов
/ 11 июля 2011

Извините за задание основного вопроса, я изучаю C, и я запутался в присвоении значения для списка.Я запутался с моим собственным вопросом, который всплывает в моей голове ..: (

Так, например, у меня есть структура ниже

typedef struct {
    int value_in_use;
} structA;

typedef struct structB {
    structA conn;
    struct structB *next, *prev;
} structB

typedef struct {
    structB *head, *tail;
} structC;

, и я хочу присвоить значение "value_in_use"«равно 1. Я совершенно сбит с толку, поскольку, как я понимаю, в списке мне нужно сначала пройтись от головы (StructC), и мне нужно идти внутрь списка, пока я не попаду в structA и не назначу ему значение.Так что-то вроде

 structC *C = NULL;
 C = (structC *) malloc(sizeof(structC));
 int assign=1;
 &C->structB.head->conn.value_in_use=assign;

Между тем, я подумал, что на самом деле могу назначить указатель на structA напрямую и присвоить ему значение. Поэтому я могу просто сказать

structA *ue = NULL;
ue = (structA *) malloc(sizeof(structA));
ue->value_in_use = 100;

Как этоотличаются для присвоения значения списка во время выполнения в первой части и второй части? Я полагаю, что я могу использовать оба для присвоения значения (или?) ..

Большое спасибо за то, что поделились своими знаниями со мной.

Ответы [ 4 ]

3 голосов
/ 11 июля 2011

Первый фактически не будет работать. Вы пытаетесь следовать за указателем головы из C, но вы не знаете, куда указывает этот указатель (т.е. malloc не является рекурсивным).

Для первого случая вам нужно сделать что-то вроде этого:

structC * c = malloc(sizeof(structC));
structB * b = malloc(sizeof(structB));
c->head = b;
c->tail = b;
b->next = NULL;
b->prev = NULL;
c->head->conn.value_in_use = 1;

Обратите внимание, что нам не нужно выделять структуру structA отдельно, так как она встроена в B.

1 голос
/ 11 июля 2011

Сначала вам нужно будет выделить память для structC, затем вам нужно выделить память для указателей внутри нее (*head, *tail), а затем вы можете присвоить значение conn.

Итак, вот подробности трехэтапной процедуры с объяснением:

Шаг 1:

structC *C = NULL;
C = (structC *) malloc(sizeof(structC));

C теперь просто указатель на тип struct C, это означает, что он просто указывает на память размером с тип указателя где-то в стеке. Используя malloc, вы выделяете (резервируете) пространство размером struct C.

Шаг 2:

   C->head= (structA *) malloc(sizeof(structA));

Теперь указатель head внутри структуры C(structC) снова просто указывает на размер памяти указателя. Вам нужно выделить его размер (structA), используя приведенный выше оператор malloc.

Шаг 3:

Как только C->head указывает на память, достаточно большую, чтобы вместить strct A, теперь вы можете присвоить ей значение по вашему выбору.

C->head->value_in_use = 100;
0 голосов
/ 11 июля 2011

Вы пишете в случайную память во втором примере, оператор адреса (&) является виновником (я удивлен, что C-компилятор не уловил ошибку).

В третьем примере вы просто выделяете память для structA, на который указывает ua, который не связан ни с чем, напоминающим древовидную структуру.Поскольку вы реализовали structB, память для conn является частью записи, если память для structB выделяется динамически с malloc, тогда вы получаете conn бесплатно как часть выделенной памяти.Если structB создается в статической памяти или в стеке как «обычная» (с точки зрения языков, в которой не используются указатели или динамическое распределение памяти) переменная, то запись conn разделяет эту же память.

Надеюсь, я не прибавил путаницы (извините за отсутствие навыков английского)

Могу дать вам несколько полезных советов:

Первое: я рекомендуювы используете более описательные имена в качестве начала.Почему бы не root, node и data для конструкций.

Второе: я рекомендую прочитать хорошую книгу для начинающих о C. Язык программирования C на языке Kernighan & Ritchie - это классика, но он не имеет большого значения с указателями, его легко читать для кого-либо без какого-либознакомство с другими языками программирования, но не книга для начала программирования.Указатели на C Кеннета Рика концентрируются на частях C, которые отличаются от других языков программирования, в основном на указателях и модели памяти C.Указатели на C также обеспечивают хорошую реализацию базовых структур данных, таких как деревья.Насколько я знаю, в Интернете нет хороших статей для начинающих программистов на Си.

Третье: прочитайте хорошую книгу или веб-страницу о структурах данных и алгоритмах, которые можно использовать с ними.Я видел несколько хороших веб-страниц на эту тему, но сейчас не могу их найти.

0 голосов
/ 11 июля 2011

Я не совсем уверен, с чего начать. Обратите внимание, что structA, structB и structC, похоже, представляют разные «уровни», так сказать, реализации вашего двусвязного списка. structA представляет фактические данные или элементы списка, structB представляет элемент данных и его соединения, а structC представляет весь список. Также обратите внимание, что structC содержит только указатели на значения в списке. Выделив structC, как в вашем первом примере кода, он не будет содержать никакой полезной информации или выделять место для членов. Вы должны немедленно очистить память, потому что указатели не будут действительными. Таким образом, ваш первый пример кода не будет работать. Я ожидаю, что вы будете делать что-то вроде (предупреждение: непроверенный код)

structC* c = malloc(sizeof(structC)); // note: don't cast the pointer from malloc in C
structB* b = malloc(sizeof(structB)); // you now have a data member
memset(b, 0, sizeof(structB));
c->head = b;
c->tail = b;
b->conn.value_in_use = 1;

Теперь у вас есть список, в котором используется один участник.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...