目錄
簡介:
基本要求:
代碼的實現(xiàn):
1、Contact.h
2、test.c
3、Cantact.c
運行效果圖:
部分復(fù)雜函數(shù)流程圖
前兩周是本人的實驗周,抽到的課題是“手機(jī)通信錄的實現(xiàn)”,課題大致如下:
簡介:
(1)用C/C++設(shè)計出模擬手機(jī)通信錄系統(tǒng),實現(xiàn)對手機(jī)中的通信錄進(jìn)行管理。
(2)將通訊錄用文件存儲,人員信息包括:姓名、手機(jī)號碼、家庭電話號碼、辦公電話、電子郵件、分組。
(3)其中:手機(jī)號碼、家庭電話號碼、辦公電話不能同時為空;分組說明:未知、同事、親戚、朋友、家人、同學(xué)等還可以自己創(chuàng)建分組
(4)文件類型可以是文本文件或二進(jìn)制文件。
基本要求:
(1)首先向客戶展示一個歡迎界面,并提醒客戶輸入任意鍵進(jìn)入主菜單,在菜單中客戶進(jìn)行操作選擇,而且客戶操作完后還可以根據(jù)需求進(jìn)行返回主菜單進(jìn)行其他操作。
(2)增加功能:
能錄入新人員記錄。
(3)查看功能:
選擇此功能時,當(dāng)選中某類時,顯示出此類所有數(shù)據(jù)中的姓名和電話號碼。
(4)拔號功能:
能顯示出通信錄中所有人的姓名,當(dāng)選中某個姓名時,屏幕上模擬打字機(jī)的效果依次顯示出此人的電話號碼中的各個數(shù)字。
(5)修改功能:?.
選中某個人的姓名時,可對此人的相應(yīng)數(shù)據(jù)進(jìn)行修改。
我一看,嚯喲!這個課題好簡單??!除了“分類查找”和“撥號”是我沒寫過的,剩下的功能不都是最基礎(chǔ)的嗎?主要涉及到的知識點不就是些:數(shù)組應(yīng)用、指針和結(jié)構(gòu)體嘛!
可是轉(zhuǎn)念一想,不行,寫的那么簡單,和別的組沒有區(qū)分度,不方便老師打分呢~(bushi)
再說了,這個程序一天就可以寫完,再算上寫實驗報告和畫函數(shù)圖解也最多不過一周的事,不是對不起這兩周的實驗周嗎?(對不起,后來博主被狠狠打臉了。老師要求很嚴(yán)格,不僅被要求補(bǔ)充了一些代碼,最后寫實驗報告的時候簡直被折磨的不行,流程圖重畫了好幾遍……實驗報告一共也就寫了那么整整15個小時吧)
于是我決定,要寫就寫個詳細(xì)的通信錄程序。不僅補(bǔ)充上了“分類查找”和“模擬撥號(類似打印機(jī))”這兩個功能,我還增加了一些別的小功能:
1、“模糊查詢”(即你要找“Jackson”這個聯(lián)系人的信息,輸入“Jack”,通信錄會跳出所以名字含這個字符串的聯(lián)系人信息。對于中文名也是可以的,比如你想找“如花”,輸入“如”字按回車,它會跳出一堆“如花”、“如玉”......);
2、qsort函數(shù)實現(xiàn)排序:可以選擇按照姓名、年齡和電話號碼排序。
3、防誤觸:聽上去好像很厲害,其實很簡單,只有三行代碼就搞定了。(不過是讓用戶再次確認(rèn)自己的選擇避免造成不可挽回的損失罷了)。
總之,斷斷續(xù)續(xù)地,花了三天時間,我終于把這個小程序?qū)懲炅恕KF(xiàn)在一共有11個功能,博主暫時想不到別的了,大家如果有好的想法可以提出來。
其實它還不是特別完備,只是一個靜態(tài)的版本,我打算有時間的話把它改造成一個動態(tài)的版本,這就要涉及到我們的malloc、calloc 、free 和 realloc 函數(shù)了。
扯遠(yuǎn)了,現(xiàn)在讓我們來看看這個通信錄吧:
代碼的實現(xiàn):
1、Contact.h
宏定義的設(shè)置可以方便我們以后的修改。
#pragma once
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
#define MAX_NAME 10
#define MAX_SEX 5
#define MAX_HOME_NUM 12
#define MAX_NUM 12
#define MAX_OFFICE 15
#define MAX_DATA 100
#define MAX_E_MAIL 20
#define MAX_CLASSIFICATION 10
//創(chuàng)建聯(lián)系人結(jié)構(gòu)體
struct Peoinfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
char home_num[MAX_HOME_NUM];
char cell_num[MAX_NUM];
int age;
char office_number[MAX_OFFICE];
char e_mail[MAX_E_MAIL];
char classification[MAX_CLASSIFICATION];
};
//創(chuàng)建通訊錄結(jié)構(gòu)體
struct Contact
{
struct Peoinfo data[MAX_DATA];//存放數(shù)據(jù)
int sz;//記錄通訊錄中的有效信息個數(shù)
//int capcity;
};
//把上次存在文件中的信息加載過來
void LoadContact(struct Contact* pc);
//初始化通訊錄
void init_contact(struct Contact* con);
//添加聯(lián)系人
void addContact(struct Contact* con);
//刪除聯(lián)系人
void deleteContact(struct Contact* con);
//修改聯(lián)系人
void modifyContact(struct Contact* con);
//尋找聯(lián)系人
static int find(const struct Contact* con, char* name);
//查找聯(lián)系人
void searchContact(struct Contact* con);
//顯示聯(lián)系人信息
void showContact(struct Contact* con);
//排序聯(lián)系人(按照年齡、名字)
void sortContact(struct Contact con);
//清空聯(lián)系人
void clearContact(struct Contact* con);
//查看某一類聯(lián)系人
void checkContact(struct Contact* con);
//保存聯(lián)系人
void saveContact(struct Contact* con);
//撥號
void dialContact(struct Contact* con);
//把上次存在文件中的信息加載過來
//void LoadContact(struct Contact* pc);
//模糊查詢聯(lián)系人信息
void fuzzy_search(struct Contact* contact);
2、test.c
這里想要解釋一下為什么要加一個枚舉常量。(后面的Contact.c也添加了一個枚舉,目的是一樣的。)
枚舉的使用增加了我們代碼的可讀性和維護(hù)性:
有時候在寫一些代碼時,比如寫這個菜單,我們用了1來代表add,0代表exit,但是在后續(xù)代碼中,1和0的真實含義有時難以被區(qū)分。所以如果用枚舉的話,后續(xù)在case 后面加常量的時候就可以直接寫add,這樣,代碼的可讀性就增強(qiáng)了不少)。
注意!我們的防誤觸操作就設(shè)置在此處,因為它實在是太簡單了,沒有單獨為它寫一個函數(shù)的必要呢。
(和大家講個笑話,活躍一下氣氛。在界面設(shè)計這里呢,本來博主有一點自己的小私心,想要提醒老師我有模糊查詢這個功能,讓她夸夸我來著,但是她好像并不care,反而對我層層嵌套調(diào)用函數(shù)的addContact子功能青睞有加。)
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void Meue()
{
printf("***親愛的用戶,歡迎您使用通信錄!***\n");
printf("***溫馨提示,本通信錄支持模糊查詢的功能哦!***\n");
printf("************************************\n");
printf("***** 1.add 2.delete *****\n");
printf("***** 3.modify 4.search *****\n");
printf("***** 5.show 6.sort *****\n");
printf("***** 7.clear 8.check *****\n");
printf("***** 9.save 10.dial *****\n");
printf("***** 11.fuzzy_search *****\n");
printf("***** 0.exit *****\n");
printf("************************************\n");
}
int main()
{
int input = 0;
enum number
{
EXIT,//0
ADD,//1
DELE,//2
MODIFY,
SEARCH,
SHOW,
SORT,
CLEAR,
CHECK,
SAVE,
DIAL,
FUZZY_SEARCH,
};
struct Contact con;//通信錄
init_contact(&con);//初始化通信錄
LoadContact(&con);//把上次存在文件中的信息加載過來
do
{
Meue();
printf("請選擇:");
scanf_s("%d", &input);
switch (input)
{
case EXIT:
//這里設(shè)置一個防誤觸的功能,提醒用戶再次確認(rèn)是否要保存一下聯(lián)系人信息再退出
printf("請問需要保存一下通訊錄的信息再退出嗎?\n");
printf("********** 1.保存一下 0.直接退出 **********\n");
int q = 0;
scanf("%d", &q);
if (q==0)
{
printf("退出通信錄!\n");
break;
}
saveContact(&con);
printf("退出通信錄!\n");
break;
case ADD:
addContact(&con);
break;
case DELE:
deleteContact(&con);
break;
case MODIFY:
modifyContact(&con);
break;
case SEARCH:
searchContact(&con);
break;
case SHOW:
showContact(&con);
break;
case SORT:
sortContact(con);
break;
case CLEAR:
//這里設(shè)置一個防誤觸的功能,提醒用戶再次確認(rèn)是否要清空聯(lián)系人信息
printf("請問您確定要清空聯(lián)系人信息嗎?一旦清空,無法找回!\n");
printf("************* 1.確定清空 0.取消 *************\n");
int x = 0;
scanf("%d",&x);
if (x==1)
{
clearContact(&con);
}
break;
case CHECK:
checkContact(&con);
break;
case SAVE:
saveContact(&con);
break;
case DIAL:
dialContact(&con);
break;
case FUZZY_SEARCH:
fuzzy_search(&con);
break;
default:
printf("輸入錯誤!\n");
break;
}
} while (input);
return 0;
}
3、Cantact.c
這個源文件定義了每一個子函數(shù)的實現(xiàn),還添加了兩個小的 find 函數(shù)幫助個別子函數(shù)的實現(xiàn)。
注解都寫了,大家可以好好看一下:
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//把上次存在文件中的信息加載過來
void LoadContact(struct Contact* pc)
{
//打開文件
FILE* pf = fopen("D:\\C語言2\\手機(jī)通信錄實現(xiàn)\\contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact::fopen");
return;
}
//讀文件
struct Peoinfo tmp = { 0 };
while (fread(&tmp, sizeof(struct Peoinfo), 1, pf))
{
pc->data[pc->sz] = tmp;
pc->sz++;
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
}
//初始化通訊錄
void init_contact(struct Contact* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->data, 0, MAX_DATA * sizeof(struct Peoinfo));
}
//add中判斷是否存在相同姓名聯(lián)系人
int repetition_name(struct Contact * con, char* len)
{
int ret = find(con, len);
int i = 0;
if (ret == -1)
return 3;
else
{
int repe;
printf("已存在同名聯(lián)系人,請選擇:>\n");
printf("*** 0.重新輸入 1.覆蓋 2.新建 ***\n");
scanf("%d", &repe);
switch (repe)
{
case 0:
return 0;
case 1:
i = 0;
for (i = 0; i < con->sz - ret; i++)
{
con->data[ret + i] = con->data[ret + i + 1];
}
con->sz--;
printf("覆蓋聯(lián)系人成功!\n");
return 1;
case 2:
return 2;
}
}
}
//add中判斷是否存在相同號碼聯(lián)系人
int repetition_num(struct Contact* con, char* len)
{
int ret = findnum(con, len);
int i = 0;
if (ret == -1)
return 2;
else
{
int repe;
printf("已存在相同號碼的聯(lián)系人,請選擇:>\n");
printf("*** 0.重新輸入 1.覆蓋 ***\n");//號碼是無法相同的,所以不要新建
scanf("%d", &repe);
switch (repe)
{
case 0:
return 0;
case 1:
i = 0;
for (i = 0; i < con->sz - ret; i++)
{
con->data[ret + i] = con->data[ret + i + 1];
}
con->sz--;
printf("覆蓋聯(lián)系人成功!\n");
return 1;
}
}
}
//add中用于判斷電話號碼中是否存在非數(shù)字字符
int isnumber(const char* ps)
{
while (*ps != '\0')
{
if (*ps < '0' || *ps > '9')
{
return 0;
}
ps++;
}
if (*ps == '\0')
{
return 1;
}
}
//新建聯(lián)系人
void new(struct Contact* con, char* len)
{
char new[MAX_NAME] = {0};
strcpy(new, con->data[con->sz].name);
}
//添加聯(lián)系人
void addContact(struct Contact* con)
{
assert(con);
int ret;
int k ;
char new[MAX_NAME] = {0};
if ((con->sz) == MAX_DATA)
{
printf("通訊錄已滿!無法增加\n");
return;
}
printf("請輸入名字:>");
do
{
scanf("%s", con->data[con->sz].name);//數(shù)組名本身就是首元素地址
k = repetition_name(con, con->data[con->sz].name);
if(k==0)
printf("請重新輸入!\n");
if (k == 2)
{
printf("請輸入新的備注:>");
scanf("%s",new );
strcat(con->data[con->sz].name,new);//在名字后添加備注
}
} while (!k);
printf("請輸入性別:>");
scanf("%s", con->data[con->sz].sex);
printf("請輸入家庭電話:>");
//判斷是否有非數(shù)字字符
do
{
ret = 1;
scanf("%s", con->data[con->sz].home_num);
if (!isnumber(con->data[con->sz].home_num))
printf("提示!輸入的號碼中存在非數(shù)字字符,請重新輸入!\n");
else
ret = 0;
} while (ret);
//因為是家庭號碼,所以此處不需要判斷是否已有相同號碼聯(lián)系人存在
printf("請輸入個人電話:>");
do
{
ret = 1;
scanf("%s", con->data[con->sz].cell_num);
if (!isnumber(con->data[con->sz].cell_num))
printf("提示!輸入的號碼中存在非數(shù)字字符,請重新輸入!\n");
else
ret = 0;
} while (ret);
//判斷是否已有相同號碼聯(lián)系人存在
do
{
k = 1;
k = repetition_num(con, con->data[con->sz].cell_num);
if (!k)
{
printf("請重新輸入!\n");
scanf("%s", con->data[con->sz].cell_num);
k = 1;
}
else
k = 0;
} while (k);
printf("請輸入年齡:>");
scanf("%d", &(con->data[con->sz].age));//這里需要取地址
printf("請輸入辦公電話:>");
do
{
ret = 1;
scanf("%s", con->data[con->sz].office_number);
if (!isnumber(con->data[con->sz].office_number))
printf("提示!輸入的號碼中存在非數(shù)字字符,請重新輸入!\n");
else
ret = 0;
} while (ret);
//因為是辦公號碼,所以此處不需要判斷是否已有相同號碼聯(lián)系人存在
printf("請輸入郵箱:>");
scanf("%s", con->data[con->sz].e_mail);
printf("請輸入分類:>\n");
printf("您可以在以下選項中進(jìn)行選擇并輸入:>\n");
printf("同事 親戚 朋友 家人 同學(xué) 老師 其他\n");
scanf("%s", con->data[con->sz].classification);
con->sz++;
printf("添加聯(lián)系人成功!\n");
}
//刪除聯(lián)系人
void deleteContact(struct Contact* con)
{
if (con->sz == 0)
{
printf("通訊錄為空,無法刪除!\n");
return;
}
char name[MAX_NAME];
printf("請輸入要刪除的聯(lián)系人:");
scanf("%s", name);
int ret = find(con, name);
if (ret == -1)
printf("未找到該聯(lián)系人!\n");
else
{
int i = 0;
for (i = 0; i < con->sz - ret; i++)
{
con->data[ret + i] = con->data[ret + i + 1];
}
con->sz--;
printf("刪除聯(lián)系人成功!\n");
}
}
//修改聯(lián)系人
void modifyContact(struct Contact* con)
{
char name[MAX_NAME];
printf("請輸入要修改的聯(lián)系人:");
scanf("%s", name);
int ret = find(con, name);
if (ret == -1)
printf("未找到該聯(lián)系人!\n");
else
{
int n = 0;
do
{
int ret;
int k;
printf("請選擇你想要修改的信息:\n");
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
"0.退出修改","1.姓名", "2.性別", "3.家庭電話", "4.個人電話", "5.年齡", "6.辦公電話", "7.郵箱", "8.分類");
scanf("%d", &n);
switch (n)
{
case NAME:
printf("請輸入你想修改的姓名:");
do
{
scanf("%s", con->data[con->sz].name);//數(shù)組名本身就是首元素地址
k = repetition_name(con, con->data[con->sz].name);
if (k == 0)
printf("請重新輸入!\n");
if (k == 2)
{
printf("請輸入新的備注:>");
scanf("%s", new);
strcat(con->data[con->sz].name, new);//在名字后添加備注
}
} while (!k);
printf("修改成功!\n");
break;
case SEX:
printf("請輸入你想修改的性別:");
scanf("%s", con->data[ret].sex);
break;
case HOME_NUM:
printf("請輸入你想修改的家庭電話:");
//判斷是否有非數(shù)字字符
do
{
ret = 1;
scanf("%s", con->data[con->sz].home_num);
if (!isnumber(con->data[con->sz].home_num))
printf("提示!輸入的號碼中存在非數(shù)字字符,請重新輸入!\n");
else
ret = 0;
} while (ret);
//因為是家庭號碼,所以此處不需要判斷是否已有相同號碼聯(lián)系人存在
break;
case CELL_NUM:
printf("請輸入你想修改的手機(jī)號碼:");
do
{
ret = 1;
scanf("%s", con->data[con->sz].cell_num);
if (!isnumber(con->data[con->sz].cell_num))
printf("提示!輸入的號碼中存在非數(shù)字字符,請重新輸入!\n");
else
ret = 0;
} while (ret);
//判斷是否已有相同號碼聯(lián)系人存在
do
{
k = 1;
k = repetition_num(con, con->data[con->sz].cell_num);
if (!k)
{
printf("請重新輸入!\n");
scanf("%s", con->data[con->sz].cell_num);
k = 1;
}
else
k = 0;
} while (k);
break;
case AGE:
printf("請輸入你想修改的年齡:");
scanf("%d", &con->data[ret].age);//不是數(shù)組,需要寫地址符
break;
case OFFICE_NUMBER:
printf("請輸入你想修改的辦公電話:");
do
{
ret = 1;
scanf("%s", con->data[con->sz].office_number);
if (!isnumber(con->data[con->sz].office_number))
printf("提示!輸入的號碼中存在非數(shù)字字符,請重新輸入!\n");
else
ret = 0;
} while (ret);
//因為是辦公號碼,所以此處不需要判斷是否已有相同號碼聯(lián)系人存在
break;
case E_MAIL:
printf("請輸入你想修改的電子郵箱:");
scanf("%s", con->data[ret].e_mail);
break;
case CLASSFICATION:
printf("請輸入你想修改的分組:");
scanf("%s", con->data[ret].classification);
break;
case LEAVE:
printf("不修改退回頁面\n");
break;
default:
printf("無效操作數(shù)!\n");
}
} while (n);
}
}
//下面這些代碼是表示每次修改都要重新輸入該聯(lián)系人的所有信息的,
//因為不太方便,所以改造了一下,
//改成上面那樣,只用修改自己想要修改的信息
//else
//{
// printf("請輸入姓名:");
// scanf("%s", con->data[ret].name);
// printf("請輸入性別:");
// scanf("%s", con->data[ret].sex);
// printf("請輸入電話:");
// scanf("%s", con->data[ret].home_num);
// printf("請輸入電話:");
// scanf("%s", con->data[ret].cell_num);
// printf("請輸入年齡:");
// scanf("%d", &(con->data[ret].age));
// printf("請輸入辦公電話:");
// scanf("%s", con->data[ret].office_number);
// printf("請輸入郵箱:");
// scanf("%s", con->data[ret].e_mail);
// printf("請輸入分類:");
// scanf("%s", con->data[ret].classification);
// printf("修改聯(lián)系人成功!\n");
//}
//尋找聯(lián)系人是否存在——因為有多個功能都需要我們先去確認(rèn)是否存在聯(lián)系人,
//所以干脆把這個功能作為一個函數(shù)獨立出去
static int find(const struct Contact* con, char* name)
//加上static之后就不會被別人看到,只能在該源文件使用
{
int i = 0;
for (i = 0; i < con->sz; i++)
{
if (0 == strcmp(con->data[i].name, name))
return i;
}
return -1;//i==con->sz
}
static int findnum(const struct Contact* con, char* number)
//同樣的,查找聯(lián)系人電話我們也把它獨立出來
{
int i = 0;
for (i = 0; i < con->sz; i++)
{
if (0 == strcmp(con->data[i].cell_num, number))
return i;
}
return -1;//i==con->sz
}
//查找聯(lián)系人
void searchContact(struct Contact* con)
{
assert(con);
char name[20] = { 0 };
char number[12] = {0};
int n;
printf("請問您想要通過那種方式查找聯(lián)系人:\n");
printf("*** 1.姓名 2.電話號碼 ***\n");
int ret=0;
scanf("%d",&n);
switch (n)
{
case 1:
printf("請輸入要查找的聯(lián)系人姓名:");
scanf("%s", &name);
ret = find(con, name);
if (ret == -1)
printf("未找到該聯(lián)系人!\n");
else
{
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
"姓名", "性別","家庭電話", "個人電話", "年齡", "辦公電話", "郵箱", "分類");
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
con->data[ret].name, con->data[ret].sex, con->data[ret].home_num,
con->data[ret].cell_num, con->data[ret].age, con->data[ret].office_number,
con->data[ret].e_mail, con->data[ret].classification);
}
break;
case 2:
printf("請輸入要查找的聯(lián)系人的電話號碼:");
scanf("%s", &number);
ret = findnum(con, number);
if (ret == -1)
printf("未找到該聯(lián)系人!\n");
else
{
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
"姓名","性別", "家庭電話", "個人電話", "年齡", "辦公電話", "郵箱", "分類");
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
con->data[ret].name, con->data[ret].sex, con->data[ret].home_num,
con->data[ret].cell_num, con->data[ret].age, con->data[ret].office_number,
con->data[ret].e_mail, con->data[ret].classification);
}
break;
}
}
//顯示聯(lián)系人
void showContact(struct Contact* con)
{
assert(con);
int i = 0;
//姓名 性別 家庭電話 個人電話 年齡 辦公電話 郵箱 分類
//zhangsan 男 1245676789 13245123123 20 12538912332 67125677121@136.com 家人
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
"姓名", "性別","家庭電話", "個人電話", "年齡", "辦公電話", "郵箱", "分類");
for (i = 0; i < con->sz; i++)
{
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
con->data[i].name, con->data[i].sex, con->data[i].home_num,
con->data[i].cell_num, con->data[i].age, con->data[i].office_number,
con->data[i].e_mail, con->data[i].classification);
}
}
//按姓名排序
int name_cmp(const void* e1, const void* e2)
{
return strcmp(((struct Peoinfo*)e1)->name, ((struct Peoinfo*)e2)->name);
}
//按辦公電話排序
int office_number_cmp(const void* e1, const void* e2)
{
return strcmp(((struct Peoinfo*)e1)->office_number,((struct Peoinfo*)e2)->office_number);
}
//按年齡排序
int age_cmp(const void* e1, const void* e2)
{
return ((struct Peoinfo*)e1)->age - ((struct Peoinfo*)e2)->age;
}
//排序通訊錄
void sortContact(struct Contact con)
{
printf("********* 請選擇排序方式:**********\n");
printf("********* 1.姓名 ***********\n");
printf("********* 2.辦公電話 ***********\n");
printf("********* 3.年齡 ***********\n");
printf("************************************\n");
int a = 0;
scanf("%d", &a);
switch (a)
{
case 1:
qsort(con.data, con.sz, sizeof(con.data[0]), name_cmp);
break;
case 2:
qsort(con.data, con.sz, sizeof(con.data[0]), office_number_cmp);
break;
case 3:
qsort(con.data, con.sz, sizeof(con.data[0]), age_cmp);
break;
default:
printf("輸入錯誤\n");
break;
}
int i = 0;
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
"姓名","性別", "家庭電話", "個人電話", "年齡", "辦公電話", "郵箱", "分類");
for (i = 0; i < con.sz; i++)
{
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
con.data[i].name, con.data[i].sex, con.data[i].home_num,
con.data[i].cell_num, con.data[i].age, con.data[i].office_number,
con.data[i].e_mail, con.data[i].classification);
}
}
//清空聯(lián)系人
void clearContact(struct Contact* con)
{
con->sz = 0;
printf("清空聯(lián)系人成功!\n");
}
//查看某一類聯(lián)系人
void checkContact(struct Contact* con)
{
char classification[10];
int jude = 0;
do
{
printf("人員信息如下:\n");
printf("同事 親戚 朋友 家人 同學(xué) 老師 其他\n");
printf("請輸入查看人員的類別:\n");
scanf("%s", classification);
//用來判斷輸入字符串是否符合分類名稱
char* judgeclass[7] = { "同事", "親戚", "朋友","家人","同學(xué)","老師","其他" };
for (jude = 0; jude < 7; jude++)
{
if ((strcmp(judgeclass[jude], classification) == 0))
break;
}
if (jude == 7)
{
printf("您輸入的分類名錯誤,請重新輸入!>\n");
}
} while (jude==7);
for(int ssz= con->sz - 1;ssz>=0;ssz--)
{
if (strcmp((con->data[ssz].classification), classification) == 0)
{
printf("%-10s\t%-12s\t%-12s\t%-15s\n", "姓名", "家庭電話", "個人電話", "辦公電話");
printf("%-10s\t%-12s\t%-12s\t%-15s\n",
con->data[ssz].name, con->data[ssz].home_num,
con->data[ssz].cell_num, con->data[ssz].office_number);
}
}
printf("查找結(jié)束!\n");
}
//保存聯(lián)系人
void saveContact(struct Contact* con)
{
FILE* pf = fopen("D:\\C語言2\\手機(jī)通信錄實現(xiàn)\\contact.dat", "wb");
if (pf == NULL)
{
//顯示錯誤信息,表示是在saveContact函數(shù)內(nèi)的這個地方出錯了!
perror("SaveContact::fopen");
return;
}
//寫數(shù)據(jù)
int i = 0;
for (i = 0; i < con->sz; i++)
{
//&(con->data[i])可以寫成con->data+i,更簡單
fwrite(con->data + i, sizeof(struct Peoinfo), 1, pf);
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
//簡單提示一下
printf("保存成功!\n");
}
//撥號功能
void dialContact(struct Contact* con)
{
if (con->sz == 0)
{
printf("通信錄中沒有聯(lián)系人信息!\n");
return;
}
printf("通訊錄中所有聯(lián)系人如下:\n");
for (int i = 0; i < con->sz; i++)
{
printf("%d . 姓名:%s\n", i + 1, con->data[i].name);
}
int choice = 0;
printf("請選擇您要撥打電話的聯(lián)系人編號(輸入0返回主菜單):");
scanf("%d", &choice);
if (choice < 0 || choice > con->sz)
{
printf("輸入的編號有誤,請重新選擇!\n");
dialContact(con);//返回?fù)芴柡瘮?shù)選擇處
return;
}
if (choice == 0)
{
return;
}
printf("您選擇的聯(lián)系人是:%s\n", con->data[choice - 1].name);
printf("個人電話:");
// 模擬打字機(jī)效果逐個顯示電話號碼中的數(shù)字
for (int i = 0; i < strlen(con->data[choice - 1].cell_num); i++)
{
printf("%c", con->data[choice - 1].cell_num[i]);
Sleep(300); // 每個數(shù)字之間停頓一段時間
}
printf("\n");
printf("家庭電話:");
// 模擬打字機(jī)效果逐個顯示電話號碼中的數(shù)字
for (int i = 0; i < strlen(con->data[choice - 1].home_num); i++)
{
printf("%c", con->data[choice - 1].home_num[i]);
Sleep(300); // 每個數(shù)字之間停頓一段時間
}
printf("\n");
printf("辦公電話:");
// 模擬打字機(jī)效果逐個顯示電話號碼中的數(shù)字
for (int i = 0; i < strlen(con->data[choice - 1].office_number); i++)
{
printf("%c", con->data[choice - 1].office_number[i]);
Sleep(300); // 每個數(shù)字之間停頓一段時間
}
printf("\n");
}
// 子函數(shù),實現(xiàn)模糊查找功能
void fuzzy_search(struct Contact* contact)
{
assert(contact);
char fuzzy_name[10] = {0};
printf("請輸入想要查詢的聯(lián)系人的姓名:\n");
scanf("%s",fuzzy_name);
char* key = fuzzy_name;
// 檢查通訊錄中是否有聯(lián)系人信息,如果沒有,無法進(jìn)行模糊查詢
if (contact->sz == 0)
{
printf("通訊錄中沒有聯(lián)系人信息!\n");
return;
}
int index[MAX_DATA];
int count = 0;
// 遍歷通訊錄中的每個聯(lián)系人
for (int i = 0; i < contact->sz; i++)
{
struct Peoinfo* person = &contact->data[i];
// 在聯(lián)系人的各個字段中查找是否包含要查找的字符串key
if (strstr(person->name, key))
{
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5s\t%-15s\t%-20s\t%-10s\n",
"姓名", "性別", "家庭電話", "個人電話", "年齡", "辦公電話", "郵箱", "分類");
printf("%-10s\t%-5s\t%-12s\t%-12s\t%-5d\t%-15s\t%-20s\t%-10s\n",
person->name, person->sex, person->home_num, person->cell_num, person->age, person->office_number,
person->e_mail, person->classification);
index[count++] = i;
}
}
// 如果沒有找到匹配的聯(lián)系人,則輸出提示信息
if (count == 0)
{
printf("未找到匹配的聯(lián)系人!\n");
}
else
{
printf("共找到 %d 個匹配的聯(lián)系人,分別為:", count);
for (int i = 0; i < count; i++)
{
printf("第%d個聯(lián)系人 ", index[i]+1);
//讓聯(lián)系人看起來是從第1個開始排序的,即下標(biāo)0處跳過
}
printf("\n");
}
}
運行效果圖:
1、增加聯(lián)系人
?總的顯示給大家看一下:
?現(xiàn)在假設(shè)我們重新輸入,來看看如果出現(xiàn)名字相同的聯(lián)系人,程序會有什么反應(yīng)吧:
?
?
?
來看看新建同名聯(lián)系人后的小米和小米(1)吧:?
?那電話號碼相同的呢?可以新建嗎?當(dāng)然不行,和姓名相同時的代碼略有不同:
?如果選擇覆蓋呢?
?小米不見了呢?。▽Σ黄穑∶祝?img src="https://imgs.yssmx.com/Uploads/2023/10/734496-10.png" alt="switch模糊查詢,進(jìn)階C語言,小游戲,通訊錄的實現(xiàn),智能手機(jī),c語言,算法" referrerpolicy="no-referrer" />
?當(dāng)然,我們迷人的addContact函數(shù)還有一個功能,就是會判斷你輸入的三個電話號碼中是否存在非數(shù)字字符,來看一下吧:
2、刪除聯(lián)系人
?總的顯示給大家看一下:
?3、修改聯(lián)系人信息:
??總的顯示給大家看一下:
4、尋找單個聯(lián)系人?
?5、顯示整個通訊錄(剛剛已經(jīng)展示過了)
6、排序
?
?
7、清除所有聯(lián)系人
?8、按分類查找某一類的聯(lián)系人?
?9、保存到文件里
?已經(jīng)保存到當(dāng)前目錄下了:
10、模擬撥號(它是像打印機(jī)一樣慢慢一個數(shù)字一個數(shù)字打印的,這里演示不了)
11、模糊查詢?
12、把上次已經(jīng)存好在文件中的信息加載過來:
當(dāng)初次使用時:
?如果已有信息(這里博主為了演示,把剛剛上面舉的例子都刪除了,所以現(xiàn)在的數(shù)據(jù)是博主又重新輸入的,和上面的聯(lián)系人信息存在不同,請見諒):
?現(xiàn)在已經(jīng)保存好了:
我們重啟程序看看:?成功讀取了呢!?
好了!以上就是我的手機(jī)通信錄的整個代碼實現(xiàn)。
如果你認(rèn)真看到這里,說明你應(yīng)該對它的實現(xiàn)很感興趣吧。
心動不如行動!實踐是很重要的!現(xiàn)在,打開電腦,開始碼代碼吧。
博主建議,各位兄臺先自己實現(xiàn)一下,如果遇到邏輯不通的地方,可以畫一個圖解幫助自己理解,
實在是遇到不理解的地方可以再回來看看。自己寫一遍真的不一樣!??!
部分復(fù)雜函數(shù)流程圖
最后,因為兩個結(jié)構(gòu)體的關(guān)系有一點不好理解,所以博主畫了一個總的說明圖(圖1):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖1
下面是一些稍微復(fù)雜的函數(shù)的流程圖(實驗報告要求要畫,我覺得比代碼難搞1000倍!超累的?。。。?/p>
添加聯(lián)系人函數(shù):用于將新的聯(lián)系人信息添加到通訊錄中。該功能包括輸入聯(lián)系人的各項信息,然后將這些信息保存到通訊錄中。在保存之前,可能需要進(jìn)行一些驗證和處理,例如檢查通訊錄是否已滿、檢查是否存在重復(fù)的姓名或電話號碼等。
該函數(shù)用于將新的聯(lián)系人信息添加到通訊錄中。該功能包括輸入聯(lián)系人的各項信息,然后將這些信息保存到通訊錄中。在保存之前,可能需要進(jìn)行一些驗證和處理,例如檢查通訊錄是否已滿、檢查是否存在重復(fù)的姓名、存入電話號碼前先判斷輸入的是否為數(shù)字、是否存在重復(fù)的電話號碼等,如圖2-1-1所示。其中,添加聯(lián)系人函數(shù)用到了5個小的功能函數(shù),它們在“修改聯(lián)系人函數(shù)”時也會再次被調(diào)用。find函數(shù)流程圖,用來尋找整個通信錄中是否有該名字的字符串,如圖2-1-2所示;findnum函數(shù)流程圖,用來尋找整個通信錄中是否已有相同號碼的字符串,如圖2-1-3所示;isnumber函數(shù)流程圖,用來判斷輸入號碼中是否含有非數(shù)字字符,如圖2-1-4所示;repetition_name函數(shù)流程圖,用于判斷是否有相同姓名的聯(lián)系人,如圖2-1-5所示;repetition_num函數(shù),用于判斷是否有相同號碼的聯(lián)系人,如圖2-1-6所示。
圖2-1-1 添加聯(lián)系人功能(第1種實現(xiàn))
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖2-1-2 fun函數(shù)(查找同名聯(lián)系人)
? ? ?? ? ? ? ???圖2-1-3 funnum函數(shù)(查找相同號碼聯(lián)系人)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖2-1-4 isnumber函數(shù)(判斷是否有非數(shù)字字符)
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖2-1-5 repetition_name函數(shù)?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖2-1-6 repetition_num函數(shù)
?修改聯(lián)系人信息函數(shù):在已有的通訊錄中修改聯(lián)系人的相關(guān)信息的函數(shù)。要求用戶輸入要修改的聯(lián)系人姓名作為唯一標(biāo)識信息,然后遍歷整個通訊錄,查找是否存在該聯(lián)系人。如果存在該聯(lián)系人,用戶可以根據(jù)需要選擇需要修改的信息并進(jìn)行修改,修改后的信息會被更新到通訊錄中,如果沒有找到該聯(lián)系人,則會給出相應(yīng)的提示信息。
在已有的通信錄中修改聯(lián)系人的相關(guān)信息的函數(shù),先判斷通信錄是否為空,若為空則提醒用戶并退出,不為空則要求用戶輸入要修改的聯(lián)系人姓名,作為唯一標(biāo)識信息,然后遍歷整個通信錄,查找是否存在該聯(lián)系人。若存在該聯(lián)系人,用戶可以根據(jù)需要選擇需要修改的信息并進(jìn)行修改,修改后的信息會被更新到通信錄中,若沒有找到該聯(lián)系人,則會給出相應(yīng)的提示信息。流程圖如圖3所示。
?查找特定聯(lián)系人函數(shù):根據(jù)姓名或號碼查找特定聯(lián)絡(luò)人信息。這個功能允許用戶通過輸入聯(lián)系人的姓名或號碼來查找該聯(lián)系人的信息,如果找到,則返回該聯(lián)系人的詳細(xì)信息,否則返回查找失敗的信息。
查找特定聯(lián)系人信息流程圖如圖5所示。?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如圖5??查找特定聯(lián)系人信息
模糊查詢函數(shù):在通訊錄中根據(jù)關(guān)鍵字模糊搜索聯(lián)系人信息的功能。該功能可以讓用戶快速查找到包含特定關(guān)鍵字的聯(lián)系人信息。根據(jù)輸入的關(guān)鍵字,遍歷通訊錄中的所有聯(lián)系人信息,查找包含關(guān)鍵字的聯(lián)系人信息并輸出。?
模糊查詢函數(shù)如圖6所示
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? 圖6? 模糊查詢函數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-734496.html
本次內(nèi)容到這里就結(jié)束啦!謝謝認(rèn)真看到這里的你呀!文章來源地址http://www.zghlxwxcb.cn/news/detail-734496.html
到了這里,關(guān)于實驗課題——最全手機(jī)通信錄實現(xiàn)版本(【含注釋】848行代碼)?。。。ò:樵?、分類查找、模擬撥號、qsort函數(shù)實現(xiàn)排序、文件存儲、防誤觸等功能)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!