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



我正在尝试编写一个程序,该程序将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: %dn", 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   %.2fn", sArray[i].name, sArray[i].number, sArray[i].gpa);
    }
}
//Main
int main(){
    getStudents();
    writeToFile();
    displayStudents();
    return 0;
}

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

照片

但是,您的名称在struct中很长,它将为int的名称4字节编写32个字符,而float的4个字节为4个字节。字符串中的null终结器之后的字符不会使其无法度过。在您的情况下," dychii 0" 7个字符,在那之后25个字符并不重要。

顺便说一下,而不是

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

你可以说

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

它将更可读。

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

如果要将文件存储在文本模式下,以便可以在普通编辑器中打开它,则可以尝试这样的东西:

//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, "%fn", 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: %dn", 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

返回的值

相关内容

  • 没有找到相关文章