Передача массива структуры в функцию в C - PullRequest
0 голосов
/ 19 ноября 2018

Нужен ли * перед моим массивом struct (в аргументах функции) при передаче структуры в функцию по ссылке? Причина, по которой я думаю, что мы этого не делаем, заключается в том, что массив необходим для передачи адреса, по которому расположен первый объект.

Мне кажется, что мне просто повезло, мой код работает:

#include <stdio.h>

struct member {
    char lastName[30];
    char gender;
    int age;
};

void readAndUpdate(struct member *people[]); 

// begin main function
int main(void){

    struct member *people[30]; 

    readAndUpdate(people);


} // end main function

// begin function which reads a .dat file and propogates the array with the data in the .dat file
void readAndUpdate(struct member *people[]){



}

Я работал над своим кодом еще с помощью комментаторов, и у меня есть следующее, которое работает правильно. Я случайно создал массив указателей.

#include <stdio.h>
#define MAXPEOPLE 3 

struct member {
    char lastName[30];
    char gender;
    int age;
};

void readAndUpdate(struct member *person, size_t maxpeople); 
void populateDatFile();
void displayMembers(struct member *person, size_t maxpeople);

// begin main function
int main(void){

    struct member people[2]; 

    populateDatFile(); // program will first populate the .dat file with the given specs

    readAndUpdate(people, MAXPEOPLE);

    printf("The data was read and input as follows:\n\n");
    displayMembers(people, MAXPEOPLE);


} // end main function

// function which displays the entire array of struct members
void displayMembers(struct member *person, size_t maxpeople){

    int i=0;

    for (i=0;i<3;i++){

    printf("%s ", person[i].lastName);
    printf("%c ", person[i].gender);
    printf("%d ", person[i].age);
    printf("\n");
    }

} // end displayMembers function

// function which loads the .dat file with hardcoded structs
void populateDatFile(){

    struct member person1={"Gates", 'M', 60};
    struct member person2={"Jobs", 'M', 55};
    struct member person3={"Jane", 'F', 45};    

    FILE *file;
    file = fopen("question3.dat","w");
    if(file == NULL)
        printf("question3.dat cannot be opened!\n");
    else
        printf("question3.dat was opened successfully.\n");

    fprintf(file, "%s %c %d\n", person1.lastName, person1.gender, person1.age);
    fprintf(file, "%s %c %d\n", person2.lastName, person2.gender, person2.age);
    fprintf(file, "%s %c %d\n", person3.lastName, person3.gender, person3.age);

    fclose(file);
} // end function populateDatFile

// begin function which reads a .dat file and propogates the array with the data in the .dat file
void readAndUpdate(struct member *person, size_t maxpeople){

    int i=0;

    FILE *file;
    file = fopen("question3.dat","r");
    if(file == NULL)
        printf("question3.dat cannot be opened!\n");
    else
        printf("question3.dat was opened successfully.\n");

    fscanf(file, "%s", &person->lastName);
    fscanf(file, " %c", &person->gender);
    fscanf(file, "%d", &person->age);

    fscanf(file, "%s", &person[1].lastName);
    fscanf(file, " %c", &person[1].gender);
    fscanf(file, "%d", &person[1].age);

    fscanf(file, "%s", &person[2].lastName);
    fscanf(file, " %c", &person[2].gender);
    fscanf(file, "%d", &person[2].age);

    fclose(file);

} // end function readAndUpdate

1 Ответ

0 голосов
/ 19 ноября 2018

У вас есть код «ОК, но…». И есть несколько весьма значительных «но», о которых нужно беспокоиться.

Первый вопрос: является ли то, что вы написали, тем, что вы намеревались написать. Вы определили массив указателей на структуры, но не инициализировали его вообще. Возможно, вы намеревались определить массив структур, а не массив указателей, который затем меняет остальную часть обсуждения. В настоящее время я воспринимаю то, что вы написали, как «все в порядке - вот что я намеревался написать».

Вы правильно передаете массив функции. Функция не знает, насколько большой массив вы передали. Вы должны привыкнуть говорить функциям, насколько велик массив.

Вы не ссылаетесь на массив внутри функции. Это не все плохо; Вы не определили память, на которую указывает каждый из указателей в массиве. Предположительно, вы будете динамически распределять элементы по мере их добавления, а затем будете ссылаться на них правильно, используя стрелки ->, а не точки .:

void readAndUpdate(size_t max, struct member *people[max])
{
    for (size_t i = 0; i < max; i++)
    {
        people[i] = malloc(sizeof(*people[i]));
        if (people[i] == NULL)
            …handle error appropriately…
        strcpy(people[i]->lastName, "Unknown");
        people[i]->gender = 'N';   // Neuter — unknown
        people[i]->age = 0;        // Babies only
    }
}

int main(void)
{
    struct member *people[30] = { NULL }; 
    readAndUpdate(30, people);
    return 0;
}

Если количество записей на самом деле не фиксировано, то функция readAndUpdate() должна сообщать, сколько было инициализировано.


Я не собирался создавать массив указателей.

OK; тогда правила игры меняются:

void readAndUpdate(size_t max, struct member people[max])
{
    for (size_t i = 0; i < max; i++)
    {
        strcpy(people[i].lastName, "Unknown");
        people[i].gender = 'N';   // Neuter — unknown
        people[i].age = 0;        // Babies only
    }
}

int main(void)
{
    struct member people[30] = { { "", 0, 0 } }; 
    readAndUpdate(30, people);
    return 0;
}

Структуры уже распределены и инициализируются всеми байтами, равными нулю. Код в функции использует . вместо -> для ссылки на члены. * взято из определения переменных и параметров.

...