c语言实现简单通讯录

我们都知道通讯录有的一些基本简单的功能就是:
1.增加联系人 2.删除联系人
3.查找联系人 4.改动联系人
5.显示联系人 6. 清空联系人
7.给联系人排序 0. 退出
具有了这些基本的功能之后就是一个简单的通讯录了。说起来是不是很简单,当我初始准备确实现它的时候,我觉得真的好难好难。
其实简单的方法就是开始就给它一块固定大小的空间,比如100, 1000,但是如果我们这样去实现一个通讯录,就感觉太死板了,如果我的联系人比较广泛,申请固定大小的空间不足以存储了怎么办?还有就是如果我的联系人就那么几个,那么一开始给定太多的内存,是不是造成了空间的浪费呢?
想到了这些问题后,我就想到了使用动态内存(malloc),这使得我们的通讯录更加的灵活,使用起来也特别的方便。
但是问题就来了,具体我要怎么去动态申请一块空间?然后当我申请的空间不够的时候,怎么让它自动的增加一定大小的空间,这个问题困扰了我很久,最后终于找到了解决的办法。
一. 首先使用malloc动态申请一块内存,malloc使用方法如下:

void *malloc( size_t size );

2.当申请的空间不够的时候,使用realloc函数进行续接,在使用之前我们要注意的就是realloc这个函数,的返回值有可能不是初始申请空间的首地址,所以在使用它时候一定要小心。使用方法如下:

void *realloc( void *memblock, size_t size );

3.注意把这所有的一切都做完了以后,千万记得动态内存的释放,否则产生野指针就麻烦了。

解决了这些个问题以后,其他的都不难了,接下来我们看看具体的实现过程。

//头文件"contact.h"

#ifndef __CONTACT_H__
#define __CONTACT_H__

#define  NAME_MAX 10  
#define  SEX_MAX 3
#define  TEL_MAX 12
#define  ADDR_MAX 12
#define  INC 10  //不够存储时再增加
#define  FIR 10 //初始申请10个人的空间

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


enum OP  //枚举所有的函数,使程序的可读性更高
{
    EXIT,
    ADD,
    DEL,
    SEARCH,
    CHANGE,
    DISP,
    EMPTY,
    RANK
};

typedef struct Contact   //定义一个结构体保存联系人相关信息
{
    char name[NAME_MAX];     //名字
    char sex[SEX_MAX];       //性别
    int age;                //年龄
    char tel[TEL_MAX];      //电话
    char addr[ADDR_MAX];     //住址
}Contact;

typedef struct List
{
    Contact* data;
    int count;
    int sz;
}List, *Peo;

void Init_contact(Peo p);//动态内存申请
void Add_contact(Peo p);//添加联系人
void Del_contact(Peo p);//删除联系人
void Search_contact(Peo p);//查找联系人
void Change_contact(Peo p);//改动联系人
void Disp_contact(Peo p);//显示联系人
void Empty_contact(Peo p);//清空联系人
void Rank_contact(Peo p);//联系人排序
void release(Peo p);//动态内存释放





#endif  //__CONTACT_H__
//函数部分 contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void Init_contact(Peo p)  //初始化并动态申请一块空间
{
    p->data = (Contact *)malloc(sizeof(Contact));

    if(p->data == NULL)
    {
        printf("%s\n", strerror(errno));
        exit(0);
    }
    else
    {
        memset(p->data, 0, FIR*sizeof(Contact));
        p->count = 0;
        p->sz = FIR;
    }
}

static void Check_contact(Peo p) //检查是否人数是否达到上限,\
                                    由于只是做简单检测,所以适用了static
{

    if((p->count) == (p->sz))
    {
        Contact *ptr = (Contact*)realloc(p->data,(p->count+INC)*sizeof(Contact));
        if(ptr == NULL)
        {
            printf("%s\n", strerror(errno));
            exit(0);
        }
        else
        {
            p->data = ptr;
            p->sz += INC;
        }
    }
}

static int find(Peo p, char name[]) //查看是否存在某个人
{
    int i = 0;
    if(p->count == 0)
        printf("通讯录为空\n");
    for(i=0; i<p->count; i++)
    {
        if(strcmp(p->data[i].name, name) == 0)
            return i;
    }
    return -1;
}

void Add_contact(Peo p) //添加联系人
{
    Check_contact(p);
    printf("输入名字:");
    scanf("%s", p->data[p->count].name);
    printf("输入性别:");
    scanf("%s", p->data[p->count].sex);
    printf("输入年龄:");
    scanf("%d", &p->data[p->count].age);
    printf("输入电话:");
    scanf("%s", p->data[p->count].tel);
    printf("输入住址:");
    scanf("%s", p->data[p->count].addr);
    p->count++;
}

void Del_contact(Peo p)//删除联系人
{
    int i = 0;
    int j = 0;
    int ret = 0;
    char name[NAME_MAX] = {0};
    Check_contact(p);
    printf("请输入要删除的人名:");
    scanf("%s", name);
    ret = find(p, name);
    if(ret == -1)
    {
        printf("不存在这个人\n");
        return;
    }
    for(j=ret; j<p->count; j++)
    {
        p->data[j] = p->data[j+1];
    }

        p->count--;
        printf("删除成功\n");
}

void Search_contact(Peo p)//查找某个联系人
{
    int i = 0;
    //int j = 0;
    int ret = 0;
    char name[NAME_MAX] = {0};
    Check_contact(p);
    printf("请输入要查找的人名:");
    scanf("%s", name);
    ret = find(p, name);
    if(ret == -1)
    {
        printf("要查找的人不存在\n");
        return;
    }
    else
    {
        printf("%10s%5s%5s%10s%10s\n","name", "sex", "age", "tel", "addr");
        printf("%10s%5s%5d%10s%10s\n", p->data[i].name, 
                                        p->data[i].sex,
                                        p->data[i].age,
                                        p->data[i].tel,
                                        p->data[i].addr );
    }
}
void Change_contact(Peo p) //改动某个联系人
{
    int ret = 0;
    int a = 0;
    char name[NAME_MAX] = {0};
    printf("请输入要改的人名:");
    scanf("%s", name);
    ret = find(p, name);
    if(ret == -1)
    {
        printf("不存在这个人\n");
        return;
    }
    printf("请选择改动类型:");
    //printf("*************************************************\n");
    printf("1.名字 2.性别 3.年龄 4.电话 5.住址 0.退出\n");//选择确定的改动方式
    //printf("*************************************************\n");
    scanf("%d", &a);
    switch(a)
    {
    case 1:
        printf("name:");
        scanf("%s", p->data[ret].name);
        break;
    case 2:
        printf("sex:");
        scanf("%s", p->data[ret].sex);
        break;
    case 3:
        printf("age:");
        scanf("%d", &p->data[ret].age);
        break;
    case 4:
        printf("tel:");
        scanf("%s", p->data[ret].tel);
        break;
    case 5:
        printf("addr:");
        scanf("%s", p->data[ret].addr);
        break;
    case 0:
        break;
    default:
        printf("输入有误:");
    }


}

void Disp_contact(Peo p) //显示联系人
{
    int i  = 0;
    printf("%10s%5s%5s%10s%10s\n","name", "sex", "age", "tel", "addr");
    for(i=0; i<p->count; i++)
    {
        printf("%10s%5s%5d%10s%10s\n", p->data[i].name, 
                                        p->data[i].sex,
                                        p->data[i].age,
                                        p->data[i].tel,
                                        p->data[i].addr );
    }
}

void Empty_contact(Peo p) //清空联系人
{
    p->count = 0;
}

void Rank_contact(Peo p) //联系人按照名字排序
{
    int i = 0;
    int j = 0;
    for(i=0; i<p->count; i++)
    {
        for(j=0; j<p->count-i-1; j++)
        {
            if(strcmp(p->data[j].name, p->data[j+1].name)>0)
            {
                Contact tmp = p->data[j];
                p->data[j] = p->data[j+1];
                p->data[j+1] = tmp;
            }
        }
    }
}

void release(Peo p) //动态内存释放,很重要,避免产生野指针
{
    if(p->data != NULL)
    {
        free(p->data);
    }
    p->data = NULL;
}
//测试函数部分 test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void menu()
{
    printf("*****************************************************\n");
    printf("************    address lists     *******************\n");
    printf("********1 add             2 delete              *****\n");
    printf("********3 search          4 change              *****\n");
    printf("********5 disp            6 empty               *****\n");
    printf("********7 rank            0 exit                *****\n");
    printf("*****************************************************\n");

}

int main()
{
    int input = 0;
    List con;
    int ret = 0;
    //法一:初始化一个函数指针数组,通过数组下标去进行函数调用
    void (*pfun[8])(Peo) = {NULL ,Add_contact, Del_contact, Search_contact,
                                Change_contact, Disp_contact, Rank_contact};
    Init_contact(&con);
    do
    {
    menu();
    printf("请选择>");
    scanf("%d", &input);
    (*pfun[input])(&con);
    //法二:使用switch case 语句进行函数调用
    /*switch(input)
    {
    case ADD:
        Add_contact(&con);
        break;
    case RANK:
        Rank_contact(&con);
        break;
    case DEL:
        Del_contact(&con);
        break;
    case SEARCH:
        Search_contact(&con);
        break;
    case CHANGE:
        Change_contact(&con);
        break;
    case DISP:
        Disp_contact(&con);
        break;
    case EMPTY:
        Empty_contact(&con);
        break;
    case EXIT:
        release(&con);
        break;
    default:
        printf("输入有误:\n");
        break;

    }*/
    }while(input);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章