我正在尝试编写一个程序,该程序将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)函数getStudents
,writeToFile
和displayStudents
即使您说应该返回任何内容。也许您真的希望它们成为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