Project C语言是什么?如何入门学习?

99ANYc3cd6
预计阅读时长 32 分钟
位置: 首页 C语言 正文

这个项目非常适合初学者到中级学习者,因为它涵盖了 C 语言的核心知识点,包括:

Porject c语言
(图片来源网络,侵删)
  • 结构体:封装不同类型的数据。
  • 文件操作:将数据持久化存储到硬盘。
  • 指针:高效地传递和操作数据。
  • 函数:模块化编程,提高代码可读性和复用性。
  • 循环和条件判断:控制程序流程。
  • 动态内存分配:处理不确定数量的学生数据。

项目目标

创建一个命令行程序,可以实现对学生信息的增、删、改、查功能,并将数据保存在一个文件中,程序关闭后再次打开时,数据依然存在。


功能设计

  1. 添加学生信息:输入学生的学号、姓名和三门课程的成绩。
  2. 显示所有学生信息:以表格形式列出所有学生的数据。
  3. 根据学号查询学生:输入学号,查找并显示该学生的详细信息。
  4. 根据学号修改学生信息:输入学号,找到该学生并修改其姓名或成绩。
  5. 根据学号删除学生:输入学号,从系统中删除该学生记录。
  6. 退出系统:将所有数据保存到文件并退出程序。

第一步:定义数据结构

我们需要一个结构体来表示一个学生,一个学生应该包含学号、姓名和成绩。

// student.h (可以创建一个头文件,或者直接写在 main.c 中)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LEN 50
#define COURSE_NUM 3
#define FILENAME "students.dat"
// 定义学生结构体
typedef struct {
    int id;                     // 学号
    char name[MAX_NAME_LEN];    // 姓名
    float scores[COURSE_NUM];   // 三门课程的成绩
} Student;

第二步:主程序框架和函数声明

我们将所有功能都封装成独立的函数,这样 main 函数会非常清晰。

// main.c
#include "student.h"
// 函数声明
void showMenu();
void addStudent(Student *students, int *count);
void displayAllStudents(const Student *students, int count);
void searchStudent(const Student *students, int count);
void modifyStudent(Student *students, int count);
void deleteStudent(Student *students, int count);
void saveToFile(const Student *students, int count);
void loadFromFile(Student *students, int *count);
int main() {
    Student students[100]; // 假设最多存储100个学生
    int studentCount = 0;
    int choice;
    // 程序启动时,从文件加载数据
    loadFromFile(students, &studentCount);
    do {
        showMenu();
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                addStudent(students, &studentCount);
                break;
            case 2:
                displayAllStudents(students, studentCount);
                break;
            case 3:
                searchStudent(students, studentCount);
                break;
            case 4:
                modifyStudent(students, studentCount);
                break;
            case 5:
                deleteStudent(students, studentCount);
                break;
            case 6:
                printf("正在保存数据并退出系统...\n");
                saveToFile(students, studentCount);
                break;
            default:
                printf("无效的输入,请重新选择!\n");
        }
    } while (choice != 6);
    return 0;
}
// 显示主菜单
void showMenu() {
    printf("\n========== 学生成绩管理系统 ==========\n");
    printf("  1. 添加学生信息\n");
    printf("  2. 显示所有学生信息\n");
    printf("  3. 查询学生信息\n");
    printf("  4. 修改学生信息\n");
    printf("  5. 删除学生信息\n");
    printf("  6. 退出系统\n");
    printf("====================================\n");
}

第三步:实现核心功能函数

现在我们来逐一实现每个功能函数。

Porject c语言
(图片来源网络,侵删)

添加学生

// 添加学生信息
void addStudent(Student *students, int *count) {
    if (*count >= 100) {
        printf("学生数量已达上限,无法添加!\n");
        return;
    }
    Student s;
    printf("请输入学号: ");
    scanf("%d", &s.id);
    // 检查学号是否已存在
    for (int i = 0; i < *count; i++) {
        if (students[i].id == s.id) {
            printf("该学号已存在!\n");
            return;
        }
    }
    printf("请输入姓名: ");
    scanf("%s", s.name);
    printf("请输入三门课程的成绩 (用空格分隔): ");
    for (int i = 0; i < COURSE_NUM; i++) {
        scanf("%f", &s.scores[i]);
    }
    students[*count] = s;
    (*count)++;
    printf("学生信息添加成功!\n");
}

显示所有学生

// 显示所有学生信息
void displayAllStudents(const Student *students, int count) {
    if (count == 0) {
        printf("当前没有学生信息!\n");
        return;
    }
    printf("\n%-10s %-20s %-10s %-10s %-10s\n", "学号", "姓名", "课程1", "课程2", "课程3");
    printf("------------------------------------------------\n");
    for (int i = 0; i < count; i++) {
        printf("%-10d %-20s ", students[i].id, students[i].name);
        for (int j = 0; j < COURSE_NUM; j++) {
            printf("%-10.1f ", students[i].scores[j]);
        }
        printf("\n");
    }
}

查询学生

// 查询学生信息
void searchStudent(const Student *students, int count) {
    if (count == 0) {
        printf("当前没有学生信息!\n");
        return;
    }
    int id;
    printf("请输入要查询的学号: ");
    scanf("%d", &id);
    for (int i = 0; i < count; i++) {
        if (students[i].id == id) {
            printf("\n%-10s %-20s %-10s %-10s %-10s\n", "学号", "姓名", "课程1", "课程2", "课程3");
            printf("------------------------------------------------\n");
            printf("%-10d %-20s ", students[i].id, students[i].name);
            for (int j = 0; j < COURSE_NUM; j++) {
                printf("%-10.1f ", students[i].scores[j]);
            }
            printf("\n");
            return; // 找到后直接返回
        }
    }
    printf("未找到学号为 %d 的学生!\n", id);
}

修改学生

// 修改学生信息
void modifyStudent(Student *students, int count) {
    if (count == 0) {
        printf("当前没有学生信息!\n");
        return;
    }
    int id;
    printf("请输入要修改的学号: ");
    scanf("%d", &id);
    for (int i = 0; i < count; i++) {
        if (students[i].id == id) {
            printf("找到学生: %s\n", students[i].name);
            printf("请输入新的姓名 (直接回车保持原值): ");
            char newName[MAX_NAME_LEN];
            getchar(); // 清除输入缓冲区中的换行符
            fgets(newName, MAX_NAME_LEN, stdin);
            newName[strcspn(newName, "\n")] = 0; // 去掉fgets读取的换行符
            if (strlen(newName) > 0) {
                strcpy(students[i].name, newName);
            }
            printf("请输入新的三门课程成绩 (用空格分隔,-1表示保持原值): \n");
            for (int j = 0; j < COURSE_NUM; j++) {
                float newScore;
                scanf("%f", &newScore);
                if (newScore != -1) {
                    students[i].scores[j] = newScore;
                }
            }
            printf("学生信息修改成功!\n");
            return;
        }
    }
    printf("未找到学号为 %d 的学生!\n", id);
}

删除学生

// 删除学生信息
void deleteStudent(Student *students, int *count) {
    if (*count == 0) {
        printf("当前没有学生信息!\n");
        return;
    }
    int id;
    printf("请输入要删除的学号: ");
    scanf("%d", &id);
    for (int i = 0; i < *count; i++) {
        if (students[i].id == id) {
            // 将后面的所有学生前移一位
            for (int j = i; j < *count - 1; j++) {
                students[j] = students[j + 1];
            }
            (*count)--; // 学生总数减一
            printf("学号为 %d 的学生信息已删除!\n", id);
            return;
        }
    }
    printf("未找到学号为 %d 的学生!\n", id);
}

文件操作 (保存和加载)

这是实现数据持久化的关键。

// 将数据保存到文件
void saveToFile(const Student *students, int count) {
    FILE *fp = fopen(FILENAME, "wb"); // "wb" 表示以二进制写入模式打开
    if (fp == NULL) {
        printf("无法打开文件进行保存!\n");
        return;
    }
    // 先写入学生数量
    fwrite(&count, sizeof(int), 1, fp);
    // 再写入所有学生数据
    fwrite(students, sizeof(Student), count, fp);
    fclose(fp);
}
// 从文件加载数据
void loadFromFile(Student *students, int *count) {
    FILE *fp = fopen(FILENAME, "rb"); // "rb" 表示以二进制读取模式打开
    if (fp == NULL) {
        // 文件不存在是正常情况,说明是第一次运行
        printf("未找到数据文件,将创建新文件,\n");
        *count = 0;
        return;
    }
    // 先读取学生数量
    fread(count, sizeof(int), 1, fp);
    // 再读取所有学生数据
    fread(students, sizeof(Student), *count, fp);
    fclose(fp);
    printf("成功从文件加载 %d 条学生记录,\n", *count);
}

第四步:编译和运行

  1. 保存代码:将所有代码保存为 main.c 文件。
  2. 编译:打开终端或命令提示符,使用 GCC 进行编译。
    gcc main.c -o student_manager
  3. 运行
    • 在 Windows 上:student_manager.exe
    • 在 Linux/macOS 上:./student_manager

如何进一步改进(进阶方向)

这个项目已经是一个功能完整的 C 语言程序了,如果你想继续提升,可以考虑以下方向:

  1. 使用动态内存分配:用 mallocrealloc 替换固定大小的数组 Student students[100],这样系统可以处理任意数量的学生,直到内存耗尽。
  2. 更友好的用户界面:使用 ncurses 库(在 Linux 上)或 Windows API(在 Windows 上)创建一个更美观的基于文本的用户界面。
  3. 增加排序功能:按总分、平均分或学号对学生进行排序后显示。
  4. 数据验证:在输入成绩时,确保输入的是有效数字(0-100分)。
  5. 错误处理:增加更健壮的错误处理机制,比如文件权限问题、磁盘空间不足等。
  6. 模块化:将每个功能(如 add.c, display.c, file_io.c)拆分到不同的 .c 文件中,并将对应的声明放到 .h 文件中,这是一个大型项目的标准做法。

这个项目是学习 C 语言的一个绝佳实践,希望你能动手试试!

Porject c语言
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
volatile关键字到底有什么用?
« 上一篇 今天
织梦如何修改用户名和密码?
下一篇 » 今天

相关文章

取消
微信二维码
支付宝二维码

目录[+]