Указатель Structer и массив указателей char массив malloc

Я хочу сделать массив structer, но я не знаю размер массива structer, поэтому мне нужно использовать structer указателя, и я хочу сделать массив char в structer, и я не знаю размер массива char, поэтому мне нужно использовать указатель char в этом structer, но я не понимаю функции malloc и realloc. Как я могу это сделать ?

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

struct School{
    char *school_name;
    int student_size;
}*high_school;




void createSchool(struct School *s, char *schl_name, int student, int school_size)
{
    int i = 0;

    if(school_size == 1){
        s = (struct School*) malloc(sizeof(struct School));
    }
    else{
        s = (struct School*) realloc(s, (school_size*sizeof(struct School)));
    }

    (s+(school_size-1))->student_size = student;
    (s+(school_size-1))->school_name = (char *) malloc(20); // 20 it is not important

    (s+(school_size-1))->school_name = schl_name;
     for(i; i<school_size; i++){
        printf("%s\t%d\n",(s+i)->school_name, (s+i)->student_size);
    }
    printf("\n\n");
}

int main()
{
    int i = 1;
    createSchool(high_school, "Harvard", 50, i);
    i++;
    createSchool(high_school, "Oxford", 40, i);
    i++;
    createSchool(high_school, "MIT", 30, i);
}

Я хочу сделать скриншот:

Harvard 50

Harvard 50
Oxford 40

Harvard 50
Oxford 40
MIT 30

но скрин программы:

Harvard 50


└1q     7405760
Oxford  40


        7405760
(null)  0
MIT     30

person Onur Varsak    schedule 24.10.2016    source источник
comment
Не преобразовывать результат malloc в C   -  person phuclv    schedule 24.10.2016


Ответы (1)


Ваш указатель внутри createSchool имеет локальную область действия, поэтому глобальный указатель не изменяется. Более быстрое исправление состоит в том, чтобы вернуть новую выделенную память обратно вызывающей стороне.

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

struct School{
    char *school_name;
    int student_size;
}*high_school;

struct School* createSchool(struct School *s, char *schl_name, int student, int school_size)
{

    if(school_size == 1)
    {
        s = malloc(sizeof(struct School));
    }
    else
    {
        s = realloc(s, (school_size*sizeof(struct School)));
    }

    if (s != NULL)
    {
        s[school_size-1].student_size = student;
        s[school_size-1].school_name = malloc(strlen(schl_name)+1);

        strcpy(s[school_size-1].school_name, schl_name);

        for(int i=0; i<school_size; i++)
        {
            printf("%s\t%d\n", s[i].school_name, s[i].student_size);
        }
        printf("\n\n");
    }

    return s;
}

int main(void)
{
    int i = 1;
    high_school = createSchool(high_school, "Harvard", 50, i);
    i++;
    high_school = createSchool(high_school, "Oxford", 40, i);
    i++;
    high_school = createSchool(high_school, "MIT", 30, i);
}
  1. Минимальная подпись для main int main (void)
  2. Обратите внимание, что возвращаемое значение malloc/realloc необходимо проверять.
  3. С вашим кодом в случае сбоя realloc вы теряете указатель на уже выделенную память. Таким образом, вы должны использовать временный указатель для сохранения результата realloc и проверки целостности. После этого вы можете переназначить его своему указателю.

struct School* createSchool(struct School *s, char *schl_name, int student, int school_size)
{

    if(school_size == 1){
        s = malloc(sizeof(struct School));
    }
    else
    {
        struct School *temp = realloc(s, (school_size*sizeof(struct School)));

        if (temp == NULL)
            return s;

        s = temp;    
    }

    if (s != NULL)
    {
        s[school_size-1].student_size = student;
        s[school_size-1].school_name = malloc(strlen(schl_name)+1);

        strcpy(s[school_size-1].school_name, schl_name);

        for(int i=0; i<school_size; i++)
        {
            printf("%s\t%d\n", s[i].school_name, s[i].student_size);
        }
        printf("\n\n");
    }

    return s;
}

Другое решение может быть реализовано с использованием двойного указателя:

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

struct School{
    char *school_name;
    int student_size;
}*high_school;

void createSchool(struct School **s, char *schl_name, int student, int school_size)
{

    if(school_size == 1)
    {
        *s = malloc(sizeof(struct School));
    }
    else
    {
        struct School *temp = realloc(*s, (school_size*sizeof(struct School)));

        if (temp == NULL)
            return;

        *s = temp;
    }

    if (*s != NULL)
    {
        (*s)[school_size-1].student_size = student;
        (*s)[school_size-1].school_name = malloc(strlen(schl_name)+1);

        strcpy((*s)[school_size-1].school_name, schl_name);

        for(int i=0; i<school_size; i++)
        {
            printf("%s\t%d\n", (*s)[i].school_name, (*s)[i].student_size);
        }
        printf("\n\n");
    }
}

int main(void)
{
    int i = 1;
    createSchool(&high_school, "Harvard", 50, i);
    i++;
    createSchool(&high_school, "Oxford", 40, i);
    i++;
    createSchool(&high_school, "MIT", 30, i);
}

И последнее, обратите внимание, что для присвоения имени школы вы можете просто использовать:

    (*s)[school_size-1].school_name = schl_name;
person LPs    schedule 24.10.2016