C++中FILE实操作---C++来实现学生管理系统【Final_version*(੭*ˊᵕˋ)੭*ଘ】

/*C++类来实现学生管理系统*/ /***********************************************************/ //该系统实现了那些操作 //1、菜单、增、删、改、查、打印、保存、载入 //2、检查是否已经存在的学号 //3、实现二级菜单 选择性修改等操作 //4、学号/姓名/成绩可以实现排序 同时 实现综合程序的方法 排序函数的汇总 多种方法选择 //5、除了实现冒泡排序,还实现了选择排序算法 //6、实现了控制台背景颜色和字体颜色像模板似可以调整 //========================================================== //学到的知识点: //1--绝对路径,指定盘符 //2--相对路径,不指定盘符,在执行文件的当前目录下 //3--void类型,即什么类型都能接受,double int char 等都可以传送 //4--刷新添加,每次写入将之前清零 保存写入现有的所有 //5--停止条件: 1】写入write停止条件: 内存中数据为0时候,有效数据的位置,即g_user[i].m_Num!=0 // 2】加载Load 停止条件: 文件中数据读取返回值为0,读取不到数据时,即int n=fread(&us, 1, sizeof(us), pf)=0 //6--fwrite : 两种模式 w 写入 清空原来写入 // a(append)追加,原来基础上写入 //7--堆栈调用:debug模式下调用堆栈来查看程序的堆栈 压入调出情况 程序最好压入少,否则栈满了会崩溃 // 当选择菜单选择0退出时,可能还有数据在栈内压这呢。 // 尽量保持多级菜单复用时候考虑压栈等 一般三级 //8--排序算法:冒泡排序 VS 选择排序 // 冒泡:简单,构架好想,但每次移动,移动次数多 // 选择:难度,构架难想,但移动次数比较少 //9--生命周期:类成员变量的生命期 // a)类成员函数(在对象构造之后,即实例化)被各个成员函数都可以调用,类似C语言对全局变量的调用 // b)Time(类的对象) = Time(内部成员变量) // c)Begin_Time(类对象内成员变量) :对象定义时,也是构造函数执行时 // d)Over_Time (类对象内成员变量) :对象析构函数时,所有需要在析构函数内写入堆栈释放语句即可。 //?????????????????????????????// //未解决问题: //1、写入到txt文件中的数据有乱码【正常,txt不支持这个格式的查看,ue可以查看十六进制】 //2、项目多少有点不稳定,好像在选择修改地方【已修复bug!---后面少了break】 /***********************************************************/ #include"Stu_CW.h" int main(){ Stu_CW stu_mag; stu_mag.Welcome_String(); system("color 4f"); //stu_mag.String_Pr(); system("pause"); system("cls"); stu_mag.Start(); return 0; }
/*重要的点一定记住*/ /***********************************************/ //1、关于重定义的问题 // ฅʕ•͡头文件专注声明用,不可以用作全局变量引用等, •ʔฅ // 即申明全局变量,全局函数一定要在cpp中申明,其他类引用该全局变量 // 就include该cpp的h文件,然后extern一下就好了。否则容易出现该重复定义错误。 /**********************************************/ #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<stdlib.h> #include<iostream> using namespace std; class Stu_CW{ //默认是私有保护 void Print(); //打印 void Save(); //保存 void Add(); //增 void Delete(); //删 void Modify(); //改 void Find(); //查 int Sort_Judge(int choose_sort_m, int nMin, int j);//排序判断 void Gather_Sort(int m);//汇总排序 int DisplayMenu(); //子菜单显示 int Color_Set(); //颜色设置 public://公开接口 此处函数对外开放,内部函数可以在类内调用其它私有函数 Stu_CW();//自构函数如果放在私有区,那么久无法初始化 ~Stu_CW(); void String_Pr(); //字符串显示 int Menu(); //主菜单^(* ̄(oo) ̄)^ void Load(); //载入 void Start(); // 纯属学习娱乐用 static int Learning_Code(int para, char * point, double Math); // 输出显示界面 void Welcome_String(); };
#include"Stu_CW.h" struct SUser{//结构体 每个接头体保存三个数据 int m_Num; //学号数据 char m_Name[20]; //姓名数据 float m_Math; //成绩数据 }; SUser g_user[10000];//可以实现保存10000条数据记录 Stu_CW::Stu_CW(){ } Stu_CW::~Stu_CW(){ } void Stu_CW::Print(){ printf("\n==========================\n"); printf("学号\t姓名\t成绩\n");//其中\t挺好用的 int i = 0, num = 0; while (g_user[i].m_Num){//0.1f只取一位 if (g_user[i].m_Num > 0){//将-1屏蔽 不打印 =0 停止退出循环 printf("%d\t%s\t%0.1f\n", g_user[i].m_Num, &g_user[i].m_Name, g_user[i].m_Math); //这里注意,数组加引用就有问题了,数组第一个代表的是指针 //所以此处用g_user[i].m_Math 而不能用&g_user[i].m_Math ++num; } ++i;//这里很重要,必须是先+后赋值 } printf("当前共用: %d 条记录\n", num); printf("==========================\n\n"); } void Stu_CW::Save(){ FILE *p; int i = 0; p = fopen("学生管理系统.txt", "w"); if (!p){ puts("\n文件不存在/未保存文件!\n"); return; } while (g_user[i].m_Num){//不为0时才存储,否则全部存储就浪费 if (-1 != g_user[i].m_Num){ //删除时候g_user[i].m_Num=-1 去掉这种情况 fwrite(&g_user[i], 1, sizeof(g_user[i]), p);//将什么,以什么样的方式写入哪里的文件 //每次写一块,总共写多少块 /*fprintf(p, "%d %s %f", &g_user[i]);*/ } ++i; } fclose(p); } void Stu_CW::Load(){ FILE *pf = fopen("学生管理系统.txt", "r"); int i = 0, choose_key = 0; if (!pf){ puts("文档中未保存数据,请重新录入"); printf("\n 请选择:(1)继续 (2)退出"); scanf_s("%d", &choose_key); switch (choose_key){ case 1: return; case 2: return; } } //SUser us;//定义一个结构体大小的结构体对象 创建临时结构体 传送到g_user /*int n = fread(&g_user, 1, sizeof(us), pf);//读入方法一 while (n){ ++i; n = fread(&g_user[i], 1, sizeof(us), pf); }*/ //while (fread(&us, 1, sizeof(us), pf))//读入方法二 // g_user[i++] = us;//每次读入的数据放到g_user while (fread(&g_user[i++], 1, sizeof(SUser), pf) > 0);//读入方法三 fclose(pf); printf("\n"); //Print(); } void Stu_CW::Add(){//增 //一共可以录入[10000]条数据,即为截止条件 int i = 0;//结构体中学号录入指针+1 int j = 0;//保持i的不动,即将g_user[i].m_Num作为被比较对象 int com_Num;//定义一个临时变量来检查是否有已存在的学号,输入时,将学号数据赋给该变量, //然后再给g_user[i].m_Num,同所有g_user[i].m_Num中i之前数据比较 while (g_user[i].m_Num)//{//此处不能使g_user非零;应该是结构体中的某一个数据非零 //想想g_user结构体中的名字怎么可能=0? i++;//先取值用,后++ 从0开始赋值 printf("请输入学号: "); scanf_s("%d", &com_Num);//scanf_s("%s"不能添加其他的\n之类的 否则不现实 g_user[i].m_Num = com_Num; j = i; while (g_user[i].m_Num){//学号非空来检查是否重定义 --j; if (g_user[j].m_Num == com_Num){ printf("学号已存在,请重新是输入\n"); printf("请输入学号: "); scanf_s("%d", &com_Num); j = i;//输入的数据还需要在检查一次 } if (j < 0){ break; } } printf("请输入姓名: "); scanf_s("%s", g_user[i].m_Name, sizeof(g_user[i].m_Name)); //scanf_s("%s", g_user[i].m_Name) 直接这样,无法输入/崩溃 printf("请录入数学成绩: "); scanf_s("%f", &g_user[i].m_Math); Save(); Print(); } void Stu_CW::Delete(){//删 printf("\n请输入需要删除的学号序列号: "); int i = 0; int s_num = 0;//需要中间变量存储输入值,将和g_user[i].m_Num int flag = 0;//设置标志位 作为判断是否找到被删除的序号 scanf_s("%d", &s_num); while (g_user[i].m_Num){ if (g_user[i].m_Num == s_num){ g_user[i].m_Num = -1;//为什么不填0呢?填0代表结束了,后续的数据无法使用。 //-1只是代表不打,但不会结束跳出循环;0会结束,跳出循环 flag = 1; break; } ++i;//往下找的同时,将s_num同g_user[i].m_Num对比; } if (flag == 0){//如果没找到需要删除的学号的序号 puts("\n\n 并未找到您所需要删除的学号 \n\n"); return; } else{//找到了 Save(); Print(); } } void Stu_CW::Modify(){//改 int i = 0, s_num = 0, modify_i = 0; printf("\n请输入您需要修改的记录的学号: "); scanf_s("%d", &s_num); while (g_user[i].m_Num){//内容非空的情况下,进行学号数据的对比 if (g_user[i].m_Num == s_num){ printf("\n\n (1)选择修改学号\n\n\n (2)选择修改姓名\n\n\n (3)选择修改成绩\n\n"); printf("\n请选择需要修改的内容的选项: "); scanf_s("%d", &modify_i); do{ switch (modify_i){ case 1: printf("请重新修改学号: "); scanf_s("%d", &g_user[i].m_Num); break; case 2: printf("请重新修改姓名: "); scanf_s("%s", g_user[i].m_Name, sizeof(g_user[i].m_Name)); break; case 3: printf("请重新修改成绩: "); scanf_s("%f", &g_user[i].m_Math); break; } modify_i = 0; } while (modify_i); break; } ++i;//先增后赋值 } if (!g_user[i].m_Num){//!g_user[i].m_Num即g_user[i].m_Num==0,即搜索到最后没有相同的内容 puts("\n未找到您需要修改记录的序号!"); return; } Save(); Print(); } void Stu_CW::Find(){//查 int i = 0, s_num = 0; printf("\n请输入需要查找的学号信息: "); scanf_s("%d", &s_num); while (g_user[i].m_Num){ if (g_user[i].m_Num == s_num){ printf("\n学号\t姓名\t成绩\n"); printf("%d\t%s\t%0.1f\n", g_user[i].m_Num, g_user[i].m_Name, g_user[i].m_Math); system("pause"); break; } ++i; } if (!g_user[i].m_Num){ puts("\n不存在您查找的内容\n"); return; } } int Stu_CW::Sort_Judge(int choose_sort_m, int nMin, int j){ if (choose_sort_m == 1) return g_user[nMin].m_Num > g_user[j].m_Num; if (choose_sort_m == 2) return strcmp(g_user[nMin].m_Name, g_user[j].m_Name) > 0; if (choose_sort_m == 3) return g_user[nMin].m_Math < g_user[j].m_Math; return 0; } void Stu_CW::Gather_Sort(int m){ int i = 0, n = 0, nMin = 0; while (g_user[n].m_Num)//循环的特点--[2][1][],即是否有学号存在,即g_user[n].m_Num是否未 ++n;//一直循环,最后获得n极为总数 /*选择排序算法实现部分*/ while (i < n - 1){ nMin = i; int j = i + 1; while (j < n){ if (Sort_Judge(m, nMin, j)){ SUser sortNum = g_user[nMin]; g_user[nMin] = g_user[j]; g_user[j] = sortNum; } ++j; } ++i; } /*冒泡排序算法实现部分*/ /*for (i = 0; i < n - 1; i++){//冒泡法既然是前者VS后者,需用两层循环,此为外循环 for (j = 0; j < n - (i + 1); j++){//j总小于i一个数 拿第一个数同后面每一个数进行比较(内循环);然后拿第二个数(外循环)同。。。 if (Sort_Judge(m, j)){//选择模式 语句更加简短 SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 g_user[j] = g_user[j + 1]; g_user[j + 1] = sortNum; } //switch (m){// 排序汇总函数选择方法一 //case 1: // if (g_user[j].m_Num>g_user[j + 1].m_Num){//前后对比 内循环数据来比较就行 // SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 // g_user[j] = g_user[j + 1]; // g_user[j + 1] = sortNum; // } // break; //case 2: // if (strcmp(g_user[j].m_Name,g_user[j + 1].m_Name)>0){//前后对比 内循环数据来比较就行 // SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 // g_user[j] = g_user[j + 1]; // g_user[j + 1] = sortNum; // } // break; //case 3: // if (g_user[j].m_Math<g_user[j + 1].m_Math){//前后对比 内循环数据来比较就行 成绩高,排名越靠前 // SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 // g_user[j] = g_user[j + 1]; // g_user[j + 1] = sortNum; // } // break; //} } }*/ } //void SortByNum(){ // //冒泡法,基本数据排序算法 // //特点 前面数据同后面数据对比,如果不合适将数据依次对调 // //前提 先获得存在多少实际数据//如果结构体g_user[10000]全用太浪费 // int i = 0, n = 0,j=0; // while (g_user[n].m_Num)//循环的特点--[2][1][],即是否有学号存在,即g_user[n].m_Num是否未 // ++n;//一直循环,最后获得n极为总数 // for (i=0; i < n - 1; i++){//冒泡法既然是前者VS后者,需用两层循环,此为外循环 // for (j=0; j < n - (i + 1); j++){//j总小于i一个数 拿第一个数同后面每一个数进行比较(内循环);然后拿第二个数(外循环)同。。。 // if (g_user[j].m_Num>g_user[j+1].m_Num){//前后对比 内循环数据来比较就行 // SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 // g_user[j] = g_user[j + 1]; // g_user[j + 1] = sortNum; // } // } // } // //} //void SortByName(){ // //直接调用SortByName代码 只需要修改一句,即对比那个地方 // int i = 0, n = 0, j = 0; // while (g_user[n].m_Num)//循环的特点--[2][1][],即是否有学号存在,即g_user[n].m_Num是否未 // ++n;//一直循环,最后获得n极为总数 // for (i = 0; i < n - 1; i++){//冒泡法既然是前者VS后者,需用两层循环,此为外循环 // for (j = 0; j < n - (i + 1); j++){//j总小于i一个数 拿第一个数同后面每一个数进行比较(内循环);然后拿第二个数(外循环)同。。。 // if (strcmp(g_user[j].m_Name,g_user[j + 1].m_Name)>0){//前后对比 内循环数据来比较就行 // SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 // g_user[j] = g_user[j + 1]; // g_user[j + 1] = sortNum; // } // } // } // /*注*///strcmp 两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。如: // //"A"<"B" "a">"A" "computer">"compare" //} //void SortByMath(){ // //直接调用SortByName代码 只需要修改一句,即对比那个地方 // int i = 0, n = 0, j = 0; // while (g_user[n].m_Num)//循环的特点--[2][1][],即是否有学号存在,即g_user[n].m_Num是否未 // ++n;//一直循环,最后获得n极为总数 // for (i = 0; i < n - 1; i++){//冒泡法既然是前者VS后者,需用两层循环,此为外循环 // for (j = 0; j < n - (i + 1); j++){//j总小于i一个数 拿第一个数同后面每一个数进行比较(内循环);然后拿第二个数(外循环)同。。。 // if (g_user[j].m_Math>g_user[j + 1].m_Math){//前后对比 内循环数据来比较就行 // SUser sortNum = g_user[j];//每次到循环申请一个结构体作为中间传递变量 g_user[i]数据全部传递 // g_user[j] = g_user[j + 1]; // g_user[j + 1] = sortNum; // } // } // } //} int Stu_CW::DisplayMenu(){ Print(); printf("\n==========================\n"); puts("1】按学号排序");//puts专门输出字符 puts("2】按名字排序"); puts("3】按成绩排序"); puts("0】返回主菜单"); printf("==========================\n\n"); printf("请输入选项: "); int i = 0; scanf_s("%d", &i); switch (i){//按0已经考虑到直接返回主菜单,防止堆栈压满情况; case 0 case 1: //SortByNum();//排序选择方法一 Gather_Sort(i);//排序选择方法2 ---汇总的方法 break; case 2: //SortByName(); Gather_Sort(i); break; case 3: //SortByMath(); Gather_Sort(i); break; } return i; } int Stu_CW::Color_Set(){ char bg[3]; char fg[3]; char yanse[9] = "color "; /*system("color .."); system("cls");*/ puts("0 = 黑色 1 = 蓝色 2 = 绿色 3 = 湖蓝色 4 = 红色 5 = 紫色 6 = 黄色 7 = 白色 "); puts("8 = 灰色 9 = 淡蓝色 A = 淡绿色 B = 淡浅绿色 C = 淡红色 D = 淡紫色 E = 淡黄色 F = 亮白色"); printf("\n请按照您的喜好和心情b( ̄▽ ̄)d选择背景颜色: "); //=================================================== scanf_s("%s", bg, 2);//大小控制为1,读取到为空,插入,显示为0 //scanf("%s", bg); 也行 puts("0 = 黑色 1 = 蓝色 2 = 绿色 3 = 湖蓝色 4 = 红色 5 = 紫色 6 = 黄色 7 = 白色 "); puts("8 = 灰色 9 = 淡蓝色 A = 淡绿色 B = 淡浅绿色 C = 淡红色 D = 淡紫色 E = 淡黄色 F = 亮白色"); printf("\n请按照您的喜好和心情b( ̄▽ ̄)d选择前景颜色: "); scanf_s("%s", fg, 2); //scanf("%s", fg); /*printf("color 1A"); printf("\n%s", strcat(strcat(yanse, bg), fg));*/ system(strcat(strcat(yanse, bg), fg));// return 0; } int Stu_CW::Menu(){//菜单 puts("1】浏览所有信息");//puts专门输出字符 puts("2】添加信息"); puts("3】删除信息"); puts("4】修改信息"); puts("5】查找信息"); puts("6】颜色设置"); puts("0】退出"); printf("请选择: "); int i = 0; scanf_s("%d", &i); switch (i){ case 1: DisplayMenu(); Print(); break; case 2: Add(); break; case 3: Delete(); break; case 4: Modify(); break; case 5: Find(); break; case 6: Color_Set(); break; } return i; } void Stu_CW::String_Pr(){ printf("\n\t\t-----------------------------------\n"); printf("\t\t***********************************\n"); printf("\n\t\t *** 欢迎使用学生管理系统 ***\n"); printf("\n\t\t *** 香草←作家 ***\n"); printf("\n\t\t *** 2017/8/5 3:00 ***\n"); printf("\t\t***********************************"); printf("\n\t\t-----------------------------------"); } void Stu_CW::Start(){//初始加载 Load(); while (Menu()){//无限循环 }; } // 纯属学习类的添加 类的成员函数添加 int Stu_CW::Learning_Code(int para, char * point, double Math) { return 0; } // 输出显示界面 void Stu_CW::Welcome_String() { cout << " \t\t\t┏┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┓" <<endl; cout << " \t\t\t┃ ********************************************** ┃" << endl; cout << " \t\t\t┃***┏┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┓***┃" << endl; cout << " \t\t\t┃***┃****************************************┃***┃" << endl; cout << " \t\t\t┃***┃*** ***┃***┃" << endl; cout << " \t\t\t┃***┃*** 欢迎使用学生管理系统 ***┃***┃" << endl; cout << " \t\t\t┃***┃*** ***┃***┃" << endl; cout << " \t\t\t┃***┃*** ***┃***┃" << endl; cout << " \t\t\t┃***┃*** (~ ̄▽ ̄)~轻心御风 ***┃***┃" << endl; cout << " \t\t\t┃***┃*** ***┃***┃" << endl; cout << " \t\t\t┃***┃*** 2017.08.06|3:00pm ***┃***┃" << endl; cout << " \t\t\t┃***┃*** ***┃***┃" << endl; cout << " \t\t\t┃***┗┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┛***┃" << endl; cout << " \t\t\t┃ ********************************************** ┃" << endl; cout << " \t\t\t┗┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┛" << endl; }

浙公网安备 33010602011771号