我需要读入一个文件,然后将每个struct大小的字符分配给struct数组的一部分。
因此,前30个字符将是第一个,后三十个字符将是最后一个,其后的9个字符将是ssn。这将是阵列中的第一个学生。第二个学生将在第69个字符之后开始,第三个学生将在第138个字符之后开始,依此类推。
在文件中,将包含以下内容: 约翰\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0smith \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0123456789jack \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0myers \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0987654321
将转换为:
allStudents [0] .first =约翰
allStudents [0] .last =史密斯
allStudents [0] .ssn = 123456789
allStudents [1] .first = jack
allStudents [1] .last = myers
allStudents [1] .ssn = 987654321
这是当前设置:
struct student allStudents[1000];
struct student {
char first[30];
char last[30];
char ssn[9];
};
void findStudents() {
int i;
FILE *fp;
char *temp;
int counter = 0;
int counter2 = 0;
fp = fopen("students.db","rt");
while( ( temp[counter2] = fgetc(fp) ) != EOF )
{
for (i = 0 ; i < 30 ; i++) {
strcat(allStudents[counter].first, temp);
counter2++;
}
for (i = 0 ; i < 30 ; i++) {
strcat(allStudents[counter].last, temp);
counter2++;
}
for (i = 0 ; i < 9 ; i++) {
strcat(allStudents[counter].ssn, temp);
counter2++;
}
counter++;
}
fclose(fp);
}
答案 0 :(得分:1)
正如评论中提到的,这里存在多个问题,从不为char *temp
分配内存到使用长度为9的char数组存储9个字符长的数字,到没有终止字符的空间。
尝试进行尽可能小的更改,我将结构中的ssn
大小从9更改为10,以便存储终止字符。请记住,您可能已经使用整数将数据存储在其中,并且在内存存储方面会更加有效。
我想指出的另一件事是您的struct student allStudents[1000]
数组。即使数据库中只有2条记录,也要立即分配1000 * sizeof(struct)
字节。更好的方法可能是使用链表。或者只是拥有一个结构指针数组(struct student *allStudents[1000]
),该数组最初会占用更少的内存,但是您将不得不为每个新的结构分配内存。
我假设您不允许更改students.db
文件,但是我们仍然需要添加该终止字符,因此,单个记录的文件中将有69字节,结构中的文件中将有70字节。如果允许,我建议您更改它。
struct student {
// max allowed first and last name length should be 29 to ensure a space for terminating character
char first[30];
char last[30];
char ssn[10];
}
struct student allStudents[1000];
void findStudents() {
int counter = 0;
// if you want to just read the file use "r" mode, if you're writing in it you can use "r+" or "w+", but there is no "rt" as far as I know
FILE *fp = fopen("students.db", "r");
// you should always check if file is opened
if(fp == NULL) {
printf("File not opened");
return;
}
// allocate memory where you will store a single record read from a file
// note -1 since your struct is now 70bytes large and a record in file is 69
// and for that reason we are using calloc instead of malloc, since calloc fills allocated memory with zero
char *temp = (char*) calloc(1, sizeof(struct student) - 1);
// instead of using fgetc for reading a single character, it's better to use fread here
// fread returns number of elements successfully read which should be 69 if everything is alright
while( ( fread(temp, 1, sizeof(struct student) - 1, fp) ) == sizeof(struct student) - 1 ) {
// copy the content we read into the structure
// we copy only 69 bytes here, leaving the last byte of structure untouched
// and it will be 0x00 (terminating character for your ssn)
memcpy(&allStudents[counter], temp, sizeof(struct student) - 1);
counter++;
}
// free the allocated memory and close the file since you won't be using them anymore
free(temp);
fclose(fp);
}
我还建议您也许从您的student.db
数据库返回已读条目的数量。
我写此代码的前提是您不能更改student.db
的文件结构,但是如果允许,请考虑所提到的建议。