【C语言实战(60)】打造校园信息管理系统(简易版),开启高效校园管理新篇章

目录

  • 一、项目需求与模块设计
    • [1.1 核心模块](#1.1 核心模块)
    • [1.2 模块交互](#1.2 模块交互)
    • [1.3 数据存储](#1.3 数据存储)
  • 二、核心模块实现
    • [2.1 教师管理模块](#2.1 教师管理模块)
    • [2.2 课程管理模块](#2.2 课程管理模块)
    • [2.3 模块关联](#2.3 模块关联)
  • 三、项目整合与实战
    • [3.1 整合三大模块](#3.1 整合三大模块)
    • [3.2 权限控制](#3.2 权限控制)
    • [3.3 测试](#3.3 测试)

一、项目需求与模块设计

1.1 核心模块

  • 学生管理:复用第 41 - 43 篇的功能,能够实现学生信息的录入、查询、修改和删除等操作。学生信息包括学号、姓名、年龄、性别等基本信息。通过这些功能,可以方便地对学生数据进行维护和管理 ,比如添加新入学的学生信息,或者修改学生的成绩等。
  • 教师管理:类似于学生管理模块,主要存储教师的工号、姓名以及所教授的课程信息。可以实现教师信息的录入,当学校新招聘教师时,将其信息录入系统;查看教师的详细信息,了解教师的授课情况;修改教师的信息,如教师更换所授课程时进行信息更新;删除教师信息,当教师离职时从系统中移除其相关数据。此外,还能统计教师任课数量,方便学校了解教师的教学工作量。
  • 课程管理:用于存储课程号、课程名以及任课教师等信息。可以对课程信息进行有效的管理,确保课程数据的准确性和完整性。

1.2 模块交互

  • 课程管理与教师的关联:一个教师可以教授多门课程,在系统中通过在课程管理模块中记录任课教师的工号,来建立课程与教师之间的联系。这样,当需要查询某门课程的任课教师时,或者查看某个教师所教授的所有课程时,都可以通过这种关联关系快速获取到相关信息。
  • 学生管理与课程的关联:一个学生可以选择多门课程,在学生管理模块中添加选课功能,记录学生所选课程及成绩。通过这种方式,能够清晰地了解每个学生的选课情况和学习成绩,为学生的学业评估和教学管理提供数据支持。

1.3 数据存储

采用多个二进制文件分别存储学生、教师、课程数据。使用二进制文件存储数据具有以下优势:

  • 存储效率高:二进制文件直接以二进制形式存储数据,不需要进行字符转换,占用空间小,能够更高效地利用存储空间。例如,对于整数类型的数据,在二进制文件中可以直接存储其对应的二进制值,而文本文件则需要将其转换为字符形式存储,会占用更多的空间。
  • 读写速度快:二进制文件的读写操作相对简单,不需要进行复杂的解析和转换,因此读写速度比文本文件快很多。在处理大量数据时,这种速度优势尤为明显,能够提高系统的性能和响应速度。
  • 数据完整性好:二进制文件能够准确地存储数据的原始形式,不会因为字符编码等问题导致数据丢失或损坏,保证了数据的完整性和准确性。

在具体实现中,分别创建 students.dat、teachers.dat、courses.dat 等二进制文件来存储学生、教师和课程数据。在写入数据时,使用 fwrite 函数将结构体数据写入文件;在读取数据时,使用 fread 函数从文件中读取数据到结构体变量中 。例如,对于学生数据的存储和读取:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

// 定义学生结构体
typedef struct {
    int id;
    char name[50];
    int age;
    char gender[10];
} Student;

// 将学生数据写入文件
void saveStudentsToFile(Student *students, int size, const char *filename) {
    FILE *fp = fopen(filename, "wb");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    fwrite(students, sizeof(Student), size, fp);
    fclose(fp);
}

// 从文件中读取学生数据
Student* loadStudentsFromFile(int *size, const char *filename) {
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        perror("无法打开文件");
        return NULL;
    }
    fseek(fp, 0, SEEK_END);
    long fileSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    *size = fileSize / sizeof(Student);
    Student *students = (Student*)malloc(*size * sizeof(Student));
    fread(students, sizeof(Student), *size, fp);
    fclose(fp);
    return students;
}

通过这种方式,实现了学生、教师和课程数据的持久化存储,保证了系统在运行过程中数据的安全性和可靠性。

二、核心模块实现

2.1 教师管理模块

  • 教师信息录入:定义教师结构体Teacher,包含工号id、姓名name和课程数组courses。在录入教师信息时,提示用户输入工号、姓名,然后根据实际情况输入教师所教授的课程信息,将这些信息存储到Teacher结构体变量中,并使用fwrite函数将其写入teachers.dat文件。示例代码如下:
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义教师结构体
typedef struct {
    int id;
    char name[50];
    char courses[10][50];
    int courseCount;
} Teacher;

// 教师信息录入函数
void addTeacher() {
    FILE *fp = fopen("teachers.dat", "ab");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    Teacher teacher;
    printf("请输入教师工号: ");
    scanf("%d", &teacher.id);
    printf("请输入教师姓名: ");
    scanf("%s", teacher.name);
    printf("请输入教师教授课程数量: ");
    scanf("%d", &teacher.courseCount);
    for (int i = 0; i < teacher.courseCount; i++) {
        printf("请输入第 %d 门课程名称: ", i + 1);
        scanf("%s", teacher.courses[i]);
    }
    fwrite(&teacher, sizeof(Teacher), 1, fp);
    fclose(fp);
    printf("教师信息录入成功!\n");
}
  • 教师信息查看:从teachers.dat文件中读取教师信息并显示。使用fread函数从文件中读取数据到Teacher结构体数组中,然后遍历数组,输出每个教师的详细信息。示例代码如下:
c 复制代码
// 教师信息查看函数
void viewTeachers() {
    FILE *fp = fopen("teachers.dat", "rb");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    Teacher teacher;
    while (fread(&teacher, sizeof(Teacher), 1, fp) == 1) {
        printf("教师工号: %d\n", teacher.id);
        printf("教师姓名: %s\n", teacher.name);
        printf("教授课程数量: %d\n", teacher.courseCount);
        for (int i = 0; i < teacher.courseCount; i++) {
            printf("第 %d 门课程名称: %s\n", i + 1, teacher.courses[i]);
        }
        printf("\n");
    }
    fclose(fp);
}
  • 教师信息修改:首先根据教师工号查找要修改的教师信息,然后提示用户输入需要修改的字段(姓名、课程等),更新结构体变量中的相应信息,最后将修改后的结构体写回文件。示例代码如下:
c 复制代码
// 教师信息修改函数
void modifyTeacher() {
    FILE *fp = fopen("teachers.dat", "rb+");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    int id, choice;
    printf("请输入要修改的教师工号: ");
    scanf("%d", &id);
    Teacher teacher;
    int found = 0;
    while (fread(&teacher, sizeof(Teacher), 1, fp) == 1) {
        if (teacher.id == id) {
            found = 1;
            printf("1. 修改姓名\n2. 修改课程\n请选择要修改的项: ");
            scanf("%d", &choice);
            switch (choice) {
                case 1:
                    printf("请输入新的姓名: ");
                    scanf("%s", teacher.name);
                    break;
                case 2:
                    printf("请输入新的课程数量: ");
                    scanf("%d", &teacher.courseCount);
                    for (int i = 0; i < teacher.courseCount; i++) {
                        printf("请输入第 %d 门课程名称: ", i + 1);
                        scanf("%s", teacher.courses[i]);
                    }
                    break;
                default:
                    printf("无效选择!\n");
            }
            fseek(fp, -sizeof(Teacher), SEEK_CUR);
            fwrite(&teacher, sizeof(Teacher), 1, fp);
            printf("教师信息修改成功!\n");
            break;
        }
    }
    if (!found) {
        printf("未找到该教师!\n");
    }
    fclose(fp);
}
  • 教师信息删除:根据教师工号找到要删除的教师信息,将文件中该教师信息后面的内容向前移动覆盖要删除的信息,然后截断文件。示例代码如下:
c 复制代码
// 教师信息删除函数
void deleteTeacher() {
    FILE *fp = fopen("teachers.dat", "rb+");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    int id;
    printf("请输入要删除的教师工号: ");
    scanf("%d", &id);
    Teacher teacher;
    FILE *temp = fopen("temp.dat", "wb");
    int found = 0;
    while (fread(&teacher, sizeof(Teacher), 1, fp) == 1) {
        if (teacher.id != id) {
            fwrite(&teacher, sizeof(Teacher), 1, temp);
        } else {
            found = 1;
        }
    }
    fclose(fp);
    fclose(temp);
    if (found) {
        remove("teachers.dat");
        rename("temp.dat", "teachers.dat");
        printf("教师信息删除成功!\n");
    } else {
        remove("temp.dat");
        printf("未找到该教师!\n");
    }
}
  • 统计教师任课数量:在读取教师信息时,统计每个教师结构体中的courseCount字段即可得到教师的任课数量。示例代码如下:
c 复制代码
// 统计教师任课数量函数
void countTeacherCourses() {
    FILE *fp = fopen("teachers.dat", "rb");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    Teacher teacher;
    while (fread(&teacher, sizeof(Teacher), 1, fp) == 1) {
        printf("教师 %s 任课数量: %d\n", teacher.name, teacher.courseCount);
    }
    fclose(fp);
}

2.2 课程管理模块

  • 课程信息管理:定义课程结构体Course,包含课程号id、课程名name和任课教师工号teacherId。通过fwrite和fread函数实现课程信息的写入和读取文件操作。在录入课程信息时,提示用户输入课程号、课程名和任课教师工号;查看课程信息时,从文件中读取并显示;修改课程信息时,先查找再更新;删除课程信息时,类似教师信息删除的操作。示例代码如下:
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义课程结构体
typedef struct {
    int id;
    char name[50];
    int teacherId;
} Course;

// 课程信息录入函数
void addCourse() {
    FILE *fp = fopen("courses.dat", "ab");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    Course course;
    printf("请输入课程号: ");
    scanf("%d", &course.id);
    printf("请输入课程名: ");
    scanf("%s", course.name);
    printf("请输入任课教师工号: ");
    scanf("%d", &course.teacherId);
    fwrite(&course, sizeof(Course), 1, fp);
    fclose(fp);
    printf("课程信息录入成功!\n");
}

// 课程信息查看函数
void viewCourses() {
    FILE *fp = fopen("courses.dat", "rb");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    Course course;
    while (fread(&course, sizeof(Course), 1, fp) == 1) {
        printf("课程号: %d\n", course.id);
        printf("课程名: %s\n", course.name);
        printf("任课教师工号: %d\n", course.teacherId);
        printf("\n");
    }
    fclose(fp);
}

// 课程信息修改函数
void modifyCourse() {
    FILE *fp = fopen("courses.dat", "rb+");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    int id, choice;
    printf("请输入要修改的课程号: ");
    scanf("%d", &id);
    Course course;
    int found = 0;
    while (fread(&course, sizeof(Course), 1, fp) == 1) {
        if (course.id == id) {
            found = 1;
            printf("1. 修改课程名\n2. 修改任课教师工号\n请选择要修改的项: ");
            scanf("%d", &choice);
            switch (choice) {
                case 1:
                    printf("请输入新的课程名: ");
                    scanf("%s", course.name);
                    break;
                case 2:
                    printf("请输入新的任课教师工号: ");
                    scanf("%d", &course.teacherId);
                    break;
                default:
                    printf("无效选择!\n");
            }
            fseek(fp, -sizeof(Course), SEEK_CUR);
            fwrite(&course, sizeof(Course), 1, fp);
            printf("课程信息修改成功!\n");
            break;
        }
    }
    if (!found) {
        printf("未找到该课程!\n");
    }
    fclose(fp);
}

// 课程信息删除函数
void deleteCourse() {
    FILE *fp = fopen("courses.dat", "rb+");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    int id;
    printf("请输入要删除的课程号: ");
    scanf("%d", &id);
    Course course;
    FILE *temp = fopen("temp.dat", "wb");
    int found = 0;
    while (fread(&course, sizeof(Course), 1, fp) == 1) {
        if (course.id != id) {
            fwrite(&course, sizeof(Course), 1, temp);
        } else {
            found = 1;
        }
    }
    fclose(fp);
    fclose(temp);
    if (found) {
        remove("courses.dat");
        rename("temp.dat", "courses.dat");
        printf("课程信息删除成功!\n");
    } else {
        remove("temp.dat");
        printf("未找到该课程!\n");
    }
}
  • 按教师查询课程:遍历课程文件,当课程结构体中的teacherId与输入的教师工号相同时,输出该课程信息。示例代码如下:
c 复制代码
// 按教师查询课程函数
void queryCoursesByTeacher() {
    FILE *fp = fopen("courses.dat", "rb");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    int teacherId;
    printf("请输入教师工号: ");
    scanf("%d", &teacherId);
    Course course;
    int found = 0;
    while (fread(&course, sizeof(Course), 1, fp) == 1) {
        if (course.teacherId == teacherId) {
            found = 1;
            printf("课程号: %d\n", course.id);
            printf("课程名: %s\n", course.name);
            printf("任课教师工号: %d\n", course.teacherId);
            printf("\n");
        }
    }
    if (!found) {
        printf("该教师没有授课信息!\n");
    }
    fclose(fp);
}
  • 按课程查询教师:根据课程号在课程文件中找到对应的课程信息,获取任课教师工号,然后在教师文件中查找该工号对应的教师信息并输出。示例代码如下:
c 复制代码
// 按课程查询教师函数
void queryTeacherByCourse() {
    FILE *courseFp = fopen("courses.dat", "rb");
    FILE *teacherFp = fopen("teachers.dat", "rb");
    if (courseFp == NULL || teacherFp == NULL) {
        perror("无法打开文件");
        return;
    }
    int courseId;
    printf("请输入课程号: ");
    scanf("%d", &courseId);
    Course course;
    int found = 0;
    while (fread(&course, sizeof(Course), 1, courseFp) == 1) {
        if (course.id == courseId) {
            found = 1;
            Teacher teacher;
            while (fread(&teacher, sizeof(Teacher), 1, teacherFp) == 1) {
                if (teacher.id == course.teacherId) {
                    printf("教师工号: %d\n", teacher.id);
                    printf("教师姓名: %s\n", teacher.name);
                    printf("教授课程数量: %d\n", teacher.courseCount);
                    for (int i = 0; i < teacher.courseCount; i++) {
                        printf("第 %d 门课程名称: %s\n", i + 1, teacher.courses[i]);
                    }
                    printf("\n");
                    break;
                }
            }
            break;
        }
    }
    if (!found) {
        printf("未找到该课程!\n");
    }
    fclose(courseFp);
    fclose(teacherFp);
}

2.3 模块关联

在学生管理模块中添加 "选课" 功能,定义学生选课结构体StudentCourse,包含学生学号studentId、课程号courseId和成绩score。在学生选课时,提示用户输入学号、课程号和成绩,将这些信息存储到StudentCourse结构体变量中,并写入studentCourses.dat文件。示例代码如下:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

// 定义学生选课结构体
typedef struct {
    int studentId;
    int courseId;
    float score;
} StudentCourse;

// 学生选课函数
void selectCourse() {
    FILE *fp = fopen("studentCourses.dat", "ab");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    StudentCourse sc;
    printf("请输入学生学号: ");
    scanf("%d", &sc.studentId);
    printf("请输入课程号: ");
    scanf("%d", &sc.courseId);
    printf("请输入成绩: ");
    scanf("%f", &sc.score);
    fwrite(&sc, sizeof(StudentCourse), 1, fp);
    fclose(fp);
    printf("选课成功!\n");
}

在需要查询学生所选课程及成绩时,从studentCourses.dat文件中读取数据,根据学号或课程号进行筛选和输出 。例如,查询某个学生所选课程及成绩的示例代码如下:

c 复制代码
// 查询学生所选课程及成绩函数
void queryStudentCourses() {
    FILE *fp = fopen("studentCourses.dat", "rb");
    if (fp == NULL) {
        perror("无法打开文件");
        return;
    }
    int studentId;
    printf("请输入学生学号: ");
    scanf("%d", &studentId);
    StudentCourse sc;
    int found = 0;
    while (fread(&sc, sizeof(StudentCourse), 1, fp) == 1) {
        if (sc.studentId == studentId) {
            found = 1;
            printf("课程号: %d, 成绩: %.2f\n", sc.courseId, sc.score);
        }
    }
    if (!found) {
        printf("该学生没有选课记录!\n");
    }
    fclose(fp);
}

通过以上方式,实现了学生管理模块与课程管理模块之间的关联,能够准确记录学生所选课程及成绩,为校园信息管理系统提供了完整的数据支持。

三、项目整合与实战

3.1 整合三大模块

为了将学生管理、教师管理和课程管理这三大模块整合到一起,设计一个主菜单是必不可少的。主菜单为用户提供了一个清晰的操作界面,通过选择不同的选项,用户可以方便地切换到各个模块进行相应的操作。以下是主菜单的设计思路和示例代码:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

// 主菜单函数
void mainMenu() {
    int choice;
    while (1) {
        system("cls"); // 清屏,对于Linux系统可使用system("clear")
        printf("校园信息管理系统\n");
        printf("1. 学生管理\n");
        printf("2. 教师管理\n");
        printf("3. 课程管理\n");
        printf("4. 退出\n");
        printf("请选择操作: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                // 调用学生管理模块的相关函数,例如显示学生管理子菜单
                system("cls");
                printf("学生管理模块\n");
                // 这里可以添加具体的学生管理操作选项和调用相应函数
                system("pause"); // 暂停,等待用户按键继续,对于Linux系统可使用getchar()两次实现类似效果
                break;
            case 2:
                // 调用教师管理模块的相关函数,例如显示教师管理子菜单
                system("cls");
                printf("教师管理模块\n");
                // 调用教师信息录入、查看等函数
                viewTeachers();
                system("pause");
                break;
            case 3:
                // 调用课程管理模块的相关函数,例如显示课程管理子菜单
                system("cls");
                printf("课程管理模块\n");
                // 调用课程信息录入、查看等函数
                viewCourses();
                system("pause");
                break;
            case 4:
                exit(0); // 退出程序
            default:
                printf("无效选择,请重新输入!\n");
                system("pause");
        }
    }
}

在上述代码中,mainMenu函数通过一个无限循环来持续显示主菜单。用户输入选择后,通过switch语句根据用户的选择调用相应模块的功能函数。如果用户选择退出(选项 4),则使用exit(0)函数退出程序。对于无效的选择,会提示用户重新输入。

3.2 权限控制

为了确保系统的安全性和数据的保密性,对不同用户设置不同的权限是非常重要的。在本系统中,简单地区分了管理员和普通用户。管理员拥有最高权限,可以对学生、教师和课程信息进行全面的操作,包括录入、修改、删除等;而普通用户仅具有查看学生和课程信息的权限,不能进行修改和删除等敏感操作。以下是权限控制的实现思路和示例代码:

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 模拟登录函数,返回1表示管理员,2表示普通用户,0表示登录失败
int login() {
    char username[50], password[50];
    printf("请输入用户名: ");
    scanf("%s", username);
    printf("请输入密码: ");
    scanf("%s", password);

    if (strcmp(username, "admin") == 0 && strcmp(password, "admin123") == 0) {
        return 1; // 管理员
    } else if (strcmp(username, "user") == 0 && strcmp(password, "user123") == 0) {
        return 2; // 普通用户
    } else {
        return 0; // 登录失败
    }
}

int main() {
    int userType = login();
    if (userType == 0) {
        printf("登录失败,程序退出!\n");
        return 1;
    }

    // 根据用户类型显示不同的菜单和操作权限
    if (userType == 1) {
        // 管理员菜单和操作
        mainMenu();
    } else {
        // 普通用户菜单和操作
        int choice;
        while (1) {
            system("cls");
            printf("普通用户界面\n");
            printf("1. 查看学生信息\n");
            printf("2. 查看课程信息\n");
            printf("3. 退出\n");
            printf("请选择操作: ");
            scanf("%d", &choice);

            switch (choice) {
                case 1:
                    // 调用查看学生信息函数
                    system("cls");
                    printf("学生信息查看\n");
                    // 这里添加查看学生信息的具体实现
                    system("pause");
                    break;
                case 2:
                    // 调用查看课程信息函数
                    system("cls");
                    printf("课程信息查看\n");
                    // 这里添加查看课程信息的具体实现
                    system("pause");
                    break;
                case 3:
                    exit(0);
                default:
                    printf("无效选择,请重新输入!\n");
                    system("pause");
            }
        }
    }

    return 0;
}

在上述代码中,login函数用于模拟用户登录,根据输入的用户名和密码判断用户类型并返回相应的值。在main函数中,根据用户类型显示不同的菜单和提供不同的操作权限。如果是管理员用户,则调用mainMenu函数显示完整的系统功能菜单;如果是普通用户,则显示仅包含查看功能的菜单。

3.3 测试

为了验证系统的正确性和稳定性,需要对系统进行全面的测试。在测试过程中,模拟添加教师、创建课程、学生选课等操作,然后检查数据关联的正确性,确保各个模块之间的交互符合预期。以下是测试过程的示例:

  1. 添加教师:使用教师管理模块中的添加教师功能,添加一位教师,例如工号为 1001,姓名为 "张老师",教授课程为 "数学" 和 "物理"。
  2. 创建课程:使用课程管理模块中的添加课程功能,创建两门课程,课程号分别为 1 和 2,课程名分别为 "数学" 和 "物理",任课教师工号为 1001。
  3. 学生选课:假设已有学生学号为 2024001,使用学生管理模块中的选课功能,让该学生选择课程号为 1 和 2 的课程,并分别输入成绩,例如数学成绩为 90,物理成绩为 85。
  4. 验证数据关联
    • 查询教师授课信息:通过按教师查询课程功能,输入教师工号 1001,检查是否能正确显示 "数学" 和 "物理" 两门课程信息。
    • 查询课程任课教师:通过按课程查询教师功能,输入课程号 1,检查是否能正确显示任课教师 "张老师" 的信息。
    • 查询学生选课及成绩:通过学生管理模块中的查询学生所选课程及成绩功能,输入学生学号 2024001,检查是否能正确显示所选课程 "数学" 和 "物理" 以及对应的成绩 90 和 85。

通过以上测试步骤,可以有效地验证系统中数据关联的正确性,确保校园信息管理系统能够正常运行,满足实际使用的需求。在实际测试过程中,还可以进一步增加测试用例,覆盖更多的边界情况和异常情况,以提高系统的可靠性和稳定性。

相关推荐
王RuaRua4 小时前
VScode C/C++环境配置
c语言·c++·vscode
一匹电信狗7 小时前
【牛客CM11】链表分割
c语言·开发语言·数据结构·c++·算法·leetcode·stl
GilgameshJSS9 小时前
STM32H743-ARM例程35-DHCP
c语言·arm开发·stm32·单片机·嵌入式硬件
GilgameshJSS9 小时前
STM32H743-ARM例程34-BootROM
c语言·arm开发·stm32·单片机·嵌入式硬件
Jack电子实验室10 小时前
深入理解C语言函数指针:从基础到实战应用
java·c语言·算法
La Pulga10 小时前
【STM32】FLASH闪存
android·c语言·javascript·stm32·单片机·嵌入式硬件·mcu
zhangx1234_11 小时前
C语言题目1
c语言·开发语言·数据结构
小年糕是糕手11 小时前
【C/C++刷题集】二叉树算法题(一)
c语言·数据结构·c++·算法·leetcode·学习方法·改行学it
憨憨崽&1 天前
C语言、Java、Python 的选择与未来发展以及学习路线
java·c语言·python