如何使用C中的动态内存分配将结构写入文件

时间:2016-11-26 08:09:11

标签: c struct malloc fwrite

我试图编写一个程序,从用户那里获取n个学生,将它们存储在一个结构中,然后将它们存储在一个文件中。

当我尝试将元素存储在文件中时,它似乎只是收集了名称和大量垃圾。

我认为问题可能是我如何分配内存,但我不确定。

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

struct Student {
    char name[32];
    int number;
    float gpa;
}sArray[100];

//Global variables
int totalStudents;
int i;

//Reads From the User
//a number of records to read
//b all records (name, number, gpa)
//c return list of students - TODO!

struct Student getStudents(){
    //Get number of elements
    printf("Enter Number of Students: ");
        scanf("%d", &totalStudents);
    sArray[totalStudents];
    printf("You Entered: %d\n", totalStudents);

    for(i=0;i<totalStudents;i++){
        printf("Enter Student %d Name: \n", i+1);
        scanf("%s", sArray[i].name);
        printf("Enter Student %d Number: \n", i+1);
        scanf("%d", &sArray[i].number);
        printf("Enter Student %d GPA: \n", i+1);
        scanf("%f", &sArray[i].gpa);
    }

    //Allocate memory
    struct Student *ptr;
    ptr = (struct Student*) malloc(totalStudents * sizeof(struct Student));
    free(ptr);
}

//Writes records to a File called student.db
int writeToFile(){
    FILE *fp;

    if((fp = fopen("student.db", "wb")) == NULL){
        puts("Error, File Could Not Be Opened.");
    }
    else{
        for(i=0;i<totalStudents;i++){
            fwrite(&sArray[i], sizeof(sArray[i]), 1, fp);
        }
    }
    fclose(fp);

}

//Switch Function - TODO!

//Print Function
struct Student displayStudents(){
    for(i=0;i<totalStudents;i++){
        printf("%s   %d   %.2f\n", sArray[i].name, sArray[i].number, sArray[i].gpa);
    }
}
//Main
int main(){
    getStudents();
    writeToFile();
    displayStudents();

    return 0;

}

如果我的输入值为{1,Dychii,123,4},则将其写入文件:

Photo

2 个答案:

答案 0 :(得分:1)

无论你在struct中的名字有多长,它都会为int的4个字节写入32个字符,为float写4个字节。字符串中的null终止符后面的字符不匹配。在你的情况下&#34; Dychii \ 0&#34; 7个字符,之后25个字符并不重要。

顺便而不是

fwrite(&sArray[i], sizeof(sArray[i]), 1, fp);
你可以说

fwrite(&sArray[i], sizeof(Student), 1, fp);

稍微更具可读性。

答案 1 :(得分:0)

您正在写入二进制文件。这意味着您创建的文件与数据存储在内存中的方式相同。这也意味着您无法在普通编辑器中打开文件并对其有任何意义。使用十六进制编辑器,如果您知道变量如何存储在内存中,您可能能够理解它。

如果您想以文本模式存储文件,以便可以在普通编辑器中打开它,您可以尝试这样的事情:

//Writes records to a File called student.db
void writeToFile(){
    FILE *fp;

    if((fp = fopen("student.db", "w")) == NULL){   //Note: only w
        puts("Error, File Could Not Be Opened.");
    }
    else{
        for(i=0;i<totalStudents;i++){
            fprintf(fp, "%s ", sArray[i].name);
            fprintf(fp, "%d ", sArray[i].number);
            fprintf(fp, "%f\n", sArray[i].gpa);
        }
    }
    fclose(fp);
}

除此之外,您还有一些代码问题:

1)sArray[totalStudents];无效 - 只需删除它

2)即使你说他们应该,函数getStudentswriteToFiledisplayStudents也不会返回任何内容。也许你真的希望它们是void

动态内存

你说你想使用动态内存。但目前你没有。这段代码:

//Allocate memory
struct Student *ptr;
ptr = (struct Student*) malloc(totalStudents * sizeof(struct Student));
free(ptr);

分配一些内存然后再次释放它。换句话说 - 代码什么都不做。事实上,您目前只使用全球sArray所有地方。

如果要使用动态内存,则应首先进行此更改:

struct Student {
    char name[32];
    int number;
    float gpa;
};  // Get rid of global variable sArray[100];

然后,您需要更改当前使用sArray的其余代码中的所有位置。

一个例子:

struct Student* getStudents(){   // Return a pointer to struct Student
    //Get number of elements
    printf("Enter Number of Students: ");
    scanf("%d", &totalStudents);
    printf("You Entered: %d\n", totalStudents);

    // Allocate memory
    struct Student* ptr;
    ptr = malloc(totalStudents * sizeof(struct Student));

    for(i=0;i<totalStudents;i++){
        printf("Enter Student %d Name: \n", i+1);
        scanf("%s", ptr[i].name);
        printf("Enter Student %d Number: \n", i+1);
        scanf("%d", &(ptr[i].number));
        printf("Enter Student %d GPA: \n", i+1);
        scanf("%f", &(ptr[i].gpa));
    }

    return ptr;    // Return a pointer to struct Student
}

希望这能为您提供更新其他代码部分的想法。

最终评论:您应该添加错误检查。那是

a)始终检查scanf

返回的值

b)始终检查malloc

返回的值