?
????????????????????????????????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?個人主頁:秋風(fēng)起,再歸來~
? ?????????????????????????????????????????? ? ? ? ? ? ? ?? ???? ? ? ? ? ? ? ???文章專欄:C語言實戰(zhàn)項目 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??個人格言:悟已往之不諫,知來者猶可追
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????? ? ? ? ? ? ? ? ? ?克心守己,律己則安!
1、前言
友友們,這篇文章是基于單鏈表來實現(xiàn)通訊管理系統(tǒng)的,所以一定要先看完我之前寫過的一篇關(guān)于單鏈表的實現(xiàn)(文章鏈接)的文章哦~
其實基于單鏈表實現(xiàn)通訊錄的思路與基于順訊表實現(xiàn)通訊錄的思路是一樣的,在這里我就不進行贅述了。如果還沒有看過我之前寫的一篇基于順序表實現(xiàn)通訊錄(文章鏈接)的寶子們一定要去看看哦~
2、各種接口的實現(xiàn)
以下是我們希望實現(xiàn)的接口~
//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//前置聲明
typedef struct SListNode contact;
//用戶數(shù)據(jù)
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//初始化通訊錄
void InitContact(contact** con);
//添加通訊錄數(shù)據(jù)
void AddContact(contact** con);
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con);
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con);
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con);
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con);
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con);
2.1 初始化通訊錄
我們希望在初始化通訊錄時導(dǎo)入之前我們原有文件中的數(shù)據(jù),那我們就可以進行如下的操作~
//從文件中導(dǎo)入原數(shù)據(jù)
void DLoadContact(contact** con)
{
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
perror("open fail\n");
return;
}
PeoInfo p = { 0 };
while (fread(&p, sizeof(PeoInfo),1,pf))
{
SListPushBack(con, p);
}
printf("歷史數(shù)據(jù)導(dǎo)入成功!\n");
fclose(pf);
pf = NULL;
}
在初始化通訊錄之后加載數(shù)據(jù)!?
//初始化通訊錄
void InitContact(contact** con)
{
assert(con);
(*con) = NULL;
DLoadContact(con);
}
2.2?添加通訊錄數(shù)據(jù)
//添加通訊錄數(shù)據(jù)
void AddContact(contact** con)
{
assert(con);
PeoInfo p = {0};
printf("請輸入添加聯(lián)系人的姓名:");
scanf("%s", p.name);
printf("請輸入添加聯(lián)系人的性別:");
scanf("%s", p.sex);
printf("請輸入添加聯(lián)系人的年齡:");
scanf("%d", &(p.age));
printf("請輸入添加聯(lián)系人的電話:");
scanf("%s", p.tel);
printf("請輸入添加聯(lián)系人的住址:");
scanf("%s", p.addr);
SListPushBack(con,p);
printf("\n");
}
2.3?刪除通訊錄數(shù)據(jù)
在查找通訊錄數(shù)據(jù)之外封裝一個函數(shù)(findByName)來通過名字查找聯(lián)系人!
(因為我們在之后的查找和修改接口中都會用到這個方法,所以我們把它封裝成一個函數(shù)方便我們后續(xù)的使用!)
//通過名字查找聯(lián)系人
contact* findByName(contact* con,char* name)
{
assert(con);
contact* cur = con;
while (cur)
{
if (strcmp(cur->data.name, name) == 0)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
在原有單鏈表的刪除指定數(shù)據(jù)的接口上進行封裝(讓單鏈表搖身一變成為通訊錄?。?/strong>
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con)
{
assert(con && (*con));
char name[NAME_MAX];
printf("請輸入你要刪除的聯(lián)系人的名字:");
scanf("%s", name);
contact* pos = findByName(*con,name);
if (pos == NULL)
{
printf("您要刪除的聯(lián)系人不存在!\n");
return;
}
SListErase(con, pos);
printf("刪除成功!\n");
}
2.4?展示通訊錄數(shù)據(jù)
遍歷我們的通訊錄打印信息!
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con)
{
assert(con);
contact* cur = con;
printf("名字\t\t性別\t\t年齡\t\t電話\t\t住址\n");//打印表頭
while (cur)
{
printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
cur->data.name,
cur->data.sex,
cur->data.age,
cur->data.tel,
cur->data.addr);
cur = cur->next;
}
}
2.5?查找通訊錄數(shù)據(jù)
//通過名字查找聯(lián)系人
contact* findByName(contact* con,char* name)
{
assert(con);
contact* cur = con;
while (cur)
{
if (strcmp(cur->data.name, name) == 0)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
在接口內(nèi)部調(diào)用該函數(shù)!?
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("請輸入你要查找的聯(lián)系人的名字:");
scanf("%s", name);
contact* ret = findByName(con, name);
if (ret == NULL)
{
printf("您要查找的聯(lián)系人不存在!\n");
return;
}
printf("找到了!\n");
printf("名字\t\t性別\t\t年齡\t\t電話\t\t住址\n");//打印表頭
printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
ret->data.name,
ret->data.sex,
ret->data.age,
ret->data.tel,
ret->data.addr);
}
2.6?修改通訊錄數(shù)據(jù)
//通過名字查找聯(lián)系人
contact* findByName(contact* con,char* name)
{
assert(con);
contact* cur = con;
while (cur)
{
if (strcmp(cur->data.name, name) == 0)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
在接口內(nèi)部調(diào)用該函數(shù)!?
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con)
{
assert(con);
char name[NAME_MAX];
printf("請輸入你要修改的聯(lián)系人的名字:");
scanf("%s", name);
contact* ret = findByName(*con, name);
if (ret == NULL)
{
printf("您要修改的聯(lián)系人不存在!\n");
return;
}
PeoInfo p = { 0 };
printf("請輸入修改后聯(lián)系人的姓名:");
scanf("%s", p.name);
printf("請輸入修改后聯(lián)系人的性別:");
scanf("%s", p.sex);
printf("請輸入修改后加聯(lián)系人的年齡:");
scanf("%d", &(p.age));
printf("請輸入修改后聯(lián)系人的電話:");
scanf("%s", p.tel);
printf("請輸入修改后聯(lián)系人的住址:");
scanf("%s", p.addr);
SListModify(ret, p);
printf("修改成功!\n");
}
2.7 銷毀通訊錄數(shù)據(jù)
因為我們希望在退出通訊管理系統(tǒng)的時候可以將我們的操作都保留下來,所以我們可以對其進行文件操作!
//將輸入的數(shù)據(jù)保存到文件中
void SaveContact(contact** con)
{
FILE* pf = fopen("contact.txt", "wb");
if (pf == NULL)
{
perror("open fail!\n");
return;
}
contact* cur = *con;
while (cur)
{
fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);
cur = cur->next;
}
printf("歷史數(shù)據(jù)保存成功!\n");
fclose(pf);
pf = NULL;
}
?在銷毀通訊錄之前保留數(shù)據(jù)!
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con)
{
SaveContact(con);
SListDestroy(con);
}
3、完整源碼
SeqList.h
#pragma once//避免頭文件被多次引用
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"
typedef PeoInfo SListDataType;//便于改變數(shù)據(jù)類型
//定義一個結(jié)構(gòu)體類型的節(jié)點
typedef struct SListNode
{
SListDataType data;
struct SListNode* next;//存儲下一個節(jié)點的地址
}SListNode;
//1. 新節(jié)點的創(chuàng)建
SListNode* SListCreatNode(SListDataType x);
//2. 打印單鏈表
void PrintSList(SListNode* phead);
//3. 頭插
void SListPushFront(SListNode** phead, SListDataType x);
//4. 頭刪
void SListPopFront(SListNode** phead);
//5. 尾差
void SListPushBack(SListNode** phead, SListDataType x);
//6. 尾刪
void SListPopBack(SListNode** phead);
//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x);
//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x);
//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x);
//10. 在任意位置刪除
void SListErase(SListNode** phead, SListNode* pos);
//11. 銷毀單鏈表
void SListDestroy(SListNode** phead);
Contact.h
#define _CRT_SECURE_NO_WARNINGS
//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//前置聲明
typedef struct SListNode contact;
//用戶數(shù)據(jù)
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//初始化通訊錄
void InitContact(contact** con);
//添加通訊錄數(shù)據(jù)
void AddContact(contact** con);
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con);
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con);
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con);
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con);
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con);
SeqList.c
#include"SList.h"
//1. 新節(jié)點的創(chuàng)建
SListNode* SListCreatNode(SListDataType x)
{
SListNode* NewNode = (SListNode*)malloc(sizeof(SListNode));//開辟空間
if (NewNode == NULL)//判斷空間是否開辟成功
{
perror("malloc fail");
return NULL;
}
NewNode->data = x;//賦值
NewNode->next = NULL;//置空
return NewNode;
}
#if 0
//2. 打印單鏈表
void PrintSList(SListNode* phead)
{
if (phead == NULL)
{
printf("NULL");//如果鏈表沒有元素就打印NULL
return;
}
SListNode* cur = phead;
//循環(huán)單鏈表打印
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
#endif
//3. 頭插
void SListPushFront(SListNode** phead, SListDataType x)
{
assert(phead);
SListNode* newnode = SListCreatNode(x);//創(chuàng)建一個新節(jié)點
newnode->next = *phead;
*phead = newnode;
}
//4. 頭刪
void SListPopFront(SListNode** phead)
{
assert(phead);
assert(*phead);//如果沒有數(shù)據(jù)就不用頭刪,并報錯
SListNode* cur = (*phead)->next;
free(*phead);
*phead = cur;
}
//5. 尾插
void SListPushBack(SListNode** phead, SListDataType x)
{
assert(phead);
if (*phead == NULL)
{
*phead = SListCreatNode(x);//創(chuàng)建新節(jié)點并插入
}
else
{
SListNode* tail = *phead;
while (tail->next != NULL)//找到尾節(jié)點
{
tail = tail->next;
}
tail->next = SListCreatNode(x);//創(chuàng)建新節(jié)點并插入
}
}
//6. 尾刪
void SListPopBack(SListNode** phead)
{
assert(phead);
assert(*phead);//鏈表為空就不進行尾刪
SListNode* tail = *phead;
if (tail->next == NULL)//如果鏈表就只有一個元素就進行頭刪
{
SListPopFront(phead);
}
else
{
while (tail->next->next != NULL)
{
tail = tail->next;
}
free(tail->next);
tail->next = NULL;
}
}
#if 0
//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x)
{
assert(phead);
while (phead->next != NULL)//注意最后一個節(jié)點是沒有查找的
{
if (phead->data == x)
return phead;
phead = phead->next;
}
if (phead->data == x)
return phead;//最后一個節(jié)點沒有查找
else
return NULL;//沒找到
}
#endif
//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x)
{
assert(pos);
pos->data = x;
}
//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x)
{
assert(phead);
assert(*phead);
if (pos == *phead)//如果pos位置剛好是第一個節(jié)點就進行頭插
{
SListPushFront(phead, x);
}
else
{
SListNode* newnode = SListCreatNode(x);
SListNode* cur = *phead;
while (cur->next != pos)//找到pos前一個節(jié)點
{
cur = cur->next;
}
cur->next = newnode;
newnode->next = pos;
}
}
//10. 在任意位置刪除
void SListErase(SListNode** phead, SListNode* pos)
{
assert(phead && *phead && pos);
if (pos == *phead)//如果pos位置就是第一個節(jié)點就進行頭刪
{
SListPopFront(phead);
}
else
{
SListNode* cur = *phead;
while (cur->next != pos)//找到pos前一個節(jié)點
{
cur = cur->next;
}
cur->next = pos->next;
free(pos);
}
}
//11. 銷毀單鏈表
void SListDestroy(SListNode** phead)
{
assert(*phead && phead);
SListNode* cur = *phead;
while (cur != NULL)
{
SListNode* tmp = cur->next;
free(cur);
cur = tmp;
}
*phead = NULL;
}
Contact.c
#include"SList.h"
//從文件中導(dǎo)入原數(shù)據(jù)
void DLoadContact(contact** con)
{
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
perror("open fail\n");
return;
}
PeoInfo p = { 0 };
while (fread(&p, sizeof(PeoInfo),1,pf))
{
SListPushBack(con, p);
}
printf("歷史數(shù)據(jù)導(dǎo)入成功!\n");
fclose(pf);
pf = NULL;
}
//初始化通訊錄
void InitContact(contact** con)
{
assert(con);
(*con) = NULL;
DLoadContact(con);
}
//添加通訊錄數(shù)據(jù)
void AddContact(contact** con)
{
assert(con);
PeoInfo p = {0};
printf("請輸入添加聯(lián)系人的姓名:");
scanf("%s", p.name);
printf("請輸入添加聯(lián)系人的性別:");
scanf("%s", p.sex);
printf("請輸入添加聯(lián)系人的年齡:");
scanf("%d", &(p.age));
printf("請輸入添加聯(lián)系人的電話:");
scanf("%s", p.tel);
printf("請輸入添加聯(lián)系人的住址:");
scanf("%s", p.addr);
SListPushBack(con,p);
printf("\n");
}
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con)
{
assert(con);
contact* cur = con;
printf("名字\t\t性別\t\t年齡\t\t電話\t\t住址\n");//打印表頭
while (cur)
{
printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
cur->data.name,
cur->data.sex,
cur->data.age,
cur->data.tel,
cur->data.addr);
cur = cur->next;
}
}
//通過名字查找聯(lián)系人
contact* findByName(contact* con,char* name)
{
assert(con);
contact* cur = con;
while (cur)
{
if (strcmp(cur->data.name, name) == 0)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con)
{
assert(con && (*con));
char name[NAME_MAX];
printf("請輸入你要刪除的聯(lián)系人的名字:");
scanf("%s", name);
contact* pos = findByName(*con,name);
if (pos == NULL)
{
printf("您要刪除的聯(lián)系人不存在!\n");
return;
}
SListErase(con, pos);
printf("刪除成功!\n");
}
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("請輸入你要查找的聯(lián)系人的名字:");
scanf("%s", name);
contact* ret = findByName(con, name);
if (ret == NULL)
{
printf("您要查找的聯(lián)系人不存在!\n");
return;
}
printf("找到了!\n");
printf("名字\t\t性別\t\t年齡\t\t電話\t\t住址\n");//打印表頭
printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
ret->data.name,
ret->data.sex,
ret->data.age,
ret->data.tel,
ret->data.addr);
}
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con)
{
assert(con);
char name[NAME_MAX];
printf("請輸入你要修改的聯(lián)系人的名字:");
scanf("%s", name);
contact* ret = findByName(*con, name);
if (ret == NULL)
{
printf("您要修改的聯(lián)系人不存在!\n");
return;
}
PeoInfo p = { 0 };
printf("請輸入修改后聯(lián)系人的姓名:");
scanf("%s", p.name);
printf("請輸入修改后聯(lián)系人的性別:");
scanf("%s", p.sex);
printf("請輸入修改后加聯(lián)系人的年齡:");
scanf("%d", &(p.age));
printf("請輸入修改后聯(lián)系人的電話:");
scanf("%s", p.tel);
printf("請輸入修改后聯(lián)系人的住址:");
scanf("%s", p.addr);
SListModify(ret, p);
printf("修改成功!\n");
}
//將輸入的數(shù)據(jù)保存到文件中
void SaveContact(contact** con)
{
FILE* pf = fopen("contact.txt", "wb");
if (pf == NULL)
{
perror("open fail!\n");
return;
}
contact* cur = *con;
while (cur)
{
fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);
cur = cur->next;
}
printf("歷史數(shù)據(jù)保存成功!\n");
fclose(pf);
pf = NULL;
}
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con)
{
SaveContact(con);
SListDestroy(con);
}
?這里我就沒有單獨去寫一個菜單了,本身的意義也并不大,但是如果友友們想寫一個來玩一玩,可以看看我之前那篇基于順序表實現(xiàn)通訊錄(文章鏈接),那里有菜單的模版(只要改幾個接口的名字就行了)~
4、?完結(jié)散花
好了,這期的分享到這里就結(jié)束了~
如果這篇博客對你有幫助的話,可以用你們的小手指點一個免費的贊并收藏起來喲~
如果期待博主下期內(nèi)容的話,可以點點關(guān)注,避免找不到我了呢~
我們下期不見不散~~文章來源:http://www.zghlxwxcb.cn/news/detail-855954.html
??
??文章來源地址http://www.zghlxwxcb.cn/news/detail-855954.html
到了這里,關(guān)于基于單鏈表實現(xiàn)通訊管理系統(tǒng)!(有完整源碼!)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!