12. 加载班级信息功能的实现

加载班级信息功能需要从 CSV 文件中读取数据,然后解析这些数据保存到 class_rooms 数组中。需要注意的一点是我们将所有班级的信息都存入到了一个文本文件中,我们在读取数据时需要将这些学生信息根据第一列的班级名称来进行分组,将这一行数据归属于对应的班级。因此在读取一个新行数据并处理完成后,我们将当前行的班级名称存储于字符数组 last_class_title 中供下次比较使用。

在读取一行数据后,我们要解析逗号的位置,然后,将逗号替换成字符串结束符 '\0', 然后用指针分别记录每个字符串的位置。解析完毕后,在调用 class_room 模块内的 add_student_by_info 函数,将此数据添加到某个班级。

具体代码如下

文件 school.c

// 加载班级信息,成功返回 1, 失败返回 0;
int load_from_csv_file(const char *path_name)
{
    FILE * file = fopen(path_name, "r");  // 打开文件
    // 记录之前的班级名,重复班级名的学生是同一班的学生
    char last_class_title[MAX_CLASS_TITLE_LEN] = "";
    char line_buf[100] = ""; // 读取一行数据的缓冲区。
    char *pclass_title;  // 指向班级名
    char *pstudent_name;  //  指向学生名
    char *pchinese_score;  // 指向语文成绩的字符串
    char *pmath_score;  // 指向语文成绩的字符串
    char *p;  // 用于指向每一行行数据的临时指针

    if (NULL == file) {
        printf("打开文件失败,读取文件失败!\n");
        return 0;
    }

    class_room_count = 0;  //  清空原有数据

    // 读取一行,跳过头部的第一行标题
    fgets(line_buf, sizeof(line_buf), file);
    // 每次读取一行,然后解析每一行的数据
    while(NULL != fgets(line_buf, sizeof(line_buf), file)) {
        // 解析每一行的数据
        pclass_title = line_buf;
        // 找到逗号,逗号改成班级名的尾零
        p = strstr(line_buf, ",");
        if (NULL == p)
            goto finished;
        *p = '\0';
        p++;  // 指向学生姓名
        // 指向学生姓名的起始地址。
        pstudent_name = p;
        p = strstr(p, ",");
        if (NULL == p)
            goto finished;
        *p = '\0';
        p++; // 指向语文成绩;

        // 指向学生语文成绩的起始地址。
        pchinese_score = p;
        p = strstr(p, ",");
        if (NULL == p)
            goto finished;
        *p = '\0';
        p++; // 指向语文成绩;

        // 指向学生数学成绩的起始地址。
        pmath_score = p;

        // 判断 班级名称发生改变。则说明已经是不同的班级
        if (0 != strcmp(last_class_title, pclass_title)) {
            // 如果已经超出了班级个数,则直接返回
            if (class_room_count == MAX_CLASS_COUNT_IN_SCHOOL) {
                goto finished;
            } else {
                // 初始化当前的班级信息
                strcpy(class_rooms[class_room_count].class_title, pclass_title);
                class_rooms[class_room_count].student_count = 0;
                class_room_count++;
            }
            strcpy(last_class_title, pclass_title);
        }
        //
        // 将此学生信息添加到 class_room_count-1 这个班级中
        add_student_by_info(&class_rooms[class_room_count-1],
            pstudent_name, atoi(pchinese_score), atoi(pmath_score));
        // 解析完毕,
    }
finished:
    fclose(file);
    return 1;
}

文件 class_room.c

// 将此学生添加到 aclass 这个班级中。成功返回1, 失败返回 0。
int add_student_by_info(class_room_t *aclass, const char * student_name,
    int chinese_score,int math_score)
{
    if(aclass->student_count >= MAX_STU_COUNT_IN_CLASS_ROOM)
        return 0;  // 满了
    strcpy(aclass->student[aclass->student_count].name, student_name);
    aclass->student[aclass->student_count].chinese_score = chinese_score;
    aclass->student[aclass->student_count].math_score = math_score;
    aclass->student_count++;
    return 1;
}