Получить данные глубоко в структурах C - PullRequest
0 голосов
/ 24 апреля 2018

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

                      1
          ptr ---> |------|       2
                   | next ---> |------|
                   | data |    | next |
                   |------|    | data | <= data which i desire to get 
                               |------|

Как мне получить доступ к нужным данным, если я действительно не хочу объявлять другую переменную-указатель?

Что делать, если требуемые данные еще глубже?

Я попробовал что-то подобное для теста, но мне кажется, что это немного "не в порядке", и я очень удивлен тем, что не было предупреждений компилятора:

ptr2struct.c

#include <stdio.h>
#include <stdlib.h>

typedef struct Structure structure;
struct Structure {
    int data;
    structure *next;
};

int main()
{
    structure *ptr = malloc(sizeof(*ptr));

    /* First structure */
    ptr->data = 1;
    ptr->next = malloc(sizeof(ptr->next));

    /* Second structure */
    ptr->next->data = 2;
    ptr->next->next = malloc(sizeof(ptr->next->next));

    /* Third structure, why not */
    ptr->next->next->data = 3;
    ptr->next->next->next = NULL;

    printf("ptr->data = %d\n", ptr->data);
    printf("ptr->next->data = %d\n", ptr->next->data);
    printf("ptr->next->next->data = %d\n", ptr->next->next->data);

    return 0;
}

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

Кстати, это не мое HW, просто любопытство :)

Хорошего дня и спасибо за советы!

1 Ответ

0 голосов
/ 24 апреля 2018

Первое, что неправильно, это:

structure *ptr = malloc(sizeof(ptr));

, который выделяет достаточно места для хранения ptr, который является указателем, вам нужно

structure *ptr = malloc(sizeof(*ptr));

Распределив всеправильно, доступ к вещам в первом элементе, как это:

ptr->data; // the data
ptr->next; // pointer to the next struct in the chain

Доступ к вещам во втором struct, как это

ptr->next->data; // data in the second struct
ptr->next->next; // pointer to the third struct

и т. д.

ИмеяПросто прочитайте некоторые комментарии к этому вопросу, я должен добавить, что ptr->next->next опасен по своей природе, если вы не знаете, что и ptr, и ptr->next не равны нулю.Кроме того, malloc не гарантирует обнуление памяти, поэтому после вызова malloc вы всегда должны убедиться, что указатель next равен NULL.

Если у вас длинная цепочка, а последний элементчто означает наличие NULL next, вы можете перебирать цепочку с помощью цикла for, например,

for (structure* current = ptr ; current != NULL ; current = current->next)
{
    printf("%d\n", current->data);
}

или, если вы хотите найти n th элемент

structure* ptrAtIndex(structure* start, int index) 
{
    for (structure* current = ptr, int i = 0 ; current != NULL ; current = current->next, i++)
    {
        if (i == index)
        {
            return current;
        }
    }
    return NULL; // The chain wasn't long enough
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...