#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<assert.h>
#include<stdbool.h>
#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 15
#define ADDR_MAX 100
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
typedef struct PersonInfo SLDataType;
typedef struct SListNode
{
SLDataType data;
struct SListNode* next;
}SLNode;
typedef SLNode contact;
void InitList(SLNode** phead)//初始化节点
{
*phead = NULL;
}
void SLPrint(SLNode* phead)//打印函数
{
//备份phead,临时变量存储
SLNode* pcur = phead;//pcur是node1的地址
while (pcur)
{
printf("%d -> ", pcur->data);
pcur = pcur->next;//pcur->next是下一个地址
}
printf("NULL\n");
}
SLNode* SLBuyNode(SLDataType x)//创建新节点
{
SLNode* node = (SLNode*)malloc(sizeof(SLNode));
if (node == NULL)
return;
node->data = x;//结构体能直接传值
node->next = NULL;
return node;
}
void SLPushBack(SLNode** pphead, SLDataType x)//尾插
//SLPushBack(&plist, 1) 传入的是地址的地址,采用二级指针来接收
{
assert(pphead);
SLNode* node = SLBuyNode(x);
if (*pphead == NULL)//链表为空,则创建新节点
{
*pphead = node;
return;//跳过以下部分
}
SLNode* pcur = *pphead;//备份
//此时 pcur 指向第头节点
while (pcur->next)
{
pcur = pcur->next;
//找到倒数第二个节点
}
pcur->next = node;
}
void SLPushFront(SLNode** pphead, SLDataType x)//头插
{
assert(pphead);
SLNode* node = SLBuyNode(x);
//若头结点为空,以下代码也可以进行头插操作
node->next = *pphead;//*pphead 是第一个结点的地址
*pphead = node;//node成为新的头节点
}
void SLPopBack(SLNode** pphead)//尾删
{
assert(pphead);
assert(*pphead);//第一个节点不能为空
//只有一个结点的情况
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
return;
}
SLNode* ptail = *pphead;//ptail指向最后一个节点
SLNode* prev = NULL;//倒数第二个节点
//找到尾节点和尾节点前一个结点
while (ptail->next != NULL)
{
prev = ptail;
ptail = ptail->next;
}
prev->next = NULL;
free(ptail);
ptail = NULL;
}
void SLFrontBack(SLNode** pphead)//头删
{
assert(pphead);
assert(*pphead);//第一个节点不能为空
SLNode* del = *pphead;//备份头节点
*pphead = (*pphead)->next;//指向新的头结点
free(del);
del = NULL;
}
/*
//找到按照x查找节点
SLNode* SLFind(SLNode** pphead, SLDataType x)
{
SLNode* pcur = *pphead;
while (pcur)
{
if (pcur->data == x)
return pcur;
pcur = pcur->next;
}
return NULL;
}
*/
//在指定位置之前插入数据
void SLInsert(SLNode** pphead, SLNode* pos, SLDataType x)
{
assert(pphead);//链表非空
assert(*pphead);//第一个节点非空
assert(pos);//位置非空
SLNode* node = SLBuyNode(x);
//只有一个结点的情况 ( pos指向第一个节点 )
if (pos == *pphead)
{
node->next = *pphead;
*pphead = node;
return;
}
//先找到pos前一个结点
SLNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
// prev node pos
node->next = pos;
prev->next = node;
}
//在指定位置之后插入数据
void SLInsertAfter(SLNode* pos, SLDataType x)
{
assert(pos);//位置非空
SLNode* node = SLBuyNode(x);
node->next = pos->next;
pos->next = node;
//此时有 pos 的地址但没有 pos->next ,不能颠倒
}
//删除指定pos节点
void SLErase(SLNode** pphead, SLNode* pos)
{
assert(pphead);
assert(*pphead);
assert(pos);
//要删除头结点
if (pos == *pphead)
{
*pphead = (*pphead)->next;
free(pos);
return;
}
//找 pos 前的节点
SLNode* prev = *pphead;
while (prev->next != pos)
{
prev = prev->next;
}
prev->next = pos->next;
free(pos);
pos = NULL;
}
//删除指定pos节点之后的节点
void SLEraseAfter(SLNode* pos)
{
// pos 及 pos->next 非空
assert(pos && pos->next);
SLNode* del = pos->next;//先保存 pos->next
pos->next = del->next;
free(del);
}
//销毁链表
void SLDestroy(SLNode** pphead)
{
assert(pphead);
SLNode* pcur = *pphead;
//销毁结点之前,先保存下一个结点的地址
while (pcur)
{
SLNode* del = pcur->next;//存储下一个节点
free(pcur);
pcur = del;
}
*pphead = NULL;
}
SL *s 等价于 contact * con
void InitContact(contact** con)//通讯录初始化
{
InitList(con);
}
void DestoryContact(contact** con)//通讯录销毁
{
SLDestroy(con);
}
void ShowContact(contact* con)//打印通讯录
{
printf("\n%-15s %-15s %-15s %-15s %-15s\n", "姓名", "性别", "年龄", "电话", "地址");
contact* cur = con;
while (cur)
{
printf("%-15s %-15s %-15d %-15s %-15s\n",
cur->data.name,
cur->data.sex,
cur->data.age,
cur->data.tel,
cur->data.addr);
cur = cur->next;
}
printf("\n");
}
void AddContact(contact** con)//添加联系人
{
PeoInfo info;
printf("请输入要添加联系人的信息:\n");
printf("请输入联系人姓名:\n");
scanf("%s", info.name);
printf("请输入联系人性别:\n");
scanf("%s", info.sex);
printf("请输入联系人年龄:\n");
scanf("%d", &(info.age));
printf("请输入联系人电话:\n");
scanf("%s", info.tel);
printf("请输入联系人地址:\n");
scanf("%s", info.addr);
//数据存储在info中
//往通讯录(顺序表)中插入数据
SLPushBack(con, info);
printf("\n");
}
contact* FindByName(contact* con, char name[])//查找下标
{
contact* cur = con;
while (cur)
{
if (strcmp(cur->data.name, name) == 0)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void FindContact(contact* con)//查找联系人
{
printf("请输入要查找联系人姓名: ");
char name[NAME_MAX];
scanf("%s", name);
contact* pos = FindByName(con, name);
if (pos == NULL)
{
printf("要查找的人不存在!\n");
return;
}
printf("\n%s的信息如下:\n", name);
printf("%-15s %-15s %-15s %-15s %-15s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-15s %-15s %-15d %-15s %-15s\n",
pos->data.name,
pos->data.sex,
pos->data.age,
pos->data.tel,
pos->data.addr);
}
void DelContact(contact** con)//删除联系人
{
char name[NAME_MAX];
printf("请输入要删除的用户姓名: \n");
scanf("%s", name);
contact* pos = FindByName(*con, name);
if (pos == NULL)
{
printf("要删除的用户不存在!\n");
return;
}
SLErase(con, pos);
printf("删除成功!\n");
}
void ModifyContact(contact** con)//修改联系人
{
printf("\n请输入要修改联系人姓名: ");
char name[NAME_MAX];
scanf("%s", name);
contact* pos = FindByName(*con, name);
if (pos == NULL)
{
printf("要查找的人不存在!\n");
return;
}
printf("\n请输入要修改联系人的信息:\n");
printf("请输入要修改联系人姓名:\n");
scanf("%s", pos->data.name);
printf("请输入要修改联系人性别:\n");
scanf("%s", pos->data.sex);
printf("请输入要修改联系人年龄:\n");
scanf("%d", &(pos->data.age));
printf("请输入要修改联系人电话:\n");
scanf("%s", pos->data.tel);
printf("请输入要修改联系人地址:\n");
scanf("%s", pos->data.addr);
printf("\n");
}
void DestroyContactFile(contact** con)//销毁通讯录
{
SLDestroy(con);
}
void menu()
{
printf("\n");
printf("********************通讯录********************\n");
printf("**** 1、添加联系人 2、删除联系人 ****\n");
printf("**** 3、修改联系人 4、查找联系人 ****\n");
printf("**** 5、查看通讯录 0、退出通讯录 ****\n");
printf("**********************************************\n");
printf("\n");
}
int main()
{
//slttrst();
//slttrst1();
contact* con;// SeqList con
InitContact(&con);
int op = -1;
do {
menu();
printf("请进行你的选择: \n");
scanf("%d", &op);
switch (op)
{
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("输入有误请重新输入:\n");
break;
}
} while (op != 0);
return 0;
}
单链表实现简易通讯录(内附源码)
最新推荐文章于 2024-03-10 00:55:59 发布