大家好,我是蘇貝,本篇博客帶大家實現(xiàn)通訊錄,如果你覺得我寫的還不錯的話,可以給我一個贊??嗎,感謝??
一. 前言
本文將使用C語言來實現(xiàn)通訊錄管理系統(tǒng),該通訊錄包括若干聯(lián)系人,和每個聯(lián)系人的姓名、年齡、性別、電話、地址。此通訊錄的功能包括:增加聯(lián)系人信息,刪除聯(lián)系人信息,查找聯(lián)系人信息,修改聯(lián)系人信息,顯示所有聯(lián)系人信息,根據(jù)名字順序給所有聯(lián)系人信息排序
二. 通訊錄的實現(xiàn)
首先,我們建立1個contact.h文件,即一個頭文件,用來聲明。建立1個test.c文件,用來測試代碼。再建立1個contact.c文件,用來寫實現(xiàn)上述6個功能的代碼
2.1 寫出基本框架
下面的代碼就是通訊錄的基本框架,很多程序的基本框架和下面代碼相似,用do-while循環(huán)來決定實現(xiàn)什么功能。變量input作為循環(huán)的判斷條件,如果選擇0,則退出循環(huán),選擇1~6之間的數(shù)則執(zhí)行對應的功能,選擇其它數(shù)則提示輸入錯誤,再進入循環(huán)
int main()
{
int input = 0;
do
{
menu();
printf("請選擇:");
scanf("%d", input);
switch (input)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 0:
printf("退出程序\n");
break;
default:
printf("選擇錯誤,請重新輸入\n");
break;
}
} while (input);
return 0;
}
2.2 制作menu菜單
基本框架中有menu菜單,那讓我們來了解一下如何寫menu菜單,即一個名為menu的函數(shù)。菜單界面就像餐廳里服務員遞給你的菜單,根據(jù)菜單里的內(nèi)容進行選擇。選擇1~6,實現(xiàn)特定功能;選擇0,退出程序
void menu()
{
printf("-----------------------------------\n");
printf("***********************************\n");
printf("****** 1.Add 2.Del ******\n");
printf("****** 3.Select 4.Modify ******\n");
printf("****** 5.Show 6.Sort ******\n");
printf("****** 0.exit ******\n");
printf("***********************************\n");
printf("-----------------------------------\n");
}
2.3 創(chuàng)建聯(lián)系人和通訊錄結(jié)構(gòu)體
因為聯(lián)系人信息包括姓名、年齡、性別、電話、地址,而且它們的類型和所占大小不同,所以我們想到構(gòu)建一個聯(lián)系人結(jié)構(gòu)體,為了書寫分別,我們將struct PeoInfo重命名為PeoInfo。
typedef struct PeoInfo
{
char name[20];
int age;
char gender[5];
char tele[12];
char addr[30];
}PeoInfo;
現(xiàn)在我們將上面字符數(shù)組都確定了最大元素個數(shù),那如果有一天我們發(fā)現(xiàn)有一個人的地址不止30個字節(jié)怎么辦呢?我們接下來的代碼里面也可能有addr[30],所以以后修改起來不太方便。因此,不妨我們用define定義一些標識符常量,之后敲代碼時需要用到字符大小就寫標識符常量而非一個數(shù)字,這樣可以方便以后修改數(shù)組的大小
#define NAME_MAX 20
#define GENDER_MAX 5
#define TELE_MAX 30
#define ADDR_MAX 30
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char gender[GENDER_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
如果我們想存儲若干個聯(lián)系人的信息,那我們就要定義一個數(shù)組,數(shù)組有若干個元素,元素的類型是PeoInfo,很自然的,我們用define定義的標識符常量來表示數(shù)組的最大元素個數(shù)。通訊錄除了要有所有聯(lián)系人信息外,也應該可以告訴我們有多少個聯(lián)系人,所以通訊錄里要有2個東西,一個是若干聯(lián)系人信息,一個是聯(lián)系人的個數(shù),它們的類型不同,所以用結(jié)構(gòu)體表示通訊錄
#define MAX 1000
typedef struct Contact
{
PeoInfo data[MAX];
int sz;
}Contact;
2.3 的都是聲明語句,所以都放在contact.h文件中
2.4 定義通訊錄并初始化
通訊錄的定義簡簡單單,不用多說
Contact con;
我們來想想如何將它初始化。(如果不初始化,那么con里面的內(nèi)容都是隨機值)
在test.c文件中調(diào)用初始化函數(shù),在contact.h中聲明初始化函數(shù),在contact.c文件中定義函數(shù)。結(jié)構(gòu)體傳參時最好是傳址而非傳值,且初始化需要改變結(jié)構(gòu)體的內(nèi)容,所以只能傳址
InitContact(&con);
初始化就是將變量con的元素sz的值賦值為0,并且data數(shù)組里面的元素也都是0。sz不用多說,將data數(shù)組里面的元素全變?yōu)?,只需應用我們之前介紹過的memset函數(shù)了解memset函數(shù)
void InitContact(Contact* pc)
{
assert(pc);//斷言
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
2.5 使用枚舉常量優(yōu)化代碼
如果不讓你看菜單,你能知道上面基本框架的switch語句中的case 1~6分別是什么意思嗎?如果你和我一樣不太記得的話,那我們可以使用枚舉常量來幫助我們識別。枚舉常量如果我們自己不去主動賦值的話,它們的值會從0開始,依次+1,所以EXIT的值為0,ADD的值為1……
enum Option
{
EXIT,//0
ADD,
DEL,
SELECT,
MODIFY,
SHOW,
SORT
};
所以switch語句中的case語句后面的值可以用帶提示的枚舉常量代替
switch (input)
{
case ADD:
break;
case DEL:
break;
case SELECT:
break;
case MODIFY:
break;
case SHOW:
break;
case SORT:
break;
case EXIT:
printf("退出程序\n");
break;
default:
printf("選擇錯誤,請重新選擇\n");
break;
}
2.6 增加聯(lián)系人信息
在test.c文件中調(diào)用函數(shù)
case ADD:
AddContact(&con);
break;
在contact.c文件中定義函數(shù)。先判斷通訊錄是否滿了,若沒滿則輸入聯(lián)系人信息,最好一定要記得sz++。注意:輸入年齡的scanf語句中,記得要&
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通訊錄已滿,增加失敗\n");
return;
}
printf("請輸入名字:");
scanf("%s",pc->data[pc->sz].name );
printf("請輸入年齡:");
scanf("%d", &(pc->data[pc->sz].age));
printf("請輸入性別:");
scanf("%s", pc->data[pc->sz].gender);
printf("請輸入電話:");
scanf("%s", pc->data[pc->sz].tele);
printf("請輸入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
2.7 刪除聯(lián)系人信息
在test.c文件中調(diào)用函數(shù)
case DEL:
DelContact(&con);
break;
在contact.c文件中定義函數(shù)。先判斷通訊錄是否為空,不為空時,輸入要刪除的人的姓名,在通過for循環(huán)搜索是否有該姓名的聯(lián)系人,因為除了刪除聯(lián)系人信息功能需要搜索以外,查找和修改聯(lián)系人信息也需要通過for循環(huán)搜索是否有該姓名的聯(lián)系人,所以不妨將其封裝成一個函數(shù)。若沒有找到這個姓名的聯(lián)系人,返回-1,否則返回該姓名的下標。
找到該姓名的聯(lián)系人以后做刪除操作,刪除操作只需要讓下標后面的元素依次向前進一位,覆蓋掉下標的位置即可。所以循環(huán)的結(jié)束條件是i < pc->sz - 1,不要搞錯。覆蓋時只需要pc->data[i] = pc->data[i + 1];因為如果結(jié)構(gòu)體的類型完全相同,那就可以整體賦值。最后sz–??赡苡腥俗⒁獾搅?,這個刪除操作不能刪除最后一個元素,是的,但沒有關系,因為我們的sz–了,所以之后的遍歷中不會再遍歷原本的最后一個元素
int FindOfName(char* name, Contact* pc)
{
assert(name && pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(name, (pc->data[i].name)))
return i;
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
if (pc->sz == 0)
{
printf("通訊錄為空,刪除失敗\n");
return;
}
printf("請輸入要刪除的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要刪除的人\n");
return;
}
int i = 0;
for (i = ret; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("刪除成功\n");
}
2.8 查找聯(lián)系人信息
查找聯(lián)系人信息同樣需要搜索函數(shù)FindOfName(name, pc);,如果要查找的人存在,那么會返回它的下標,再通過下標對這個人信息進行打印。為了直觀的看出各個信息是屬于哪一類的,我們可以在打印前打印提示信息,注意:年齡是%-5s,后面打印信息時是%-5d
void SelectContact(Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("請輸入要查找的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要查找的人\n");
return;
}
printf("%-20s%-5s%-5s%-30s%-30s\n", "姓名", "年齡", "性別", "電話", "地址");
printf("%-20s%-5d%-5s%-30s%-30s\n", pc->data[ret].name, pc->data[ret].age,
pc->data[ret].gender, pc->data[ret].tele, pc->data[ret].addr);
}
2.9 修改聯(lián)系人信息
修改聯(lián)系人信息同樣需要搜索函數(shù)FindOfName(name, pc);,如果要想修改的人存在,那么會返回它的下標,再通過下標對這個人的全部信息重新輸入
void ModifyContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("請輸入要修改的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要修改的人\n");
return;
}
printf("請輸入名字:");
scanf("%s", pc->data[ret].name);
printf("請輸入年齡:");
scanf("%d", &(pc->data[ret].age));
printf("請輸入性別:");
scanf("%s", pc->data[ret].gender);
printf("請輸入電話:");
scanf("%s", pc->data[ret].tele);
printf("請輸入地址:");
scanf("%s", pc->data[ret].addr);
}
2.10 打印所有聯(lián)系人信息
打印所有聯(lián)系人信息,無非就是遍歷并打印所有元素,同樣加上提示信息
void ShowContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通訊錄為空,打印無意義\n");
return;
}
int i = 0;
printf("%-20s%-5s%-5s%-30s%-30s\n", "姓名", "年齡", "性別", "電話", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s%-5d%-5s%-30s%-30s\n", pc->data[i].name, pc->data[i].age,
pc->data[i].gender, pc->data[i].tele, pc->data[i].addr);
}
}
2.11 以名字排序所有聯(lián)系人
使用qsort函數(shù)可快速排序,了解qsort函數(shù)
int cmp(const void* a, const void* b)
{
return strcmp((char*)a, (char*)b);
}
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);
printf("排序成功\n");
}
三. 模塊化代碼實現(xiàn)
3.1 test.c
#include"contact.h"
void menu()
{
printf("-----------------------------------\n");
printf("***********************************\n");
printf("****** 1.Add 2.Del ******\n");
printf("****** 3.Select 4.Modify ******\n");
printf("****** 5.Show 6.Init ******\n");
printf("****** 7.sort 0.exit ******\n");
printf("***********************************\n");
printf("-----------------------------------\n");
}
enum Option
{
EXIT,
ADD,
DEL,
SELECT,
MODIFY,
SHOW,
INIT,
SORT
};
int main()
{
Contact con;
//初始化通訊錄
InitContact(&con);
int input = 0;
do
{
menu();
printf("請選擇:");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SELECT:
SelectContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case INIT:
InitContact(&con);
break;
case SORT:
SortContact(&con);
break;
case EXIT:
printf("退出程序\n");
break;
default:
printf("選擇錯誤,請重新選擇\n");
break;
}
} while (input);
return 0;
}
3.2 contact.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#define NAME_MAX 20
#define GENDER_MAX 5
#define TELE_MAX 30
#define ADDR_MAX 30
#define MAX 1000
typedef struct PeoInfo
{
char name[NAME_MAX];
int age;
char gender[GENDER_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contact
{
PeoInfo data[MAX];
int sz;
}Contact;
//初始化通訊錄
void InitContact(Contact* pc);
//增加聯(lián)系人
void AddContact(Contact* pc);
//刪除聯(lián)系人
void DelContact(Contact* pc);
//打印通訊錄
void ShowContact(Contact* pc);
//查找聯(lián)系人
void SelectContact(Contact* pc);
//修改聯(lián)系人信息
void ModifyContact(Contact* pc);
//以名字排序所有聯(lián)系人
void SortContact(Contact* pc);
3.3 contact.c
#include"contact.h"
//初始化通訊錄
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
//增加聯(lián)系人
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == MAX)
{
printf("通訊錄已滿,增加失敗\n");
return;
}
printf("請輸入名字:");
scanf("%s",pc->data[pc->sz].name );
printf("請輸入年齡:");
scanf("%d", &(pc->data[pc->sz].age));
printf("請輸入性別:");
scanf("%s", pc->data[pc->sz].gender);
printf("請輸入電話:");
scanf("%s", pc->data[pc->sz].tele);
printf("請輸入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("增加成功\n");
}
int FindOfName(char* name, Contact* pc)
{
assert(name && pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(name, (pc->data[i].name)))
return i;
}
return -1;
}
//刪除聯(lián)系人
void DelContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
if (pc->sz == 0)
{
printf("通訊錄為空,刪除失敗\n");
return;
}
printf("請輸入要刪除的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要刪除的人\n");
return;
}
int i = 0;
for (i = ret; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("刪除成功\n");
}
//打印通訊錄
void ShowContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通訊錄為空,打印無意義\n");
return;
}
int i = 0;
printf("%-20s%-5s%-5s%-30s%-30s\n", "姓名", "年齡", "性別", "電話", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s%-5d%-5s%-30s%-30s\n", pc->data[i].name, pc->data[i].age,
pc->data[i].gender, pc->data[i].tele, pc->data[i].addr);
}
}
//查找聯(lián)系人
void SelectContact(Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("請輸入要查找的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要查找的人\n");
return;
}
printf("%-20s%-5s%-5s%-30s%-30s\n", "姓名", "年齡", "性別", "電話", "地址");
printf("%-20s%-5d%-5s%-30s%-30s\n", pc->data[ret].name, pc->data[ret].age,
pc->data[ret].gender, pc->data[ret].tele, pc->data[ret].addr);
}
//修改聯(lián)系人信息
void ModifyContact(Contact* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("請輸入要修改的人的名字:");
scanf("%s", name);
int ret = FindOfName(name, pc);
if (ret == -1)
{
printf("找不到要修改的人\n");
return;
}
printf("請輸入名字:");
scanf("%s", pc->data[ret].name);
printf("請輸入年齡:");
scanf("%d", &(pc->data[ret].age));
printf("請輸入性別:");
scanf("%s", pc->data[ret].gender);
printf("請輸入電話:");
scanf("%s", pc->data[ret].tele);
printf("請輸入地址:");
scanf("%s", pc->data[ret].addr);
}
int cmp(const void* a, const void* b)
{
return strcmp((char*)a, (char*)b);
}
//以名字排序所有聯(lián)系人
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);
printf("排序成功\n");
}
3.4 結(jié)果演示
四. 存在的問題
前面實現(xiàn)的通訊錄有什么問題呢?
1.錄入的信息,等程序結(jié)束后,還存在嗎?不存在了,因為數(shù)據(jù)是存放內(nèi)存中的,只要程序退出,掉電,都會
丟失怎么解決呢?用文件存儲,數(shù)據(jù)庫…
2.通訊錄的大小是固定的100個元素,存放100個人的信息如果信息太多,空間小了;如果信息太少,空間大了。怎么解決?用動態(tài)內(nèi)存管理!
所以期待博主的下一篇優(yōu)化的通訊錄管理系統(tǒng)吧文章來源:http://www.zghlxwxcb.cn/news/detail-717306.html
好了,那么本篇博客就到此結(jié)束了,如果你覺得本篇博客對你有些幫助,可以給個大大的贊??嗎,感謝看到這里,我們下篇博客見??文章來源地址http://www.zghlxwxcb.cn/news/detail-717306.html
到了這里,關于【C語言】實現(xiàn)通訊錄管理系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!