[小项目]c语言实现数据库操作(低仿)
20.03.02更新
注意:
本文章下的程序运行有可能会出现逻辑错误,修改版在这。文章里的文字倒是没错,如果你熟悉缓冲区和文件内光标的话建议看本文代码的时候不要太严格,一切以新版为主。
要求
- 登录
- 创建数据库
- 删除数据库
- 选择数据库
- 创建数据表
- 删除数据表
- 实现对数据的增删改查
- 退出登录
- 输入密码时不回显,用*代替
我对于各种功能的实现思路
1. 登录
这个登录是阉割版的,本文代码已经迭代到第二个版本了,在初始版本是有注册功能的。第一版因为审题不认真误以为是要用c语言连接mysql来实现,开始debug的时候被告知是要用c语言直接实现。既然题目没要求注册我也就没加上注册功能。(懒
2. 通过使用getch函数实现密码显示为*
输入密码的要求是不回显,同时显示为*,除此之外还要没有缓冲区机制,那么头文件conio.h之下的getch()就刚好满足所有需求,具体代码将在下面给出。
3.数据库系统设计
我们知道,数据库系统要有三层,数据库、表、表里的数据。因此,一个表一个txt文件,以换行符划分每一条数据,而数据库则是一个包含表名的txt文件。
4. 数据库内部
数据库有一个重要的特点:选择了某个库就只能库内的表,不允许使用跨库调用表。所以在创建表的时候将表的url存入到数据库文件中,为了方便区分,一个表一行。在调用表的时候要检查一下数据库里面有没有这个表。有这个表才允许下一步操作。
============================================
在mysql里面,创建一个表可以设定任意数量的字段,字段名、字段类型和字段长度可以任意定义。但是要用c语言来实现难度有点大。
5.通过妥协解决字段类型和长度问题(手动狗头)
字段类型和字段数量排列组合有无限可能,无法预测用户需求。一开始想要通过预定义+用户输入的方式来实现动态创建结构体,真正实践的时候发现无法实现。想了许久最终还是做出了妥协。仔细想想,在不需要运算只需要存储和输出的情况下, 整型、浮点型、字符、字符串都可以改用字符串类型,字段长度(数组)可以用malloc()来动态分配(虽然最后我没有采用这种方法),但是由于字段长度大概也不会超过20,为了方便用户(还有我)操作,最终决定统一使用长度为20的字符数组来存储字段。
6.通过虚拟文件头解决“任意”字段数和字段名
字段名对于程序员来说没有意义,对于用户来说只需要在输出的时候输出在最上面就行了,所以字段名可以当做数据来处理,只是在后续删除、修改操作中要做保护不要让字段名被修改(具体的保护措施我在下面再讲)。又因为大多数表格字段数在四五个左右,所以我构造了一个由四个长度为20的字符串组成的结构体,用作数据的容器。因此,在创建表的时候先输入字段数(小于5),将字段数存储在文件的最开头,和下一行字段名组成一个以虚拟的“文件头。每次声明结构体的时候将所有数组初始化为NULL,用户输入多少行就循环多少次输入,未被输入的字段默认为空,实现5以内任意字段数。修改和增加数据时都要读取文件头来确认用户需要输入多少字段。
7.通过双参数实现操作行判定,设置差值保护文件头
在修改和删除的时候用户需要删除某一行的时候,将其输入值加2才是真正的行数,输入行和实际行分别用两个参数来储存,实际行迭代,直到两参数相等的时候执行修改和删除。
8.通过狸猫换太子实现数据的删除和修改
由于文件打开方式只有读、写、追加,所以想要直接实现精确到行的操作是行不通的。通过上网我学会了一招“狸猫换太子”。既然要狸猫换太子,那么首先肯定要准备一个“狸猫”文件,为了使他的文件名不和其他文件出现冲突,学习库里参数命名的方法,在前面用两条_作前缀,那么我就将其命名为“__temp.txt”。用户输入需要修改行之后,就开始逐行将太子文件的内容复制狸猫文件里,当实际行和输入行相等的时候,该跳过跳过,该输入新的输入新的,然后再继续复制剩余的数据。为了不出现真假太子这一幕,在狸猫变太子之前,真太子不能留!找来杀手remove()解决,最后再让rename()帮狸猫做最后的化妆,至此可以说已经实现了狸猫换太子了。
10.通过dos命令实现一点美化
window。h里的system()函数可实现使用dos命令,dos命令可以改窗口名、清屏、改配色。这里我只是使用了清屏,其他读者可以自行尝试。
代码结构
除了主函数,所有函数都可以重复调用。所有函数的返回值都是整型的,每个函数调用的时候外面都包裹了一层while循环,通过用户输入决定返回值,从而决定是否继续使用某功能。
各部分代码实现
1.主函数
int main(){int i=0;while(i<MAXTIME){if(login()){//账号密码正确的时候while(database_func());//记得加分号,否则他会以为while的循环体是break;实际上循环体是空语句;break;}//否则继续循环i++;//记得加,否则无限循环}if(i==MAXTIME){system("cls");printf("已达到输入次数上限,程序即将自动关闭!");Sleep(2000);return 0;}system("cls");printf("感谢宁的使用,再见!");return 0;
}
2.输入密码的实现
printf("请输入密码:");
while(i<MAXLEN){ch = getch();//conio.h,无回显,无缓冲区if(ch == '\r'){ //回车结束输入/*对于不同的字符输入函数,回车键产生的字符不同用户按下回车键时,getchar() 将读取到\n字符,而 getch() 将读取到\r字符*/printf("\n");break;}if(ch=='\b'&&i>0){ //按下删除键i--;printf("\b \b");}//else if 和 else 还是有区别的else if(isprint(ch)){ //输入可打印字符,ctype.hpassword[i] = ch;printf("*");i++;}
}
3.代码的复用的实现(以database_func为例)
int database_func(){//数据库操作菜单system("cls");//system("color 26");int flag=0,func=0;printf("功能界面\n");printf("============\n");printf(" 1.创建数据库\n 2.删除数据库\n 3.选择数据库\n 4.退出程序\n");printf("============\n");printf("请输入需要使用的功能:");scanf("%d",&func);switch(func){case 1:while(create_database());break;//创建数据库case 2:while(delete_database());break;//删除数据库case 3:while(use_database());break;//打开数据库case 4:exit(0);break;}system("cls");//使用功能后,判断是否继续使用printf("你有以下两个选择\n");printf("=================\n");printf(" 1.继续使用\n 2.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){//继续使用return 1;}if(flag==2){//退出return 0;}return 0;
}
后面的函数的复用设计都是以上面这个函数为模板做了一点修改。
4.创建表
int create_table(char *db_url){//创建表,和创建库差不多,要把表名放入库文件中system("cls");int flag=0,n=0,i=0;char tb_name[10],tb_url[15];struct datas data;printf("新建表\n");printf("=================\n");printf("请输入新表的名字(len<10):");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt");if((fp2=fopen(tb_url,"r"))==NULL){//判断是否重复建表fp2=fopen(tb_url,"w");printf("请输入新表的字段数(<=4):");scanf("%d",&n);if(n>4){printf("对不起,程序员太菜无法支持创建这么多字段的表(妥协\n");}else{for(i=0;i<n;i++){printf("请输入第%d个字段名:",i+1);switch(i){case 0:scanf("%s",data.one);break;case 1:scanf("%s",data.two);break;case 2:scanf("%s",data.three);break;case 3:scanf("%s",data.four);break;}}}fprintf(fp2,"%d\n",n);fprintf(fp2,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);fclose(fp2);fprintf(fp,"%s\n",tb_url);//把表名放进数据库中,记得换行,文件已被上层函数打开printf("创建成功!\n");Sleep(1000);return 0;//跳出循环}else{system("cls");printf("该表已经被创建,或命名错误\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新创建\n 2.取消创建表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束创建");Sleep(2000);return 0;}}
}
5.狸猫换太子(以删除表为例)
int delete_table(char *db_url){system("cls");int flag=0;char tb_name[10],tb_url[15],haven[16];printf("删除表\n");printf("=================\n");printf("请输入要删除的表的名字:");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt\n");//文件里的tb_url始终有\n跟着strcat(tb_name,".txt");//虽然语义不对,但是懒得加变量了while(fgets(haven,16,fp)!=NULL){//一行一个信息if(!(strcmp(haven,tb_url))){//发现匹配表if(!(remove(tb_name))){//成功返回零printf("删除成功!\n");Sleep(2000);return 0;//跳出循环}else{//删除失败system("cls");printf("删除出错\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新删除\n 2.结束删除表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");return 0;}}}}//匹配成功的都出去了,匹配失败才会执行下面的语句system("cls");printf("库里没有这个表");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.删除另一个表\n 2.取消删除表操作\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");Sleep(2000);return 0;}
}
注意,fp指向的是数据库文件,在之前已经定义了。这里有个坑,就是在数据库里面的表名是跟着换行符的,比较的时候记得加上,否则永远显示错误。
全部代码
#include
#include
#include
#include
#include
#include
#define MAXLEN 10//账号密码最大长度
#define MAXTIME 3//登陆最大错误次数FILE * fp;//数据库文件指针
FILE * fp2;//表文件指针
FILE * fp3;//修改时用的容器struct datas{//退一步海阔天空char one[20];char two[20];char three[20];char four[20];
};int login();
int database_func();int create_database();
int delete_database();
int use_database();int table_func();int create_table();
int delete_table();
int select_data();
int add_data();
int delete_data();
int update_data();int main(){int i=0;while(i<MAXTIME){if(login()){//账号密码正确的时候while(database_func());//记得加分号,否则他会以为while的循环体是break;实际上循环体是空语句;break;}//否则继续循环i++;//记得加,否则无限循环}if(i==MAXTIME){system("cls");printf("已达到输入次数上限,程序即将自动关闭!");Sleep(2000);return 0;}system("cls");printf("感谢宁的使用,再见!");return 0;
}//第一层调用int login(){//登录,验证密码,正确返回1,错误返回0system("cls");int i = 0,flag=0;char ch = 0;char password[MAXLEN]={0},username[MAXLEN]={0};char true_username[]="123",true_password[]="123";printf("欢迎使用数据库管理系统\n");printf("=========================\n");printf("请您先登录\n");printf("=========================\n");printf("请输入账号:");scanf("%s",username);if(!strcmp(username,true_username)){//用户名输入正确的时候printf("请输入密码:");while(i<MAXLEN){ch = getch();//conio.h,无回显,无缓冲区if(ch == '\r'){ //回车结束输入/*对于不同的字符输入函数,回车键产生的字符不同用户按下回车键时,getchar() 将读取到\n字符,而 getch() 将读取到\r字符*/printf("\n");break;}if(ch=='\b'&&i>0){ //按下删除键i--;printf("\b \b");}//else if 和 else 还是有区别的else if(isprint(ch)){ //输入可打印字符,ctype.hpassword[i] = ch;printf("*");i++;}}if(!strcmp(password,true_password)){//密码输入正确return 1;}else{//密码输入错误printf("密码输入错误!(不妨告诉你密码是123)\n");printf("宁有以下两个选择:\n");printf("=================\n");printf(" 1.再次尝试登陆\n 2.退出程序\n");printf("=================\n");printf("请输入宁的选择:");scanf("%d",&flag);if(flag==1){return 0;}else{exit(0);//stdlib.h}}}else{//用户名不对的时候printf("用户不存在!(偷偷告诉你,用户名只有123)\n");printf("宁有以下两个选择\n");printf("=================\n");printf(" 1.再次尝试登陆\n 2.退出程序\n");printf("=================\n");printf("请输入宁的选择:");scanf("%d",&flag);if(flag==1){return 0;}else{exit(0);//stdlib.h}}
}int database_func(){//数据库操作菜单system("cls");//system("color 26");int flag=0,func=0;printf("功能界面\n");printf("============\n");printf(" 1.创建数据库\n 2.删除数据库\n 3.选择数据库\n 4.退出程序\n");printf("============\n");printf("请输入需要使用的功能:");scanf("%d",&func);switch(func){case 1:while(create_database());break;//创建数据库case 2:while(delete_database());break;//删除数据库case 3:while(use_database());break;//打开数据库case 4:exit(0);break;}system("cls");//使用功能后,判断是否继续使用printf("你有以下两个选择\n");printf("=================\n");printf(" 1.继续使用\n 2.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){//继续使用return 1;}if(flag==2){//退出return 0;}return 0;
}//第二层调用,父函数为database_funcint create_database(){//创建数据库system("cls");int flag=0;char db_name[10],db_url[15];printf("新建数据库\n");printf("=================\n");printf("请输入新库的名字(len<10):");scanf("%s",db_name);strcpy(db_url,db_name);strcat(db_url,".txt");if((fp=fopen(db_url,"r"))==NULL){//判断是否重复建库fp=fopen(db_url,"w");fclose(fp);//记得!printf("创建成功!\n");Sleep(1000);return 0;//跳出循环}else{system("cls");printf("该库已经被创建,或命名错误\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新创建\n 2.取消创建数据库\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束创建");Sleep(1000);return 0;}}
}int delete_database(){//删除数据库system("cls");int flag=0;char db_name[10],db_url[15];printf("删除数据库\n");printf("=================\n");printf("请输入要删除的数据库的名字:");scanf("%s",db_name);strcpy(db_url,db_name);strcat(db_url,".txt");if(!(remove(db_url))){//成功返回零,没有测试过行不行printf("删除成功!\n");Sleep(1000);return 0;//跳出循环}else{system("cls");printf("%s\n",strerror(errno));printf("你有以下两个选择\n");printf("=================\n");printf(" 1.再次删除\n 2.取消删除数据库\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");Sleep(2000);return 0;}}
}int use_database(){//打开数据库system("cls");int flag=0;char db_name[10],db_url[15];printf("打开数据库\n");printf("=================\n");printf("请输入要打开的数据库的名字:");scanf("%s",db_name);strcpy(db_url,db_name);strcat(db_url,".txt");if((fp=fopen(db_url,"a+"))!=NULL){//判断数据库是否存在printf("成功打开!\n");Sleep(1000);while(table_func(db_url));fclose(fp);return 0;//跳出循环}else{system("cls");printf("该库已经不存在\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.打开另一个\n 2.取消打开数据库\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束创建");Sleep(2000);return 0;}}
}//第三层调用,父函数为use_databaseint table_func(char * db_url){//表操作菜单system("cls");int flag=0,func=0;char db_name[10]={0};//有些库名可以显示全,有些就被阉割了一些strcpy(db_name,strtok(db_url,".txt"));printf("%s库\n",db_name);printf("============\n");printf(" 1.创建表\n 2.删除表\n 3.增加信息\n 4.删除信息\n 5.修改信息\n 6.查询信息\n 7.退出程序\n");printf("============\n");printf("请输入需要使用的功能:");scanf("%d",&func);switch(func){case 1:while(create_table(db_url));break;//创建表case 2:while(delete_table(db_url));break;//删除表case 3:while(select_data(db_url));break;//查询数据case 4:while(add_data(db_url));break;//创建数据case 5:while(delete_data(db_url));break;//删除数据case 6:while(update_data(db_url));break;//修改数据case 7:exit(0);break;}//使用功能后,判断是否继续使用system("cls");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.继续使用\n 2.退出库\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){//继续使用return 1;}if(flag==2){//退出return 0;}if(flag==3){exit(0);}return 0;
}//第四层调用,父函数为table_funcint create_table(char *db_url){//创建表,和创建库差不多,要把表名放入库文件中system("cls");int flag=0,n=0,i=0;char tb_name[10],tb_url[15];struct datas data;printf("新建表\n");printf("=================\n");printf("请输入新表的名字(len<10):");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt");if((fp2=fopen(tb_url,"r"))==NULL){//判断是否重复建表fp2=fopen(tb_url,"w");printf("请输入新表的字段数(<=4):");scanf("%d",&n);if(n>4){printf("对不起,程序员太菜无法支持创建这么多字段的表(妥协\n");}else{for(i=0;i<n;i++){printf("请输入第%d个字段名:",i+1);switch(i){case 0:scanf("%s",data.one);break;case 1:scanf("%s",data.two);break;case 2:scanf("%s",data.three);break;case 3:scanf("%s",data.four);break;}}}fprintf(fp2,"%d\n",n);fprintf(fp2,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);fclose(fp2);fprintf(fp,"%s\n",tb_url);//把表名放进数据库中,记得换行,文件已被上层函数打开printf("创建成功!\n");Sleep(1000);return 0;//跳出循环}else{system("cls");printf("该表已经被创建,或命名错误\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新创建\n 2.取消创建表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束创建");Sleep(2000);return 0;}}
}int delete_table(char *db_url){system("cls");int flag=0;char tb_name[10],tb_url[15],haven[16];printf("删除表\n");printf("=================\n");printf("请输入要删除的表的名字:");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt\n");//文件里的tb_url始终有\n跟着strcat(tb_name,".txt");//虽然语义不对,但是懒得加变量了while(fgets(haven,16,fp)!=NULL){//一行一个信息????????????????????????????????????if(!(strcmp(haven,tb_url))){//发现匹配表if(!(remove(tb_name))){//成功返回零,没有测试过行不行printf("删除成功!\n");Sleep(2000);return 0;//跳出循环}else{//删除失败system("cls");printf("删除出错\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新删除\n 2.结束删除表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");return 0;}}}}//匹配成功的都出去了,匹配失败才会执行下面的语句system("cls");printf("库里没有这个表");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.删除另一个表\n 2.取消删除表操作\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");Sleep(2000);return 0;}
}int select_data(char *db_url){system("cls");int flag=0,a;struct datas data={0};//初始化;char tb_name[10],tb_url[15],haven[16];printf("查询表\n");printf("=================\n");printf("请输入要查询的表的名字:");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt\n");strcat(tb_name,".txt");while(fgets(haven,16,fp)!=NULL){//一行一个信息if(!strcmp(haven,tb_name)){//发现匹配表if((fp2=fopen(tb_url,"r"))!=NULL){fscanf(fp2,"%d\n",&a);//把字段数读取掉while(fscanf(fp2,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four)){printf("%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);}printf("查询成功!\n");fclose(fp2);printf("输入任意键继续......");getchar();//读取任意键,达到暂停的效果return 0;//跳出循环}else{system("cls");printf("文件出错\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新查询\n 2.结束查询表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");return 0;}}}}//匹配成功的都出去了,匹配失败才会执行下面的语句system("cls");printf("库里没有这个表");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.查询另一个表\n 2.取消查询表操作\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");Sleep(2000);return 0;}
}int add_data(){system("cls");int flag=0,i=0,n=0;struct datas data={0};//初始化结构体char tb_name[10],tb_url[15],haven[16];printf("增加数据\n");printf("=================\n");printf("请输入要增加数据的表的名字:");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt\n");strcat(tb_name,".txt");while(fgets(haven,16,fp)!=NULL){//一行一个信息????????????????????????????????????if(!strcmp(haven,tb_name)){//发现匹配表if((fp2=fopen(tb_url,"a+"))!=NULL){fscanf(fp2,"%d\n",&n);for(i=0;i<n;i++){printf("请输入第%d个字段名:",i+1);switch(i){case 0:scanf("%s",data.one);break;case 1:scanf("%s",data.two);break;case 2:scanf("%s",data.three);break;case 3:scanf("%s",data.four);break;}}fprintf(fp2,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);printf("添加数据成功!\n");fclose(fp2);printf("输入任意键继续......");getchar();//读取任意键,达到暂停的效果return 0;//跳出循环}else{system("cls");printf("文件出错\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新查询\n 2.结束查询表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");return 0;}}}}//匹配成功的都出去了,匹配失败才会执行下面的语句system("cls");printf("库里没有这个表");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.查询另一个表\n 2.取消查询表操作\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");Sleep(2000);return 0;}
}int delete_data(){system("cls");int flag=0,i=1,n;//这里初始化i为1struct datas data={0};//初始化结构体char tb_name[10],tb_url[15],haven[16];printf("删除数据\n");printf("=================\n");printf("请输入要删除数据的表的名字:");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt\n");strcat(tb_name,".txt");while(fgets(haven,16,fp)!=NULL){//一行一个信息????????????????????????????????????if(!strcmp(haven,tb_name)){//发现匹配表if((fp2=fopen(tb_url,"w+"))!=NULL){fp3=fopen("__temp.txt","w+");//修改专用文件printf("请输入要删除的行号:");scanf("%d",&n);n=n+2;//确保前两行不会被删掉while(fscanf(fp2,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four)){if(i==n){continue;}else{fprintf(fp3,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);}i++;}fclose(fp2);remove(tb_url);//删除旧文件rename("__temp.txt",tb_url);fclose(fp3);printf("删除数据成功!\n");Sleep(1000);//读取任意键,达到暂停的效果return 0;//跳出循环}else{system("cls");printf("文件出错\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新删除\n 2.结束删除表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");return 0;}}}}//匹配成功的都出去了,匹配失败才会执行下面的语句system("cls");printf("库里没有这个表");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.删除另一个表的数据\n 2.取消删除表操作\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束删除");Sleep(2000);return 0;}
}int update_data(){system("cls");int flag=0,i=1,n,t;//这里初始化i为1struct datas data={0};//初始化结构体char tb_name[10],tb_url[15],haven[16];printf("修改数据\n");printf("=================\n");printf("请输入要修改数据的表的名字:");scanf("%s",tb_name);strcpy(tb_url,tb_name);strcat(tb_url,".txt\n");strcat(tb_name,".txt");while(fgets(haven,16,fp)!=NULL){//一行一个信息????????????????????????????????????if(!strcmp(haven,tb_name)){//发现匹配表if((fp2=fopen(tb_url,"w+"))!=NULL){fp3=fopen("__temp.txt","w+");//修改专用文件printf("请输入要修改的行号:");scanf("%d",&n);fscanf(fp2,"%d\n",&t);for(i=0;i<t;i++){printf("请输入第%d个字段名:",i+1);switch(i){case 0:scanf("%s",data.one);break;case 1:scanf("%s",data.two);break;case 2:scanf("%s",data.three);break;case 3:scanf("%s",data.four);break;}}while(fscanf(fp2,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four)){if(i==n){fprintf(fp3,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);}else{fprintf(fp3,"%22s%22s%22s%22s\n",data.one,data.two,data.three,data.four);}i++;}fclose(fp2);remove(tb_url);//删除旧文件rename("__temp.txt",tb_url);//重命名fclose(fp3);printf("修改数据成功!\n");Sleep(1000);//读取任意键,达到暂停的效果return 0;//跳出循环}else{system("cls");printf("文件出错\n");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.重新修改\n 2.结束修改表\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束修改");return 0;}}}}//匹配成功的都出去了,匹配失败才会执行下面的语句system("cls");printf("库里没有这个表");printf("你有以下两个选择\n");printf("=================\n");printf(" 1.修改另一个表的数据\n 2.取消修改表操作\n 3.退出程序\n");printf("=================\n");printf("请输入你的选择:");scanf("%d",&flag);if(flag==1){return 1;//再次创建}if(flag==2){return 0;//跳出循环}if(flag==3){exit(0);}else{printf("没有该选项!\n结束修改");Sleep(2000);return 0;}
}
总结
版本一的代码复用方面做得很差,版本二吸收了版本一的经验,在设计各个函数结构和返回值的时候花了一点心思。同时对一个项目的做法有了一些改变。在写版本一的时候是从头到尾一气呵成,码字一时爽,debug火葬场,debug的时候发现有些地方根本实现不了,逻辑上出错,这时候要改的话就伤筋动骨(因为有些错误的实现在程序中多次用到)。写版本二的时候受到了敏捷开发的启发,模块化、没写一个模块debug一次,保证始终有“可用版本”,同时因为刚刚写完的模块印象会比较深,所以debug起来也非常快。
有了这次的经验,版本一改起来应该很快,而且调用了mysql.h的话很多地方不需要妥协,使用体验起来肯定会更加舒服。等有时间的时候将版本一改改再发上来。(完)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
