学生信息管理系统SIMS

来源:互联网 发布:视频系统源码 编辑:程序博客网 时间:2024/05/17 06:35
学生信息管理系统SIMS
[root@matrix sims]# ll总计 108-rwxr-xr-x 1 root root 23947 05-08 23:50 a-rw-r--r-- 1 root root   198 05-04 12:00 ABOUT-rw-r--r-- 1 root root    43 05-07 16:44 demo.c-rw-r--r-- 1 root root   288 05-05 13:58 EXAMPLE-rw-r--r-- 1 root root   401 05-08 23:50 main.c-rw-r--r-- 1 root root   291 05-04 20:22 Makefile-rw-r--r-- 1 root root 17960 05-07 20:17 misc.c-rw-r--r-- 1 root root  3088 05-07 20:17 misc.h-rw-r--r-- 1 root root   140 05-04 12:03 README[root@matrix sims]# makegcc -c main.cgcc -c misc.cgcc -o a main.o misc.o[root@matrix sims]# a////////欢迎使用(学生信息管理系统SIMS)\\\\\\\\______________________________________________用户名: root口令: hacker认证失败,请检查字母大小写是否正确。用户名: root口令: hacking______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 4______________________________________________全部(0) 模糊(1) 条件(2)查询方式: 0[X]记录查询失败!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 1______________________________________________当前位置(主页/添加记录)学号: 101姓名: Jeff Conrad性别: M年龄: 24电话: 10086出生(年): 1988出生(月): 3出生(日): 24语文成绩: 78数学成绩: 78英语成绩: 88本次索引节点为1[V]记录添加成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 1______________________________________________当前位置(主页/添加记录)学号: 102姓名: Junkie Pro性别: F年龄: 25电话: 10000出生(年): 1988出生(月): 4出生(日): 3语文成绩: 99数学成绩: 34英语成绩: 55本次索引节点为2[V]记录添加成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 1______________________________________________当前位置(主页/添加记录)学号: 101[X]ID冲突!学号: 103姓名: Lady GaGa性别: M年龄: 35电话: 12580出生(年): 1978出生(月): 8出生(日): 3语文成绩: 99数学成绩: 56英语成绩: 44本次索引节点为3[V]记录添加成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 4______________________________________________全部(0) 模糊(1) 条件(2)查询方式: 0学号 姓名         性别 年龄 电话        出生       语文 数学 英语 节点......................................................................101  Jeff Conrad  M    24   10086       1988-03-24 78   78   88   1  102  Junkie Pro   F    25   10000       1988-04-03 99   34   55   2  103  Lady GaGa    M    35   12580       1978-08-03 99   56   44   3  ......................................................................记录: 共3项[V]记录查询成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 4______________________________________________全部(0) 模糊(1) 条件(2)查询方式: 1关键字: a学号 姓名         性别 年龄 电话        出生       语文 数学 英语 节点......................................................................101  Jeff Conrad  M    24   10086       1988-03-24 78   78   88   1  103  Lady GaGa    M    35   12580       1978-08-03 99   56   44   3  ......................................................................记录: 共2项[V]记录查询成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 4______________________________________________全部(0) 模糊(1) 条件(2)查询方式: 2资料: 学号( 0) 姓名( 1) 性别( 2) 年龄( 3) 电话( 4) 生日: 年份( 5) 月份( 6) 号数( 7) 成绩: 语文( 8) 数学( 9) 英语(10)序号: 2性别: M101  Jeff Conrad  M    24   10086       1988-03-24 78   78   88   1  103  Lady GaGa    M    35   12580       1978-08-03 99   56   44   3  ......................................................................记录: 共2项[V]记录查询成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 2______________________________________________学号: 104[X]ID无效!学号: 103确定删除? (y or n): y[V]记录删除成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 4______________________________________________全部(0) 模糊(1) 条件(2)查询方式: 0学号 姓名         性别 年龄 电话        出生       语文 数学 英语 节点......................................................................101  Jeff Conrad  M    24   10086       1988-03-24 78   78   88   1  102  Junkie Pro   F    25   10000       1988-04-03 99   34   55   2  ......................................................................记录: 共2项[V]记录查询成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 3______________________________________________学号: 101姓名: Jeff Conrad性别: F年龄: 10086电话: 10086出生(年): 1989出生(月): 3出生(日): 26语文成绩: 99数学成绩: 98英语成绩: 98[V]记录修改成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 4______________________________________________全部(0) 模糊(1) 条件(2)查询方式: 0学号 姓名         性别 年龄 电话        出生       语文 数学 英语 节点......................................................................101  Jeff Conrad  F    1008610086       1989-03-26 99   98   98   1  102  Junkie Pro   F    25   10000       1988-04-03 99   34   55   2  ......................................................................记录: 共2项[V]记录查询成功!______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 6______________________________________________~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~功能模块:        增加  删除  修改  查询~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~按下回车键返回: ______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 7______________________________________________~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                欢迎使用SIMS v3版本: 3.0.0发行者: Junkie Pro创建日期: 2013年05月01日QQ: 614616185~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~按下回车键返回: ______________________________________________增加(1) 删除(2) 修改(3) 查询(4)设置(5) 帮助(6) 关于(7) 退出(0)选项: 0____________________________________________________________________________________________\\\\\\\\感谢使用(学生信息管理系统SIMS)////////[root@matrix sims]# [root@matrix sims]# '/root/project/sims/ABOUT' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~欢迎使用SIMS v3版本: 3.0.0发行者: Junkie Pro创建日期: 2013年05月01日QQ: 614616185~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[root@matrix sims]# '/root/project/sims/README' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~功能模块:增加  删除  修改  查询~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[root@matrix sims]# '/root/project/sims/Makefile' a: misc.h main.o misc.ogcc -o a main.o misc.omisc.o: misc.h misc.cgcc -c misc.cmain.o: misc.h main.cgcc -c main.cclean:rm -f *.oreset: rm -f DATABASE.DBrestore: ls -l EXAMPLE && cp -f EXAMPLE DATABASE.DB && echo RESTORE OK || echo NO EXAMPLEhelp:clearcat README | more[root@matrix sims]# '/root/project/sims/DATABASE.DB' [root@matrix sims]# '/root/project/sims/EXAMPLE' [root@matrix sims]# '/root/project/sims/main.c' #include "misc.h"int main(){system("clear");Head();if (Login("root", "hacking", 3)){//待办----文件Tail();return -1;}while (1){DividingLine('_', 1, 46);Body();int cn = ChoiceNumber("", OPTION_EXIT, OPTION_ABOUT, 3);if (-1 == cn){Tail();return -1;//建议不在此使用break;以增强程序的扩展性}if (Execute(cn))break;}Tail();return 0;}[root@matrix sims]# '/root/project/sims/misc.h' #ifndef __MISC_H__#define __MISC_H__#define DATABASE "DATABASE.DB"#define TABLE_HEAD 128#define TABLE_TAIL 256#define KEYWORD_LIMIT 100//关键字上限为100个字符(百度一下,你就知道)#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>//enum枚举: 默认从0开始递增, 手动起始值(保险起见)enum {DATATYPE_CHAR = 0, DATATYPE_INT, DATATYPE_FLOAT, DATATYPE_DOUBLE, DATATYPE_STRING};enum {OPTION_EXIT = 0, OPTION_ADD, OPTION_DEL, OPTION_EDIT, OPTION_QUERY, OPTION_SETTING, OPTION_HELP, OPTION_ABOUT};typedef enum {QUERY_ALL, QUERY_LIKE, QUERY_WHERE} query_e;//将QUERY_ALL排在第一位是因为键盘布局typedef enum {CON_ID = 0, CON_NAME, CON_SEX, CON_AGE, CON_TELEPHONE, CON_YEAR, CON_MONTH, CON_DAY, CON_CHINESE, CON_MATH, CON_ENGLISH, } CONDITION;//看个人习惯,建议设置为0,而不是1enum {SYMBOL_YES, SYMBOL_NO};//数字数位typedef struct {size_t year, month, day;} date_s;typedef struct {char fill_a:3;size_t content;char fill_b:5;} table_s;typedef struct {table_s start;size_t id;char name[20];char sex[4];size_t age;char telephone[12];date_s birth;struct result_s {size_t chinese, math, english;} score;size_t inode;table_s end;} student_s;int Login(const char *username, const char *password, size_t n);//登录void CleanStdin(void);//清理stdin流中残留数据int ClearLF(char *str, size_t n);//清除字符串中'\n'字符 LF(line feed)int IsNull(const char *str);//检测字符串是否为空void Head(void);//显示系统头部信息void Body(void);//显示系统主要信息void Tail(void);//显示系统退出信息int ChoiceNumber(const char *prompt, int begin, int end, size_t n);//选择数字int IsExistID(size_t s_id);//检测ID是否存在int Edit(size_t n);//修改记录int Del(size_t n);//删除记录int Execute(size_t n);//执行对应功能int IsExistFile(const char *path);//检测文件是否存在int ReadText(const char *path);//显示文本文件内容void DividingLine(int c, size_t row, size_t col);//打印分界线int Add(const size_t etc);//添加记录int GetData(const char *prompt, int type, void *var, size_t n);//输入数据int GetString(const char *prompt, char *ptr, size_t len, size_t n);//输入字符串int ProduceInode(void);//生成索引节点int CountRecord(void);//统计记录条目int SearchString(const char *keyword, const char *content);//搜索字符串void InitCA(char *ca, size_t n);//初始化字符数组int Query(int flag);//查询所有数据void ShowMe(const char *path, const char *object);//显示指定文本内容int ChooseKey(const char *prompt);//获取一个按键int NumericDigits(int integer, int flag);int DigitalConversionString(int integer, char *buf, size_t size, int flag);int ReverseString(char *src, size_t len);//逆转字符串void Debug(void);#endif//__MISC_H__//增加重建索引节点,序列递增修改原始节点号,//1,3,5//在生成新节点后删除了2号节点//1,2,3//重建索引节点后//可以按照索引节点进行数据库排序[root@matrix sims]# '/root/project/sims/misc.c' #include "misc.h"int Login(const char *username, const char *password, size_t n){;if (!(username && password))return -1;size_t len_user = strlen(username),    len_pswd = strlen(password);if (!(len_user && len_pswd))return -1;char rec_user[len_user + 2],  rec_pswd[len_pswd + 2];//多一个字节用于检测用户是否过多输入size_t siz_user = sizeof(rec_user),    siz_pswd = sizeof(rec_pswd);while(n--){printf("用户名: ");fgets(rec_user, siz_user, stdin);if (IsNull(rec_user))if (ClearLF(rec_user, strlen(rec_user)))CleanStdin();printf("口令: ");fgets(rec_pswd, siz_pswd, stdin);if (IsNull(rec_pswd))if (ClearLF(rec_pswd, strlen(rec_pswd)))CleanStdin();if (strcmp(username, rec_user) || strcmp(password, rec_pswd)){puts("认证失败,请检查字母大小写是否正确。");continue;}return 0;}return -1;}void CleanStdin(void){scanf("%*[^\n]");scanf("%*c");}int ClearLF(char *str, size_t n){int i = 0;for (i = 0; i < n; i++)if ('\n' == str[i]){str[i] = '\0';return 0;}return -1;}int IsNull(const char *str){;if (!str)return 0;return strlen(str) > 0 ? -1 : 0;}void Head(void){puts("////////欢迎使用(学生信息管理系统SIMS)\\\\\\\\\\\\\\\\");DividingLine('_', 1, 46);}void Body(void){printf("增加(%d)\t删除(%d)\t修改(%d)\t查询(%d)\n设置(%d)\t帮助(%d)\t关于(%d)\t退出(%d)\n", OPTION_ADD, OPTION_DEL, OPTION_EDIT, OPTION_QUERY, OPTION_SETTING, OPTION_HELP, OPTION_ABOUT, OPTION_EXIT);}void Tail(void){DividingLine('_', 1, 46);puts("\\\\\\\\\\\\\\\\感谢使用(学生信息管理系统SIMS)////////");}int ChoiceNumber(const char *prompt, int begin, int end, size_t n){while(n--){int num = -1;printf("%s: ", IsNull(prompt) ? prompt : "选项");int sv = scanf("%d", &num);CleanStdin();if (sv && num >= begin && num <= end)return num;printf("[X]错误%s!\n", IsNull(prompt) ? prompt : "选项");}return -1;}int IsExistID(size_t s_id){int res = -1;if (IsExistFile(DATABASE))return -1;FILE *fp = fopen(DATABASE, "rb");if (!fp)return -1;student_s t = {};while(!feof(fp)){if (1 != fread(&t, sizeof(student_s), 1, fp))break;if (s_id == t.id){res = 0;break;}}fclose(fp);fp = NULL;return res;}int Edit(size_t n){;if (IsExistFile(DATABASE))return -1;int dest = -1;int sid = -1;while(n--){if (!GetData("学号", DATATYPE_INT, &sid, 1))if (!IsExistID(sid)){dest = 0;break;}else puts("[X]ID无效!");}if (dest)return -1;FILE *fp = fopen(DATABASE, "rb+");if (!fp)return -1;student_s tmp = {};int res = !0;while (!feof(fp)){if (1 != fread(&tmp, sizeof(student_s), 1, fp))break;if (sid == tmp.id){res = res && !GetString("姓名", tmp.name, sizeof(tmp.name) / sizeof(*tmp.name), 2) && !GetString("性别", tmp.sex, sizeof(tmp.sex) / sizeof(*tmp.sex), 2) && !GetData("年龄", DATATYPE_INT, &tmp.age, 2) && !GetString("电话", tmp.telephone, sizeof(tmp.telephone) / sizeof(*tmp.telephone), 2) && !GetData("出生(年)", DATATYPE_INT, &tmp.birth.year, 2) && !GetData("出生(月)", DATATYPE_INT, &tmp.birth.month, 2) && !GetData("出生(日)", DATATYPE_INT, &tmp.birth.day, 2) && !GetData("语文成绩", DATATYPE_INT, &tmp.score.chinese, 2) && !GetData("数学成绩", DATATYPE_INT, &tmp.score.math, 2) && !GetData("英语成绩", DATATYPE_INT, &tmp.score.english, 2);if (res){fseek(fp, -sizeof(student_s), SEEK_CUR);if (1 == fwrite(&tmp, sizeof(tmp), 1, fp)){fclose(fp);fp = NULL;return 0;}}fclose(fp);fp = NULL;return -1;}}}int Del(size_t n){size_t sid = 0;if (IsExistFile(DATABASE))return -1;while (n--){if (!GetData("学号", DATATYPE_INT, &sid, 1)){if (IsExistID(sid))puts("[X]ID无效!");elsebreak;}}if (-1 == n)return -1;n = 3;int cn = 0;while(n--){cn = ChooseKey("确定删除? (y or n)");if ('n' == cn)return -1;else if ('y' == cn)break;}if (-1 == n)return -1;FILE *fp = fopen(DATABASE, "rb");if (!fp){fclose(fp);fp = NULL;return -1;}int con = 1;while (con){char *tfa = "tmp_";int tfb = rand();char tf[strlen(tfa) + NumericDigits(tfb, SYMBOL_NO) + 1];InitCA(tf, sizeof(tf));sprintf(tf, "%s%d", tfa, tfb);tf[sizeof(tf) - 1] = 0;if (IsExistFile(tf)){con = 0;FILE *dest = fopen(tf, "wb+");if (!dest)return -1;FILE *src = fopen(DATABASE, "rb");if (!src){fclose(dest);dest = NULL;return -1;}student_s ts = {};while(!feof(src)){if (1 != fread(&ts, sizeof(student_s), 1, src))break;if (sid != ts.id)if (1 != fwrite(&ts, sizeof(student_s), 1, dest))break;}fclose(dest);fclose(src);dest = src = NULL;remove(DATABASE);rename(tf, DATABASE);return 0;}}return -1;}int Execute(size_t n){DividingLine('_', 1, 46);switch(n){case OPTION_EXIT:return -1;case OPTION_ADD:if (Add(3))puts("[X]记录添加失败!");elseputs("[V]记录添加成功!");break;case OPTION_DEL:if (Del(3))puts("[X]记录删除失败!");elseputs("[V]记录删除成功!");break;case OPTION_EDIT:if (Edit(3))puts("[X]记录修改失败!");elseputs("[V]记录修改成功!");break;case OPTION_QUERY:printf("全部(%d) 模糊(%d) 条件(%d)\n", QUERY_ALL, QUERY_LIKE, QUERY_WHERE);query_e flag = QUERY_ALL;flag = ChoiceNumber("查询方式", QUERY_ALL, QUERY_WHERE, 3);if (CountRecord() <= 0 || Query(flag))//目前可以省略CountRecord();该形式表达式可以在其它功能中采用puts("[X]记录查询失败!");elseputs("[V]记录查询成功!");break;case OPTION_SETTING:puts("初始化数据库?");break;case OPTION_HELP:ShowMe("README", "帮助文档");break;case OPTION_ABOUT:ShowMe("ABOUT", "关于文档");break;default:;}return 0;//为了扩展性暂时不写在default范围内}int IsExistFile(const char *path){;if (!IsNull(path))return -1;FILE *fp = fopen(path, "r");if (fp){fclose(fp);fp = NULL;return 0;}return -1;}int ReadText(const char *path){FILE *fp = fopen(path, "rt");int c = -1;if (fp){while((c = fgetc(fp)) != EOF)putc(c, stdout);fclose(fp);fp = NULL;}elsereturn -1;return 0;}void DividingLine(int c, size_t row, size_t col){int i = 0;while (row--){for (i = 0; i < col; i++)printf("%c", c);puts("");}}int Add(const size_t etc){puts("当前位置(主页/添加记录)");//可以使用函数来改写FILE *fp = NULL;if (IsExistFile(DATABASE)){fp = fopen(DATABASE, "wb+");if (!fp)return -1;}else {fp = fopen(DATABASE, "ab+");//追加总是在末尾写入,rb+覆盖写入,不允许追加,在原有基础上修改if (!fp)return -1;}int n = etc;//使用结构体指针,巩固知识点。student_s dat = {0};dat.start.content = TABLE_HEAD;dat.end.content = TABLE_TAIL;int res = 0;int tms = 2;while(tms--){if (!GetData("学号", DATATYPE_INT, &dat.id, 1))if (IsExistID(dat.id)){res = !0;break;}elseputs("[X]ID冲突!");}res = res && !GetString("姓名", dat.name, sizeof(dat.name) / sizeof(*dat.name), 2) && !GetString("性别", dat.sex, sizeof(dat.sex) / sizeof(*dat.sex), 2) && !GetData("年龄", DATATYPE_INT, &dat.age, 2) && !GetString("电话", dat.telephone, sizeof(dat.telephone) / sizeof(*dat.telephone), 2) && !GetData("出生(年)", DATATYPE_INT, &dat.birth.year, 2) && !GetData("出生(月)", DATATYPE_INT, &dat.birth.month, 2) && !GetData("出生(日)", DATATYPE_INT, &dat.birth.day, 2) && !GetData("语文成绩", DATATYPE_INT, &dat.score.chinese, 2) && !GetData("数学成绩", DATATYPE_INT, &dat.score.math, 2) && !GetData("英语成绩", DATATYPE_INT, &dat.score.english, 2) && !(-1 == (dat.inode = ProduceInode()));//在即将写入文件时删除数据文件返回失败状态(-1)if (res){if (1 != fwrite(&dat, sizeof(student_s), 1, fp)){puts("[X]写入数据时发生错误!");fclose(fp);fp = NULL;//FILE*关闭后仍可用,虽不能真正写入文件,但程序可能照常运行,置为空指针,则写入是会段错误,便于发现潜在隐患return -1; }printf("本次索引节点为%d\n", dat.inode);fclose(fp);fp = NULL;return 0;}fclose(fp);fp = NULL;return -1;}int GetData(const char *prompt, int type, void *var, size_t n){while (n--){printf("%s: ", prompt);int is = 0;switch (type){case DATATYPE_CHAR:is = scanf("%c", var);break;case DATATYPE_INT:is = scanf("%d", var);break;case DATATYPE_FLOAT:case DATATYPE_DOUBLE:is = scanf("%f", var);break;case DATATYPE_STRING://is = fgets/scanf("%s")break;default:return -1;}CleanStdin();if (is)return 0;puts("[X]输入错误!");}return -1;}int GetString(const char *prompt, char *ptr, size_t len, size_t n){while(n--){printf("%s: ", prompt);fgets(ptr, len, stdin);if (IsNull(ptr)){if (ClearLF(ptr, strlen(ptr)))CleanStdin();if (IsNull(ptr))return 0;}}return -1;}int ProduceInode(void){;size_t inode = 0;if (IsExistFile(DATABASE))return -1;FILE *fp = fopen(DATABASE, "rb");if (!fp)return -1;student_s t = {};while(!feof(fp))if (1 == fread(&t, sizeof(student_s), 1, fp))inode = t.inode > inode ? t.inode : inode;fclose(fp);fp = NULL;return ++inode;}int CountRecord(void){;size_t count = 0;if (IsExistFile(DATABASE))return -1;FILE *fp = fopen(DATABASE, "rb");if (!fp)return -1;student_s t;while(!feof(fp))if (1 == fread(&t, sizeof(student_s), 1, fp)){if (t.start.content != TABLE_HEAD || t.end.content != TABLE_TAIL)//主要检测表头return -1;count++;}if (ftell(fp) != count * sizeof(student_s))//检测表尾return -1;fclose(fp);fp = NULL;return count;}int SearchString(const char *keyword, const char *content){;if (!(IsNull(keyword) && IsNull(content)))return -1;size_t len_k = strlen(keyword),    len_c = strlen(content);if (len_k > len_c)return -1;int i = 0, j = 0;char match[len_k + 1];for (i = 0; i < len_c - len_k + 1; i++){//关系类型: 一对多InitCA(match, sizeof(match));for (j = i; j < i + len_k; j++)match[j - i] = content[j];match[j - i] = 0;if (!strcmp(match, keyword))return 0;}return -1;}void InitCA(char *ca, size_t n){int i = 0;for (i = 0; i < n; i++)ca[i] = 0;}//usleep(500000);//睡眠0.1秒钟//检测字段是否为ASCII字符集中数据,否则认为是汉子,占用不同的位宽//编写整数转换字符串函数sprintfint Query(int flag){;if (CountRecord() <= 0)return -1;FILE *fp = fopen(DATABASE, "rb");if (!fp)return -1;student_s t = {};size_t cnt = 0;void Header(void){puts("学号 姓名         性别 年龄 电话        出生       语文 数学 英语 节点");DividingLine('.', 1, 70);}void Footer(const char *NullPrompt){DividingLine('.', 1, 70);if (!cnt)if (IsNull(NullPrompt))puts(NullPrompt);elseputs("[*]数据库文件已发生变化!");printf("记录: 共%u项\n", cnt);}void format(char *buf){//根据非ASCII字符个数和ASCII个数来确定%s,其它数据类型保持不变}int SAll(void){Header();while (!feof(fp)) {if (1 != fread(&t, sizeof(student_s), 1, fp))break;printf("%-5u%-13s%-5s%-5u%-12s%04u-%02u-%02u %-5u%-5u%-5u%-3u\n", t.id, t.name, t.sex, t.age, t.telephone, t.birth.year, t.birth.month, t.birth.day, t.score.chinese, t.score.math, t.score.english, t.inode), cnt++;}fclose(fp);fp = NULL;Footer(NULL);return 0;}int SLike(const char *keyword){Header();char buf[KEYWORD_LIMIT + 1] = {0};while (!feof(fp)) {if (1 != fread(&t, sizeof(student_s), 1, fp))break;int c = -1;#define MATCHING(Flag, Var) \InitCA(buf, sizeof(buf)); \sprintf(buf, #Flag, Var); \/*printf("正在匹配第%d项中的%s\n", ftell(fp) / sizeof(student_s), #Var);*/ \c = c && SearchString(keyword, buf); \if (!c) break;//该行语句属于宏MATCHINGint wc = 1;while (wc--){MATCHING(%u,  t.id);MATCHING(%s,  t.name);MATCHING(%s,  t.sex);MATCHING(%u,  t.age);MATCHING(%s,  t.telephone);MATCHING(%u,  t.birth.year);MATCHING(%u,  t.birth.month);MATCHING(%u,  t.birth.day);MATCHING(%u,  t.score.chinese);MATCHING(%u,  t.score.math);MATCHING(%u,  t.score.english);}if (!c)printf("%-5u%-13s%-5s%-5u%-12s%04u-%02u-%02u %-5u%-5u%-5u%-3u\n", t.id, t.name, t.sex, t.age, t.telephone, t.birth.year, t.birth.month, t.birth.day, t.score.chinese, t.score.math, t.score.english, t.inode), cnt++;}fclose(fp);fp = NULL;Footer("[*]没有匹配内容!");return 0;}int SWhere(void){#define PREC printf("%-5u%-13s%-5s%-5u%-12s%04u-%02u-%02u %-5u%-5u%-5u%-3u\n", src.id, src.name, src.sex, src.age, src.telephone, src.birth.year, src.birth.month, src.birth.day, src.score.chinese, src.score.math, src.score.english, src.inode), cnt++;printf("资料: 学号(%2d) 姓名(%2d) 性别(%2d) 年龄(%2d) 电话(%2d) \n生日: 年份(%2d) 月份(%2d) 号数(%2d) \n成绩: 语文(%2d) 数学(%2d) 英语(%2d)\n", CON_ID, CON_NAME, CON_SEX, CON_AGE, CON_TELEPHONE, CON_YEAR, CON_MONTH, CON_DAY, CON_CHINESE, CON_MATH, CON_ENGLISH);int cn = ChoiceNumber("序号", CON_ID, CON_ENGLISH, 3);if (-1 == cn)return -1;student_s dest = {0}, src = {0};int res = -1;#define DECIDE(C) \if (-1 == (C)) {\fclose(fp); \fp = NULL; \return -1; \}#define DPI(arg1, arg2) \while (!feof(fp)) {\if (1 != fread(&src, sizeof(student_s), 1, fp)) break;\if (arg1 == arg2) PREC;}#define DPS(arg1, arg2) \while (!feof(fp)) {\if (1 != fread(&src, sizeof(student_s), 1, fp)) break;\if (!strcmp(arg1, arg2)) PREC;}switch (cn) {case CON_ID:DECIDE(GetData("学号", DATATYPE_INT, &dest.id, 2));DPI(dest.id, src.id);break;case CON_NAME:DECIDE(GetString("姓名", dest.name, sizeof(dest.name) / sizeof(*dest.name), 2));DPS(dest.name, src.name);break;case CON_SEX:DECIDE(GetString("性别", dest.sex, sizeof(dest.sex) / sizeof(*dest.sex), 2));DPS(dest.sex, src.sex);break;case CON_AGE:DECIDE(GetData("年龄", DATATYPE_INT, &dest.age, 2));DPI(dest.age, src.age);break;case CON_TELEPHONE:DECIDE(GetString("电话", dest.telephone, sizeof(dest.telephone) / sizeof(*dest.telephone), 2));DPS(dest.telephone, src.telephone);break;case CON_YEAR:DECIDE(GetData("年份", DATATYPE_INT, &dest.birth.year, 2));DPI(dest.birth.year, src.birth.year);break;case CON_MONTH:DECIDE(GetData("月份", DATATYPE_INT, &dest.birth.month, 2));DPI(dest.birth.month, src.birth.month);break;case CON_DAY:DECIDE(GetData("号数", DATATYPE_INT, &dest.birth.day, 2));DPI(dest.birth.day, src.birth.day);break;case CON_CHINESE:DECIDE(GetData("语文", DATATYPE_INT, &dest.score.chinese, 2));DPI(dest.score.chinese, src.score.chinese);break;case CON_MATH:DECIDE(GetData("数学", DATATYPE_INT, &dest.score.math, 2));DPI(dest.score.math, src.score.math);break;case CON_ENGLISH:DECIDE(GetData("英语", DATATYPE_INT, &dest.score.english, 2));DPI(dest.score.english, src.score.english);break;}fclose(fp);fp = NULL;Footer("[*]没有匹配内容!");return 0;}if (QUERY_ALL == flag){return SAll();}else if (QUERY_LIKE == flag){char keyword[KEYWORD_LIMIT + 1];InitCA(keyword, sizeof(keyword));if (GetString("关键字", keyword, sizeof(keyword), 3)){fclose(fp);fp = NULL;return -1;}return SLike(keyword);}else if (QUERY_WHERE == flag){return SWhere();}elsereturn -1;}void ShowMe(const char *path, const char *object){if (IsExistFile(path)){printf("[X]打开%s失败!\n", object);return ;}ReadText(path);ChooseKey(NULL);}int ChooseKey(const char *prompt){int c = 0;if (!IsNull(prompt))prompt = "按下回车键返回";printf("%s: ", prompt);if ('\n' != (c = fgetc(stdin)))CleanStdin();return c;}int NumericDigits(int integer, int flag){//条件查询可能不用这个函数,条件查询中直接比较两个值是否完全相等,包含数据类型int count = 0;if (SYMBOL_YES == flag)//仅限于符号count = integer < 0 ? 1 : 0;else if (SYMBOL_NO == flag);elsereturn -1;integer = integer < 0 ? -1 * integer : integer;do {count++;integer /= 10;} while (integer);return count;}int DigitalConversionString(int integer, char *buf, size_t size, int flag){//字符串转换数字,使用逆向算法即可int-'0'InitCA(buf, size);if (SYMBOL_YES == flag){if (integer < 0)*buf++ = '-';}else if (SYMBOL_NO == flag);elsereturn -1;integer = integer < 0 ? -1 * integer : integer;//可以省略该条语句,直接对负数操作效果一样do {*buf++ = '0' + integer % 10;integer /= 10;} while (integer);return 0;}int ReverseString(char *src, size_t len){//将来为了支持WHERE *str*;char buf[len + 1];InitCA(buf, sizeof(buf));strcpy(buf, src);int i = 0;for (i = 0; i < len; i++){src[i] = buf[len - i - 1];}puts(buf);puts(src);}void Debug(void){int i = -54321;int is = NumericDigits(i, SYMBOL_YES);char buf[is + 1];printf("-----%d\n", sizeof(buf));DigitalConversionString(i, buf, is, SYMBOL_YES);DigitalConversionString(i, buf, is, SYMBOL_YES);puts(buf);ReverseString(buf, strlen(buf));}
原创粉丝点击