C语言项目实战 --学生成绩管理系统
项目开发基本流程
- 可行性分析和项目开发计划
技术可行性:软硬件、技术人员条件、项目是否能实现
经济可行性:成本估算、开发时间、经济效益评估,看这个项目是否有开发价值
社会可行性:审批、法律操作是否可行 - 需求分析
问题分析与识别
-
- 功能需求:软件要具备和实现的功能
-
- 性能需求:软件技术性能指标
-
- 环境需求:软件运行需要额软硬件环境
分析与综合,到处软件的逻辑模型:
在分析与综合中,逐步细化软件模型,划分各个子功能采用图文混合的方式建立系统的逻辑模型
编写文档
- 环境需求:软件运行需要额软硬件环境
- 概要设计
设计软件及系统结构:
经一个复杂的系统按功能进行模块划分,高内聚、低耦合。
确定每个模块的功能混合模块之间的调用关系。
确定模块之间的接口。
数据结构及数据库设计:
数据结构、模块接口之间通信的数据结构
编写概要设计文档:
测试计划、测试用例 - 详细设计
为每个模块进行详细的算法设计、处理过程使用算法描述出来
模块内的数据结构设计与定义
对数据库进行物理设计
编写详细设计说明书
使用伪代码来描述模块算法和细节处理 - 编码
在前一阶段的基础上,选择合适的语言进行物理实验
-
- 程序语言设计的选择
项目应用领域
软件开发的方法
软件执行的环境
软件发开人员的知识储备
- 程序语言设计的选择
-
- 程序设计风格
源程序的编码规范
数据说明(注释)
效率
- 程序设计风格
- 测试
-
- 测试的重要性
测试原则与分类
- 测试的重要性
-
- 测试流程
单元测试
集成测试
压力测试
版本发布
a阶段:Alpha测试,主要看有么有功能上的缺失或者系统上的大错误
b阶段:Beta测试,给用户使用测试,Beta1–Beta2
c阶段:Rc测试(release candidate)Rc1 --Rc2–Rc3 基本稳定版本,没有大的修改了
- 测试流程
- 软件发布、维护与运营
一、可行性分析及项目开发计划
可行性分析
- 技术可行性:
硬件:c高级语言,跟硬件平台无关,编写的程序可以在任何硬件平台运行
软件:纯软件的业务逻辑操作,只依赖C标准库,软件上没有什么问题
技术人员的要求:只要有c语言的基础
综上所述,项目可以实现 - 经济可行性:
- 社会可行性:
方便电子化管理、无纸化绿色低碳环保办公
项目开发计划
- 时间进度安排
资源安排
人力
软硬件资源
经费
成本风险评估
二、需求分析
问题分析与识别
- 功能需求:
实现学生信息的添加、删除、查询、修改等功能
学生成绩的磁盘保存
方便的人机交互功能 - 性能需求:
软件运行稳定
速度快、效率高
可移植性好,在不同的处理器的操作系统平台上都可以正常使用
健壮性:对于出错处理完善
人机交互友好,操作简单易用,容易上手
扩展性好:采用模块化编程、添加删除新功能模块方便
分析与综合,导出软件的逻辑模型
- 菜单人际交互
- 存储模块
- 成绩添加
- 成绩删除
- 成绩查询
- 成绩打印
编写文档
《需求规格说明书》
三、概要设计
- 学生成绩管理系统结构设计
模块划分
菜单及人机交互模块、成绩存储模块、成绩打印、成绩添加、成绩删除、成绩修改、成绩统计等
模块功能
void student_save();
void student_add();
void student_delete();
void student_print();
void student_tongji();
void student_modify();
void student_menu();
模块之间的调用关系:
菜单模块根据用户输入选择调用其他模块的函数,实现各种操作。
模块之间的接口:
结构体数组 :struct student stu[50];
数组的长度:int actual_len;
链表
- 数据结构设计
struct student
{
unsigned int no;
char name[10];
char sex;
unsigned char age;
float chinese;
float english;
float math;
}
- 编写概要设计文档
首先main函数里面通过主菜单模块,根据用户的输入,执行不同的操作;成绩添加、删除、查询、打印、保存等,每个模块功能通过每个模块定义的函数回来实现,具体的参数可以根据实际的需要动态修改,
程序运行时,首先从数据文件中读取学生信息,使用一个全局的结构体数组,来保存学生的信息,每个数组元素代表一个学生的信息,同事全局变量actual_len表示当前处理的学生人数,当进行添加、修改、删除等操作,学生人数和信息会动态发生变化,药剂师保存到磁盘文件中,与磁盘文件保持一致。
四、详细设计
-
模块详细设计
-
菜单及人机交互
1:首先要打印菜单,提醒用户输入操作选项
2:处理用户输入,根据用户选择调用不同的模块
3:清屏,然后重新打印菜单,进入循环,再次提醒用户输入
4:模块函数
void student_save(int *len,struct student stu[]));
void student_add(int *len,struct student stu[]));
void student_delete(int *len,struct student stu[]));
void student_print(int len,struct student stu[]));
void student_tongji(int len,struct student stu[]));
void student_modify(int len,struct student stu[]));
void student_menu(); -
成绩添加
void student_add(int *len,struct student stu[])
{
首先我们要定义一个结构体变量:
提醒用户输入学生信息:
把这个结构体变量保存到数组中
更新数组的实际长度:更新实际的学生人数
刷新到文件中
} -
成绩删除
void student_delete(int *len,struct student stu[])
{
提示用户输入学生信息
根据学号还是根据姓名
找到这个变量在数组中的位置
删除这个数组元素
后边的数组元素迁移
更改数组的当前实际长度
刷新到文件中
} -
成绩查询
void student_find(int len,struct student stu[])
{
提醒用户根据学好还是根据姓名查找
用户选择
根据姓名或者学号找到在数组中的位置
打印整个数组元素的信息
} -
成绩修改
void student_modify(int len,struct sstudent stu[])
{
提醒用户输入姓名或者学号
根据姓名或者学号找到在数组中的位置
提醒用户修改选项
根据用户修改选项,提醒用户键入修改值
将修改的数组元素保存到文件中
}
-
成绩保存
void student_save(int len ,struct student stu[])
{
以写的方式,打开当前的文件
将数组元素逐个写入到文件
关闭文件
} -
成绩统计
void student_tongji(int len,struct student stu[]))
{
逐个对数组元素进行计算
}
编码(1)
main.c
#include<stdio.h>
#include"student.h"
int actual_len = 0;
struct student stu[50];
struct student std[2] = {
{1001,"Xun",'M',18,99,98,97},
{1002,"Jan",'M',18,99,98,97},
};
int main() {
student_menu();
}
void student_menu()
{
while (1) {
printf("---------------------------------------------------------------------------\n");
printf("\t\t欢迎使用学生成绩管理系统\n");
printf("\t1:成绩添加\t2:成绩删除\n");
printf("\t3:成绩查询\t4:成绩修改\n");
printf("\t5:成绩统计\t6:返主菜单\n");
printf("---------------------------------------------------------------------------\n");
int sec = 0;
printf("请输入选项:");
scanf("%d", &sec);
switch (sec)
{
case 1:
student_array_add(&actual_len, stu);
break;
case 2:
student_array_delate(&actual_len, stu);
break;
case 3:
student_find(actual_len, stu);
break;
case 4:
student_modify(actual_len, stu);
break;
case 5:
student_count(actual_len, stu);
case 6:
system("cls");
student_menu();
default:
printf("输入错误!");
}
}
}
int main01() {
#if 0//查看内存文件中的真实数据模块
//storge
printf("actual_len = %d\n", actual_len);
student_array_init(&actual_len, stu);
printf("actual_len = %d\n", actual_len);
student_print(actual_len, stu);
#endif
#if 0 //保存与删除模块
student_array_add(&actual_len, stu);
//student_array_delate(&actual_len, stu);
#endif
#if 0
student_find(actual_len, stu);
#endif
#if 0
student_modify(actual_len, stu);
#endif
#if 0
student_count(actual_len, stu);
#endif //
}
stduent.c
#include<stdio.h>
#include<string.h>
#include"student.h"
void array_print(struct student stu)
{
printf("学号\t姓名\t性别\t年龄\t语文\t\t英语\t\t数学\n");
printf("%d\t%s\t%c\t%d\t%f\t%f\t%f\n", stu.no, stu.name, stu.sex, stu.age, stu.chinese, stu.english, stu.math);
}
void student_print(int len,struct student stu[])
{
printf("学号\t姓名\t性别\t年龄\t语文\t\t英语\t\t数学\n");
for(int i=0;i<len;i++)
printf("%d\t%s\t%c\t%d\t%f\t%f\t%f\n",stu[i].no, stu[i].name, stu[i].sex, stu[i].age, stu[i].chinese, stu[i].english, stu[i].math);
}
int student_save(int len, struct student stu[])
{
FILE * fp;
if ((fp = fopen("student.dat","wb")) == NULL)
{
printf("文件打开失败!\n");
return -1;
}
for (int i = 0; i < len; i++)
{
fwrite(&stu[i], sizeof(struct student), 1, fp);
if (ferror(fp))
{
printf("数据写入失败!\n");
return -2;
}
}
fclose(fp);
return 0;
}
int student_array_init(int *len,struct student stu[])
{
FILE *fp;
if ((fp = fopen("student.dat", "ab+"))== NULL)
{
printf("文件打开失败!\n");
return -1;
}
int i = 0;
fread(&stu[i], sizeof(struct student), 1, fp);
while (!feof(fp))
{
i++;
fread(&stu[i], sizeof(struct student), 1, fp);
if (ferror(fp))
{
printf("数据读取失败!\n");
return -2;
}
}
*len = i;
fclose(fp);
return 0;
}
int student_array_add(int* len, struct student stu[])
{
struct student std;
int num,i;
printf("请输入要添加的学生信息人数:");
scanf("%d", &num);
for (i = 0; i < num; i++)
{
printf("请输入第%d个学生信息:\n",i+1);
printf("学号<1000>:");
scanf("%d", &std.no);
printf("姓名:");
scanf("%s", &std.name);
rewind(stdin);
printf("性别(M/F):");
scanf("%c", &std.sex);
printf("年龄:");
scanf("%d", &std.age);
printf("语文:");
scanf("%f", &std.chinese);
printf("英语:");
scanf("%f", &std.english);
printf("数学:");
scanf("%f", &std.math);
stu[*len] = std;
(*len)++;
}
student_save(*len, stu);
student_print(*len, stu);
return 0;
}
int stu_del_by_name(char name[], int* len, struct student stu[])
{
int i = 0;
for (i; i < *len; i++)
{
if (strcmp(name, stu[i].name) == 0)
{
break;
}
}
if(i == *len)
{
printf("error:无法找到学生%s的信息!\n",name);
return -1;
}
for (i; i < *len - 1; i++)
{
stu[i] = stu[i + 1];
(*len)--;
return 0;
}
return 0;
}
int stu_del_by_no(int no,int* len, struct student stu[])
{
int i;
for (i = 0; i < *len; i++)
{
if (stu[i].no == no)
break;
}
if (i == *len)
{
printf("删除失败,无法找到学号 %d 的信息!\n", no);
return -1;
}
for (i; i < *len - 1; i++)
stu[i] = stu[i + 1];
(*len)--;
return 0;
}
int student_array_delate(int* len, struct student stu[])
{
student_array_init(len, stu);
student_print(*len, stu);
int select;
printf("------------------------------\n");
printf("请选择查询删除的方式:\n");
printf("1:根据学生姓名查找删除\n2:根据学生学号查找删除\n(1/2):");
scanf("%d", &select);
if (select == 1)
{
char name[20];
printf("请输入要删除的学生姓名:");
scanf("%s", name);
stu_del_by_name( name, len, stu);
}
else if (select == 2)
{
int no;
printf("请输入要删除的学生学号");
scanf("%d", &no);
stu_del_by_no(no,len, stu);
}
else
{
printf("无效输入!\n");
return -1;
}
student_save(*len, stu);
student_print(*len, stu);
return 0;
}
int stu_find_by_name(char name[], int len, struct student stu[])
{
int i;
for (i=0; i < len; i++)
{
if (strcmp(name, stu[i].name) == 0)
break;
}
if (i == len)
{
printf("error:无法找到学生%s的信息!\n", name);
return -1;
}
printf("查找成功,该学生信息:\n");
array_print(stu[i]);
return 0;
}
int stu_find_by_no(int no, int len, struct student stu[])
{
int i;
for (i = 0; i < len; i++)
{
if (no == stu[i].no)
break;
}
if (i == len)
{
printf("查询失败,无法找到学号%d的信息!\n", no);
return -1;
}
printf("查找成功,该学生信息:\n");
array_print(stu[i]);
return 0;
}
int student_find(int len, struct student stu[])
{
int select;
printf("------------------------------\n");
printf("请选择查询的方式:\n");
printf("1:根据学生姓名查询\n2:根据学生学号查询\n(1/2):");
scanf("%d", &select);
if (select == 1)
{
char name[20];
printf("请输入要查询的学生姓名:\n");
scanf("%s", name);
stu_find_by_name(name, len, stu);
}
else if (select == 2)
{
int no;
printf("请输入要查询的学生学号:\n");
scanf("%d", &no);
stu_find_by_no(no, len, stu);
}
else
{
printf("无效输入!\n");
return -1;
}
return 0;
}
int stu_modify_by_name(char name[], int len, struct student stu[])
{
int i;
for (i = 0; i < len; i++)
{
if (strcmp(name, stu[i].name) == 0)
break;
}
if (i == len)
{
printf("error:无法找到学生%s的信息!\n", name);
return -1;
}
array_print(stu[i]);
printf("请输入需要修改的成员:\n");
printf("1:修改学号\n2:修改姓名\n3:修改性别\n4:修改年龄\n5:修改语文\n6:修改英语\n7:修改数学");
int num;
scanf("%d", &num);
switch (num)
{
case 1:
printf("将学号修改为:");
scanf("%d", &stu[i].no);
break;
case 2:
printf("将姓名修改为:");
scanf("%s", &stu[i].name);
break;
case 3:
printf("将性别修改为:");
scanf("%c", &stu[i].sex);
break;
case 4:
printf("将年龄修改为:");
scanf("%d", &stu[i].age);
break;
case 5:
printf("将语文修改为:");
scanf("%f", &stu[i].chinese);
break;
case 6:
printf("将英语修改为:");
scanf("%f", &stu[i].english);
break;
case 7:
printf("将数学修改为:");
scanf("%f", &stu[i].math);
break;
default:
printf("输入错误!");
}
return 0;
}
int stu_modify_by_no(int no, int len, struct student stu[])
{
int i;
for (i = 0; i < len; i++)
{
if (no == stu[i].no)
break;
}
if (i == len)
{
printf("查询失败,无法找到学号%d的信息!\n", no);
return -1;
}
array_print(stu[i]);
printf("请输入需要修改的成员:\n");
printf("1:修改学号\n2:修改姓名\n3:修改性别\n4:修改年龄\n5:修改语文\n6:修改英语\n7:修改数学\n:");
int num;
scanf("%d", &num);
switch (num)
{
case 1:
printf("将学号修改为:");
scanf("%d", &stu[i].no);
break;
case 2:
printf("将姓名修改为:");
scanf("%s", &stu[i].name);
break;
case 3:
printf("将性别修改为:");
scanf("%c", &stu[i].sex);
break;
case 4:
printf("将年龄修改为:");
scanf("%d", &stu[i].age);
break;
case 5:
printf("将语文修改为:");
scanf("%f", &stu[i].chinese);
break;
case 6:
printf("将英语修改为:");
scanf("%f", &stu[i].english);
break;
case 7:
printf("将数学修改为:");
scanf("%f", &stu[i].math);
break;
default:
printf("输入错误!");
}
return 0;
}
int student_modify(int len, struct student stu[])
{
int select;
printf("------------------------------\n");
printf("请选择查找修改的方式:\n");
printf("1:根据学生姓名查找修改\n2:根据学生学号查找修改\n(1/2):");
scanf("%d", &select);
if (select == 1)
{
char name[20];
printf("请输入要修改的学生姓名:\n");
scanf("%s", name);
stu_modify_by_name(name, len, stu);
}
else if (select == 2)
{
int no;
printf("请输入要修改的学生学号:\n");
scanf("%d", &no);
stu_modify_by_no(no, len, stu);
}
else
{
printf("无效输入!\n");
return -1;
}
student_save(len, stu);
student_print(len, stu);
return 0;
}
int student_count(int len, struct student stu[])
{
student_array_init(&len, stu);
float chinese_avr = 0, english_avr = 0, math_avr = 0;
int chinese_fail = 0, english_fail = 0, math_fail = 0;
for (int i = 0; i < len ;i++)
{
chinese_avr += stu[i].chinese;
english_avr += stu[i].english;
math_avr += stu[i].math;
}
chinese_avr /= len;
english_avr /= len;
math_avr /= len;
for (int i = 0; i < len; i++)
{
if (stu[i].chinese < 60)
chinese_fail++;
if (stu[i].english < 60)
english_fail++;
if (stu[i].math < 60)
math_fail++;
}
printf("------------------------------------------------------------------\n");
printf("语文平均成绩为:%f\n英语平均成绩为:%f\n数学平均成绩为:%f\n", chinese_avr, english_avr, math_avr);
printf("------------------------------------------------------------------\n");
printf("语文不及格人数为:%d\n", chinese_fail);
printf("英语不及格人数为:%d\n", english_fail);
printf("数学不及格人数为:%d\n", math_fail);
printf("------------------------------------------------------------------\n");
return 1;
}
stduent.h
#pragma once
#ifndef __STUDENT_H__
#define __STUDENT_H__
struct student {
unsigned int no;
char name[10];
char sex;
int age;
float chinese;
float english;
float math;
};
void array_print(struct student stu); //一种简单的结构体打印方式,直接传结构体名称(首地址)就能打印
void student_print(int len, struct student stu[]);//结构体数组打印,第一个参数是结构体数组长度,第二个参数是结构体数组的地址
int student_save(int len, struct student stu[]);//把结构体数组保存到文件中
int student_array_init(int* len, struct student stu[]);//把文件中的结构体数组读取到stu[]
int student_array_add(int* len, struct student stu[]);//向文件中添加结构体数组
int student_array_delate(int* len, struct student stu[]);//1:删除文件中的一个结构体数组
int stu_del_by_no(int no,int *len, struct student stu[]);//2:按照学号删除文件中的一个结构体数组(属于1中的一个小函数)
int stu_del_by_name(char name[], int* len, struct student stu[]);//3:按照姓名删除文件中的一个结构体数组(属于1中的一个小函数)
int student_find(int len, struct student stu[]);//查询文件中的结构体,
int stu_find_by_name(char name[], int len, struct student stu[]);
int stu_find_by_no(int no, int len, struct student stu[]);
int student_modify(int len, struct student stu[]);
int stu_modify_by_name(char name[],int len,struct student stu[]);
int stu_modify_by_no(int no, int len, struct student stu[]);
int student_count(int len, struct student stu[]);
void student_menu();
#endif