按照惯例,一波课程设计走起~
这次写的是通讯录管理系统,经过几番大修和N+1次小修之后BUG已经很少了~先来看看期间遇到的哪些问题吧:
Qusetion
1:针对手机号的排序问题(即交换结构体)
2:文件写入和调用时乱码的问题
3:界面美化问题和用户体验感优化
一:针对手机号的排序问题(即交换结构体)
void swap(person *p){ //交换结构体
person *temp;
temp = p->next->next; //temp=p3
p->next->next = p->next->next->next; //p3=p4
temp->next = p->next; //p4=p2
p->next = temp; //p2=p3
}
emmm,你可以试着想想四个杯子在一起放着(p1-p4),然后再拿出一个空的(temp),把第三个杯子的水倒入空杯子中,然后第四个杯子倒入第三个,第二个倒入第四个,第三个倒入第二个,即完成结构体的交换= = 好了自己理解理解~
然后应用:
while (p2->next->next != NULL){
if (atoi(p2->next->phone)>atoi(p2->next->next->phone)){ //防止输入非int型数据
swap(p2); k++;
}
p2 = p2->next;
}
即可完成~
二:文件写入和调用时乱码的问题
void save(person *head){ //**保存文件信息**
FILE *fp;
if ((fp = fopen("1.txt", "w")) == NULL){
cout << "The file 1.txt can not be opened." << endl;
return;
}
person *p = head->next;
while (p != NULL){
fprintf(fp, "%s %s %s %s \n", p->name, p->city, p->phone,p->num);
p = p->next;
}
fclose(fp);
}
如果运行,可以发现这里是不会报错的。 而运行程序后,输入数据,程序就会出错而关闭,此时输入的数据并未存储下来,进而也就无法读取。
想办法处理,发现定义的数据类型不尽相同:
struct person {
char name[20];
char city[20];
char phone[20];
int num;
struct person *next;
};
手机号num定义的是int整型变量,所以先将上面的%s换为%d,再运行试试。结果继续报错,也未成功存储数据。
再来看看读取文件的错误:
void duqu(person *head){ //**读取文件信息**
FILE *fp;
if ((fp = fopen("1.txt", "r")) == NULL){
return;
}
while (!feof(fp)){
person *p = head;
person *p2 = new person;
fscanf(fp, "%s %s %s %d", p2->name, p2->city, p2->phone,p2->num);
while (p->next != NULL){
p = p->next;
}
p->next = p2;
p2->next = NULL;
}
fclose(fp);
}
细心地同学会发现,已经把%s改了过来,但是读取数据时候程序仍然会出错停止运行,然而更扯淡的是改来改去Dev都不会报错= = 此时发现这款编译器的辣鸡之处了!
忽然想起某大佬(刘性大佬)曾说过scanf使用格式,发现没有加取地址符&,改正之,运行,仍然报错。后来搜寻无果,只得重头看起代码来~发现person *p = head ;
定义在while里,从头到尾都是打渣子的,并未起到应该起的作用,只是p2指向的缓存区不停地读值,释放,肯定会报错。将它定义在while前,即在FILE *fp;
后,就完美解决了问题~输入也运行并保存成功了!!
三:界面美化问题和用户体验感优化
读取文件时,如果1.txt不存在,将会创建该txt文本文档 ,并出现一行美美的提示语~
void duqu(person *head){ //**读取文件信息**
FILE *fp;
person *p = head;
if ((fp = fopen("1.txt", "r+")) == NULL){
cout<<"\n\n\n\n\n\n\n 初次启动 系统加载中";
Sleep(500);cout << "●";Sleep(500);cout << "●";Sleep(500);cout << "●";
Sleep(500);cout << "●";Sleep(500);cout << "●";Sleep(500);cout << "●";
return;
}
else{
while (!(feof(fp))){
person *p2 = new person;
fscanf(fp, "%s %s %s %d\n", &p2->name, &p2->city, &p2->phone, &p2->num);
p->next = p2;
p = p->next;
p->next = NULL;
}
}
fclose(fp);
}
效果如图:
在显示功能中加入:cout << "显示完成\n" << endl;system("pause");cout << "返回主菜单";
在输入联系人功能中排除相同姓名用户(理论是可以重名的,但是强迫症= =)
while (p->next != NULL){
if (strcmp(p->next->name, p2->name) == 0){
cout << "此联系人已经存在\n即将返回主窗口" << endl;
Sleep(1000);
return;
}
p = p->next;
}
在修改联系人功能中加入和添加相同的功能:
while (p3->next != NULL){
if (strcmp(p3->next->name, p2->name) == 0){
cout << "与其他联系人姓名重复 即将返回主菜单";
Sleep(1000);
return;
}
p3 = p3->next;
}
界面美化:
添加大量Sleep(),getch(),system()等函数,提升用户体验感和友好度。
因为某兔子说过,一款程序写的再好,如果用户体验感极差,它也是要GG的~
感谢某兔学姐,某李性大佬,某浪学长给予的大力支持与鼓励!