#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
struct ADS
{ char name[20];
char street[20];
char city[20];
char tele[20];
struct ADS* next;
};
int total=0; //统计通讯录人数
void Save( struct ADS *head);
struct ADS* Create() //创建单链表,返回结构体指针
{ int total=0;
int k=0,i=0;
struct ADS *head,*p1,*p2,*p3; //p1,p2移动,p3遍历
char saveflag; //接收选择:Y 或 Y
head=p1=p2=NULL;
while(1) //循环可以实现多次添加记录
{
p1=( struct ADS*)malloc(sizeof( struct ADS));
printf(“请输入姓名或键入“*”结束\n”);
scanf(“%s”,p1->name);
if (strcmp(p1->name,”*”)==0)
{
if(total==0)
{ printf(“当前没记录……\n”);
free(p1);
return (head); //返回头指针
}
else { break; }
}
printf(“请输入所在街道:\n”);
scanf(“%s”,p1->street);
printf(“请输入所在城市:\n”);
scanf(“%s”,p1->city);
printf(“请输入电话号码:\n”);
scanf(“%s”,p1->tele);
if (k>0) //判断通讯录能否存在标志
{
p3=head; //p3遍历
while(p3!=NULL)
{ if((strcmp(p1->name,p3->name)==0)&&(strcmp(p1->tele,p3->tele)==0))
{ free(p1);
printf(“记录已存在,请按任意键返回主菜单重新输入。\n”);
i=1;
getchar();break;
}
if((strcmp(p1->name,p3->name))&&(strcmp(p1->tele,p3->tele))&&(p3==p2))
{ i=0;break; } //跳出第一个内循环
p3=p3->next;
}
if (i==1) { break; } //跳出第二个内循环
}
if(head==NULL) //首次创建
{ head=p1;p2=p1; }
else
{ p2->next=p1; p2=p1; } //第二次之后p2后移
total++; //录入成功加1
k++;
}
p2->next=NULL;
if(i==0)
{free(p1);
printf(“\n新建通讯录成功,当前共有%d个联系人,保存?(Y or N)\n”,total);
getchar();
scanf(“%c”,&saveflag);
if (saveflag==”y”||saveflag==”Y”)
Save(head);
else
printf(“未保存成功。请返回主菜单退出系统前按7保存。\n”);
}
return head;
}
void Save(struct ADS *head)
{
FILE *fp; //定义文件指针接收fopen返回值,用于最后关闭文件
struct ADS* t;
if ((fp=fopen(“address_list.txt”,”w”))==NULL)
{
printf(“fail to open file!|\n”);
getchar();
exit(0);
}
t=head;
while(t!=NULL)
{
fprintf(fp,” %s %s %s %s\n”,t->name,t->street,t->city,t->tele); //将链表的东西写入文件
t=t->next;
}
fclose(fp);
printf(“\n保存成功,请按任意键返回主菜单……\n”);
getchar();
getchar();
}
struct ADS* Output()
{
FILE *fp;
struct ADS *t1,*t2,*head=NULL;
char ch;
if((fp=fopen(“address_list.txt”,”r”))==NULL)
{
printf(“fail to open file!\n”);
printf(“请按任何键退出……\n”);
getchar();
exit(0);
}
ch=fgetc(fp);
if(ch==EOF)
{
printf(“文件为空,请重新建立通讯录。\n请按任意键返回主菜单……\n”);
getchar();
return(head);
}
else
{rewind(fp); } //指针移向开头
t1=(struct ADS*)malloc(sizeof(struct ADS)); //申请动态空间,t1接下去
head=t1;
printf(“\t姓名\t街道\t 城市\t 电话号码\n”);
printf(” –\n”);
while(!feof(fp))
{
fscanf(fp,”%s %s %s %s”,t1->name,t1->street,t1->city,t1->tele);
printf(“\t%s\t%s\t%s\t%s\t\t\n”,t1->name,t1->street,t1->city,t1->tele);
total++;
t1->next=(struct ADS*)malloc(sizeof(struct ADS)); //t1->next赋给下一个申请的结点
t2=t1;
t1=t1->next;
}
t2->next=NULL;
free(t1);
fclose(fp);
printf(“\nOK!请按任意键返回菜单……\n”);
getchar();
getchar();
return head;
}
void Search(struct ADS* head)
{
int count=1;
struct ADS* p;
int flag,searchflag=1; //判断数据能否符合要求标志
char name[10],temp; //存放输入的名字
p=head; //# 漏 #
printf (“请输入查询名字:\n”);
scanf(“%s”,name);
while(p!=NULL)
{
if(strcmp(name,p->name)==0)
{
printf(“%d”,count);
count++;
printf(“\t姓名:%s\t街道:%s\t城市:%s\t电话号码:%s\n”,p->name,p->street,p->city,p->tele);
flag=1;
}
p=p->next;
}
if(flag==0)
{printf(“未找到您要的记录!\n能否重新查询? Y or N \n”);}
scanf(“%c”,&temp);
getchar();
getchar();
if(temp==”y”||temp==”Y”) {searchflag=1;}
else {searchflag=0; system(“cls”);}
}
struct ADS* Delete(struct ADS *head)
{
struct ADS *p1,*p2,*p3; //p3是遍历整个链表,p1,p2是用来检查目的结点
char saveflag; //存录与否
char temp,name[10];
int i;
p1=head;
p2=head;
p3=head;
printf(“请输入要删除的姓名:\n”);
scanf(“%s”,name);
while(p3!=NULL) //遇到所寻结点时赋值i,进一步操作
{ if (strcmp(p3->name,name)==0)
{ i=1; break; } //找到即赋值为1
if ((strcmp(p3->name,name)!=0)||(p3->next==NULL))
{ i=0; } //不存在即为0
p3=p3->next; //p3后移
}
if(i==1)
{
while((strcmp(p1->name,name))!=0&&(p1!=NULL))
{p2=p1; //p2(在p1前面)指向p1
p1=p1->next; //p1后移,进行下一步
}
}
if(i==0)
{
printf(“未找到您所查找的姓名,请检查能否输入正确?\n请按任意键返回主菜单……\n”);
getchar();
}
if((i==1)&&(p1!=NULL)) //所寻结点非末结点
{
printf(“您要删除的通讯录记录为:\n\n”);
printf(“\t姓名\t街道\t城市\t\t电话号码\n”);
printf(“–\n”);
printf(“%s\t\t%s\t%s\t%s\t\t\n”,p1->name,p1->street,p1->city,p1->tele);
printf(“问一下能否删除该记录? Y or N \n”);
scanf(“%c”,&saveflag);
if (saveflag==”y”||saveflag==”Y”)
{
if (p1==head) head=p1->next; //目标结点为首结点,删除
else p2->next=p1->next; //删除非首结点的目的结点
free(p1); //释放p1空间
printf(“删除成功,能否存录? Y or N ?\n”);
scanf(“%c”,&temp);
if (temp==”y”||temp==”Y”)
{ Save(head); total–; printf(“\nDelete ok!\n”); } //记录减一
else
{ printf(“保存失败,请重新进行上一步操作……\n”);
printf(“请按任意键返回主菜单!\n”);
getchar();
}
}
}
return (head);
}
struct ADS* Delete_all(struct ADS* head)
{ FILE *fp;
char ch;
getchar();
printf(“确定删除全部记录?Y or N \n”);
scanf(“%c”,&ch);
if (ch==”N”) return head;
remove(“address_list”); //直接删除文件
if((fp=fopen(“address_list.txt”,”w”))==NULL)
printf(“fail to open file!\n”);
return 0;
}
struct ADS* Add(struct ADS* head) //返回结构体指针
{
char saveflag; //存录与否
int i=0,k=0;
struct ADS *p1,*p2,*p3; //p3遍历,p1,p2临时移动
struct ADS * add; //add存放添加信息
p1=head; //先让p1指向头指针
system(“cls”);
while(p1!=NULL)
{ p2=p1;
p1=p1->next;
}
printf(“请输入添加人姓名、街道、城市、电话号码:\n”);
add=(struct ADS *)malloc(sizeof(struct ADS));
scanf(“%s%s%s%s”,add->name,add->street,add->city,add->tele);
p3=head; //p3遍历
while(p3!=NULL)
{
if((strcmp(add->name,p3->name)==0)&&(strcmp(add->tele,p3->tele)==0))
{
free(add); //释放重复空间
printf(“记录已存在,请按任意键返回主菜单重新输入。\n”);
i=1;
getchar(); break;
}
if((strcmp(add->name,p3->name)==0)&&(strcmp(add->tele,p3->tele))&&(p3==p2))
//到了最后一个点还没有和它相同的结点时
{ i=0; break; } // 跳出第一个循环
p3=p3->next;
}
if(i==0)
{
add->next=NULL;
if(p1==head) head=add;
else {p2->next=add;} //最后一个p2结点的next插入add
total++;
k++;
free(p1);
printf(“新添电话号码成功,能否存录?Y or N\n”);
getchar();
scanf(“%c”,&saveflag);
if(saveflag==”Y”||saveflag==”y”)
{ Save(head); total++; }
else
{printf(“保存失败,请重新进行上一步操作……\n”);
getchar();
}
}
return (head);
}
struct ADS* load()
{ FILE *fp;
struct ADS *p1,*p,*head=NULL;
char ch;
if((fp=fopen(“address_list”,”r”))==NULL)
//if((fp=fopen(“address_list”,”w”))==NULL)
{ printf(“fail to open file!\n”);
getchar();
exit(0);
}
/* ch=fgetc(fp);
if(ch==EOF)
{ printf(“文件为空,请返回主菜单选择1.新建。\n”);
return (head);
}
else rewind(fp);*/
p1=(struct ADS *)malloc(sizeof(struct ADS));
head=p1;
while(!feof(fp))
{ if(fread(p1,sizeof(struct ADS),1,fp)!=1) break;
p1->next=(struct ADS *)malloc(sizeof(struct ADS));
p=p1;
p1=p1->next;
}
p1->next=NULL;
//free(p);
fclose(fp);
return head;
}
int main()
{ int n;
struct ADS *head=NULL;
while(1) //非零为真即可无限循环
{
printf(“\n”);
printf(“\t\t\t\t\t# # # # # # # 欢迎使用 # # # # # # # \n”);printf(“\n”);
printf(“\t\t\t\t # # # # # # # # 通讯录管理系统 # # # # # # # # #\n”);printf(“\n”);
printf(” \t\t\t\t\t* 1.新建 * 2.显示 *\n\t\t\t\t\t* 3.新添 * 4.查询 *\n”);
printf(” \t\t\t\t\t* 5.删减 * 6.全删 *\n\t\t\t\t\t* 7.保存 * 8.退出 *\n”);
printf(“\n”);
printf(“\t\t\t\t请选择操作(1—6):\n”);printf(“\n”);
scanf(“%d”,&n); //分支选择
switch(n)
{
case 1:head=Create();break;
case 2:head=Output();break;
case 3:head=Add(head);break;
case 4:head=load();Search(head);break;
case 5:head=Delete(head);break;
case 6:head=Delete_all(head);system(“cls”);break;
case 7:Save(head);break;
case 8:exit(0);system(“cls”);break;
default:printf(“您输入有误,请重新输入……\n”);
}
}
return 0;
}
这通讯录管理系统的查询功能由于在首次查询时没有读取文件,所以听老师建议加了个load函数进去,但是调试不了,总是出错……尴尬,哪位高手可以帮本人看看load函数哪里出错了?请指点……
30
提醒:再牛×的老师也无法代替学生本人领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
15
本人试了下查询,load()出来居然有乱码,本人改了下load加载文件部分,你看看,希望对你有帮助
printf(” –\n”);
while(fgets((char*)t1, sizeof(struct ADS), fp))
{
sscanf((char*)t1,”%s %s %s %s”,t1->name,t1->street,t1->city,t1->tele);
printf(“\t%s\t%s\t%s\t%s\t\t\n”,t1->name,t1->street,t1->city,t1->tele);
total++;
t1->next = t1;
memset(t1, 0, sizeof(struct ADS));
}
free(t1);
10
v=pum[0];pum++;