| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 750 人关注过本帖
标题:一个通讯录程序(C)
只看楼主 加入收藏
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
结帖率:0
收藏
 问题点数:0 回复次数:4 
一个通讯录程序(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
请按任意键继续. . .
搜索更多相关主题的帖子: 通讯录 
2010-07-11 12:11
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
不好意思,上面的执行结果粘贴错误了(程序无误哟)!正确的结果,我懒得粘贴了。有兴趣的读者拷贝到本机执行一下就好了:)

注意:输入字符串时有长度的限制哟!
2010-07-11 12:17
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
版本二:在能使用const的地方尽量使用const。
提示:读者需要知道const的作用。如:const int *p; const int *const p; int *const p;的区别。

#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(const Record *const newRecord, const Record *const root)
{
    Record *tmpRec = (Record *)root;
    if(NULL == newRecord)
    {
        return FAILURE;
    }
   
    if(NULL == root)
    {
        return FAILURE;
    }
   
    while(NULL != tmpRec->next)
    {
        tmpRec = tmpRec->next;
    }
    tmpRec->next = (Record*)newRecord;
    //printf("Add a record successfully!\n");

    return SUCCESS;   
}

/*功    能:在带头结点的动态链表中按姓名查找*/
/*形式参数:name指向姓名,root是动态链表的头结点*/
/*返 回 值:找到指定姓名的记录,返回指向该结点的指针,否则返回0*/
const Record *const findRecord(const char *const name, const Record *const 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(const Record *const rp)
{
   free(rp->name);
   free(rp->tel);
   free(rp->email);
   free(rp->address);               
   free((void*)rp);
}

/*功    能:清空动态链表中的所有结点*/
/*形式参数:root是动态链表的头结点*/
/*返 回 值:无*/
void removeRecords(Record *const 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(const Record *const 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(const char *const filename, const Record *const 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(const char *const filename, const Record *const 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;   
}
2010-07-11 16:26
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
再顶起来,这么好的东西,没人读吗?:)哈
2010-07-13 16:19
束缚袭霜
Rank: 2
等 级:论坛游民
帖 子:21
专家分:30
注 册:2010-7-4
收藏
得分:0 
楼主就是malloc()函数用太多了,不如直接在结构体中定义,这样节省系统资源的。

还有佩服楼主的恒心和连续性。

我是自学的,所以……
2010-07-13 18:34
快速回复:一个通讯录程序(C)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.038680 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved