разобрать одну структуру, чтобы функционировать из массива структур - PullRequest
0 голосов
/ 28 марта 2011

Я новичок в C, но не в программировании. Я был вынужден изменить программу на C, чтобы она собирала несколько частей данных и помещала их в массив. Мне не разрешено размещать фактический исходный код, поэтому я сделал следующий пример, который иллюстрирует то, что я пытаюсь сделать:

#include <windows.h>

typedef struct 
{
    int size;
    long rpm;
} ENGINE;


typedef struct 
{
    int doors;
    int wheels;
    ENGINE engine;
} CAR;

int newCar(CAR *car)
{
    ENGINE eng;
    eng.rpm=30000;
    eng.size=1600;
    car->doors=4;
    car->wheels=4;
    car->engine=eng;
    return 0;

}


int getCars(CAR *cars[], int n)
{
    int i = 0;
    for (i=0; i<n; i++)
    {
        newCar(cars[i]);
    }

    return 0;
}

int carCount(int *count)
{
    *count = 4;
    return 0;
}

int main()
{
    int n = 0;
    CAR *cars = (CAR*) malloc(sizeof(CAR));
    carCount(&n);

    cars = (CAR*)realloc(cars, n * sizeof(CAR));
    cars[1].doors = 2;
    getCars(&cars,n);

}

Приведенный выше код компилируется, но завершается неудачно, когда я пытаюсь установить элементы структуры car внутри процедуры newCar. Я не уверен, что мой realloc на массиве cars делает то, что я хочу, я основал это на некоторых других публикациях на stackoverflow. Это выглядит хорошо? Как я могу получить доступ к членам автомобиля из рутины нового автомобиля? Это разумный способ сделать это? Большое спасибо:)

Ответы [ 5 ]

1 голос
/ 28 марта 2011

Вам не нужны двойные косвенные указания!Простой указатель на CAR может указывать на разные CAR.

Создайте пространство для нужного вам количества CAR: ok

Можно легко сделать указатель на первый CAR в этом пространстве, чтобы указать надругие CAR.

    CAR *cars = malloc(sizeof(CAR));

, если malloc не выдал ошибку cars указывает на место, достаточно большое, чтобы вместить 1 CAR

    cars = realloc(cars, n * sizeof(CAR));

если realloc не завершился с ошибкой cars теперь указывает на пространство, достаточно большое, чтобы вместить n автомобилей
, передать этот указатель на ваши функции, а также количество автомобилей, на которые он указывает

    getCars(cars, n);

и использовать указатель в функциях

int getCars(CAR *cars, int n)
{
    int i = 0;
    for (i=0; i<n; i++)
    {
        /* here, cars[0] is the first car; cars[1] is the second ... */
        /* we can pass the address with &cars[i]                     */
        /* or make arithmetic with the pointer itself:               */
        newCar(cars+i);
    }
    return 0;
}
0 голосов
/ 29 марта 2011

Причина, по которой ваш код дает сбой, состоит в том, что в main, cars - простая скалярная переменная, и вы вызываете подпрограмму с ее адресом в качестве аргумента. В getCars, cars - это массив указателей, поэтому cars[i] читайте перед адресом, который вы передали в качестве аргумента. И здесь это неправильно, потому что адрес - это адрес одной скалярной переменной, а не адрес таблицы.

Чтобы получить право, вы должны вызвать подпрограмму со значением main s cars, которое в точности соответствует адресу таблицы, которую вы создали с помощью malloc / realloc. Обратите внимание, что в этом случае прототип подпрограммы будет просто

int getCars(CAR *cars, int n)
0 голосов
/ 28 марта 2011

В getCars вы определяете cars как CAR *cars[], то есть массив указателей на CAR.

В main, &cars - это указатель намассив из CAR s.

Код может скомпилироваться, возможно, потому что оба преобразуются в CAR**.

Я переписал бы код следующим образом:

int newCar(CAR** car)
{
    *car = (CAR*)malloc(sizeof(CAR));
    ENGINE eng;
    eng.rpm=30000;
    eng.size=1600;
    (*car)->doors=4;
    (*car)->wheels=4;
    (*car)->engine=eng;
    return 0;
}

int getCars(CAR *cars[], int n)
{
    int i = 0;
    for (i=0; i<n; i++)
    {
        newCar(&cars[i]);
    }

    return 0;
}

int main()
{
    int n = 0;
    CAR** cars = (CAR**) malloc(sizeof(CAR*));
    carCount(&n);

    cars = (CAR**)realloc(cars, n * sizeof(CAR*));
    getCars(cars,n);
    cars[1]->doors = 2;
}

и т. Д.

0 голосов
/ 28 марта 2011

Например, чтобы использовать malloc, вам нужен заголовок stdlib.h. Поскольку вы преобразуете указатель из malloc в (CAR *), компилятор предполагает, что malloc возвращает int, и предупреждение не генерируется.

0 голосов
/ 28 марта 2011

Обычно вы используете malloc(n * sizeof(CAR)).Функция realloc полезна только при программировании на луну.

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