一,项目描述:
仿QQ好友管理是模拟QQ里好友管理的,程序启动后模拟注册和登录模块,注册登录成功后显示好友列表,可以对这些好友进行管理。项目采用链表来存储分组信息的管理,组内好友也是采用链表来存储的!整体就是链表里面嵌套一个链表!
二,多个功能实现:
- 注册功能的实现,账号和密码存储在内存中;
- 登录功能的实现,从注册时保存信息进行比对,判断是否输入正确;
- 添加好友的功能,选添加好友的时候自己输入好友的姓名,年龄等信息;
- 分组模块的管理,使用链表建立一个分组链表,专门给分组用的;把已有的好友分别移植分组内,内部也采用一个链表来存好友的信息。
三,模块实现:
1.账号登陆注册模块
typedef struct LandNode //账号密码储存结点
{
char account[99];
char passcode[99];
Manage* M; //M是指向该账号的用户信息
}LandNode;
typedef struct //账号密码储存列表
{
LandNode* LN;
int length; //length记录存储账号的个数
}LandList;
LandList* Init_Land() //初始化账号密码储存列表
{
LandList* L = (LandList*)malloc(sizeof(LandList));
if (L == NULL)
{
printf("分配内存失败!");
exit(0);
}
L->LN = (LandNode*)malloc(sizeof(LandNode) * MAX); //该处是创建了一个初始账号
strcpy(L->LN[0].account, "admin");
strcpy(L->LN[0].passcode, "12345678");
L->length = 1;
L->LN[0].M = Init_Manage();
return L;
}
int Search_Account(LandList* L, char account[99]) //从账号密码存储列表进行查找账号
{
for (int i = 0; i < L->length; i++)
{
if (strcmp(L->LN[i].account, account) == 0)
return i;
}
return -1;
}
void addAccount(LandList* L) //注册添加新账号
{
char add_account[99], add_passcode[99];
printf("请输入需注册的账号:");
scanf("%s", add_account);
getchar();
if (Search_Account(L, add_account) != -1)
{
printf("该账户已存在,请重新输入账号:");
scanf("%s", add_account);
getchar();
}
printf("请输入需注册的密码:");
scanf("%s", add_passcode);
getchar();
puts("");
strcpy(L->LN[L->length].account, add_account);
strcpy(L->LN[L->length].passcode, add_passcode);
L->LN[L->length].M = Init_Manage();
L->length++;
}
void input_land(char account[], char passcode[], LandList* L) //进行登录操作
{
char command[10];
printf("请输入登录指令1,或注册指令2:");
while (1)
{
scanf("%s", command);
getchar();
if (!strcmp(command, "2"))
{
addAccount(L); break;
}
else if (!strcmp(command, "1"))
break;
else
printf("无效指令,请重新输入:");
}
printf("请输入账号:\n");
gets(account);
printf("请输入密码:\n");
gets(passcode);
}
//从账号密码存储列表进行查找
int Search_Land(LandList* L, char account[99], char passcode[99])
{
for (int i = 0; i < L->length; i++)
{
if (strcmp(L->LN[i].account, account) == 0)
if (strcmp(L->LN[i].passcode, passcode) == 0)
return i;
else
return -1;
}
return -1;
}
2.一个账号里存储的好友信息创建模块
typedef struct FNode //树结点
{
char name[60];
char gender[10];
int age;
struct FNode* Lch, * Rch;
}FNode, Btree;
typedef struct Form //分组结点
{
char Fname[60];
FNode* firstnext;
}Form, AdjList[MAX];
typedef struct //管理系统
{
AdjList v;
int length;
}Manage;
Btree* Init_Btree() //初始化树
{
Btree* T = (Btree*)malloc(sizeof(Btree));
if (T == NULL)
{
printf("分配内存失败!");
exit(0);
}
T->Lch = T->Rch = NULL;
return T;
}
Manage* Init_Manage() //初始化管理系统
{
Manage* M = (Manage*)malloc(sizeof(Manage));
if (M == NULL)
{
printf("分配内存失败!");
exit(0);
}
strcpy(M->v[0].Fname, "我的好友");
M->length = 1;
for (int i = 0; i < MAX; i++)
{
M->v[i].firstnext = NULL;
}
return M;
}
3.添加好友模块
void addFriend(Btree** T, char name[], char gender[], int age) //添加好友
{ //该处要用二级指针才能带回T
if (!(*T)) //添加好友使用了二叉排序树
{
(*T) = Init_Btree();
strcpy((*T)->name, name);
strcpy((*T)->gender, gender);
(*T)->age = age;
}
else if (strcmp(name, (*T)->name) < 0)
{
addFriend(&(*T)->Lch, name, gender, age);
}
else if (strcmp(name, (*T)->name) > 0)
{
addFriend(&(*T)->Rch, name, gender, age);
}
}
4.删除好友模块
//主体应用了删除排序树中结点的方法
Btree* deleteFriend(Manage* M, char name[]) //删除好友
{
gets(name); //这里是输入要删除好友的名字
Btree* p, * f, * q, * s; //p是指向小组里的树的头节点,f是p的亲结点
for (int i = 0; i < M->length; i++)
{
int flag = 0; //flag用来判断是否找到删除好友的名字
p = M->v[i].firstnext;
f = NULL;
while (p)
{
if (strcmp(p->name, name) == 0)
break;
f = p;
if (strcmp(p->name, name) > 0)
p = p->Lch;
else
p = p->Rch;
}
if (!p && i == M->length - 1)
return NULL;
if (!p)
continue;
if (p->Lch && p->Rch) //p的左右子树不为空
{
q = p;
s = p->Lch;
while (s->Rch) //q指向s的亲节点,s是寻找p的前驱结点
{
q = s;
s = s->Rch;
}
strcpy(p->name, s->name); 找到p的前驱结点,将s的值赋值给p,删除s
strcpy(p->gender, s->gender);
p->age = s->age;
if (q != p)
q->Rch = s->Lch;
else //p没有右子树
q->Lch = s->Lch;
flag = 1;
return s;
}
else if (!p->Lch && p->Rch)
{
q = p;
p = p->Rch;
flag = 1;
}
else if (!p->Rch && p->Lch)
{
q = p;
p = p->Lch;
flag = 1;
}
else
{
q = p;
p = p->Lch;
flag = 1;
}
if (!f) //当删除的是根结点,且左右子树有一个或两个为空
M->v[i].firstnext = p;
else if (f->Lch == q)
f->Lch = p;
else if (f->Rch == q)
f->Rch = p;
if (flag == 0 && i == M->length - 1)
{
printf("好友列表中没有该好友\n\n");
break;
}
return q;
}
}
5.创建小组
void add_Group(Manage* M) //创建小组
{
char name[99];
printf("请输入新建小组名称:");
gets(name);
for (int i = 0; i < M->length; i++)
{
if (strcmp(name, M->v[i].Fname) == 0)
{
printf("该小组已存在,请重新输入:");
gets(name);
break;
}
}
puts("");
strcpy(M->v[M->length].Fname, name);
M->length++;
}
6.移动好友到分组
void moveFriend(Manage* M) //移动好友到分组
{
char name[60], Fname[60];
printf("请输入要移动的好友名字:");
Btree* t = deleteFriend(M, name);
while (1)
{
if (t == NULL)
{
printf("该好友不存在,请重新输入好友名称:");
t = deleteFriend(M, name);
}
else
break;
}
printf("请输入将好友移动到某个小组的名称:");
while (1)
{
gets(Fname);
int flag = 0;
for (int i = 0; i < M->length; i++)
{
if (strcmp(M->v[i].Fname, Fname) == 0)
{
flag = 1;
addFriend(&M->v[i].firstnext, t->name, t->gender, t->age); //这调用的添加好友模块
free(t);
t = NULL;
break;
}
}
if (flag == 1)
break;
else
printf("该小组不存在,请重新输入:");
}
puts("");
}
7.查看某个小组的好友模块
void showGroup(Manage* M)
{
printf("请输入需要查看的小组名称:");
char nameGroup[99];
gets(nameGroup);
for (int i = 0; i < M->length; i++)
{
if (strcmp(nameGroup, M->v[i].Fname) == 0)
{
printf("%s:\n", nameGroup);
InOrder(M->v[i].firstnext); //调用了中序遍历
puts("");
}
}
}
8.查看所有好友模块
void showFriend(Manage* M) //遍历好友列表
{
printf("-------------------好友列表-------------------\n");
for (int i = 0; i < M->length; i++)
{
if (Empty(M->v[i].firstnext))
{
printf("%s:\n\n", M->v[i].Fname);
continue;
}
printf("%s:\n", M->v[i].Fname);
InOrder(M->v[i].firstnext); //调用二叉树的中序遍历
if (i != M->length - 1)
puts("");
}
printf("----------------------------------------------\n\n");
}
四,完整代码实现
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 32222
typedef struct FNode //树结点
{
char name[60];
char gender[10];
int age;
struct FNode* Lch, * Rch;
}FNode, Btree;
typedef struct Form //分组结点
{
char Fname[60];
FNode* firstnext;
}Form, AdjList[MAX];
typedef struct //管理系统
{
AdjList v;
int length;
}Manage;
Btree* Init_Btree() //初始化树
{
Btree* T = (Btree*)malloc(sizeof(Btree));
if (T == NULL)
{
printf("分配内存失败!");
exit(0);
}
T->Lch = T->Rch = NULL;
return T;
}
Manage* Init_Manage() //初始化管理系统
{
Manage* M = (Manage*)malloc(sizeof(Manage));
if (M == NULL)
{
printf("分配内存失败!");
exit(0);
}
strcpy(M->v[0].Fname, "我的好友");
M->length = 1;
for (int i = 0; i < MAX; i++)
{
M->v[i].firstnext = NULL;
}
return M;
}
void add_Group(Manage* M) //创建小组
{
char name[99];
printf("请输入新建小组名称:");
gets(name);
for (int i = 0; i < M->length; i++)
{
if (strcmp(name, M->v[i].Fname) == 0)
{
printf("该小组已存在,请重新输入:");
gets(name);
break;
}
}
puts("");
strcpy(M->v[M->length].Fname, name);
M->length++;
}
void addFriend(Btree** T, char name[], char gender[], int age) //添加好友
{
if (!(*T))
{
(*T) = Init_Btree();
strcpy((*T)->name, name);
strcpy((*T)->gender, gender);
(*T)->age = age;
}
else if (strcmp(name, (*T)->name) < 0)
{
addFriend(&(*T)->Lch, name, gender, age);
}
else if (strcmp(name, (*T)->name) > 0)
{
addFriend(&(*T)->Rch, name, gender, age);
}
}
Btree* deleteFriend(Manage* M, char name[]) //删除好友
{
gets(name); //输入删除好友名字
Btree* p, * f, * q, * s; //p是指向小组里的树的头节点,f是p的亲结点
for (int i = 0; i < M->length; i++)
{
int flag = 0; //flag用来判断是否找到删除好友的名字
p = M->v[i].firstnext;
f = NULL;
while (p)
{
if (strcmp(p->name, name) == 0)
break;
f = p;
if (strcmp(p->name, name) > 0)
p = p->Lch;
else
p = p->Rch;
}
if (!p && i == M->length - 1)
return NULL;
if (!p)
continue;
if (p->Lch && p->Rch)
{
q = p;
s = p->Lch;
while (s->Rch) //q指向s的亲节点,s是寻找p的前驱结点
{
q = s;
s = s->Rch;
}
strcpy(p->name, s->name); // 找到p的前驱结点,将s的值赋值给p,删除s
strcpy(p->gender, s->gender);
p->age = s->age;
if (q != p)
q->Rch = s->Lch;
else //p没有右子树
q->Lch = s->Lch;
flag = 1;
return s;
}
else if (!p->Lch && p->Rch)
{
q = p;
p = p->Rch;
flag = 1;
}
else if (!p->Rch && p->Lch)
{
q = p;
p = p->Lch;
flag = 1;
}
else
{
q = p;
p = p->Lch;
flag = 1;
}
if (!f) //当删除的是根结点,且左右子树有一个或两个为空
M->v[i].firstnext = p;
else if (f->Lch == q)
f->Lch = p;
else if (f->Rch == q)
f->Rch = p;
if (flag == 0 && i == M->length - 1)
{
printf("好友列表中没有该好友\n\n");
break;
}
return q;
}
}
void InOrder(Btree* T) //中序遍历遍历树
{
if (!T)
return;
InOrder(T->Lch);
printf("姓名:%s \t性别:%s \t年龄:%d\n", T->name, T->gender, T->age);
InOrder(T->Rch);
}
int Empty(Btree* T) //判断树是否为空
{
return T == NULL ? 1 : 0;
}
void showFriend(Manage* M) //遍历好友列表
{
printf("-------------------好友列表-------------------\n");
for (int i = 0; i < M->length; i++)
{
if (Empty(M->v[i].firstnext))
{
printf("%s:\n\n", M->v[i].Fname);
continue;
}
printf("%s:\n", M->v[i].Fname);
InOrder(M->v[i].firstnext);
if (i != M->length - 1)
puts("");
}
printf("----------------------------------------------\n\n");
}
void showGroup(Manage* M) //遍历某个小组的好友
{
printf("请输入需要查看的小组名称:");
char nameGroup[99];
gets(nameGroup);
for (int i = 0; i < M->length; i++)
{
if (strcmp(nameGroup, M->v[i].Fname) == 0)
{
printf("%s:\n", nameGroup);
InOrder(M->v[i].firstnext);
puts("");
}
}
}
void input_message(char name[], char gender[], int* age) //输入好友信息
{
printf("请输入好友姓名:");
gets(name);
printf("请输入好友性别:");
gets(gender);
printf("请输入好友年龄:");
scanf("%d", &(*age));
getchar();
if (*age < 0)
{
printf("年龄输入不合法,请重新输入:");
scanf("%d", &(*age));
getchar();
}
puts("");
}
typedef struct LandNode //账号密码储存结点
{
char account[99];
char passcode[99];
Manage* M;
}LandNode;
typedef struct //账号密码储存列表
{
LandNode* LN;
int length;
}LandList;
LandList* Init_Land() //初始化账号密码储存列表
{
LandList* L = (LandList*)malloc(sizeof(LandList));
if (L == NULL)
{
printf("分配内存失败!");
exit(0);
}
L->LN = (LandNode*)malloc(sizeof(LandNode) * MAX);
strcpy(L->LN[0].account, "admin");
strcpy(L->LN[0].passcode, "12345678");
L->length = 1;
L->LN[0].M = Init_Manage();
return L;
}
int Search_Account(LandList* L, char account[99]) //从账号密码存储列表进行查找账号
{
for (int i = 0; i < L->length; i++)
{
if (strcmp(L->LN[i].account, account) == 0)
return i;
}
return -1;
}
void addAccount(LandList* L) //注册添加新账号
{
char add_account[99], add_passcode[99];
printf("请输入需注册的账号:");
scanf("%s", add_account);
getchar();
if (Search_Account(L, add_account) != -1)
{
printf("该账户已存在,请重新输入账号:");
scanf("%s", add_account);
getchar();
}
printf("请输入需注册的密码:");
scanf("%s", add_passcode);
getchar();
puts("");
strcpy(L->LN[L->length].account, add_account);
strcpy(L->LN[L->length].passcode, add_passcode);
L->LN[L->length].M = Init_Manage();
L->length++;
}
void input_land(char account[], char passcode[], LandList* L) //进行登录操作
{
char command[10];
printf("请输入登录指令1,或注册指令2:");
while (1)
{
scanf("%s", command);
getchar();
if (!strcmp(command, "2"))
{
addAccount(L); break;
}
else if (!strcmp(command, "1"))
break;
else
printf("无效指令,请重新输入:");
}
printf("请输入账号:\n");
gets(account);
printf("请输入密码:\n");
gets(passcode);
}
//从账号密码存储列表进行查找
int Search_Land(LandList* L, char account[99], char passcode[99])
{
for (int i = 0; i < L->length; i++)
{
if (strcmp(L->LN[i].account, account) == 0)
if (strcmp(L->LN[i].passcode, passcode) == 0)
return i;
else
return -1;
}
return -1;
}
void moveFriend(Manage* M) //移动好友到分组
{
char name[60], Fname[60];
printf("请输入要移动的好友名字:");
Btree* t = deleteFriend(M, name);
while (1)
{
if (t == NULL)
{
printf("该好友不存在,请重新输入好友名称:");
t = deleteFriend(M, name);
}
else
break;
}
printf("请输入将好友移动到某个小组的名称:");
while (1)
{
gets(Fname);
int flag = 0;
for (int i = 0; i < M->length; i++)
{
if (strcmp(M->v[i].Fname, Fname) == 0)
{
flag = 1;
addFriend(&M->v[i].firstnext, t->name, t->gender, t->age);
free(t);
t = NULL;
break;
}
}
if (flag == 1)
break;
else
printf("该小组不存在,请重新输入:");
}
puts("");
}
void fun() //该函数是用来展示指令的
{
printf("\n----------------------------------指令列表------------------------------------------\n");
printf("指令1:登录账号 指令2:注册账号 指令3:添加好友\n");
printf("指令4:创建小组 指令5:移动好友到分组 指令6:删除好友\n");
printf("指令7:查看好友列表 指令8:重新登录或创建账号 指令9:查看某个小组的好友\n");
printf("指令10:结束程序\n\n");
}
int main()
{
char name[60], gender[10];
int age, choice;
char account[99], passcode[99];
Btree* k;
LandList* L = Init_Land(); //初始化账号模块
fun();
while (1)
{
int i;
input_land(account, passcode, L); //登录或注册
i = Search_Land(L, account, passcode); //核对账号密码
if (i != -1)
printf("登陆成功!\n\n");
else
{
printf("登录失败!\n\n");
continue;
}
showFriend(L->LN[i].M);
while (1)
{
printf("请输入指令:");
scanf("%d", &choice);
getchar();
if (choice == 8)
break;
switch (choice)
{
case 3: //添加好友
input_message(name, gender, &age);
addFriend(&L->LN[i].M->v[0].firstnext, name, gender, age); break;
case 4: //移动好友到分组
add_Group(L->LN[i].M); break;
case 5: //创建小组
moveFriend(L->LN[i].M); break;
case 6: //删除好友
printf("请输入要删除好友的名字:");
k = deleteFriend(L->LN[i].M, name);
while (1)
{
if (k == NULL)
{
printf("该好友不存在,请重新输入:");
k = deleteFriend(L->LN[i].M, name);
}
else
break;
}
puts(""); break;
case 7: //查看所有好友
showFriend(L->LN[i].M); break;
case 9: //查看某个小组好友
showGroup(L->LN[i].M); break;
case 10: //退出程序
printf("退出成功!");
exit(0); break;
default:
printf("无效指令!\n");
}
}
}
return 0;
}