C语言课程设计:机房收费管理系统
项目概述
1 项目背景 随着计算机技术的普及,学校、企事业单位的机房使用频率越来越高,传统的手工登记和收费方式效率低下、容易出错、难以统计,为了提高机房管理效率,实现收费的自动化和规范化,开发一个机房收费管理系统势在必行。

(图片来源网络,侵删)
2 项目目标 本系统旨在使用C语言开发一个基于控制台的应用程序,实现对机房上机用户信息、上机记录和收费信息进行高效、准确的管理,主要目标包括:
- 实现用户(学生)信息的增、删、改、查。
- 实现用户上机登记、下机结算功能。
- 自动计算上机费用。
- 提供简单的数据统计功能(如日收入、总收入)。
- 系统操作界面友好,交互简单。
3 开发环境
- 编程语言: C语言 (C99标准)
- 开发工具: Visual Studio Code / Dev-C++ / Code::Blocks / Visual Studio
- 编译器: GCC / MinGW / MSVC
- 操作系统: Windows / Linux / macOS
系统分析与功能设计
1 功能模块划分 系统主要分为以下几个核心模块:
- 主控模块: 显示系统主菜单,根据用户选择调用其他功能模块。
- 用户管理模块:
- 添加用户:录入新用户的信息(学号、姓名、密码、余额等)。
- 删除用户:根据学号删除指定用户。
- 修改用户信息:修改用户密码或充值。
- 查询用户:按学号或姓名查询用户信息。
- 上机管理模块:
- 用户上机:验证用户身份,记录上机时间和机位。
- 用户下机:计算上机时长和费用,扣除用户余额,记录下机时间。
- 统计查询模块:
- 查看所有上机记录。
- 统计当日总收入。
- 统计总上机人数。
- 数据持久化:
- 系统启动时从文件(如
users.dat,records.dat)中加载数据。 - 系统退出时将内存中的数据保存回文件。
- 系统启动时从文件(如
2 系统流程图

(图片来源网络,侵删)
graph TD
A[开始] --> B[系统启动, 加载数据];
B --> C{显示主菜单};
C -->|1. 用户管理| D[用户管理子菜单];
C -->|2. 上机管理| E[上机/下机操作];
C -->|3. 统计查询| F[统计查询功能];
C -->|0. 退出系统| G[保存数据, 退出];
D --> D1[添加/删除/修改/查询用户];
E --> E1[用户上机登记];
E --> E2[用户下机结算];
F --> F1[查看记录/统计收入];
D1 --> C;
E1 --> C;
E2 --> C;
F1 --> C;
G --> H[结束];
数据结构设计
为了高效地管理数据,我们采用结构体(struct)来定义核心数据模型,并使用文件进行存储。
1 用户信息结构体
// 用户信息结构体
typedef struct {
char id[20]; // 学号
char name[50]; // 姓名
char password[20]; // 密码
double balance; // 账户余额
int status; // 状态: 0-未上机, 1-已上机
int seat_id; // 占用机位号 (0表示未占用)
} User;
2 上机记录结构体
// 上机记录结构体
typedef struct {
char user_id[20]; // 学号
char name[50]; // 姓名
time_t login_time; // 上机时间 (time_t类型)
time_t logout_time; // 下机时间
double fee; // 本次消费金额
int seat_id; // 机位号
} Record;
3 核心数据结构

(图片来源网络,侵删)
- 用户数组: 使用一个结构体数组
User users[MAX_USERS]来存储所有用户信息。 - 记录数组: 使用一个结构体数组
Record records[MAX_RECORDS]来存储所有上机记录。 - 文件:
users.dat: 存储所有用户信息。records.dat: 存储所有上机记录。
核心功能代码实现
1 主函数与菜单
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#define MAX_USERS 1000
#define MAX_RECORDS 5000
#define FEE_PER_HOUR 2.0 // 每小时收费2元
// ... (在此处插入上面定义的结构体) ...
User users[MAX_USERS];
Record records[MAX_RECORDS];
int user_count = 0;
int record_count = 0;
// 函数声明
void load_data();
void save_data();
void show_main_menu();
void user_management();
void computer_usage();
void statistics_query();
// 主函数
int main() {
load_data();
show_main_menu();
save_data();
return 0;
}
// 显示主菜单
void show_main_menu() {
int choice;
while (1) {
system("cls || clear"); // 清屏
printf("\n\n\n");
printf("\t\t\t+--------------------------------+\n");
printf("\t\t\t| 机房收费管理系统 |\n");
printf("\t\t\t+--------------------------------+\n");
printf("\t\t\t| 1. 用户管理 |\n");
printf("\t\t\t| 2. 上机管理 |\n");
printf("\t\t\t| 3. 统计查询 |\n");
printf("\t\t\t| 0. 退出系统 |\n");
printf("\t\t\t+--------------------------------+\n");
printf("\t\t\t请选择您的操作: ");
scanf("%d", &choice);
switch (choice) {
case 1: user_management(); break;
case 2: computer_usage(); break;
case 3: statistics_query(); break;
case 0: printf("\n\t\t感谢使用,再见!\n"); return;
default: printf("\n\t\t无效的输入,请按任意键重试..."); getchar(); getchar();
}
}
}
2 用户管理模块 (示例:添加用户)
void add_user() {
if (user_count >= MAX_USERS) {
printf("用户数量已达上限,无法添加!\n");
getchar(); getchar();
return;
}
User new_user;
printf("请输入学号: "); scanf("%s", new_user.id);
printf("请输入姓名: "); scanf("%s", new_user.name);
printf("请输入初始密码: "); scanf("%s", new_user.password);
printf("请输入初始余额: "); scanf("%lf", &new_user.balance);
new_user.status = 0;
new_user.seat_id = 0;
users[user_count++] = new_user;
printf("用户添加成功!\n");
getchar(); getchar();
}
// ... (其他用户管理函数如 delete_user, modify_user, find_user 等) ...
void user_management() {
int choice;
while(1) {
system("cls || clear");
printf("\n--- 用户管理 ---\n");
printf("1. 添加用户\n");
printf("2. 删除用户\n");
printf("3. 修改用户信息\n");
printf("4. 查询用户\n");
printf("0. 返回主菜单\n");
printf("请选择: ");
scanf("%d", &choice);
switch(choice) {
case 1: add_user(); break;
// case 2: delete_user(); break;
// case 3: modify_user(); break;
// case 4: find_user(); break;
case 0: return;
default: printf("无效选择!"); getchar(); getchar();
}
}
}
3 上机管理模块 (核心逻辑)
void user_login() {
char id[20], password[20];
printf("请输入学号: "); scanf("%s", id);
printf("请输入密码: "); scanf("%s", password);
for (int i = 0; i < user_count; i++) {
if (strcmp(users[i].id, id) == 0 && strcmp(users[i].password, password) == 0) {
if (users[i].status == 1) {
printf("该用户已在机房上机!\n");
getchar(); getchar();
return;
}
users[i].status = 1;
users[i].login_time = time(NULL); // 记录当前时间
printf("请选择机位号 (1-50): ");
scanf("%d", &users[i].seat_id);
printf("上机成功!当前时间: %s", ctime(&users[i].login_time));
getchar(); getchar();
return;
}
}
printf("学号或密码错误!\n");
getchar(); getchar();
}
void user_logout() {
char id[20];
printf("请输入学号: "); scanf("%s", id);
for (int i = 0; i < user_count; i++) {
if (strcmp(users[i].id, id) == 0) {
if (users[i].status == 0) {
printf("该用户未上机!\n");
getchar(); getchar();
return;
}
time_t logout_time = time(NULL);
double hours = difftime(logout_time, users[i].login_time) / 3600.0;
double fee = hours * FEE_PER_HOUR;
if (fee > users[i].balance) {
printf("余额不足!当前欠费: %.2f元\n", fee - users[i].balance);
// 可以选择强制下机或提示充值
users[i].status = 0;
users[i].seat_id = 0;
getchar(); getchar();
return;
}
// 扣费
users[i].balance -= fee;
users[i].status = 0;
int seat = users[i].seat_id;
users[i].seat_id = 0;
// 添加到记录
records[record_count].login_time = users[i].login_time;
records[record_count].logout_time = logout_time;
records[record_count].fee = fee;
strcpy(records[record_count].user_id, users[i].id);
strcpy(records[record_count].name, users[i].name);
records[record_count].seat_id = seat;
record_count++;
printf("下机成功!\n");
printf("上机时长: %.2f 小时\n", hours);
printf("消费金额: %.2f 元\n", fee);
printf("当前余额: %.2f 元\n", users[i].balance);
getchar(); getchar();
return;
}
}
printf("未找到该用户!\n");
getchar(); getchar();
}
void computer_usage() {
int choice;
while(1) {
system("cls || clear");
printf("\n--- 上机管理 ---\n");
printf("1. 用户上机\n");
printf("2. 用户下机\n");
printf("0. 返回主菜单\n");
printf("请选择: ");
scanf("%d", &choice);
switch(choice) {
case 1: user_login(); break;
case 2: user_logout(); break;
case 0: return;
default: printf("无效选择!"); getchar(); getchar();
}
}
}
4 数据持久化 (文件读写)
void save_data() {
FILE *fp_user = fopen("users.dat", "wb");
if (fp_user == NULL) {
perror("无法打开用户文件");
return;
}
fwrite(&user_count, sizeof(int), 1, fp_user);
fwrite(users, sizeof(User), user_count, fp_user);
fclose(fp_user);
FILE *fp_record = fopen("records.dat", "wb");
if (fp_record == NULL) {
perror("无法打开记录文件");
return;
}
fwrite(&record_count, sizeof(int), 1, fp_record);
fwrite(records, sizeof(Record), record_count, fp_record);
fclose(fp_record);
}
void load_data() {
FILE *fp_user = fopen("users.dat", "rb");
if (fp_user != NULL) {
fread(&user_count, sizeof(int), 1, fp_user);
fread(users, sizeof(User), user_count, fp_user);
fclose(fp_user);
}
FILE *fp_record = fopen("records.dat", "rb");
if (fp_record != NULL) {
fread(&record_count, sizeof(int), 1, fp_record);
fread(records, sizeof(Record), record_count, fp_record);
fclose(fp_record);
}
}
项目扩展与优化建议
一个优秀的课程设计不仅要实现基本功能,还要考虑其扩展性和健壮性。
-
数据结构优化:
- 用户管理: 使用链表代替数组,实现动态内存分配,避免
MAX_USERS的限制。 - 机位管理: 创建一个
Seat结构体数组,实时显示每个机位的使用状态(空闲/占用,占用者是谁),并在用户上机/下机时更新。
- 用户管理: 使用链表代替数组,实现动态内存分配,避免
-
功能增强:
- 多种计费方式: 实现按时计费、按天计费、包月套餐等多种模式。
- 权限管理: 增加管理员账号和普通用户账号,普通用户只能查询和上机/下机,管理员才能进行用户管理。
- 数据报表: 生成更详细的报表,如月度收入报表、用户上机时长排行榜等。
- 图形化界面: 使用 EasyX (Windows) 或 GTK / Qt (跨平台) 库,将控制台程序升级为带图形界面的应用程序,提升用户体验。
-
代码健壮性:
- 输入验证: 对所有用户输入进行严格验证,防止非法输入导致程序崩溃(输入字母代替数字)。
- 错误处理: 增加对文件操作、内存分配等可能出错的地方进行更完善的错误处理和提示。
- 代码规范: 遵循良好的代码风格,添加必要的注释,使代码易于阅读和维护。
项目总结
通过本次课程设计,我成功地开发了一个功能基本完备的机房收费管理系统,在实践中,我深入理解了C语言中结构体、文件操作、指针、函数等核心知识的应用,更重要的是,我学会了如何将一个复杂的需求分解为若干个模块,并逐步实现,体验了从需求分析到代码实现再到测试优化的完整软件开发流程。
虽然本系统还有一些可以改进的地方,但作为课程设计,它已经达到了预期的目标,巩固了我的编程能力,并锻炼了我的问题解决能力和系统设计思维。
