Как исправить мой код, чтобы вернуть указатель на структуру из функции - PullRequest
0 голосов
/ 03 ноября 2019

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

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

struct details
{
    char name[100];
    int age;
};

struct details * details_pointer(int n)
{
    struct details pointer_x[n];
    struct details *pointer = pointer_x;
    for (int i=0; i<n; i++)
    {
        printf("Student %d:\n", i);
        printf("name:\n");
        fgets(pointer[i].name, 100, stdin);
        printf("age:\n");
        scanf("%d", pointer[i]. age);
    }
    return pointer;
}

int main()
{
    int n;
    printf("Type the number of persons:\n");
    scanf("%d", &n);
    struct details *student = details_pointer(n);
    printf("\nName: %s\n", (*student).name);
    printf("Age: %d\n", (*student).age);
    system("pause");
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 03 ноября 2019

Проблема здесь в том, что вы возвращаете структурную переменную (pointer_x), которая размещена локально в стеке внутренней функции details_pointer(), но эта память больше не резервируется для вас, как только она возвращается. Это означает, что вы получаете (в лучшем случае) мусор.

Вы должны либо выделить память в функции и вернуть ее (и не забудьте освободить ее!) Или передать данные в функциюзаполните его.

void get_details(int n, struct details p[n])
{
  for (int i = 0; i < n; i++)
  {
    // do stuff with p[i]
  }
}

int main()
{
   ...
   scanf("%d", &n);
   struct details students[n];
   get_details(n, students);

   printf("\nName: %s\n", students[0].name);
   ...
}

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

РЕДАКТИРОВАТЬ: Два замечания о вашем существующем details_pointer() функция.

1) В fgets(pointer[i].name, 100, stdin) рекомендуется вывести число байтов из размера массива, если он известен;в этом случае это так, поэтому рекомендуем fgets(pointer[i].name, sizeof(pointer[i].name), stdin). Ваш не является неправильным, но легче поддерживать, если размеры изменятся в будущем.

2) scanf("%d", pointer[i].age) должен взять адрес .age, чтобы заполнить его значениетам;вы передаете номер вместо адреса, что, безусловно, неверно.

1 голос
/ 04 ноября 2019

Хорошо, так что если назначение требует динамического выделения, то это то, что мы должны сделать.

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

Повторный просмотр вашего кода:

struct details *details_pointer(int n)
{
    struct details *students = (struct details *)malloc(n * sizeof(struct details));

    .... do stuff with students[0] and the like

    return students;
}

При этом используется функция malloc() - memory allocate - library, чтобы получить некоторое пространство, и она остается действительнойпока вы не отпустите. Количество байтов - это то, сколько вы хотите (n), умноженное на количество байтов в одна вещь (sizeof(struct details))

Позже:

int main()
{
    struct details *student = details_pointer(n);
    .. do stuff

    free(student);
}

Теперь использует этой памяти и возвращает ее обратно в ОС, когда вы закончите.

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