【问题标题】:Trying to input a strcture, first time works great, second time crashes尝试输入结构,第一次效果很好,第二次崩溃
【发布时间】:2018-07-05 03:13:53
【问题描述】:

您好,我正在输入具有这两种结构的孩子的家庭结构:

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);
}

编辑:我更改了代码,但它仍然不起作用,它需要我写一些描述,所以在这里..

【问题讨论】:

  • 点击链接阅读。这就是我提供链接的原因。
  • pdata 的类型为 family **。我相信pdata[x] 将其视为family * 类型的数组,而不是指向family 类型数组的指针。
  • 你没有把pdata[i]-&gt;的所有实例都改成(*pdata)[i].
  • @AlexAlex 他们不一样。指针数组将使用索引偏移量来查找指针,然后取消引用以查找对象。需要取消引用指向数组的指针以获取数组,然后使用索引偏移量在数组中查找对象。

标签: c loops struct


【解决方案1】:
  int main() {
    int size;
    family *a = NULL;
    size=initializeHouse(&a);
  }

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

size = initializeHouse(&a);

该函数将其作为family**

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

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

然后*pdata 指向分配的结构数组,而不是指向这些结构的指针。每个struct都被(*pdata)[i]访问,也就是说->解引用双指针pdata得到数组中第一个元素的地址,然后用下标访问数组元素。

所以你的任务应该是

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

你使用点.操作符来访问成员,因为下标访问的结果是一个结构体,不是一个指向结构体的指针。

【讨论】:

  • 我不知道这是否是一个错字,但你漏掉了*。应该是 (*pdata)[i].lastName ;这只是为姓氏分配字符串,而不是结构。
  • 我像你说的那样编辑了它,仍然崩溃......我在编辑中发布代码。
  • @AlexAlex: 不要改变你的 cmets -> 这让你很难跟上
  • 抱歉,我将编辑后的代码添加到我的帖子中,仍然崩溃,还有什么问题吗?
  • @AlexAlex:您必须将所有匹配项从 &amp;pdata[i] 更改为 (*pdata)[i]
【解决方案2】:

这个使用(*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);
}

【讨论】:

    【解决方案3】:

    了解内存布局很重要。

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

    你基本上有这个:fam 是一个未初始化的 family 类型的指针。 pdata 是一个用fam 地址初始化的双指针。 malloc call 为size family-objects 分配空间。通过*pdata = malloc(...) 你正在初始化fam

    这是您拥有的基本内存布局。 base 是返回的地址 马洛克。 slfstruct family 对象的大小,fpl 是对象的大小 指针指向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 对象的形式显示内存,第二行 行在指针(指向struct family 对象)方面向您显示相同的内存。 这个是很重要的区别,因为pdata[i]返回给你一个 指针,而不是对象。

    记住pdata是双指针,pdata[i]等价于pdata + i, 那是从base 开始的ith 指针。

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

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

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


    编辑

    我看到 user3121023 撤回了他的回答。基本上它做到了:

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

    在循环中。

    【讨论】:

      【解决方案4】:

      修复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;
      }
      

      【讨论】:

        猜你喜欢
        • 2020-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-13
        • 1970-01-01
        • 2022-06-30
        相关资源
        最近更新 更多