仿QQ好友管理系统

一,项目描述:

        仿QQ好友管理是模拟QQ里好友管理的,程序启动后模拟注册和登录模块,注册登录成功后显示好友列表,可以对这些好友进行管理。项目采用链表来存储分组信息的管理,组内好友也是采用链表来存储的!整体就是链表里面嵌套一个链表!

二,多个功能实现:

  1. 注册功能的实现,账号和密码存储在内存中;
  2. 登录功能的实现,从注册时保存信息进行比对,判断是否输入正确;
  3. 添加好友的功能,选添加好友的时候自己输入好友的姓名,年龄等信息;
  4. 分组模块的管理,使用链表建立一个分组链表,专门给分组用的;把已有的好友分别移植分组内,内部也采用一个链表来存好友的信息。

三,模块实现:

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;
}

注意:本人模块顺序调的并不是很好,可以按照指令的顺序来看。那个小组删除模块我没有写,忘了。需要的自己添加一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值