#include<stdio.h> /*I/O函数*/
#include<stdlib.h> /*其它说明*/
#include<string.h> /*字符串函数*/
#define LEN 15 /* 学号和姓名最大字符数,这里设置的是15*/
#define N 200 /* 最大学生人数,200*/
/*比较 <> 和 ""
<> 直接从系统目录下查找包含这个文件
"" 先从工程的项目目录下查找这个,如果没有,再到系统目录下查找
*/
struct record //(record)是一个集合,它把一组相关数据聚集在一个存储单元里,记录中的每个元素称作字段
{
char code[LEN + 1]; /* 学号 加 1是为了LEN留余,不加1,也没有关系,只要不越界就行了 name相同*/
char name[LEN + 1]; /* 姓名 同上*/
int age; /* 年龄*/
char sex; /* 性别*/
float score[3]; /* 3门课程成绩*/
}stu[N]; //stu[N] 是存放N个元素的数组,数组中的每个元素都是struct record {………………}中的结构体对象
int k = 1,n = 0, m = 0;/*定义全局变量, n代表当前记录的学生总人数,m为新增加的学生人数*/
/*******函数声明********/
void readfile(); /* 读入数据*/
void seek(); /* 查找信息*/
void insert(); /* 插入数据*/
void display(); /* 显示信息*/
void save(); /* 保存信息*/
void menu(); /* 菜单*/
int main() // 主函数 menu读取一个字符 整数,字符在内存中映射为ASCII码
{
while (k)
{
menu();
}
system("pause");
return 0;
}
/* 从文件中读取数据到结构体数组*/
void readfile()
{
char filename[LEN + 1]; /* 文件名*/
FILE* fp; /* 文件指针*/
int i = 0;
printf("请输入以存有学生信息的文件名:\n");
scanf("%s", filename);
if ((fp = fopen(filename, "r")) == NULL) /* 以只读的方式打开指定文件,:打开文件名为filename的文件,根据fopen的返回值(fp),
判断该文件是否打开,如果没有打开,则打印"Error opening file"信息,
然后退出程序,如果正确打开,则跳过这里,执行后面的语句,*/
{
printf("打开文件%s错误", filename);
printf("你需要先选择菜单4增加学生信息\n");
system("pause");/* system("PAUSE");和system("pause");用和效果一样,因为dos命令是不区分大小写的。
system("PAUSE") 是暂停的意思,等待用户信号;不然控制台程序会一闪即过,你来不及看到执行结果。 */
return;
}
/* 循环读入学生信息*/
while (fscanf(fp, "%s%s%d%c%f%f%f", stu[i].code, stu[i].name, &stu[i].age, &stu[i].sex, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]) == 7)
{
i++;
}
n = i;
if (0 == i)
printf("文件为空,你需要先选择菜单4增加学生信息\n");
else
printf("读入成功\n");
fclose(fp);
system("pause");
}
/* 查找信息*/
void seek() /*查找*/
{
int i, item, flag;
char s1[21]; /* 以姓名和学号最长长度+1为准 :LEN+1 防止越界 chars1[]是一个字符串变量,可
以被修改,s1 是函数的栈空间区域,函数执行完成,这个空间就没了*/
printf("------------------\n");
printf("-----1.按学号查询-----\n");
printf("-----2.按姓名查询-----\n");
printf("-----3.退出本菜单-----\n");
printf("------------------\n");
while (1)//while(0)表示不执行循环语句,while(1)表示执行语句。防止越界
{
printf("请选择子菜单编号:");
scanf("%d", &item);
flag = 0; //给变量赋值
switch (item) //此处的item为我们输入的菜单选项通过switch判断选择代码。其功能就是控制流程流转的
{
case 1:
printf("请输入要查询的学生的学号:\n");
scanf("%s", s1);
for (i = 0; i < n; i++)
if (strcmp(stu[i].code, s1) == 0)
{
flag = 1;
printf("学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩\n");
printf("--------------------------------------------------------------------\n");
printf("%6s %7s %6d %6c %9.1f %10.1f %10.1f\n", stu[i].code, stu[i].name, stu[i].age, stu[i].sex, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
}
if (0 == flag)
printf("该学号不存在!\n"); break;
case 2:
printf("请输入要查询的学生的姓名:\n");
scanf("%s", s1);
for (i = 0; i < n; i++)
if (strcmp(stu[i].name, s1) == 0)
{
flag = 1;
printf("学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩\n");
printf("--------------------------------------------------------------------\n");
printf("%6s %7s %6d %6c %9.1f %10.1f %10.1f\n", stu[i].code, stu[i].name, stu[i].age, stu[i].sex, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
}
if (0 == flag)
printf("该姓名不存在!\n"); break;
case 3:return; //返回上一级
default:printf("请在1-3之间选择\n");//default只有在case匹配失败的时候才会执行
}
}
}
void sort()/*按学号排序 此处通过比较排序法(最基础的挨个比较)运算量要比其他排序法时间复杂度要高但稳定性要比较好一点复杂度简单*/
{
int i = 0, j = 0;
int tmp = 0;
printf("测试 j :\n", atoi(stu[j].code));
printf("测试 j+1:%d\n", atoi(stu[j+1].code));
for (i = 0; i < n - 1; i++) //冒泡核心,双层for循环
{
for (j = 0; j < n - 1 - i; j++)
{
//不能使用strcmp
//理由:这个函数是会从左到右一个字符一个字符判断
//例子:102 和 20会先判断第一个字符 1 和 2 于是102<20
//if (strcmp(stu[j - 1].code, stu[j].code) > 0)
if(atoi(stu[j].code)> atoi(stu[j+1].code))//此处决定按从小到大或从大到小
{
/*
c语言有一些函数可以把字符串转为数字
atof() 将字符串转换为双精度浮点型值
atoi() 将字符串转换为整型值
atol() 将字符串转换为长整型值
strtod() 将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字
strtol() 将字符串转换为长整值,并报告不能被转换的所有剩余数字
strtoul() 将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字
*/
printf("测试 j - 1:\n",atoi(stu[j - 1].code));
printf("测试 j:%d\n",atoi(stu[j].code));
record s;
s = stu[j];
stu[j] = stu[j+1];
stu[j+1] = s;
}
}
}
}
void insert()
{
int j = n, i, flag;//定义函数
printf("请输入待增加的学生数:\n");//输入插入学生数量
scanf("%d", &m);
if (m > 0)
{
do
{
flag = 1;
while (flag)
{
flag = 0;
printf("请输入第%d位学生的学号:\n", j + 1);
scanf("%s", stu[j].code);
for (i = 0; i < j; i++) /*进行检查,与之前的学号比较,如果重复,则重新输入*/
if (strcmp(stu[j].code, stu[i].code) == 0)
{
printf("已有该学号,请重新录入\n");
flag = 1;
break; /*如有重复,退出内层循环*/
}
}
//在前面的while循环内是有输入学号的
//printf("请输入第%d 个学生的学号:\n", j + 1);
//scanf("%s", stu[j].code);
printf("请输入第%d 个学生的姓名:\n", j + 1);
scanf("%s", stu[j].name);
printf("请输入第%d 个学生的年龄:\n", j + 1);
scanf("%d", &stu[j].age);
printf("请输入第%d 个学生的性别:\n", j + 1);
scanf(" %c", &stu[j].sex);
printf("请输入第%d 个学生的C语言成绩\n", j + 1);
scanf("%f", &stu[j].score[0]);
printf("请输入第%d 个学生的高等数学成绩:\n", j + 1);
scanf("%f", &stu[j].score[1]);
printf("请输入第%d 个学生的大学英语成绩:\n", j + 1);
scanf("%f", &stu[j].score[2]);
if (0 == flag)
{
j++;
}
} while (j < n + m);
}
n += m;
printf("信息增加完毕!\n\n");
system("pause");
}
/* 显示信息*/
void display()
{
sort();
int i;
printf("共有%d位学生的信息:\n", n);
if (0 != n)
{
printf("学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩\n");
printf("--------------------------------------------------------------------\n");
for (i = 0; i < n; i++)
{
printf("%7s %7s %6d %6c %9.1f %10.1f %10.1f\n", stu[i].code, stu[i].name, stu[i].age, stu[i].sex, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
}
}
system("pause");
}
/* 保存信息*/
void save()
{
int i;
FILE* fp;
char filename[LEN + 1];
printf("请输入要保存该信息的文件名:\n"); /*输入要保存的文件的名字*/
scanf("%s", filename);
fp = fopen(filename, "w");
for (i = 0; i < n; i++)
{
fprintf(fp, "%s%s%d%c%.1f%.1f%.1f\n", stu[i].code, stu[i].name, stu[i].age, stu[i].sex, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
}
printf("保存成功\n");
fclose(fp);
system("pause");
}
/* 菜单界面*/
void menu(){
int num;
printf(" \n\n \n\n");
printf(" ******************************************************\n\n");
printf(" * 学生信息管理系统 *\n \n");
printf(" ******************************************************\n\n");
printf("*********************系统功能菜单************************* \n");
printf(" ---------------------- ---------------------- \n");
printf(" ********************************************* \n");
printf(" ***********按需要选择菜单编号 ********** \n");
printf(" ********************************************* \n");
printf(" * 1.查询学生信息 * * 2.退出系统 * \n");
printf(" ********************************************* \n");
printf(" * 3.增加学生信息 * * 4.显示当前信息 * \n");
printf(" ********************************************* \n");
printf(" * 5.保存当前学生信息* * 6.退出系统 * \n");
printf(" ********************** ********************** \n");
printf(" ********************** \n");
printf(" ---------------------- ---------------------- \n");
printf("请选择菜单编号:");
scanf("%d", &num);
switch (num)//此处对菜单进行选择 原理基本类似
{
case 0:readfile(); break;
case 1:seek(); break;
case 2: break;
case 3:insert(); break;
case 4:display(); break;
case 5:save(); break;
case 6:k = 0; break;
default:printf("请在0-6之间选择\n");
}
}