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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章