如何读取文件,然后将文件中的每个结构放入数组中?

时间:2019-05-10 10:28:41

标签: c arrays file struct

我需要读入一个文件,然后将每个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);
}

1 个答案:

答案 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的文件结构,但是如果允许,请考虑所提到的建议。

相关问题