我們都知道通訊錄有的一些基本簡單的功能就是:
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;
}