一、前言
這個(gè)通訊錄是基于單鏈表實(shí)現(xiàn)的,關(guān)于單鏈表,之前已經(jīng)做過完整的實(shí)現(xiàn)方法——數(shù)據(jù)結(jié)構(gòu)——單鏈表(C語(yǔ)言版)
用單鏈表實(shí)現(xiàn)的通訊錄其實(shí)和用順序表實(shí)現(xiàn)的通訊錄類似,可以參考該文章——基于動(dòng)態(tài)順序表的應(yīng)用——通訊錄
完成該通訊錄需要引進(jìn)經(jīng)過修改后的單鏈表的文件
SList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "Contact.h"
typedef PeoInfo SLTDateType;
typedef struct SListNode
{
SLTDateType date;
struct SListNode* next;
}SLTNode;
//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);
//頭插
void SLTPushFront(SLTNode** pphead, SLTDateType x);
//尾刪
void SLTPopBack(SLTNode** pphead);
//頭刪
void SLTPopFront(SLTNode** pphead);
//在指定位置之前插入數(shù)據(jù)
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);
//在指定位置之后插入數(shù)據(jù)
void SLTInsertAfter(SLTNode* pos, SLTDateType x);
//刪除pos結(jié)點(diǎn)
void SLTErase(SLTNode** pphead, SLTNode* pos);
//刪除pos之后的結(jié)點(diǎn)
void SLTEraseAfter(SLTNode* pos);
//銷毀鏈表
void SListDesTroy(SLTNode** pphead);
SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"
//申請(qǐng)新的結(jié)點(diǎn)
SLTNode* SLTBuyNode(SLTDateType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
printf("malloc fail!");
exit(1);
}
newnode->date = x;
newnode->next = NULL;
return newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
//空鏈表 和 非空鏈表
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* ptail = *pphead;
while (ptail->next)
{
ptail = ptail->next;
}
ptail->next = newnode;
}
}
//頭插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
//尾刪
void SLTPopBack(SLTNode** pphead)
{
assert(pphead && *pphead);
//只有一個(gè)結(jié)點(diǎn)
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//多個(gè)結(jié)點(diǎn)
else
{
SLTNode* prev = *pphead;
SLTNode* ptail = *pphead;
while (ptail->next)
{
prev = ptail;
ptail = ptail->next;
}
free(ptail);
ptail = NULL;
prev->next = NULL;
}
}
//頭刪
void SLTPopFront(SLTNode** pphead)
{
assert(pphead && *pphead);
SLTNode* next = (*pphead)->next;
free(*pphead);
*pphead = next;
}
//在指定位置之前插入數(shù)據(jù)
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
assert(pphead && *pphead);
assert(pos);
if (*pphead == pos)
{
SLTPushFront(pphead, x);
}
else
{
SLTNode* newnode = SLTBuyNode(x);
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = newnode;
newnode->next = pos;
}
}
//在指定位置之后插入數(shù)據(jù)
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{
assert(pos);
SLTNode* newnode = SLTBuyNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
//刪除pos結(jié)點(diǎn)
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead && *pphead);
assert(pos);
if (pos == *pphead)
{
SLTPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
//刪除pos之后的結(jié)點(diǎn)
void SLTEraseAfter(SLTNode* pos)
{
assert(pos && pos->next);
SLTNode* del = pos->next;
pos->next = del->next;
free(del);
del = NULL;
}
//銷毀鏈表
void SListDesTroy(SLTNode** pphead)
{
assert(pphead && *pphead);
SLTNode* pcur = *pphead;
while (pcur)
{
SLTNode* next = pcur->next;
free(pcur);
pcur = next;
}
*pphead = NULL;
}
二、通訊錄的實(shí)現(xiàn)
通訊錄項(xiàng)目
創(chuàng)建一個(gè)通訊錄項(xiàng)目,包含以下文件:
Contact.h 通訊錄的頭文件,包含通訊錄的聲明以及相關(guān)函數(shù)的聲明
Contact.c 通訊錄函數(shù)的具體實(shí)現(xiàn)方法
contact.txt 保存通訊錄中的數(shù)據(jù)
SList.h 單鏈表的聲明
SList.c 單鏈表函數(shù)的聲明 文章來源:http://www.zghlxwxcb.cn/news/detail-850746.html
test.c 測(cè)試代碼,也可以當(dāng)菜單文章來源地址http://www.zghlxwxcb.cn/news/detail-850746.html
Contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//聯(lián)系人的數(shù)據(jù)
//姓名 性別 年齡 電話 地址
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//前置聲明
typedef struct SListNode contact;
//初始化通訊錄
void InitContact(contact** con);
//添加通訊錄數(shù)據(jù)
void AddContact(contact** con);
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con);
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con);
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con);
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con);
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con);
載入數(shù)據(jù)
//載入數(shù)據(jù)
void LoadContact(contact** con)
{
FILE* pf = fopen("contact.txt", "r");
//判斷讀取是否成功
if (pf == NULL)
{
perror("fopen fail!");
return;
}
//循環(huán)讀取數(shù)據(jù)
PeoInfo info;
while (fread(&info, sizeof(PeoInfo), 1, pf))
{
SLTPushBack(con, info);
}
printf("歷史數(shù)據(jù)導(dǎo)入通訊錄成功!\n");
}
初始化通訊錄
//初始化通訊錄
void InitContact(contact** con)
{
LoadContact(con);
}
添加通訊錄數(shù)據(jù)
// 添加通訊錄數(shù)據(jù)
void AddContact(contact** con)
{
PeoInfo info;
printf("請(qǐng)輸入聯(lián)系人的姓名:\n");
scanf("%s", info.name);
printf("請(qǐng)輸入聯(lián)系人的性別:\n");
scanf("%s", info.sex);
printf("請(qǐng)輸入聯(lián)系人的年齡:\n");
scanf("%d", &info.age);
printf("請(qǐng)輸入聯(lián)系人的電話:\n");
scanf("%s", info.tel);
printf("請(qǐng)輸入聯(lián)系人的地址:\n");
scanf("%s", info.addr);
SLTPushBack(con, info);
}
通過姓名查找聯(lián)系人
//通過姓名查找聯(lián)系人
contact* FindByName(contact* con, char name[])
{
contact* pcur = con;
while (pcur)
{
if (strcmp(pcur->date.name, name) == 0)
{
return pcur;
}
pcur = pcur->next;
}
return NULL;
}
刪除通訊錄數(shù)據(jù)
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con)
{
char name[NAME_MAX];
printf("請(qǐng)輸入要?jiǎng)h除的聯(lián)系人的姓名->");
scanf("%s", name);
contact* pos = FindByName(*con, name);
if (pos != NULL)
{
SLTErase(con, pos);
printf("刪除成功!\n");
}
else
{
printf("刪除失??!沒有該聯(lián)系人!\n");
}
}
展示通訊錄數(shù)據(jù)
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con)
{
printf("%6s %6s %6s %6s %6s\n", "姓名", "性別", "年齡", "電話", "地址");
contact* pcur = con;
while (pcur)
{
printf("%6s %6s %6d %6s %6s\n",
pcur->date.name,
pcur->date.sex,
pcur->date.age,
pcur->date.tel,
pcur->date.addr);
pcur = pcur->next;
}
}
查找通訊錄數(shù)據(jù)
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con)
{
char name[NAME_MAX];
printf("請(qǐng)輸入要查找的聯(lián)系人的姓名->");
scanf("%s", name);
contact* pos = FindByName(con, name);
if (pos == NULL)
{
printf("沒有該聯(lián)系人!\n");
}
else
{
printf("找到了!該聯(lián)系人的信息如下:\n");
printf("%6s %6s %6s %6s %6s\n", "姓名", "性別", "年齡", "電話", "地址");
printf("%6s %6s %6d %6s %6s\n",
pos->date.name,
pos->date.sex,
pos->date.age,
pos->date.tel,
pos->date.addr);
}
}
修改通訊錄數(shù)據(jù)
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con)
{
char name[NAME_MAX];
printf("請(qǐng)輸入要修改的聯(lián)系人的姓名->");
scanf("%s", name);
contact* pos = FindByName(*con, name);
if (pos == NULL)
{
printf("沒有該聯(lián)系人!\n");
}
else
{
printf("開始修改!\n");
printf("聯(lián)系人的新姓名為:\n");
scanf("%s", pos->date.name);
printf("聯(lián)系人的新性別為:\n");
scanf("%s", pos->date.sex);
printf("聯(lián)系人的新年齡為:\n");
scanf("%d", &pos->date.age);
printf("聯(lián)系人的新電話為:\n");
scanf("%s", pos->date.tel);
printf("聯(lián)系人的新地址為:\n");
scanf("%s", pos->date.addr);
printf("修改成功!\n");
}
}
保存通訊錄
//保存通訊錄
void SaveContact(contact* con)
{
FILE* pf = fopen("contact.txt", "w");
if (pf == NULL)
{
perror("fopen fail!");
return;
}
//將通訊錄數(shù)據(jù)寫入文件
contact* pcur = con;
while (pcur)
{
fwrite(&(pcur->date), sizeof(pcur->date), 1, pf);
pcur = pcur->next;
}
printf("通訊錄保存成功!\n");
}
銷毀通訊錄數(shù)據(jù)
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con)
{
//在銷毀通訊錄之前,保存數(shù)據(jù)
SaveContact(*con);
SListDesTroy(con);
}
三、所有源代碼
Contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//聯(lián)系人的數(shù)據(jù)
//姓名 性別 年齡 電話 地址
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//前置聲明
typedef struct SListNode contact;
//初始化通訊錄
void InitContact(contact** con);
//添加通訊錄數(shù)據(jù)
void AddContact(contact** con);
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con);
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con);
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con);
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con);
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con);
Contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
#include "SList.h"
//載入數(shù)據(jù)
void LoadContact(contact** con)
{
FILE* pf = fopen("contact.txt", "r");
//判斷讀取是否成功
if (pf == NULL)
{
perror("fopen fail!");
return;
}
//循環(huán)讀取數(shù)據(jù)
PeoInfo info;
while (fread(&info, sizeof(PeoInfo), 1, pf))
{
SLTPushBack(con, info);
}
printf("歷史數(shù)據(jù)導(dǎo)入通訊錄成功!\n");
}
//初始化通訊錄
void InitContact(contact** con)
{
LoadContact(con);
}
// 添加通訊錄數(shù)據(jù)
void AddContact(contact** con)
{
PeoInfo info;
printf("請(qǐng)輸入聯(lián)系人的姓名:\n");
scanf("%s", info.name);
printf("請(qǐng)輸入聯(lián)系人的性別:\n");
scanf("%s", info.sex);
printf("請(qǐng)輸入聯(lián)系人的年齡:\n");
scanf("%d", &info.age);
printf("請(qǐng)輸入聯(lián)系人的電話:\n");
scanf("%s", info.tel);
printf("請(qǐng)輸入聯(lián)系人的地址:\n");
scanf("%s", info.addr);
SLTPushBack(con, info);
}
//通過姓名查找聯(lián)系人
contact* FindByName(contact* con, char name[])
{
contact* pcur = con;
while (pcur)
{
if (strcmp(pcur->date.name, name) == 0)
{
return pcur;
}
pcur = pcur->next;
}
return NULL;
}
//刪除通訊錄數(shù)據(jù)
void DelContact(contact** con)
{
char name[NAME_MAX];
printf("請(qǐng)輸入要?jiǎng)h除的聯(lián)系人的姓名->");
scanf("%s", name);
contact* pos = FindByName(*con, name);
if (pos != NULL)
{
SLTErase(con, pos);
printf("刪除成功!\n");
}
else
{
printf("刪除失?。]有該聯(lián)系人!\n");
}
}
//展示通訊錄數(shù)據(jù)
void ShowContact(contact* con)
{
printf("%6s %6s %6s %6s %6s\n", "姓名", "性別", "年齡", "電話", "地址");
contact* pcur = con;
while (pcur)
{
printf("%6s %6s %6d %6s %6s\n",
pcur->date.name,
pcur->date.sex,
pcur->date.age,
pcur->date.tel,
pcur->date.addr);
pcur = pcur->next;
}
}
//查找通訊錄數(shù)據(jù)
void FindContact(contact* con)
{
char name[NAME_MAX];
printf("請(qǐng)輸入要查找的聯(lián)系人的姓名->");
scanf("%s", name);
contact* pos = FindByName(con, name);
if (pos == NULL)
{
printf("沒有該聯(lián)系人!\n");
}
else
{
printf("找到了!該聯(lián)系人的信息如下:\n");
printf("%6s %6s %6s %6s %6s\n", "姓名", "性別", "年齡", "電話", "地址");
printf("%6s %6s %6d %6s %6s\n",
pos->date.name,
pos->date.sex,
pos->date.age,
pos->date.tel,
pos->date.addr);
}
}
//修改通訊錄數(shù)據(jù)
void ModifyContact(contact** con)
{
char name[NAME_MAX];
printf("請(qǐng)輸入要修改的聯(lián)系人的姓名->");
scanf("%s", name);
contact* pos = FindByName(*con, name);
if (pos == NULL)
{
printf("沒有該聯(lián)系人!\n");
}
else
{
printf("開始修改!\n");
printf("聯(lián)系人的新姓名為:\n");
scanf("%s", pos->date.name);
printf("聯(lián)系人的新性別為:\n");
scanf("%s", pos->date.sex);
printf("聯(lián)系人的新年齡為:\n");
scanf("%d", &pos->date.age);
printf("聯(lián)系人的新電話為:\n");
scanf("%s", pos->date.tel);
printf("聯(lián)系人的新地址為:\n");
scanf("%s", pos->date.addr);
printf("修改成功!\n");
}
}
//保存通訊錄
void SaveContact(contact* con)
{
FILE* pf = fopen("contact.txt", "w");
if (pf == NULL)
{
perror("fopen fail!");
return;
}
//將通訊錄數(shù)據(jù)寫入文件
contact* pcur = con;
while (pcur)
{
fwrite(&(pcur->date), sizeof(pcur->date), 1, pf);
pcur = pcur->next;
}
printf("通訊錄保存成功!\n");
}
//銷毀通訊錄數(shù)據(jù)
void DestroyContact(contact** con)
{
//在銷毀通訊錄之前,保存數(shù)據(jù)
SaveContact(*con);
SListDesTroy(con);
}
SList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "Contact.h"
typedef PeoInfo SLTDateType;
typedef struct SListNode
{
SLTDateType date;
struct SListNode* next;
}SLTNode;
//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);
//頭插
void SLTPushFront(SLTNode** pphead, SLTDateType x);
//尾刪
void SLTPopBack(SLTNode** pphead);
//頭刪
void SLTPopFront(SLTNode** pphead);
//在指定位置之前插入數(shù)據(jù)
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);
//在指定位置之后插入數(shù)據(jù)
void SLTInsertAfter(SLTNode* pos, SLTDateType x);
//刪除pos結(jié)點(diǎn)
void SLTErase(SLTNode** pphead, SLTNode* pos);
//刪除pos之后的結(jié)點(diǎn)
void SLTEraseAfter(SLTNode* pos);
//銷毀鏈表
void SListDesTroy(SLTNode** pphead);
SList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"
//申請(qǐng)新的結(jié)點(diǎn)
SLTNode* SLTBuyNode(SLTDateType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
if (newnode == NULL)
{
printf("malloc fail!");
exit(1);
}
newnode->date = x;
newnode->next = NULL;
return newnode;
}
//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
//空鏈表 和 非空鏈表
if (*pphead == NULL)
{
*pphead = newnode;
}
else
{
SLTNode* ptail = *pphead;
while (ptail->next)
{
ptail = ptail->next;
}
ptail->next = newnode;
}
}
//頭插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{
assert(pphead);
SLTNode* newnode = SLTBuyNode(x);
newnode->next = *pphead;
*pphead = newnode;
}
//尾刪
void SLTPopBack(SLTNode** pphead)
{
assert(pphead && *pphead);
//只有一個(gè)結(jié)點(diǎn)
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
//多個(gè)結(jié)點(diǎn)
else
{
SLTNode* prev = *pphead;
SLTNode* ptail = *pphead;
while (ptail->next)
{
prev = ptail;
ptail = ptail->next;
}
free(ptail);
ptail = NULL;
prev->next = NULL;
}
}
//頭刪
void SLTPopFront(SLTNode** pphead)
{
assert(pphead && *pphead);
SLTNode* next = (*pphead)->next;
free(*pphead);
*pphead = next;
}
//在指定位置之前插入數(shù)據(jù)
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
assert(pphead && *pphead);
assert(pos);
if (*pphead == pos)
{
SLTPushFront(pphead, x);
}
else
{
SLTNode* newnode = SLTBuyNode(x);
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = newnode;
newnode->next = pos;
}
}
//在指定位置之后插入數(shù)據(jù)
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{
assert(pos);
SLTNode* newnode = SLTBuyNode(x);
newnode->next = pos->next;
pos->next = newnode;
}
//刪除pos結(jié)點(diǎn)
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
assert(pphead && *pphead);
assert(pos);
if (pos == *pphead)
{
SLTPopFront(pphead);
}
else
{
SLTNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
}
//刪除pos之后的結(jié)點(diǎn)
void SLTEraseAfter(SLTNode* pos)
{
assert(pos && pos->next);
SLTNode* del = pos->next;
pos->next = del->next;
free(del);
del = NULL;
}
//銷毀鏈表
void SListDesTroy(SLTNode** pphead)
{
assert(pphead && *pphead);
SLTNode* pcur = *pphead;
while (pcur)
{
SLTNode* next = pcur->next;
free(pcur);
pcur = next;
}
*pphead = NULL;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"
//測(cè)試代碼——菜單
void menu()
{
printf("****************通訊錄*******************\n");
printf("******1.添加聯(lián)系人 2.刪除聯(lián)系人*******\n");
printf("******3.修改聯(lián)系人 4.查找聯(lián)系人*******\n");
printf("******5.展示聯(lián)系人 0. 退出************\n");
printf("*****************************************\n");
}
int main()
{
int input = 0;
contact* con = NULL;
//初始化
InitContact(&con);
do
{
menu();
printf("選擇你的操作->");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&con);
break;
case 2:
DelContact(&con);
break;
case 3:
ModifyContact(&con);
break;
case 4:
FindContact(con);
break;
case 5:
ShowContact(con);
break;
case 0:
printf("退出通訊錄...\n");
break;
default:
printf("輸入錯(cuò)誤!請(qǐng)重新輸入!\n");
break;
}
} while (input != 0);
//銷毀通訊錄;
DestroyContact(&con);
return 0;
}
到了這里,關(guān)于數(shù)據(jù)結(jié)構(gòu)——基于單鏈表實(shí)現(xiàn)通訊管理系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!