制作一个电子通讯录,通过该通讯录存放好友ID号,姓名(英文),手机号,家庭住址,公司电话,并完成指定功能。
功能模块:主界面:菜单:1)添加好友信息(要求:ID不能相同,相同报错,重新输入,添加成功后提示)
2)列表好友信息(要求:按姓名首字母升序排序)
3)搜索好友(要求:按姓名查询,可以同名,未搜索到提示,搜索到提示并列表出来)
4)删除好友(要求:按姓名删除,未搜索到提示:若好友名唯一,直接删除,并显示好友信息,提 示已删除;若搜索到多个同名好友列表出来,输入ID,按ID删除,删除成功提示)
0)退出程序
#include<stdio.h>
#include <string.h>#include <stdlib.h>
#define MAX 100
#define TRUE 1
#define FALSE 0
#define Status int
#define fname "txl2.txt"
typedef struct
{
char ID[12];
char name[12];
char mphone[12];
char addr[40];
char comtel[16];
}DataType;
typedef struct node /*定义单链表*/
{
DataType data;
struct node *next;
}Node;
typedef Node *llist;
char *menu_1[] = {
"*********主菜单********\n",
"1.INSERT:添加好友信息\n",
"2.DISPLAY:列表好友信息\n",
"3.SERCH:搜索好友\n",
"4.DELETE:删除好友\n",
"0.退出程序\n",
"***********************\n"
};
/**********************
函数名称:fgets_wrapper
参数:buffer输入缓冲区指针;buflen最大输入字符数,实际最大输入buflen-1; fp输入流
功能:重新封装fgets函数;
解决fgets输入时最大长度超过buflen-1个字符后输入缓冲区遗留问题及输入包含'\n'问题
区别: scanf("%s",buffer) 输入字符串不能有空格;
gets(buffer)输入字符串超过buffer长度导致溢出错误;
fgets(buffer,buflen,fp)最大输入buflen-1个字符,'\n'会被输入;输入被截断后输入缓冲区有遗留
***********************/
char *fgets_wrapper(char *buffer, size_t buflen, FILE *fp)
{
if (fgets(buffer, buflen, fp) != 0)
{
size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n')
{
buffer[len-1] = '\0';
}
//清空剩余的数据
else
{
int ch;
while ((ch = getc(fp)) != EOF && ch != '\n');
}
return buffer;
}
return 0;
}
char menu(char *str[],int len) /*主菜单函数*/
{
char sel;
int i;
for (i=0 ; i<len; i++)
{
printf("%s",str[i]);
}
printf("请输入您的选择:");
scanf(" %c",&sel);
getchar();
return sel;
}
Status InitList(llist *L) /*链表的初始化*/
{
*L = (llist)malloc(sizeof(Node));
if ( NULL == *L)
{
return FALSE;
}
else
{
(*L)->next = NULL;
return TRUE;
}
}
int ListLength(llist L) /*链表长度,通讯录的成员数*/
{
int i = 0;
llist p;
p = L->next;
while (NULL != p)
{
i++;
p = p->next;
}
return i;
}
Status ListEmpty(llist L) /*判断通讯录是否为空*/
{
if ( 0 == ListLength(L))
{
return TRUE;
}
else
{
return FALSE;
}
}
Status ListInsert(llist *L,int i,DataType e) /*链表的插入,通讯录添加元素*/
{
int j=1;
llist p,q;
if (i<1 || i > ListLength(*L)+1)
{
return FALSE;
}
p = (*L);
while (NULL != p && j<i)
{
p = p->next;
j++;
}
q = (llist)malloc(sizeof(Node));
if ( NULL == q)
{
printf("内存分配失败,按回车键退出...\n");
getchar();
exit(0);
}
else{
q->data = e;
q->next = p->next;
p->next = q;
}
return TRUE;
}
Status input(DataType *e,llist L) /*通讯录成员信息输入,输入ID与通讯录原有成员ID相同时报错,并提醒重新输入信息*/
{
llist p;
p=L->next;
int i=0;
printf("请输入ID:");
fgets_wrapper(e->ID,12,stdin);
for(p;NULL !=p;p=p->next)
{
if(!strcmp(e->ID,p->data.ID))
{
printf("ID冲突,请重新输入ID\n");
input(e,L);
i++;
}
}
if( 0 ==i)
{
printf("请输入姓名:");
fgets_wrapper(e->name,12,stdin);
printf("请输入手机号:");
fgets_wrapper(e->mphone,12,stdin);
printf("请输入家庭住址:");
fgets_wrapper(e->addr,40,stdin);
printf("请输入公司电话:");
fgets_wrapper(e->comtel,16,stdin);
}
else
{
return FALSE;
}
getchar();
return TRUE;
}
Status GetElem(llist L,int i,DataType *e) /*获取通讯录中第i个成员的信息,并用e返回其值*/
{
int j=1;
llist p;
if (i<1 || i > ListLength(L))
{
return FALSE;
}
p = L;
while (NULL != p && j<i)
{
p = p->next;
j++;
}
p = p->next;
*e = p->data;
return TRUE;
}
Status output(DataType e) /*输出成员信息*/
{
printf("好友ID:%s\n",e.ID);
printf("姓名:%s\n",e.name);
printf("手机号码:%s\n",e.mphone);
printf("家庭住址:%s\n",e.addr);
printf("公司电话:%s\n",e.comtel);
return TRUE;
}
Status ListDelete(llist *L,int i,DataType *e) /*删除通讯录中第i个成员的信息,并用e返回其值*/
{
int j = 1;
llist p,q;
if ( i<1 || i>ListLength(*L))
{
return FALSE;
}
p = (*L);
while (NULL != p && j<i)
{
p = p->next;
j++;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return TRUE;
}
Status ClearList(llist *L) /*清空通讯录*/
{
int i = 0,len;
llist p,q;
if (NULL == (*L)->next)
{
return TRUE;
}
p = q = (*L)->next;
do
{
p = p->next;
free(q);
i++;
q = p;
}while(NULL != p);
(*L)->next = NULL;
printf("cleared item = %d\n",i);
return TRUE;
}
void sorted(llist M) /*对通讯录中的成员按姓名首字母升序排序*/
{
int flag=TRUE;
DataType temp;
llist p,q;
for(p=M;NULL !=p ->next ;p=p->next)
{
flag=FALSE;
for(q=p->next;NULL != q ;q=q->next)
{
if(strcmp(p->data.name,q->data.name)>0)
{
temp=p->data;
p->data=q->data;
q->data=temp;
flag=TRUE;
}
}
}
}
Status Display(llist L) /*将排序好的成员列表*/
{
sorted(L);
int i,j;
DataType e;
llist p;
if ( NULL == L->next)
{
printf("当前还没有任何记录\n");
printf("按回车键继续...\n");
getchar();
}
else
{
p = L->next;
i=1;
//for(i=0; i<L.length; i++)
while( NULL != p)
{
printf("第%d条记录\n",i);
output(p->data);
printf("\n");
p = p->next;
i++;
}
printf("按回车键继续...\n");
getchar();
}
return TRUE;
}
int * LocateList(llist L, char *str) /*找出通讯录中与所输姓名相同的成员,所有相同的成员返回成员编号,不相同的返回 -1*/
{
int i,j;
llist p;
p = L->next;
j=0;
int *a;
a=(int *)malloc(sizeof(Node)); /*每一个Node类型大小的成员分配int * 大小的空间*/
*(a+0)= - 1;
if (NULL == L->next)
{
return a;
}
else
{
i = 1;
while(NULL != p)
{
if(!strcmp(str,p->data.name))
{
j++;
*(a+j)=i;
i++;
p=p->next;
}
else
{
j++;
*(a+j)= - 1;
i++;
p=p->next;
}
}
return a;
}
}
int LocateList_num(llist L,char * str) /*找出通讯录中与所输ID相同的成员,返回成员编号*/
{
int i;
llist p;
p = L->next;
if (NULL == L->next)
{
return -1;
}
i = 1;
while(NULL != p)
{
if (!strcmp(str,p->data.ID))
{
return i;
}
else
{
p = p->next;
i++;
}
}
return -1;
}
Status query(llist L) /*输入姓名,按姓名查询,无此人提示,若有多个同名的成员,列表出来*/
{
char name[12];
int i;
DataType e;
llist p;
Status flag=0;
int *q;
printf("请输入姓名:");
fgets_wrapper(name,12,stdin);
q= LocateList(L,name);
for(i=0;i<=ListLength(L);i++)
{
if (-1 != *(q+i))
{
printf("查询到记录,显示如下:\n");
GetElem(L,*(q+i),&e);
output(e);
flag=1;
printf("\n");
}
}
if(0 == flag)
{
printf("查无此人,按回车键继续");
getchar();
}
getchar();
return TRUE;
}
Status delete(llist *L) /*输入姓名,按姓名删除成员,无此人报错提示,若只有一个成员直接删除,若有多个同名的成员,列表出来, 再输入ID,按ID删除成员*/
{
char name[12];
char ID[12];
int *str;
DataType e;
int i=0;
int j=0;
int k;
Status flag=0;
printf("请输入姓名:");
fgets_wrapper(name,12,stdin);
str = LocateList(*L,name);
for(i=1;i<=ListLength(*L);i++)
{
if (-1 != *(str+i))
{
j++;
}
}
if(0 == j)
{
printf("无此人,按回车键继续...\n");
getchar();
}
else if(j== 1)
{
for(i=1;i<=ListLength(*L);i++)
{
if (-1 != *(str+i))
{
printf("有此人,信息如下:\n");
GetElem(*L,*(str+i),&e);
output(e);
ListDelete(L,*(str+i),&e);
printf("已删除\n");
printf("按回车键继续\n");
getchar();
}
}
}
else
{
for(i=1;i<=ListLength(*L);i++)
{
if (-1 != *(str+i))
{
printf("有此人,信息如下:\n");
GetElem(*L,*(str+i),&e);
output(e);
}
}
printf("有多个同名好友,按ID号删除\n");
printf("请输入ID:");
fgets_wrapper(ID,12,stdin);
j = LocateList_num(*L,ID);
if (-1 != j)
{
GetElem(*L,j,&e);
output(e);
ListDelete(L,j,&e);
printf("已删除\n");
printf("按回车键继续...\n");
getchar();
}
else
{
printf("查无此人,按回车键继续...\n");
getchar();
}
}
return TRUE;
}
int Rfile(llist *L){ /*文件操作,标准i/0,读数据*/
FILE *fp;
DataType e;
int i,size;
if((fp=fopen(fname,"a+"))==NULL)
{
perror("打开文件失败");
return FALSE;
}
fseek(fp,0,SEEK_END);
size=ftell(fp)/sizeof(DataType); /*ftell(fp)测文件大小 ,size成员个数*/
rewind(fp);
for(i=0;i<size;i++){
fread(&e,sizeof(DataType),1,fp);
ListInsert(L,ListLength(*L)+1,e);
}
fclose(fp);
return TRUE;
}
int Wfile(llist *L){ /*标准i/o操作,写数据*/
FILE *fp;
DataType e;
llist p=(*L)->next;
if((fp=fopen(fname,"w"))==NULL)
{
perror("打开文件失败");
return FALSE;
}
while(p!=NULL)
{
e=p->data;
fwrite(&e,sizeof(DataType),1,fp);
p=p->next;
}
fclose(fp);
return TRUE;
}
/****************************************************************************************************************8*
* 制作一个电子通讯录,通过该通讯录存放好友ID号,姓名(英文),手机号,家庭住址,公司电话,并完成指定功能。
* 功能模块:主界面:菜单:1)添加好友信息(要求:ID不能相同,相同报错,重新输入,添加成功后提示)
* 2)列表好友信息(要求:按姓名首字母升序排序)
* 3)搜索好友(要求:按姓名查询,可以同名,未搜索到提示,搜索到提示并列表出来)
* 4)删除好友(要求:按姓名删除,未搜索到提示:若好友名唯一,直接删除,并显示好友信息,提示已删除;若搜索到多 个同名好友列表出来,输入ID,按ID删除,删除成功提示)
* 0)退出程序
*
*******************************************************************************************************************/
int main(int argc,char *argv[])
{
llist txl;
int k;
Status flag;
DataType e;
char sel;
flag = InitList(&txl); /*初始化*/
if (!flag)
{
printf("内存分配失败,按回车键退出...\n");
getchar();
exit(0);
}
if(FALSE == Rfile(&txl))
{
printf("文件打开失败\n");
exit(1);
}
while (1)
{
sel = menu(menu_1,7);
switch (sel)
{
case '1':memset(&e,0,sizeof(DataType));input(&e,txl);ListInsert(&txl,ListLength(txl)+1,e);printf("添加成功\n");break;
case '2':Display(txl);break;
case '3':query(txl);break;
case '4':delete(&txl);break;
case '0':printf("谢谢使用本软件,按回车键退出...\n");Wfile(&txl);getchar();exit(0);break;
default:printf("错误输入\n");break;
}
}
return 0;
}