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

标签 c arrays file struct

我需要读入一个文件,然后将每个结构大小的字符分配给结构数组的一部分。

因此,前 30 个字符将是第一个,第二个 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\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\0123456789 jack \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\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\0987654321

这将转换为:

allStudents[0].first = 约翰

allStudents[0].last = 史密斯

所有学生[0].ssn = 123456789

allStudents[1].first = jack

allStudents[1].last = 迈尔斯

所有学生[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);
}

最佳答案

正如评论中提到的,这里存在多个问题,从没有为 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 的文件结构,但如果允许,请考虑上述建议。

关于c - 如何读入文件,然后将文件中的每个结构放入数组中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56075743/

相关文章:

c - Mac OS X 上的线程,强制使用多个 CPU

c - fputs 制造问题

c++从二进制文件中读取整数,缺少一些数据

c# - 在 Windows 资源管理器窗口中突出显示文件

c - 通过修补源将自定义参数添加到 imagemagick

c - Perl 是否安装在所有 Unix 机器上?

c++ - 访问C中的数组元素

arrays - Perl - 根据值将排序数组拆分为两个数组

c - 返回指针数组

c# - 数组移位/错误索引/i = [x+y*size+z*size*size]