一个通讯录程序(C)
《C语言与程序设计大学教程》一书第11章第6题:通讯簿中每一条记录包括:姓名、电话号码、住址、邮件地址信息。根据注释完成下述程序中的函数定义。程序如下,在阅读如下程序时,需要注意:1) fputs、fgets的使用。想想为什么不用fscanf、fprintf? 2)对动态链表的操作。3)字符串指针的使用。
说明:本程序在编写时并未在意界面的友好性。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define NAME_LENGTH 12 /*姓名的长度*/
#define TEL_LENGTH 12
#define ADDRESS_LENGTH 30
#define EMAIL_LENGTH 20
#define SUCCESS 1
#define FAILURE 0
typedef struct Record
{
char *name;
char *tel;
char *address;
char *email;
struct Record *next;
}Record;
/*功 能:从键盘上接收一个人的姓名、电话、地址、email信息*/
/*返回值:Record指针*/
Record *acceptARecord()
{
Record *record = NULL;
char c;
printf("\n你确定要输入一条新记录吗(Y/N)?");
fflush(stdin);
c = getchar();
if('N' == c)
{
return NULL;
}
record = (Record*)malloc(sizeof(Record));
if(NULL == record)
{
return NULL;
}
record->name = (char*)malloc(NAME_LENGTH);
record->tel = (char*)malloc(TEL_LENGTH);
record->address = (char*)malloc(ADDRESS_LENGTH);
record->email = (char*)malloc(EMAIL_LENGTH);
fflush(stdin);
printf("请输入姓名(以回车结束):");
gets(record->name);
printf("请输入电话(以回车结束):");
gets(record->tel);
printf("请输入地址(以回车结束):");
gets(record->address);
printf("请输入电子邮件地址(以回车结束):");
gets(record->email);
record->next = NULL;
return record;
}
/*功 能:将一条记录增加到带头结点的动态链表中*/
/*形式参数:newRecord指向等加入链表的结点,root是动态链表的头结点*/
/*返 回 值:成功新加返回SUCCESS,否则返回FAILURE*/
int addRecord(Record *newRecord, Record *root)
{
Record *tmpRec = root;
if(NULL == newRecord)
{
return FAILURE;
}
if(NULL == root)
{
return FAILURE;
}
while(NULL != tmpRec->next)
{
tmpRec = tmpRec->next;
}
tmpRec->next = newRecord;
//printf("Add a record successfully!\n");
return SUCCESS;
}
/*功 能:在带头结点的动态链表中按姓名查找*/
/*形式参数:name指向姓名,root是动态链表的头结点*/
/*返 回 值:找到指定姓名的记录,返回指向该结点的指针,否则返回0*/
const Record * findRecord(char *name, Record *root)
{
Record *tmpRec = NULL;
if(NULL == root)
{
return NULL;
}
tmpRec = root->next;
while(NULL != tmpRec)
{
if(0 == strcmp(tmpRec->name, name))
{
return tmpRec;
}
tmpRec = tmpRec->next;
}
return NULL;
}
void delNode(Record *rp)
{
free(rp->name);
free(rp->tel);
free(rp->email);
free(rp->address);
free(rp);
}
/*功 能:清空动态链表中的所有结点*/
/*形式参数:root是动态链表的头结点*/
/*返 回 值:无*/
void removeRecords(Record *root)
{
Record *tmpRec = NULL, *delRec = NULL;
if(NULL == root)
{
return;
}
while(NULL != root->next)
{
tmpRec = root->next;
root->next = root->next->next;
delNode(tmpRec);
}
root->next = NULL;
}
/*功 能:打印带头结点的动态链表中所有结点中的姓名、地址、电话、email信息*/
/*形式参数:root是动态链表的头结点*/
/*返 回 值:无*/
void printRecords(Record *root)
{
Record *tmpRec = NULL;
if(NULL == root)
{
return;
}
tmpRec = root->next;
while(NULL != tmpRec)
{
printf("%s %s %s %s\n", tmpRec->name, tmpRec->tel, tmpRec->address, tmpRec->email);
tmpRec = tmpRec->next;
}
}
/*功 能:将带头结点的动态链表中的通讯录信息写入到filename指定的文本文件中*/
/*形式参数:filename指向文件名,root是动态链表的头结点*/
/*返 回 值:成功写入,则返回SUCCESS,否则返回FAILURE*/
int saveRecords(char *filename, Record *root)
{
Record *tmpRec = NULL;
FILE *fp = NULL;
if(NULL == root || NULL == root->next)
{
return FAILURE;
}
fp = fopen(filename, "w");
if(NULL == fp)
{
return FAILURE;
}
tmpRec = root->next;
while(NULL != tmpRec)
{
fputs(tmpRec->name,fp);
fputs("\n", fp);
fputs(tmpRec->tel, fp);
fputs("\n", fp);
fputs(tmpRec->address, fp);
fputs("\n", fp);
fputs(tmpRec->email, fp);
fputs("\n", fp);
//fprintf(fp, "%12s %12s %30s %20s\n", tmpRec->name, tmpRec->tel, tmpRec->address, tmpRec->email);
tmpRec = tmpRec->next;
}
fclose(fp);
}
/*功 能:将filename指定的文件中的内容读到带头结点的动态链表中*/
/*形式参数:filename指向文件名,root是动态链表的头结点*/
/*返 回 值:成功读入,则返回SUCCESS,否则返回FAILURE*/
int readRecords(char * filename, Record *root)
{
Record *tmpRec = NULL;
FILE *fp = NULL;
if(NULL == root)
{
return FAILURE;
}
fp = fopen(filename, "r");
if(NULL == fp)
{
return FAILURE;
}
while(!feof(fp))
{
tmpRec = (Record*)malloc(sizeof(Record));
if(NULL == tmpRec)
{
return FAILURE;
}
tmpRec->name = (char*)malloc(NAME_LENGTH);
tmpRec->tel = (char*)malloc(TEL_LENGTH);
tmpRec->address = (char*)malloc(ADDRESS_LENGTH);
tmpRec->email = (char*)malloc(EMAIL_LENGTH);
tmpRec->next = NULL;
//fscanf(fp, "%12s %12s %30s %20s\n", tmpRec->name, tmpRec->tel, tmpRec->address, tmpRec->email);
if(NULL == fgets(tmpRec->name, NAME_LENGTH, fp))
{
delNode(tmpRec);
break;
}
tmpRec->name[strlen(tmpRec->name)-1] = '\0';
if(NULL == fgets(tmpRec->tel, TEL_LENGTH, fp))
{
delNode(tmpRec);
break;
}
tmpRec->tel[strlen(tmpRec->tel)-1] = '\0';
if(NULL == fgets(tmpRec->address, ADDRESS_LENGTH, fp))
{
delNode(tmpRec);
break;
}
tmpRec->address[strlen(tmpRec->address)-1] = '\0';
if(NULL == fgets(tmpRec->email, EMAIL_LENGTH, fp))
{
delNode(tmpRec);
break;
}
tmpRec->email[strlen(tmpRec->email)-1] = '\0';
if(FAILURE == addRecord(tmpRec, root))
{
return FAILURE;
}
}
fclose(fp);
}
int main(void)
{
char s[NAME_LENGTH] = "";
const Record * findResult = NULL;
Record *root = (Record*)malloc(sizeof(Record)); /*动态链表的头结点*/
Record *rp = NULL;
root->next = NULL;
/*从键盘上接收若干条通讯录记录,每一条记录占据动态链表中的一个结点*/
while(1)
{
rp = acceptARecord(); /*从键盘上接收一个人的通讯信息*/
if(!rp)
break;
if(FAILURE == addRecord(rp, root))
{
break;
} /*将通讯录记录加入到动态链表中*/
}
printRecords(root); /*打印所有通讯录记录*/
saveRecords("c:\\contactRecords.txt", root); /*将通讯录中所有记录写入到文件中*/
removeRecords(root); /*删除内存中的所有通讯录记录*/
readRecords("c:\\contactRecords.txt", root); /*从文件中将记录读入到动态链表中*/
printRecords(root); /*打印所有通讯录记录*/
printf("请输入人名:");
fflush(stdin);
fgets(s, NAME_LENGTH-1, stdin);
s[strlen(s)-1]='\0';
findResult = findRecord(s, root); /*按姓名查找它的通讯信息*/
if(NULL != findResult)
{
printf("%s %s %s %s\n", findResult->name, findResult->tel, findResult->address, findResult->email);
}
removeRecords(root);
free(root); /*释放头结点*/
system("PAUSE");
return 0;
}
执行结果示意:
你确定要输入一条新记录吗(Y/N)?Y
请输入姓名(以回车结束):BJ_BOY
请输入电话(以回车结束):010-884848443434
请输入地址(以回车结束):Beijing City
请输入电子邮件地址(以回车结束):BJ_BOY@
Add a record successfully!
你确定要输入一条新记录吗(Y/N)?Y
请输入姓名(以回车结束):Zhang san
请输入电话(以回车结束):010-493994939942
请输入地址(以回车结束):Nanjing City
请输入电子邮件地址(以回车结束):Zhang_san@
Add a record successfully!
你确定要输入一条新记录吗(Y/N)?N
BJ_BOY 010-884848443434 Beijing City BJ_BOY@
Zhang san 010-493994939942 Nanjing City Zhang_san@
Add a record successfully!
Add a record successfully!
BJ_BOY 010-884848 43434 Beijing City
BJ_BOY@133 com Zhang san 010-493994939942
请输入人名:BJ_BOY
BJ_BOY 010-884848 43434 Beijing City
请按任意键继续. . .