C++学习(四十)(C语言部分)之 学生管理系统设计
涉及到的:
指针申请内存 结构体
数据结构部分
排序
文件操作
vs2013
数据结构 排序 结构体 指针
功能:
1、人工录入信息
2、删除
3、查找
4、修改
5、全部显示
6、文件的读取和保存
7、排序
设计:
学生信息 学号 名字 年龄 成绩(结构体)
1、数据 用数组存放学生信息 顺序表(数组+size+len实现) 链表(结构体指针实现)
2、增删查改
3、菜单 +提示 +界面
注册 -->注册的用户 密码 存到文件
登录 输入用户名和密码 到文件中找有没有匹配的记录
首先在项目编写过程中,将需要的功能,函数等思路罗列清楚。
大致分为以下四个板块
//******头文件 宏定义 类型定义 全局变量********
//******************函数声明*************************
//*****************主函数****************************
//******************函数定义************************
第一步,对学生信息的录入工作
先将学生属性用结构体存放
将所用到的函数首先在函数声明部分进行声明,之后再函数定义部分对所用到的函数进行定义,并在需要的时候进行调用。
最先做好的部分就是菜单和信息录入
测试结果如下所示:
发现输出有一点问题,之后再做修改。
具体测试代码笔记如下:
1 //****************头文件 宏定义 类型定义 全局变量******************** 2 #include<stdio.h> 3 #include<windows.h> 4 #include<stdlib.h> 5 #include<string.h> 6 #include<winbase.h> 7 8 //学生基本信息 9 typedef struct student 10 { 11 char stunum[12];//学号 12 char name[20];//名字 13 int age;//年龄 14 float grade;//成绩 15 //后续可以继续加 16 17 struct student*next;//如果用数组存 那么不需要指针域 链表存 需要指针域 18 }stu,*pstu; 19 //****************函数声明******************** 20 void menu();//菜单 21 void insertstu(pstu head);//录入 22 void findmenu(pstu head);//查询用菜单 23 void findbyage(pstu head);//根据年龄查找信息 24 //void changestu();//修改 25 void printall(pstu head);//全部打印 26 //---------------------------------主函数 27 void delestubynum(pstu head);//通过学号删除学员信息 28 29 void sortbygrade(pstu head);//按照分数排序 30 31 void swap(pstu a, pstu b); //交换两个节点 32 33 void insertfile(pstu head);//从文件中读取内容 34 35 void setfile(pstu head);//存档 36 37 void freenode(pstu head);//释放所有节点 38 39 void delestubygrade(pstu head);//通过成绩删除 40 41 //******************主函数******************** 42 int main() 43 { 44 45 menu(); 46 return 0; 47 } 48 49 //****************函数定义******************** 50 //菜单 51 void menu() 52 { 53 //链表 54 pstu head=(pstu)malloc(sizeof(stu));//定义头指针 55 head->next = null;//头结点的next赋值null 56 //录入文件 打开文件并且读取文件内容 (没写完 待补充 )*************** 57 insertfile(head);//读取文件内容 58 while (1)//循环一直进行 59 { 60 system("cls");//清屏函数 用于控制台的 61 printf("**************************\n"); 62 printf("****欢迎进入学生管理系统****\n"); 63 printf("1.录入学生信息\n"); 64 printf("2.查询学生信息\n"); 65 printf("3.修改学生信息\n"); 66 printf("4.删除学生信息\n"); 67 printf("5.打印所有学生信息\n"); 68 printf("6.排序\n"); 69 printf("0.退出\n"); 70 printf("输入你的选择\n\n"); 71 int choice = -1; 72 scanf("%d", &choice);//获取用户用户的操作 73 switch (choice) 74 { 75 case 1://录入 76 insertstu(head);//传递实参 77 break; 78 case 2://查询 79 findmenu(head);//查询 80 break; 81 case 3://修改 先查询 找到位置之后 再修改 82 //不写 83 break; 84 case 4://删除 //示例用学号删除学生信息 85 delestubynum(head); 86 break; 87 case 5://全部打印 88 printall(head); 89 break; 90 case 6: 91 //链表的排序 92 //默认用学号排序 换成用分数排序 93 sortbygrade(head); 94 break; 95 case 0://退出程序 96 /* 97 跳转语句 goto 98 return //跳出这个循环 99 break//跳出循环 跳出swicth 100 continue//跳过本轮循环 进入下一轮循环 101 exit(0);//函数 表示退出这个程序 stdlib.h 102 */ 103 //--------------------=========//跳出循环 104 setfile(head);//退出前存档 105 //存挡 当前所有内容 写入文件(待补充,,,,,,,,,,,> 106 //释放所有节点内存(待补充--------------------> 107 freenode(head);//释放这个链表所有结点 108 return;//跳出这个函数 109 break; 110 default: 111 //输入错误 112 //重新输入 113 printf("输入错误 请重新输入\n"); 114 sleep(2000);//休息两秒 windows.h 115 //.... 116 break; 117 } 118 } 119 } 120 121 //录入 122 void insertstu(pstu head) 123 { 124 pstu p = (pstu)malloc(sizeof(stu)); 125 printf("输入学生信息"); 126 printf("输入学号"); scanf("%s", p->stunum);//录入 127 printf("输入姓名"); scanf("%s", p->name); 128 printf("输入年龄"); scanf("%d", &p->age); 129 printf("输入成绩"); scanf("%f", &p->grade); 130 //输入完成之后 连接 131 //p->next = head->next; 132 //head->next = p;//头插 133 134 ///插入的时候同时进行排序 135 pstu temp = head; 136 //插入到合适的位置 137 while (temp->next != null) 138 { 139 if (strcmp(temp->next->stunum, p->stunum)>0)//找到第一个比他大的元素 140 { 141 break; 142 } 143 temp = temp->next; 144 } 145 //如果temp->next==null 插入放在里面的话这个节点不会被插入到链表中 因此放在外面 146 p->next = temp->next; 147 temp->next = p;//插入 148 sleep(1000);//看一下效果 149 } 150 151 //全部打印 152 void printall(pstu head) 153 { 154 pstu p = head->next; 155 while (p != null) 156 { 157 printf("学号%10s\t名字%10s\t年龄%5d\t分数%.2f\n", p->stunum, p->name, p->age, p->grade); 158 p = p->next; 159 } 160 //printf("学号\t\t名字\t\t年龄\t\t分数\n");//这个需要另外对齐 161 //while (p != null) 162 //{ 163 // printf("%s\t%s\t%d\t%.2f\n", p->stunum, p->name, p->age, p->grade); 164 // p = p->next; 165 //} 166 sleep(2000);//休息一会 167 } 168 169 //查询用菜单 170 void findmenu(pstu head) 171 { 172 system("cls"); 173 printf("请输入你要查询的方式"); 174 printf("1.按照年龄查询"); 175 176 int choice; 177 scanf("%d", &choice); 178 switch (choice) 179 { 180 case 1://根据年龄查询 181 //通过年龄区间 得到信息 可以写函数 也可以直接写 182 break; 183 } 184 } 185 186 //根据年龄查找信息 187 void findbyage(pstu head) 188 { 189 //1.根据年龄查询 190 //2.根据区间查询 191 printf("请输入一个年龄区间"); 192 int x, y;//年龄 193 scanf("%d %d", &x, &y); 194 if (x >= y) 195 { 196 for (pstu temp = head->next; temp != null; temp = temp->next) 197 { 198 if (temp->age >= y&&temp->age <= x) 199 { 200 printf("学号%10s\t名字%10s\t年龄%5d\t分数%.2f\n", temp->stunum, temp->name, temp->age, temp->grade); 201 } 202 } 203 } 204 else//x<=y 205 { 206 //自己补齐 207 } 208 sleep(2000); 209 } 210 211 //通过学号删除学员信息 212 void delestubynum(pstu head) 213 { 214 pstu p = head; 215 char stunum[20]; 216 printf("输入你要删除的学员的学号"); 217 scanf("%s", stunum); 218 //删除一个节点 要删除位置前面的结点 219 220 //for (; p->next != null; p = p->next) 221 //{ 222 // if (strmp(p->next->stunum, stunum) == 0) 223 // { 224 // break; 225 // } 226 //} 227 //if (p->next!=null) 228 //{ 229 // pstu q = p->next; 230 // p->next = q->next; 231 // free(q);//释放结点 232 // //如果多个学号相同的同学 233 // printf("删除成功"); 234 //} 235 //else 236 //{ 237 // printf("找不到对应的记录 删除失败\n"); 238 //} 239 240 for (; p->next != null; ) 241 { 242 if (strcmp(p->next->stunum, stunum) == 0) 243 { 244 pstu q = p->next; 245 p->next = q->next; 246 free(q);//释放结点 247 //如果多个学号相同的同学 248 //printf("删除成功"); 249 } 250 else 251 { 252 p = p->next;//这句不直接放在外面的原因 避免少比较一个元素 253 //比如说 a->b->c->d 254 //p 刚刚开始指向a 删除b之后 a->c->d 255 //p往后移动 c就没有参与比较 所以为了避免这种情况 p=p->next放在else中 256 } 257 } 258 sleep(2000); 259 } 260 261 //按照分数排序 262 void sortbygrade(pstu head) 263 { 264 //冒泡 插入 选择 快速 265 // 冒泡 从头到尾 如果相邻元素位置有问题 交换 266 //插入 将后面的一个结点插入到前面的有序位置中 267 //选择 交换两个节点 每次找剩下那个最小的进行交换 268 //快速 一分为2 分开进行快速排序 269 270 //快速 冒泡 选择 交换 271 //做法 :找到两个位置 进行交换 272 273 //链表的循环条件稍微改一下 274 //选择排序 275 pstu p = head->next;//第一个节点 276 pstu q, min; 277 while (p != null) 278 { 279 min = p;//刚刚开始指向p的位置 280 q = p->next;//从p的后面开始找 281 while (q != null) 282 { 283 //if (strcmp(q->stunum, min->stunum) < 0) 284 if (q->grade<min->grade) 285 { 286 min = q;//标记最小 287 } 288 q = q->next; 289 } 290 if (min == null||min == p);//不需要交换 291 else swap(p, min);//交换两个节点的数据 292 p = p->next; 293 } 294 295 296 } 297 298 //交换两个节点 写一个函数 299 void swap(pstu a, pstu b) 300 { 301 char stunum[12];//学号 302 char name[20];//名字 303 int age;//年龄 304 float grade;//成绩 305 strcpy(stunum, a->stunum); 306 strcpy(a->stunum, b->stunum); 307 strcpy(b->stunum, stunum); 308 strcpy(name, a->name); 309 strcpy(a->name, b->name); 310 strcpy(b->name, name); 311 age = a->age; 312 a->age = b->age; 313 b->age = age; 314 grade = a->grade; 315 a->grade = b->grade; 316 b->grade = grade; 317 } 318 319 //文件操作 -->数据存放文件中(保留数据) 320 //读档 321 void insertfile(pstu head)//从文件中读取内容 322 { 323 file *fp = fopen("student.txt", "r");//rwa 三选一 324 //r 文件不存在 打开失败 325 //w 文件不存在 创建文件 但是文件存在 清空文件内容 326 if (fp == null) 327 { 328 fp = fopen("student.txt", "w");//创建新文件 329 fclose(fp); 330 return; 331 } 332 //学号 名字 年龄 成绩 333 stu temp, *p; 334 while (1)//循环读取 335 { 336 fscanf(fp, "%s %s %d %f", temp.stunum, temp.name, &temp.age, &temp.grade);//读取内容 337 if (feof(fp)) break;//如果文件读到末尾 返回1 338 //feof 文件中有三个数据 当读完第三个数据的时候不会返回1 339 //读到第四个的时候有问题 340 341 p = (pstu)malloc(sizeof(stu)); 342 *p = temp;//赋值 343 //将这个节点 连到链表上 344 pstu q = head; 345 //插入到合适的位置 346 while (q->next != null) 347 { 348 if (strcmp(q->next->stunum, p->stunum)>0)//找到第一个比他大的元素 349 { 350 break; 351 } 352 q = q->next; 353 } 354 //如果temp->next==null 插入放在里面的话这个节点不会被插入到链表中 因此放在外面 355 p->next = q->next; 356 q->next = p;//插入 357 358 } 359 fclose(fp);//关闭文件 360 361 } 362 363 //存档 364 void setfile(pstu head) 365 { 366 //写入 w a 367 file *fp = fopen("student.txt", "w");//清空原内容 368 pstu p = head->next; 369 while (p != null) 370 { 371 fprintf(fp,"%s %s %d %.2f\n", p->stunum, p->name, p->age, p->grade);//写入文件 372 p = p->next; 373 } 374 fclose(fp); 375 } 376 377 void freenode(pstu head)//释放所有节点 378 { 379 pstu temp = head; 380 while (head != null) 381 { 382 temp = head; 383 head = head->next; 384 free(temp);//释放节点 385 } 386 } 387 388 //通过成绩删除 389 void delestubygrade(pstu head) 390 { 391 pstu arr[10]; 392 int len = 0; 393 int size = 10; 394 //准备数组 395 float grade; 396 printf("输入的你要删除的学生的成绩"); 397 scanf("%f", &grade); //取地址 398 pstu p = head->next; 399 while (p != null) 400 { 401 if (p->grade < grade + 3 && p->grade>grade - 3)// 浮点型 存的都是近似值 给一个区间 402 { 403 if (len < size) arr[len++] = p;//存放符合要求一个结点的位置 404 } 405 } 406 //找到所有符合要求的节点 407 for (int i = 0; i < len; ++i) 408 { 409 printf("编号%d--->学号%s,姓名%s,年龄%d,成绩%.2f",i, arr[i]->stunum, arr[i]->name, arr[i]->age, arr[i]->grade); 410 } 411 printf("输入你要删除的元素的编号"); 412 int choice; 413 scanf("%d", &choice); 414 if (choice >= 0 && choice < len)//说明有删除的元素 415 { 416 //找到结点并且删除就可以了 417 //arr[choice];//结点的地址 418 //找前面那个结点 然后删除 419 pstu temp = head; 420 while (temp!=null) 421 { 422 //找要删除的前面那个结点的位置 423 if (temp->next == arr[choice]) 424 { 425 temp->next = arr[choice]->next; 426 free(arr[choice]); 427 break; 428 } 429 temp = temp->next; 430 } 431 } 432 } 433 /* 434 //指针申请内存 结构体 435 //数据结构部分 436 //排序 437 438 time 函数 439 gettickcount 440 441 442 开始获取一次时间 结束的获取一次时间 443 时间差 --->运行时间 444 445 //测试 446 dword time1 = gettickcount(); 447 sleep(2000); 448 dword time2 = gettickcount(); 449 printf("%ld", time2 - time1); 450 getchar(); 451 452 453 454 1.算法优化 -->排序 455 2.存储优化 --->数组 单链表 双链表 456 数组 省内存 中间插入 开头插入 比较麻烦 尾端插入效率高 457 查找 访问从前往后 也可以从后往前 458 单链表 插入很方便 内存不是很省 没有长度限制 459 访问 不是很方便 460 双链表 插入方便 内存不是很省 461 访问可以从前往后 也可以从后往前 462 3.计算 右移代替除以2
注:其中部分功能并没有实现,还有一些是需要补充的,等以后有时间再补充吧
部分成功展示:
2019-04-04 10:19:07
上一篇: 运用jieba库分词
下一篇: s21day07 python笔记