程序要求用户在必要时输入一些记录(结构)并将它们附加到现有文件或创建新文件(如果没有),然后列出文件的内容。
#include <stdio.h>
#include <string.h>
#define N 25
int main() {
struct studrec {
char name[20], surname[20], sex, date[12];
} students[N];
int i, count = 0;
char another;
FILE *fileptr;
for (i = 0; i < 10; i++) {
puts("Press y to continue without adding new records");
another = getchar();
if (another == 'y' || another == 'Y') break;
while ((another = getchar()) != '\n' && another != EOF);
puts("Input info");
puts("Name: ");
if (fgets(students[i].name, sizeof(students[i].name), stdin) == NULL) return 1;
students[i].name[strlen(students[i].name)-1] = '\0';
puts("Surname: ");
if (fgets(students[i].surname, sizeof(students[i].surname), stdin) == NULL) return 1;
students[i].surname[strlen(students[i].surname)-1] = '\0';
puts("Sex (m/f): ");
students[i].sex = getchar();
while ((another = getchar()) != '\n' && another != EOF);
puts("Date (dd.mm.yyyy): ");
if (fgets(students[i].date, sizeof(students[i].date), stdin) == NULL) return 1;
students[i].date[strlen(students[i].date)-1] = '\0';
while ((another = getchar()) != '\n' && another != EOF);
}
count = i;
fileptr = fopen("students.txt", "a+");
for (i = 0; i < count; i++) fwrite(&students, sizeof(students), 1, fileptr);
rewind(fileptr);
for (i = 0; (another = fgetc(fileptr)) != EOF && i < N; i++) {
fseek(fileptr, -1, SEEK_CUR);
fread(&students, sizeof(students), 1, fileptr);
}
fclose(fileptr);
count = i;
for (i = 0; i < count; i++) printf("%20s%20s%4c%15s\n", students[i].name, students[i].surname, students[i].sex, students[i].date);
return 0;
}
写入新文件时,一切正常。 输出:
...input procedure...
Press y to continue without adding new records
y
Liam James m 12.03.1987
Abbey Trueman f 23.07.1943
Hugo Brown m 13.05.1947
但是如果我再次运行它并尝试将另一条记录追加到现有文件中,程序将失败:
...input procedure...
Press y to continue without adding new records
y
Nadia Rachmonoff f 12.07.1934
O|u
�u � u
� E�u
似乎新记录放在学生[0]中,所有其他元素都被删除。 我究竟做错了什么?也许&amp;学生指针有问题。我试过和学生[i]但是在第一次迭代后它返回了“分段错误”。据我所知,&amp;学生地址在每次fread / fwrite之后“自动”递增到下一个元素。如果不是这样,程序在第一次运行时将无法正常工作。
答案 0 :(得分:3)
您对如何处理数组有一些问题。首先,这一行:
for (i = 0; i < count; i++) fwrite(&students, sizeof(students), 1, fileptr);
你在这里做什么运行一个循环,每个记录输入一次,在每次传递中将整个25个项目的数组写入文件。因此,如果输入了3条记录,则写入 75 ,其中大多数是垃圾或冗余。你在这里想要的更像是这样:
for (i = 0; i < count; i++)
fwrite(&students[i], sizeof(students[i]), 1, fileptr);
...其中大小是数组的一个元素的大小(单个记录),地址是您当前正在编写的记录的地址而不是地址整个阵列。
稍后阅读数据时遇到类似问题:
rewind(fileptr);
for (i = 0; (another = fgetc(fileptr)) != EOF && i < N; i++) {
fseek(fileptr, -1, SEEK_CUR);
fread(&students, sizeof(students), 1, fileptr);
}
首先,fread(&students, sizeof(students), 1, fileptr);
应该更改为fwrite()
之前的fread(&students[i], sizeof(students[i]), 1, fileptr);
。原因是一样的:你在一个循环中一次读取一条记录,所以你需要每次读入那个项目而不仅仅是数组的开头,以及数据量你读的应该是记录的大小,而不是整个数组的大小。
其次,尽管修复上述内容应该可以正常工作,但您可以轻松更改循环,这样您就不需要读取循环表达式中的单个char
来检查EOF。你应该通过检查循环中fread()
的返回来检查它。类似的东西:
rewind(fileptr);
for (i = 0; i < N; i++) {
if (fread(&students[i], sizeof(students[i]), 1, fileptr) != 1)
break;
}
或者更好的是,只需阅读没有循环的N
项,并使用返回值告诉您已阅读了多少项:
rewind(fileptr);
i = fread(students, sizeof(students[0]), N, fileptr);
答案 1 :(得分:0)
以下内容整个25元素数组 count
次:
for (i = 0; i < count; i++) fwrite(&students, sizeof(students), 1, fileptr);
有两种方法可以解决这个问题:
count
元素占用的正确尺寸,并通过一次fwrite
调用将其写出来。尝试读取元素的循环也是如此:每次迭代都会读取整个25元素数组。
答案 2 :(得分:0)
您的编写代码不正确,请尝试
fwrite(students, sizeof*students, i, fileptr);
rewind(fileptr);
for (i = 0; i < N && fread(&students[i], sizeof*students, 1, fileptr); i++);