C++中FILE实操作---用C来实现【2】

C++中FILE实现操作---用C来实现

 

/*C来实现学生管理系统*/
/***********************************************************/
//该系统实现了那些操作
//1、菜单、增、删、改、查、打印、保存、载入
//2、检查是否已经存在的学号
//3、实现二级菜单 选择性修改等操作
//学到的知识点:
//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)追加,原来基础上写入
//?????????????????????????????//
//未解决问题:
//1、写入到txt文件中的数据有乱码
//2、项目多少有点不稳定,好像在选择修改地方
/***********************************************************/

  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<stdlib.h>
  5 int i = 0;
  6 struct SUser{//结构体 每个接头体保存三个数据 
  7 int m_Num; //学号数据
  8 char m_Name[20]; //姓名数据
  9 float m_Math; //成绩数据
 10 
 11 };
 12 SUser g_user[10000] ;//可以实现保存10000条数据记录
 13 void Print(){
 14 printf("\n==========================\n");
 15 printf("学号\t姓名\t成绩\n");//其中\t挺好用的
 16 int i = 0,num=0;
 17 while (g_user[i].m_Num){//0.1f只取一位
 18 if (g_user[i].m_Num > 0){//将-1屏蔽 不打印 =0 停止退出循环
 19 printf("%d\t%s\t%0.1f\n", g_user[i].m_Num, &g_user[i].m_Name, g_user[i].m_Math);
 20 //这里注意,数组加引用就有问题了,数组第一个代表的是指针
 21 //所以此处用g_user[i].m_Math 而不能用&g_user[i].m_Math
 22 ++num;
 23 }
 24 ++i;//这里很重要,必须是先+后赋值
 25 
 26 }
 27 printf("当前共用: %d 条记录\n", num);
 28 printf("==========================\n\n");
 29 }
 30 void Save(){
 31 FILE *p; int i = 0;
 32 p = fopen("学生管理系统.txt", "w");
 33 if (!p){
 34 puts("\n文件不存在/未保存文件!\n");
 35 return;
 36 }
 37 
 38 while (g_user[i].m_Num){//不为0时才存储,否则全部存储就浪费
 39 if (-1 != g_user[i].m_Num){    //删除时候g_user[i].m_Num=-1 去掉这种情况
 40 fwrite(&g_user[i], 1, sizeof(g_user[i]), p);//将什么,以什么样的方式写入哪里的文件
 41 //每次写一块,总共写多少块
 42 /*fprintf(p, "%d %s %f", &g_user[i]);*/
 43 }
 44 ++i;
 45 }
 46 fclose(p);
 47 }
 48 void Load(){
 49 FILE *pf = fopen("学生管理系统.txt", "r");
 50 int i = 0,choose_key=0;
 51 if (!pf){
 52 puts("文档中未保存数据,请重新录入");
 53 printf("\n 请选择:(1)继续 (2)退出");
 54 scanf_s("%d", &choose_key);
 55 switch (choose_key){
 56 case 1:
 57 return;
 58 case 2:
 59 return;
 60 }
 61 }
 62 
 63 //SUser us;//定义一个结构体大小的结构体对象 创建临时结构体 传送到g_user
 64 /*int n = fread(&g_user, 1, sizeof(us), pf);//读入方法一
 65 while (n){
 66 ++i;
 67 n = fread(&g_user[i], 1, sizeof(us), pf);
 68 }*/
 69 //while (fread(&us, 1, sizeof(us), pf))//读入方法二
 70 //    g_user[i++] = us;//每次读入的数据放到g_user
 71 while (fread(&g_user[i++], 1, sizeof(SUser), pf) > 0);//读入方法三
 72 fclose(pf);
 73 Print();
 74 }
 75 void Add(){// 76 //一共可以录入[10000]条数据,即为截止条件
 77 int i = 0;//结构体中学号录入指针+1
 78 int j = 0;//保持i的不动,即将g_user[i].m_Num作为被比较对象    
 79 int com_Num;//定义一个临时变量来检查是否有已存在的学号,输入时,将学号数据赋给该变量,
 80 //然后再给g_user[i].m_Num,同所有g_user[i].m_Num中i之前数据比较
 81 while (g_user[i].m_Num)//{//此处不能使g_user非零;应该是结构体中的某一个数据非零
 82 //想想g_user结构体中的名字怎么可能=0?
 83 i++;//先取值用,后++ 从0开始赋值
 84 printf("请输入学号: ");
 85 scanf_s("%d", &com_Num);//scanf_s("%s"不能添加其他的\n之类的 否则不现实
 86 g_user[i].m_Num = com_Num;
 87 j = i;
 88 while (g_user[i].m_Num){//学号非空来检查是否重定义
 89 --j;
 90 if (g_user[j].m_Num == com_Num){
 91 printf("学号已存在,请重新是输入\n");
 92 printf("请输入学号: ");
 93 scanf_s("%d", &com_Num);
 94 j = i;//输入的数据还需要在检查一次
 95 }
 96 if (j < 0){ break; }    
 97 }    
 98 printf("请输入姓名: ");
 99 scanf_s("%s", g_user[i].m_Name,sizeof(g_user[i].m_Name));
100 //scanf_s("%s", g_user[i].m_Name) 直接这样,无法输入/崩溃
101 printf("请录入数学成绩: ");
102 scanf_s("%f", &g_user[i].m_Math);
103 Save();
104 Print();    
105 }
106 void Delete(){//
107 
108 printf("\n请输入需要删除的学号序列号: ");
109 int i = 0;
110 int s_num = 0;//需要中间变量存储输入值,将和g_user[i].m_Num
111 int flag = 0;//设置标志位 作为判断是否找到被删除的序号
112 scanf_s("%d", &s_num);
113 while (g_user[i].m_Num){
114 if (g_user[i].m_Num == s_num){
115 g_user[i].m_Num = -1;//为什么不填0呢?填0代表结束了,后续的数据无法使用。
116 //-1只是代表不打,但不会结束跳出循环;0会结束,跳出循环
117 flag = 1;
118 break;
119 }
120 ++i;//往下找的同时,将s_num同g_user[i].m_Num对比;
121 }
122 if (flag == 0){//如果没找到需要删除的学号的序号
123 puts("\n\n 并未找到您所需要删除的学号 \n\n");
124 return;
125 }
126 else{//找到了
127 Save();
128 Print();
129 }
130 }
131 void Modify(){//
132 int i = 0,s_num=0,modify_i=0;
133 printf("\n请输入您需要修改的记录的学号: ");
134 scanf_s("%d", &s_num);
135 while (g_user[i].m_Num){//内容非空的情况下,进行学号数据的对比
136 if (g_user[i].m_Num == s_num){
137 printf("\n\n (1)选择修改学号\n\n\n (2)选择修改姓名\n\n\n (3)选择修改成绩\n\n");
138 printf("\n请选择需要修改的内容的选项: ");
139 scanf_s("%d", &modify_i);
140 do{
141 switch (modify_i){
142 case 1:
143 printf("请重新修改学号: ");
144 scanf_s("%d", &g_user[i].m_Num);
145 break;
146 case 2:
147 printf("请重新修改姓名: ");
148 scanf_s("%s", g_user[i].m_Name, sizeof(g_user[i].m_Name));
149 break;
150 case 3:
151 printf("请重新修改成绩: ");
152 scanf_s("%f", &g_user[i].m_Math);
153 break;
154 }
155 printf("\n请问您还需要修改吗?继续,请上述序号;停止,选择按键0回车\n");
156 printf("\n请选择: ");
157 scanf_s("%d", &modify_i);
158 } while (modify_i);    
159 break;
160 }
161 ++i;//先增后赋值
162 }
163 if (!g_user[i].m_Num){//!g_user[i].m_Num即g_user[i].m_Num==0,即搜索到最后没有相同的内容
164 puts("\n未找到您需要修改记录的序号!");
165 return;
166 }
167 Save();
168 Print();
169 }
170 void Find(){//
171 int i = 0, s_num = 0;
172 printf("\n请输入需要查找的学号信息: ");
173 scanf_s("%d", &s_num);
174 while (g_user[i].m_Num){
175 if (g_user[i].m_Num == s_num){
176 printf("\n学号\t姓名\t成绩\n");
177 printf("%d\t%s\t%0.1f\n", g_user[i].m_Num,g_user[i].m_Name,g_user[i].m_Math);
178 system("pause");
179 break;
180 }
181 ++i;
182 }
183 if (!g_user[i].m_Num){
184 puts("\n不存在您查找的内容\n");
185 return;
186 }
187 }
188 int Menu(){//菜单
189 puts("1】浏览所有信息");//puts专门输出字符
190 puts("2】添加信息");
191 puts("3】删除信息");
192 puts("4】修改信息");
193 puts("5】查找信息");
194 puts("0】退出");
195 printf("请选择: ");
196 int i = 0;
197 scanf_s("%d", &i);
198 switch (i){
199 case 1:
200 Print();
201 break;
202 case 2:
203 Add();
204 break;
205 case 3:
206 Delete();
207 break;
208 case 4:
209 Modify();
210 case 5:
211 Find();
212 }
213 return i;
214 }
215 
216 int main(){
217 Load();
218 while (Menu()){//无限循环
219 
220 };
221 return 0;
222 }
View Code

         实现编程,呈现控制台界面Load 已保存数据

                              

    内存中查看Save的数据,更加直观

    

    说明】:1、上面两幅图的意思是一致对应的

                   2、上图是控制台画面,下面是保存数据的十六进制内存形式

                   3、红色方框下数据代表:学号;绿色横线共20个字节大小代表:姓名;黑色横线共4个字节数据代表:成绩;

                         最左侧手画粉红色:内存以16个字节递增

           4、后期可以通过反编译,即更改内存中十六进制数据来实现控制台输出数据的变更。

posted @ 2017-08-04 14:40  心沉大海-汇聚成一  阅读(259)  评论(0)    收藏  举报