引言
學會創(chuàng)建一個通訊錄,對過往知識進行加深和鞏固。
文章很長,要耐心學完哦!
? ? ? ? ? ? ? ???豬巴戒:個人主頁?
???????????????所屬專欄:《C語言進階》
? ? ? ? ??跟著豬巴戒,一起學習C語言??
目錄
引言
實戰(zhàn)
建立文件
包含頭文件
結構體的使用?
通訊錄?
菜單
主脈絡的實現
初始化函數的實現
第一個功能:增加聯系人到通訊錄
第二個功能:刪除聯系人的信息
第三個功能:查找指定聯系人
第四個功能:修改指定聯系人
第五個功能:打印通訊錄中信息
第六個功能:排序通訊錄中的內容
整體的代碼實現
實戰(zhàn)
通訊錄的功能就是,記錄聯系人的信息,我們將聯系人的信息分為5個部分,分別是姓名、年齡、性別、手機號、地址。
建立文件
我們要將通訊錄的功能實現,首先要建立1個頭文件,2個源文件。
一個源文件的名字叫contact.c,用來存放實現通訊錄功能的函數
另外一個源文件叫test.c,用來實現通訊錄的整體脈絡
頭文件叫做contact.h,用來聲明contact.c中的函數,這樣在test.c運行的時候就不會報出警告。
contact.h用來聲明contact.c中的函數,test.c就要包含contact.h,自己的頭文件如下圖包含:
#include "contact.h"
????????
包含頭文件
?既然test.c包含自己的頭文件contact.h,為了簡潔方便,不妨把我們要使用的庫函數的頭文件包含在contact.h中.
contact.c也把contact.h頭文件包含,就不用再contact.c中再包含多個頭文件了。
頭文件會將功能函數聲明放在里面,供給test.c使用,contact.c用來實現功能函數。
????????
結構體的使用?
我們要將聯系人的5個信息儲存起來,而這5個信息的類型有不一樣,所以我們通過結構體將它們組合在一起,
結構體,結構是一些值的集合,這些值被稱為成員變量。結構的每個成員可以是不同類型的變量。
結構體的使用包含再兩個源文件中,所以我們將結構體的定義和聲明放在contact.h頭文件中。?
typedef,關鍵字,作用是為一個類型創(chuàng)建一個新的名字。
本來下面結構體的類型是struct PeoInfo,為了將名字簡化,用到了typedef關鍵字。
typedef struct PeoInfo
{
char name[100];
int age;
char sex[10];
char tele[12];
char addr[30];
}PeoInfo;
#define ,為了更好改變name,sex,tele,addr的最大容量,通過定義宏將參數替換。?
MAX 表示最大能容納的聯系人個數
MAX_NAME 表示name最大能容納的字符個數
MAX_SEX??表示sex最大能容納的字符個數
MAX_TELE?表示tele最大能容納的字符個數
MAX_ADDR?表示addr最大能容納的字符個數
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
????????
通訊錄?
存放在頭文件contact.h
通訊錄不僅要包含上面的5個信息,5個信息包含在一起就是一個人的信息。創(chuàng)建變量count,可以記錄通訊錄的實際人數,之后的打印功能,也要使用count來打印。
data是struct PeoInfo類型的數組。上面把struct PeoInfo簡化為PeoInfo.
data是儲存每個人信息的數組,數組的每個元素代表著一個人的信息。
typedef struct Contact
{
PeoInfo data[MAX];
int count;//記錄當前通訊錄中實際人數的個數
}Contact;
菜單
存放在test.c源文件
首先給用戶呈現的是菜單,菜單記錄著用戶可供選擇的功能,將功能可視化。
一共包含6個功能
- 增加聯系人到通訊錄
- 刪除聯系人的信息
- 查找指定聯系人
- 修改指定聯系人
- 打印通訊錄中信息
- 排序通訊錄中的內容
0.退出通訊錄
void menu()
{
printf("**********************************************\n");
printf("******** 1.add 2.del ********\n");
printf("******** 3.search 4.modify ********\n");
printf("******** 5.show 6.sort ********\n");
printf("******** 0.exit ********\n");
printf("**********************************************\n");
}
?????????
主脈絡的實現
存放在test.c
input,為鍵盤輸入的數字,選擇不同的數字代表著不同的功能。
switch語句,分支語句實現input為不同的數字,選擇不同的功能,在case 后面實現這六個功能。
創(chuàng)建新的結構體變量要進行初始化,InitContact(&con)就是用來初始化結構體的。
之所以用自定義函數InitContact,是為了簡潔和模塊化處理。
int main()
{
int input = 0;
Contact con;
//初始化通訊錄:模塊化初始化
InitContact(&con);//只能傳地址,進行修改
scanf("%d",&input);
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");
}
} while (input);
return 0;
}
????????
初始化函數的實現
存放在源文件contact.c
assert用來檢驗pc是否為空指針,如果為空指針就會報錯。頭文件<assert.h>
memset,功能是填充內存塊,將num個字節(jié)的value填充到起始地址為ptr的位置。
void InitContact(Contact* pc)
{
assert(pc);
pc->count = 0;
memset(pc->data, 0, sizeof(pc->data));
}
?test.c要想使用,就要在頭文件contact.h中進行聲明。
void InitContact(Contact* pc);
第一個功能:增加聯系人到通訊錄
功能函數的實現都會放在contact.c中。
assert用來檢驗pc是否為空指針,如果為空指針就會報錯。頭文件<assert.h>
Contact* pc是傳過來的struct Contact 類型的變量的地址,這里是傳址調用,可以改變原來結構體的內容。
如果count到了通訊錄的最大容量,就不能添加信息了,退出函數,并發(fā)出提示。
原始的count是0,每添加一個人的信息,count就要加1。
新的count表示的就是新聯系人的下標,通過pc->data[pc->count].name??的方式找到各個信息。
如果count已經達到最大值,那么就直接提示 “通訊錄已滿,無法添加” ,并結束函數。
函數實現
void AddContact(Contact* pc)
{
assert(pc);
if (pc->count == MAX)
{
printf("通訊錄已滿,無法添加\n");
return;
}
printf("請輸入名字:》");
scanf("%s", pc->data[pc->count].name);
printf("請輸入年齡:》");
scanf("%d", &(pc->data[pc->count].age));
printf("請輸入性別:>");
scanf("%s", pc->data[pc->count].sex);
printf("請輸入電話:>");
scanf("%s", pc->data[pc->count].tele);
printf("請輸入地址:>");
scanf("%s", pc->data[pc->count].addr);
pc->count++;
printf("增加成功\n");
}
????????
第二個功能:刪除聯系人的信息
assert用來檢驗pc是否為空指針,如果為空指針就會報錯。頭文件<assert.h>
Contact* pc是傳過來的struct Contact 類型的變量的地址,這里是傳址調用,可以改變原來結構體的內容。
如果count為0,就表示通訊錄里面沒有內容,也就不能刪除。直接提示?"通訊錄為空,沒有信息可以刪除" 然后退出函數。
要刪除聯系人的信息,首先要查找聯系人,之后才能刪除。所以要實現查找聯系人的功能。
1.查找
2.刪除
查找:FindByName函數實現
創(chuàng)建一個字符函數name,向name輸入我們要查找的聯系人名字,之后用name來進行對比。
首先輸入要查找的聯系人名字,通過下標 i 對data進行查找,直到找到,返回下標,或者返回-1.
名字是字符數組,用strcmp對進行比較名字,庫函數strcmp只有在相等的時候返回0。
strcmp的頭文件:<string.h>
刪除:DelContact來實現
找到要刪除的聯系人的下標,我們將它后面聯系人的信息覆蓋掉要刪除的聯系人的信息,就可以達到目的,然后對count減一,這樣count就可以表示聯系人的個數了。
本來最后一位的聯系人的信息不用進行操作,本來count是99,下標為99的聯系人信息覆蓋到下標為98的位置,下標為99的信息不用管,count--之后,count = 98,下標為99的數據就不會被我們使用到。
函數實現
static int FindByName(Contact* pc,char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
assert(pc);
int i = 0;
if (pc->count == 0)
{
printf("通訊錄為空,沒有信息可以刪除\n");
return;
}
printf("請輸入要刪除人的名字:>");
scanf("%s", name);
//刪除
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要刪除的人不存在\n");
return;
}
//2.刪除
for (i = pos; i < pc->count; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->count--;
}
????????
第三個功能:查找指定聯系人
assert用來檢驗pc是否為空指針,如果為空指針就會報錯。頭文件<assert.h>
Contact* pc是傳過來的struct Contact 類型的變量的地址,這里是傳址調用,可以改變原來結構體的內容。
建立字符數組name,輸入要查找的聯系人的信息。通過FindByName對name進行查找。
FindByName在上個功能實現了,當找到聯系人的信息,返回下標。沒找到返回-1。
我們用pos來對FindByName的返回值進行回收,如果pos等于-1,提示?"要查找的人不存在"然后
函數實現
void SeachContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
printf("請輸入需要查找的聯系人的名字:>");
scanf("%s", name);
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
//2.打印
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年齡", "性別", "電話", "地址");
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
?????????
第四個功能:修改指定聯系人
assert檢驗空指針,name用來接收要修改聯系人的姓名,通過?FindByName 查找聯系人,pos返回查找結果。Contact* pc是傳過來的struct Contact 類型的變量的地址,這里是傳址調用,可以改變原來結構體的內容。
找到結果會返回下標pos,得到下標用ps->data[pos].name就可以修改內容了。
函數實現
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
printf("請輸入需要查找的聯系人的名字:>");
scanf("%s", name);
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
printf("要修改人的信息已經找到,接下來進行修改\n");
//2.修改
printf("請輸入名字:》");
scanf("%s", pc->data[pos].name);
printf("請輸入年齡:》");
scanf("%d", &(pc->data[pos].age));
printf("請輸入性別:>");
scanf("%s", pc->data[pos].sex);
printf("請輸入電話:>");
scanf("%s", pc->data[pos].tele);
printf("請輸入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
????????
第五個功能:打印通訊錄中信息
assert檢驗空指針。為了對齊聯系人的數據,數據以最大容納量來進行打印。
%20就是按照20個字符打印,%-20就是左對齊的意思。
函數實現
void ShowContact(const Contact* pc)
{
assert(pc);
int i = 0;
//一個漢字是兩個字符
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年齡", "性別", "電話", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
????????
第六個功能:排序通訊錄中的內容
assert檢驗空指針。qsort是快速排列函數。base是要排序的起始地址,pc->data表示首元素地址。num是要比較的元素個數,通訊錄有多少個人,就比較多少個元素,num為pc->count。按名字排序,compar要比較的是通訊錄的名字,我們實現cmp_peo_by_name函數,到時候把這個函數傳過去。
cmp_peo_by_name:比較名字函數,名字是字符串,通過strcmp對字符串進行比較。
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*))
函數實現
int cmp_peo_by_name(const void* e1, const void* e2)
{
return strcmp( ((PeoInfo*)e1)->name , ((PeoInfo*)e2)->name );
}
//按照名字來排序
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name );
printf("排序成功\n");
}
????????
整體的代碼實現
test.c
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//
//1.靜態(tài)的版本
//2.動態(tài)的版本
//3.文件的版本
//
void menu()
{
printf("**********************************************\n");
printf("******** 1.add 2.del ********\n");
printf("******** 3.search 4.modify ********\n");
printf("******** 5.show 6.sort ********\n");
printf("******** 0.exit ********\n");
printf("**********************************************\n");
}
int main()
{
int input = 0;
Contact con;
//初始化通訊錄:模塊化初始化
InitContact(&con);//只能傳地址,進行修改
do
{
menu();
printf("請選擇:》");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&con);
break;
case 2:
DelContact(&con);
break;
case 3:
SeachContact(&con);
break;
case 4:
ModifyContact(&con);
break;
case 5:
ShowContact(&con);
break;
case 6:
SortContact(&con);
break;
case 0:
printf("退出通訊錄\n");
break;
default:
printf("選擇錯誤\n");
}
} while (input);
return 0;
}
contact.c文章來源:http://www.zghlxwxcb.cn/news/detail-761084.html
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void InitContact(Contact* pc)
{
assert(pc);
pc->count = 0;
memset(pc->data, 0, sizeof(pc->data));
}
void AddContact(Contact* pc)
{
assert(pc);
if (pc->count == MAX)
{
printf("通訊錄已滿,無法添加\n");
return;
}
printf("請輸入名字:》");
scanf("%s", pc->data[pc->count].name);
printf("請輸入年齡:》");
scanf("%d", &(pc->data[pc->count].age));
printf("請輸入性別:>");
scanf("%s", pc->data[pc->count].sex);
printf("請輸入電話:>");
scanf("%s", pc->data[pc->count].tele);
printf("請輸入地址:>");
scanf("%s", pc->data[pc->count].addr);
pc->count++;
printf("增加成功\n");
}
void ShowContact(const Contact* pc)
{
assert(pc);
int i = 0;
//一個漢字是兩個字符
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年齡", "性別", "電話", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
}
static int FindByName(Contact* pc,char name[])
{
assert(pc);
int i = 0;
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
void DelContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
assert(pc);
int i = 0;
if (pc->count == 0)
{
printf("通訊錄為空,沒有信息可以刪除\n");
return;
}
printf("請輸入要刪除人的名字:>");
scanf("%s", name);
//刪除
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要刪除的人不存在\n");
return;
}
//2.刪除
for (i = pos; i < pc->count; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->count--;
}
void SeachContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
printf("請輸入需要查找的聯系人的名字:>");
scanf("%s", name);
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
//2.打印
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年齡", "性別", "電話", "地址");
printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].tele,
pc->data[pos].addr);
}
void ModifyContact(Contact* pc)
{
assert(pc);
char name[MAX_NAME] = { 0 };
printf("請輸入需要查找的聯系人的名字:>");
scanf("%s", name);
//1.查找
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("要查找的人不存在\n");
return;
}
printf("要修改人的信息已經找到,接下來進行修改\n");
//2.修改
printf("請輸入名字:》");
scanf("%s", pc->data[pos].name);
printf("請輸入年齡:》");
scanf("%d", &(pc->data[pos].age));
printf("請輸入性別:>");
scanf("%s", pc->data[pos].sex);
printf("請輸入電話:>");
scanf("%s", pc->data[pos].tele);
printf("請輸入地址:>");
scanf("%s", pc->data[pos].addr);
printf("修改成功\n");
}
int cmp_peo_by_name(const void* e1, const void* e2)
{
return strcmp( ((PeoInfo*)e1)->name , ((PeoInfo*)e2)->name );
}
//按照名字來排序
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name );
printf("排序成功\n");
}
?contact.h文章來源地址http://www.zghlxwxcb.cn/news/detail-761084.html
#pragma once
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30
//類型的聲明
typedef struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
}PeoInfo;
//通訊錄
typedef struct Contact
{
PeoInfo data[MAX];
int count;//記錄當前通訊錄中實際人數的個數
}Contact;
//初始化通訊錄
void InitContact(Contact* pc);
//增加聯系人到通訊錄
void AddContact(Contact* pc);
//打印通訊錄中信息
void ShowContact(const Contact* pc);
//刪除聯系人的信息
void DelContact(Contact* pc);
//查找指定聯系人
void SeachContact(Contact* pc);
//修改指定聯系人
void ModifyContact(Contact* pc);
//排序通訊錄中的內容
//按照名字來排序
void SortContact(Contact* pc);
到了這里,關于【C語言】實戰(zhàn)項目——通訊錄的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!