c語言實現(xiàn)通訊錄管理系統(tǒng)詳細(xì)實例
一、前言
本文將會用c語言實現(xiàn)一個通訊錄的系統(tǒng),并且存儲若干人的信息,每個人的信息包括:姓名,性別,年齡,電話號碼,住址。此通訊錄系統(tǒng)的功能包括: 1.增加聯(lián)系人 2.刪除對應(yīng)的聯(lián)系人 3.查找聯(lián)系人 4.修改聯(lián)系人的信息 5.排序此通訊錄 6.打印出通訊錄每個人的信息
二、通訊錄的實現(xiàn)
1.關(guān)于通訊錄的前期準(zhǔn)備
(1)菜單的實現(xiàn)
首先關(guān)于一個通訊錄,建立一個菜單是很重要的,菜單能夠?qū)崿F(xiàn)和用戶的交互。
因此我們需要建立一個菜單,并且菜單立馬應(yīng)該包括通訊錄立馬該有的功能,以便于用戶的操作
代碼如下:
void menu()
{
printf("=====================================\n");
printf("============1.增加聯(lián)系人=============\n");
printf("============2.刪除聯(lián)系人=============\n");
printf("============3.查找聯(lián)系人=============\n");
printf("============4.修改聯(lián)系人=============\n");
printf("============5.排序通訊錄=============\n");
printf("============6.打印通訊錄=============\n");
printf("============0.退出通訊錄=============\n");
printf("=====================================\n");
}
效果差不都就是這樣子
(2)關(guān)于聯(lián)系人結(jié)構(gòu)體的創(chuàng)建
這里我們需要利用結(jié)構(gòu)體來實現(xiàn)實現(xiàn)前言中的通訊錄功能以及聯(lián)系人信息,我將利用兩個結(jié)構(gòu)體來構(gòu)建我們需要的東西。
typedef struct PeoInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
}Peo;
typedef struct Contact
{
Peo con[PON_MAX];
int sz;//記錄數(shù)量
}contact;關(guān)于第一個結(jié)構(gòu)體Peo是關(guān)于個人信息的存儲,第二個結(jié)構(gòu)體構(gòu)建了 我們需要的通訊錄,con來作為以第一個結(jié)構(gòu)體為類型的數(shù)組,sz來記錄這個結(jié)構(gòu)體存儲個人信息的數(shù)量。
(3)實現(xiàn)菜單選項的功能
我們需要根據(jù)菜單里面的選項來選擇進(jìn)行我們需要實現(xiàn)的功能,比如我們想假如一個用戶信息,我們就輸入1就會進(jìn)行用戶假如的操作,我們想退出程序我們輸入0就可以退出。我選擇利用枚舉變量的形式來實現(xiàn),講操作變成數(shù)字,利用switch選擇語句來實現(xiàn)各自的功能。
enum Option//利用枚舉變量來定義
{
exit,//0
add,//1
del,//2
search,//3
modify,//4
sort,//5
print//6
};
void test()
{
contact con;//建立結(jié)構(gòu)體
InitCon(&con);
int input = 0;
do {
menu();
scanf("%d", &input);
switch (input)
{
case add:
AddCon(&con);
break;
case del:
DelCon(&con);
break;
case search:
SearchCon(&con);
break;
case modify:
ModifyCon(&con);
break;
case sort:
SortCon(&con);
break;
case print:
PrintCon(&con);
break;
case exit:
printf("退出程序,歡迎使用!\n");
break;
default:
printf("沒有找到此數(shù)字匹配的操作!!\n");
}
} while (input);
}(4)關(guān)于全局變量的定義
為了實現(xiàn)這些變量,并且方便后期的處理數(shù)組大小,所以我們可以利用宏來實現(xiàn)這個功能
#define NAME_MAX 20//姓名的長度 #define SEX_MAX 5//性別的長度 #define TELE_MAX 12//電話號碼的長度 #define ADDR_MAX 30//地址長度 #define PON_MAX 1000//通訊錄的大小
2、通訊錄的功能實現(xiàn)
(1)初始化通訊錄
剛剛開始我們創(chuàng)建了通訊錄的結(jié)構(gòu)體,但是我們不難發(fā)現(xiàn),因為沒有定義的原因,他們里面存的都是隨機(jī)數(shù),因此我們需要對他們進(jìn)行初始化防止后面的失誤。初始化很簡單就是把我們通訊錄結(jié)構(gòu)體里面的用戶信息的結(jié)構(gòu)體類型的數(shù)組進(jìn)行初始化,這里我們可以淺淺用一個memset函數(shù)來實現(xiàn),當(dāng)然別忘了引用string的頭文件,然后sz的初始化很簡單就是初始化為0。
void InitCon(contact* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->con, 0, sizeof(pc->con));
}//初始化結(jié)構(gòu)體(2)增加聯(lián)系人
首先第一步我們完成第一步就可以創(chuàng)建關(guān)于加入聯(lián)系人的函數(shù),這個很簡單我們只需要訪問通訊錄結(jié)構(gòu)體里面的數(shù)組中的每個元素然后輸入對應(yīng)值就可以了
void AddCon(contact* pc)
{
assert(pc);
if (pc->sz == PON_MAX)
{
printf("通訊錄滿了??!\n");
}
printf("請輸入姓名:>\n");
scanf("%s", pc->con[pc->sz].name);
printf("請輸入性別:>\n");
scanf("%s", pc->con[pc->sz].sex);
printf("請輸入年齡:>\n");
scanf("%d", &(pc->con[pc->sz].age));//注意年齡在這里是一個int類型
printf("請輸入電話號碼:>\n");
scanf("%s", pc->con[pc->sz].tele);
printf("請輸入地址:>\n");
scanf("%s", pc->con[pc->sz].addr);
pc->sz++;
printf("此用戶添加成功!\n");
}
(3)打印通訊錄
打印通訊錄也很簡單,利用一個for循環(huán)根據(jù)sz的大小遍歷結(jié)構(gòu)體中的數(shù)組每個元素并且打印即可
void PrintCon(const contact* pc)
{
assert(pc);
printf("%-15s %-5s %-5s %-12s %-30s\n","姓名","性別","年齡","電話","地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-15s %-5s %-5d %-12s %-30s\n", pc->con[i].name, pc->con[i].sex, pc->con[i].age, pc->con[i].tele, pc->con[i].addr);
}
}
(4)查找聯(lián)系人
查找聯(lián)系人這邊我們需要構(gòu)建一個函數(shù),這個函數(shù)需要去根據(jù)我們想要尋找的姓名去在通訊錄中尋找這個人所對應(yīng)的位置,加入找到了就可以返回對應(yīng)位置的下標(biāo),否則返回-1。找到之后就和打印通訊錄的操作差不多打印出來就好了。
int FindByName(const contact* pc, char* name)
{
assert(pc && name);
for (int i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->con[i].name, name))
return i;
}
return -1;
}//尋找或者刪除聯(lián)系人的下標(biāo)
void SearchCon(const contact* pc)
{
assert(pc);
char name[NAME_MAX];
printf("請輸入需要尋找用戶的名字:>\n");
scanf("%s", name);
int pos = FindByName(pc, name);//pos為要尋找的人的下標(biāo)
if (pos == -1)
{
printf("查無此人\n");
}
else
{
printf("%-15s %-5s %-5s %-12s %-30s\n", "姓名", "性別", "年齡", "電話", "地址");
printf("%-15s %-5s %-5d %-12s %-30s\n", pc->con[pos].name, pc->con[pos].sex, pc->con[pos].age, pc->con[pos].tele, pc->con[pos].addr);
}
}
(5)修改聯(lián)系人
關(guān)于修改聯(lián)系人這個內(nèi)容,大多數(shù)的代碼都是直接替換所有的內(nèi)容,這樣也會讓一些本來就不用修改的信息又被修改了一遍,很麻煩,所有我的設(shè)計是,先讓用戶查找到需要修改的這個人然后選擇是修改什么信息,然后重新輸入嘞一部分的信息,這個其實就和菜單選項實現(xiàn)很相似,我們需要利用枚舉變量,并且利用do...while語句來讓他一直循環(huán)直到輸入0為止,利用switch來根據(jù)用戶的選項來跳到需要的操作。
enum Con
{
ERRO,
NAME,
SEX,
AGE,
TELE,
ADDR
};
void ModifyCon(contact* pc)
{
assert(pc);
char name[NAME_MAX];
printf("請輸入需要修改信息用戶的名字:>\n");
scanf("%s", name);
int pos = FindByName(pc, name);//pos為要尋找的人的下標(biāo)
if (pos == -1)
{
printf("查無此人\n");
}
else
{
int num = 0;
do {
printf("請輸入你想修改此用戶的信息\n");
printf(" 0.退出 1.姓名 2.性別 3.年齡 4.電話 5.地址:>\n");
scanf("%d", &num);
switch (num)
{
case NAME:
printf("請輸入你想修改的姓名:>\n");
scanf("%s", pc->con[pos].name);
break;
case SEX:
printf("請輸入你想修改的性別:>\n");
scanf("%s", pc->con[pos].sex);
break;
case AGE:
printf("請輸入你想修改的年齡:>\n");
scanf("%d", &(pc->con[pos].age));
break;
case TELE:
printf("請輸入你想修改的電話:>\n");
scanf("%s", pc->con[pos].tele);
break;
case ADDR:
printf("請輸入你想修改的地址:>\n");
scanf("%s", pc->con[pos].addr);
break;
case 0:
printf("不修改退回界面\n");
break;
default:printf("無效操作數(shù)!\n");
}
} while (num);
}
}
(6)刪除聯(lián)系人
這個操作也不算復(fù)雜,我的思路是,首先我們先利用剛剛查找的嘞個查找下標(biāo)的函數(shù),查找到我們需要尋找刪除聯(lián)系人的坐標(biāo),然后對他進(jìn)行刪除,刪除之后呢我們需要把后面的元素往前移動,這就要利用for循環(huán),但是對于for循環(huán)的次數(shù)要多加注意,因為稍不小心就會導(dǎo)致數(shù)組越界。
void DelCon(contact* pc)
{
assert(pc);
char name[NAME_MAX];
printf("請輸入需要刪除用戶的名字:>\n");
scanf("%s", name);
int pos = FindByName(pc, name);//pos為要尋找的人的下標(biāo)
if (pos == -1)
{
printf("查無此人\n");
}
else
{
for (int i = pos; i < pc->sz - 1; i++)
{
pc->con[i] = pc->con[i + 1];
}
pc->sz--;
printf("刪除成功!\n");
}
}
(7)排序通訊錄
這一步我們需要按照人名首字母的大小對于通訊錄進(jìn)行排序,就比如summer和banni,banni會在summer,這個排序其實和冒泡排序差不多,我們需要注意的是我們在交換兩個數(shù)的時候我們需要定義的的嘞個中間數(shù)為聯(lián)系人結(jié)構(gòu)體類型,以免出錯
void SortCon(contact* pc)
{
if (pc->sz == 0)
{
printf("通訊錄中沒有聯(lián)系人\n");
}
else
{
for (int i = 0; i < pc->sz - 1; i++)
{
for (int j = 0; j < pc->sz - 1 - i; j++)
{
if ((strcmp(pc->con[j].name, pc->con[j + 1].name)) > 0)
{
Peo temp = pc->con[j];
pc->con[j] = pc->con[j + 1];
pc->con[j + 1] = temp;
}
}
}
printf("排序成功!\n");
}
}
這樣我們需要的一個通訊錄就這樣實現(xiàn)了!
三、關(guān)于通訊錄的優(yōu)化
這個通訊錄我們不難發(fā)現(xiàn)他有一個致命的缺點(diǎn),就是我們初始化的通訊錄大小為1000,但是當(dāng)我們存滿還想存元素的時候,編譯器就會給我們報錯,我們就需要繼續(xù)手動增加空間,所以為了避免這樣我們可以利用動態(tài)內(nèi)存分配來定義我們的通訊錄結(jié)構(gòu)體。
1、通訊錄結(jié)構(gòu)體的改進(jìn)
這邊我們可以把之前的結(jié)構(gòu)體里面的數(shù)組變成一個指針數(shù)組,并且為了考慮這個通訊錄來回刪除增加的緣故,一個sz來記錄數(shù)組元素個數(shù)是不行的,我們需要在設(shè)定一個值為數(shù)組最大的空間,當(dāng)sz和他相等的時候我們就需要擴(kuò)充這個數(shù)組。
typedef struct Contact
{
Peo* con;
int sz;//記錄數(shù)量
int max;//記錄通訊錄當(dāng)前的最大容量
}contact;2、初始化結(jié)構(gòu)體
這個初始化結(jié)構(gòu)體,我們需要sz初始化為0,并且為con這個指針開辟一塊空間,并且賦予max一個初始值,這個初始值我們可以用宏來定義我們初始化通訊錄的大小
#define CON_MAX 3//通訊錄初始化大小
void InitCon(contact* pc)
{
assert(pc);
pc->sz = 0;
pc->max = CON_MAX;
pc->con = (Peo*)malloc(sizeof(Peo) * pc->max);
if (pc->con == NULL)
{
perror("InitContact::malloc");
return;
}
memset(pc->con, 0, pc->max * sizeof(Peo));
}3.增容
當(dāng)我們增加聯(lián)系人是sz == max的時候,我們可以利用realloc函數(shù)來實現(xiàn)擴(kuò)容,每一次擴(kuò)容兩個空間
void CheckCapacity(contact* pc)
{
//增容的代碼
if (pc->sz == pc->max)
{
Peo* tmp = (Peo*)realloc(pc->sz, (pc->max + 2) * sizeof(Peo));
if (tmp != NULL)
{
pc->sz = tmp;
}
else
{
perror("CheckCapacity::realloc");
return;
}
pc->max += 2;
printf("增容成功\n");
}
}4.釋放內(nèi)存
這邊我們可以構(gòu)建一個函數(shù)在這個程序結(jié)束之后釋放內(nèi)存
void DestroyContact(contact* pc)
{
free(pc->con);
pc->con = NULL;
pc->max = 0;
pc->sz = 0;
printf("銷毀成功\n");
}四、總結(jié)
這個通訊錄主要考察的是對于結(jié)構(gòu)體的訪問,還有對于結(jié)構(gòu)體的創(chuàng)建,在編碼的時候得務(wù)必細(xì)心,最后放上完整的源代碼供大家參考
#pragma once
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//類型的聲明
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 30
//通訊錄初始狀態(tài)的容量大小
#define DEFAULT_SZ 3
enum Option
{
EXIT,//0
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRINT
};
enum Con
{
ERRO,
NAME,
SEX,
AGE,
TELE,
ADDR
};
typedef struct PeoInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
} PeoInfo;
typedef struct Contact
{
PeoInfo* data;//可以存放1000個人的信息
int sz;//記錄通訊中已經(jīng)保存的信息個數(shù)
int capacity;//記錄通訊錄當(dāng)前的最大容量
}Contact;
//函數(shù)的聲明
//初始化通訊錄
void InitContact(Contact* pc);
//銷毀通訊錄
void DestroyContact(Contact* pc);
//增加聯(lián)系人的信息
void AddContact(Contact* pc);
//打印通訊錄中的信息
void PrintContact(const Contact* pc);
//刪除指定聯(lián)系人
void DelContact(Contact* pc);
//查找指定聯(lián)系人
void SearchContact(const Contact* pc);
//保存通訊錄的信息到文件
void SaveContact(const Contact* pc);
//通訊錄排序
void SortCon(Contact* pc);
void ModifyCon(Contact* pc);
#define _CRT_SECURE_NO_WARNINGS 1
//動態(tài)的版本
//void InitContact(Contact* pc)
//{
// assert(pc);
// pc->sz = 0;
// pc->capacity = DEFAULT_SZ;
// pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));
//
// if (pc->data == NULL)
// {
// perror("InitContact::malloc");
// return;
// }
// memset(pc->data, 0, pc->capacity * sizeof(PeoInfo));
//}
void CheckCapacity(Contact* pc)
{
//增容的代碼
if (pc->sz == pc->capacity)
{
PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));
if (tmp != NULL)
{
pc->data = tmp;
}
else
{
perror("CheckCapacity::realloc");
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
void LoadContact(Contact* pc)
{
//打開文件
FILE* pf = fopen("contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact::fopen");
return;
}
//讀文件
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pf))
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
}
//初始化通訊錄 - 文件版本
void InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = DEFAULT_SZ;
pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));
if (pc->data == NULL)
{
perror("InitContact::malloc");
return;
}
memset(pc->data, 0, pc->capacity * sizeof(PeoInfo));
//加載文件信息到通訊錄中
LoadContact(pc);
}
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
printf("銷毀成功\n");
}
void AddContact(Contact* pc)
{
assert(pc);
//靜態(tài)版本
//if (pc->sz == MAX)
//{
// printf("通訊錄已滿,無法添加\n");
// return;
//}
//動態(tài)的版本
CheckCapacity(pc);
//錄入信息
printf("請輸入名字:>");
scanf("%s", pc->data[pc->sz].name);
printf("請輸入年齡:>");
scanf("%d", &(pc->data[pc->sz].age));
printf("請輸入性別:>");
scanf("%s", pc->data[pc->sz].sex);
printf("請輸入電話:>");
scanf("%s", pc->data[pc->sz].tele);
printf("請輸入地址:>");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void PrintContact(const Contact* pc)
{
assert(pc);
int i = 0;
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年齡", "性別", "電話", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
//找到了返回下標(biāo)
//找不到返回-1
int FindByName(const Contact* pc, char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通訊錄已空,無法刪除\n");
return;
}
//刪除
//1. 找到
char name[NAME_MAX] = { 0 };
printf("請輸入要刪除人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要刪除的人不存在\n");
return;
}
//2. 刪除
int j = 0;
for (j = pos; j < pc->sz - 1; j++)
{
pc->data[j] = pc->data[j + 1];
}
pc->sz--;
printf("刪除成功\n");
}
void SearchContact(const Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("請輸入要查找人的名字:>");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年齡", "性別", "電話", "地址");
printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex,
pc->data[pos].tele, pc->data[pos].addr);
}
void SaveContact(const Contact* pc)
{
FILE* pf = fopen("contact.dat", "wb");
//回來本地建立一個contact.dat的記事本
if (pf == NULL)
{
perror("SaveContact::fopen");
return;
}
//寫文件
int i = 0;
for (i = 0; i < pc->sz; i++)
{
fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
}
void SortCon(Contact* pc)
{
if (pc->sz == 0)
{
printf("通訊錄中沒有聯(lián)系人\n");
}
else
{
for (int i = 0; i < pc->sz - 1; i++)
{
for (int j = 0; j < pc->sz - 1 - i; j++)
{
if ((strcmp(pc->data[j].name, pc->data[j + 1].name)) > 0)
{
PeoInfo temp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = temp;
}
}
}
printf("排序成功!\n");
}
}
void ModifyCon(Contact* pc)
{
assert(pc);
char name[NAME_MAX];
printf("請輸入需要修改信息用戶的名字:>\n");
scanf("%s", name);
int pos = FindByName(pc, name);//pos為要尋找的人的下標(biāo)
if (pos == -1)
{
printf("查無此人\n");
}
else
{
int num = 0;
do {
printf("請輸入你想修改此用戶的信息\n");
printf(" 0.退出 1.姓名 2.性別 3.年齡 4.電話 5.地址:>\n");
scanf("%d", &num);
switch (num)
{
case NAME:
printf("請輸入你想修改的姓名:>\n");
scanf("%s", pc->data[pos].name);
break;
case SEX:
printf("請輸入你想修改的性別:>\n");
scanf("%s", pc->data[pos].sex);
break;
case AGE:
printf("請輸入你想修改的年齡:>\n");
scanf("%d", &(pc->data[pos].age));
break;
case TELE:
printf("請輸入你想修改的電話:>\n");
scanf("%s", pc->data[pos].tele);
break;
case ADDR:
printf("請輸入你想修改的地址:>\n");
scanf("%s", pc->data[pos].addr);
break;
case 0:
printf("不修改退回界面\n");
break;
default:printf("無效操作數(shù)!\n");
}
} while (num);
}
}
void menu()
{
printf("*****************************************\n");
printf("**** 1.增加聯(lián)系人 2.刪除聯(lián)系人 ****\n");
printf("**** 3.查找聯(lián)系人 4.修改聯(lián)系人 ****\n");
printf("**** 5.通訊錄排序 6.打印通訊錄 ****\n");
printf("**** 0.退出 ****\n");
printf("******************************************\n");
}
void test()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
menu();
printf("請輸入你的選擇:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case MODIFY:
ModifyCon(&con);
break;
case SORT:
SortCon(&con);
break;
case PRINT:
PrintContact(&con);
break;
case EXIT:
SaveContact(&con);
DestroyContact(&con);
printf("感謝使用\n");
break;
default:
printf("非法輸入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
感謝閱讀?。。。?/p>
到此這篇關(guān)于c語言實現(xiàn)通訊錄管理系統(tǒng)的文章就介紹到這了,更多相關(guān)c語言通訊錄管理系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

