向动态数组写入数据时出现分段错误



我的任务是编写一个文件,其中显示用户输入的未知数量的记录。每条记录有以下字段:名、姓、地址、城市、州、邮政编码和电话号码。

我认为最好的方法是用上面的字段定义一个结构体Record,然后声明一个Record s数组,其中包含用户输入的记录数量。为了实现这一点,我将使用一个循环来获取每个记录的每个字段的输入,然后如果用户想要继续动态地在Record数组中分配额外的空间,并继续直到用户输入no。我在

行遇到访问冲突写入位置错误
scanf("%s", records[i]->fname);

我的代码有什么问题?

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct Record;
struct Record
    {
        char fname[51];
        char lname[51];
        char address[51];
        char city[51];
        char state[51];
        int zipcode;
        int phoneNumber;
    };
int main()
{
    FILE *fileWriter;
    const char filename[] = "data.txt";
    char answer = 'y';
    int size = 1;
    int i = 0;
    struct Record **records;
    records = malloc(sizeof(*records)*(size));
    while(answer == 'y' || answer == 'Y')
    {
        printf("First Name: n");
        scanf("%s", records[i]->fname);
        printf("Last Name: n");
        scanf("%s", records[i]->lname);
        printf("Address: n");
        scanf("%s", records[i]->address);
        printf("City: n");
        scanf("%s", records[i]->city);
        printf("State: n");
        scanf("%s", records[i]->state);
        printf("Zipcode: n");
        scanf("%d", records[i]->zipcode);
        printf("Phone Number: n");
        scanf("%d", records[i]->phoneNumber);
        //stores all record info
        printf("Are there anymore records? [y/n] ");
        answer = getchar();
        if(answer == 'y' || answer == 'Y')
        {
            size++;
            records[i++];
            printf("n");
        }
        records = realloc(records,sizeof(*records)*(size));
    }
    //open file
    fileWriter = fopen(filename,"wb");
    if(fileWriter != NULL)
    {
        if(fwrite(records,sizeof(*records),size,fileWriter) != 1)
        {
            fprintf(stderr, "Failed to write to %sn", filename);
            exit(1);
        }
        fclose(fileWriter);
    }
    else
    {
        printf("Error opening file.");
    }
}
<<p> 编辑版本/strong>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct Record
    {
        char fname[51];
        char lname[51];
        char address[51];
        char city[51];
        char state[51];
        int zipcode;
        int phoneNumber;
    };


int main()
{
    FILE *fileWriter;
    const char filename[] = "data.txt";
    char answer = 'y';
    int size = 1;
    int i = 0;
    struct Record *records = NULL;
    struct Record *records_temp;


    while(answer == 'y' || answer == 'Y')
    {
        struct Record *records_temp = realloc(records,(size)*sizeof(*records));
        if(records_temp == NULL)  
        {
            free(records); 
        }
        records = records_temp;
        printf("First Name: n");
        scanf("%s", records[i].fname);
        printf("Last Name: n");
        scanf("%s", records[i].lname);
        printf("Address: n");
        scanf(" %[^n]", records[i].address);
        printf("City: n");
        scanf("%s", records[i].city);
        printf("State: n");
        scanf("%s", records[i].state);
        printf("Zipcode: n");
        scanf("%d", &records[i].zipcode);
        printf("Phone Number: n");
        scanf("%d", &records[i].phoneNumber);
        //stores all record info
        printf("Are there anymore records? [y/n] ");
        answer = getchar();
        if(answer == 'y' || answer == 'Y')
        {
            size++;
            records[i++];
            printf("n");
        }
        //open file
    fileWriter = fopen(filename,"wb");
    if(fileWriter != NULL)
    {
        if(fwrite(records,sizeof(*records),size,fileWriter) != 1)
        {
            fprintf(stderr, "Failed to write to %sn", filename);
            exit(1);
        }
        fclose(fileWriter);
    }
    else
    {
        printf("Error opening file.");
    }
}
}

嗯,你得到一个段错误,因为你没有为你的records中的第一个实体分配内存。

要解决这个问题,你需要

records[size-1] = malloc(sizeof(Records));

这么说吧:records是指向Records的指针。

records = malloc(sizeof(*records)*(size));

你实际上要求size指针指向Records。但这还不够,你需要分配另一个内存来存储实际的Records所以这就是为什么我们必须

records[size - 1] = malloc(sizeof(Records));

注意:如果size> 1,那么你应该这样做:

int i = 0;
for(;i < size; i++) {
    records[i] = malloc(sizeof(Records));
}

除此之外,为什么你要用Records **,正如Arjun已经解释的那样,你应该使用Records *并修复realloc -ing新内存的部分,因为如果realloc失败,它返回NULL,你最终会在最坏的情况下出现内存泄漏或另一个段错误,无论哪种方式——这对你的程序都不好。

请参阅Arjun的帖子

当您想为Record s列表动态分配空间时,您应该这样做:

struct Record *records;
records = malloc(size * sizeof(*records));

Recordsize个数分配空间。

要增加分配的大小,应该:

struct Record *records_temp = realloc(records, newsize * sizeof(*records));
if (records_temp == NULL) {
    free(records);
    /* die with error -ENOMEM */
}
records = records_temp;

不要对同一个指针进行realloc操作。它可能导致您在失败时泄漏内存。

,您可以通过最初提供NULL指针来避免malloc()并在循环中仅使用realloc()

c89标准规定:

4.10.3.4 realloc函数

如果ptr是空指针,realloc函数的行为与malloc类似函数。

struct Record *records = NULL;
struct Record *records_temp;
size = INITIAL_SIZE;
while (/* your condition */) {
    records_temp = realloc(records, size * sizeof(*records));
    if (records_temp == NULL) {
        free(records);
        /* die with error -ENOMEM */
    }
    records = records_temp;
    /* do stuff */
    size += SIZE_INCREMENT;
}

正如Jonathan Leffler评论的那样,但他拒绝回答他的评论:

注意records[i++];行增加了i,没有做任何其他有用的事情。

也:

还要注意,struct Record;行实际上是不必要的。唯一不同的是,如果您在函数作用域中而不是在文件作用域中定义相互递归的结构(这种用法是在文件作用域中)。事实上,这一行说的是"有一个类型struct Record",下一段代码说的是"有一个类型struct Record,这就是它的定义方式"。

当Cool Guy问他这是什么意思时,Jonathan说:

struct A { … };
struct B { … };
void f(void)
{
    struct A;
    struct B
    {
         …;
        struct A *a_ref;
        …
    };
    struct A
    {
        …;
        struct B *b_ref;
        …
    };
    …
}

如果没有struct A;行,a_ref元素将指向外部定义类型struct A的结构,而不是相互递归的结构类型对。错误消息也可能非常令人困惑!然而,像这样重用类型名是一个坏主意。

相关内容

  • 没有找到相关文章