试图输入一个结构,第一次工作很好,第二次崩溃

时间:2018-01-25 19:08:23

标签: c loops struct

您好我输入了一个有这两种结构的孩子的家庭结构:

typedef struct person {
    int id;
    char* firstName;
    int age;
}person;

typedef struct family {
    char* lastName;
    person father, mother;
    person* children;
    int numChildren;
}family;

编辑:这是已编辑的功能,但仍然崩溃:

int initializeHouse(family **pdata)
{
    char temp[SIZE];
    int size, i, j;
    printf("enter the number of families\n");
    scanf("%d", &size);
    *pdata = (family*)malloc(sizeof( family)*size);
    for (i = 0; i<size; i++)
    {
        printf("Please enter the last name\n");
        scanf("%s", temp);
        (*pdata)[i].lastName = (char*)malloc(sizeof(char)* (strlen(temp) + 1));
        strcpy(pdata[i]->lastName, temp);
        printf("Enter the fathers first name\n");
        scanf("%s", temp);
        initPerson(temp, &pdata[i]->father.firstName);
        printf("enter the fathers ID\n");
        scanf("%d", &pdata[i]->father.id);
        printf("Enter the fathers age\n");
        scanf("%d", &pdata[i]->father.age);
        printf("Enter the mothers first name\n");
        scanf("%s", temp);
        initPerson(temp, &pdata[i]->mother.firstName);
        printf("enter the mothers ID\n");
        scanf("%d", &pdata[i]->mother.id);
        printf("Enter the mothers age\n");
        scanf("%d", &pdata[i]->mother.age);
        printf("enter the number of children");
        scanf("%d", &pdata[i]->numChildren);
        (*pdata)[i].children= (person*)malloc(sizeof(person)*(pdata[i]->numChildren));
        for (j = 0; j<pdata[i]->numChildren; j++)
        {
            printf("enter the kids name\n");
            scanf("%s", temp);
            initPerson(temp, &pdata[i]->children[j].firstName);
            printf("enter the kids ID\n");
            scanf("%d", &pdata[i]->children[j].id);
            printf("Enter the kids age\n");
            scanf("%d", &pdata[i]->children[j].age);

        }
    }
    return size;
}

void initPerson(char* str, char** fam)
{
    *fam = (char*)malloc(sizeof(char)*(strlen(str) + 1));
    strcpy(*fam, str);
}
编辑:我改变了代码但它仍然无法正常工作,它需要我写一些描述,所以这里是..

4 个答案:

答案 0 :(得分:1)

这个使用(*pdata)[i].的小例子并没有崩溃。

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

#define SIZE 40

typedef struct person {
    int id;
    char* firstName;
    int age;
}person;

typedef struct family {
    char* lastName;
    person father, mother;
    person* children;
    int numChildren;
}family;

int initializeHouse(family **pdata)
{
    char temp[SIZE];
    int size, i, j;
    printf("enter the number of families\n");
    scanf("%d", &size);
    *pdata = malloc(sizeof(family)*size);
    for (i = 0; i<size; i++)
    {
        printf("Please enter the last name\n");
        scanf("%39s", temp);
        (*pdata)[i].lastName = malloc(sizeof(char)* (strlen(temp) + 1));
        strcpy ( (*pdata)[i].lastName, temp);
    }
    return size;
}

int main ( void) {
    int size;
    family *a;
    size=initializeHouse(&a);
}

答案 1 :(得分:1)

  int main() {
    int size;
    family *a = NULL;
    size=initializeHouse(&a);
  }

声明指向family结构的指针。当你传递它的地址

size = initializeHouse(&a);

该函数将其作为family**

好的,到目前为止,我们都在同一页面上。分配该指针的目标时

*pdata = malloc(sizeof(family) * size);

然后*pdata指向已分配的结构数组,而不是指向这些结构的指针。每个结构都由(*pdata)[i]访问,这意味着 - &gt;取消引用双指针pdata以获取数组中第一个元素的地址,然后使用下标访问数组元素。

所以你的任务应该是

(*pdata)[i].lastName = malloc(sizeof(char)* (strlen(temp) + 1));

使用点.运算符来访问成员,因为下标访问的结果是结构,不是指向结构的指针。

答案 2 :(得分:1)

了解内存布局非常重要。

family *fam;
family **pdata = &fam;

*pdata = (family*)malloc(sizeof(family)*size);

您必须具备以下条件:famfamily类型的未初始化指针。 pdata是使用fam地址初始化的双指针。 malloc call为size family - 对象分配空间。做*pdata = malloc(...) 您正在初始化fam

这是您拥有的基本内存布局。 base是返回的地址 malloc的。 slfstruct family个对象的大小,fpl是a的大小 指针指向struct family对象。

base = address returned by malloc
sfl = sizeof(struct family)
fpl = sizeof(struct family*)

base + 0          base + slf         base + 2 * slf
+-----------------+------------------+------------------+
|struct family    | struct family    | struct family    |
+-----------------+------------------+------------------+

base + 0    base + fpl    base + 2*fpl base + 3*fpl base + 4*fpl
+------------+------------+------------+------------+-----------+
| pdata[0]   | pdata[1]   | pdata[2]   | pdata[3]   | pdata[4]  |
+------------+------------+------------+------------+-----------+

第一行显示struct family个对象的内存,第二行 row在指针方面显示相同的内存(到struct family对象)。 是非常重要的区别,因为pdata[i]会返回一个 指针,而不是对象。

请记住pdata是双指针,pdata[i]相当于pdata + i, 这是在i开始的base指针。

因为struct family的大小与大小明显不同 一个指针,你看到该块不对齐,这意味着 base + slf != base + fpl

在第一次迭代中,您很幸运,因为pdata[0](*pdata)[0]是 相同。但pdata[1]*(pdata)[1]并不相同。这样做 您正在访问的pdata[1]->lastname(而不是(*pdata)[1].lastname) 你分配内存的错误位置。

修复代码的最简单方法是更改​​pdata[i]中的(*pdata)[i],如图所示 在user3121023的回答中。

修改

我看到user3121023收回了他的答案。基本上它确实:

printf("enter the fathers ID\n");
scanf("%d", &((*pdata)[i].father.id));

在循环中。

答案 3 :(得分:0)

修复the pointers可能已解决您的问题。但是该程序有很多重复的代码和重写,如下所示将帮助您测试一小部分并轻松调试程序。

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

#define SIZE 100

typedef struct person {
    int id;
    char *firstName;
    int age;
} person;

typedef struct family {
    char *lastName;
    person father, mother;
    person *children;
    int numChildren;
} family;

void input_string(const char *prompt, char **where) {
    char temp[SIZE];
    printf("%s\n", prompt);
    scanf("%s", temp);
    *where = malloc(sizeof(char) * (strlen(temp) + 1));
    strcpy(*where, temp);
}

void input_int(const char *prompt, int *where) {
    printf("%s\n", prompt);
    scanf("%d", where);
}

void input_person(const char *name, person *person) {
    char prompt[SIZE];
    sprintf(prompt, "Enter the %s's first name", name);
    input_string(prompt, &person->firstName);
    sprintf(prompt, "Enter the %s's ID", name);
    input_int(prompt, &person->id);
    sprintf(prompt, "Enter the %s's age", name);
    input_int(prompt, &person->age);
}

void input_family(family *fam) {
    input_string("Please enter the last name", &fam->lastName);
    input_person("father", &fam->father);
    input_person("mother", &fam->mother);
    input_int("Please enter the number of children", &fam->numChildren);
    fam->children = malloc(sizeof(person) * (fam->numChildren));
    for (int i = 0; i < fam->numChildren; i++) {
        input_person("kid", &(fam->children)[i]);
    }
}

int initializeHouse(family **families) {
    int size;
    input_int("Please enter the number of families", &size);
    *families = malloc(sizeof(family) * size);
    for (int i = 0; i < size; i++) {
        input_family(&(*families)[i]);
    }
    return size;
}

int main() {
    int size = 0;
    family *a;
    size = initializeHouse(&a);
    printf("Successfully inputted %d families", size);
    return 0;
}