少女祈祷中...

前言

因为要做项目三答辩,所以要从众多的选题中找到一个相对简单的,于是就有了制作通讯录管理系统的意向。

准备

根据问题的描述,可以大致概括为结构体+文件读写+链表的操作。

题目要求如下:

  1. 问题描述:

    ​ 设计“通讯录管理系统”使其具有数据插入、修改、删除、显示和查询等 功能。

    ​ 数据包括:人名、工作单位、电话号码和E-mail地址。

  2. 功能要求

    ​ (1)可对记录中的姓名和电话号码进行修改。

    ​ (2)可增加或删除记录。

    ​ (3)可显示所有保存的记录。

    ​ (4)可按人名或电话号码进行查询。

    ​ (5)每个学生的信息包括:学号no, 姓名, 院系academic,专业major, 籍贯province,家庭地址address,电话phone等。使用结构体存取每个学生的 信息,多个学生的信息可以保存到结构体数组中。最好使用文本文件保存以往 的所有学生信息,添加、删除之后应更新该文本文件。程序运行后,应有一个 简单的操作界面。程序代码要求清晰可读,多加注释。

实施

首先定义一个嵌套结构体:

struct Message
{
    char phone[10];
    char address[50];
    char email[50];
};
struct address
{
    char name[20];
    int no[10];
    char academic[10];
    char major[10];
    char province[10];
    struct Message message;
    struct address *pnext;
};

为什么要用嵌套:因为整洁点…

为了方便,以链表的形式进行存储:

struct address *list(struct address *plast)
{
    int len = 0;
    struct address* pnew;
    printf("请输入录入人数:");
    scanf("%d", &len);
    for (int i = 0; i < len; i++)
    {
        pnew = (struct address *)malloc (sizeof(struct address));
        if (pnew == NULL)
        {
            printf("系统出错");
            exit(1);
        }
        printf("输入第%d位人员的姓名,学号,院系,专业,籍贯,家庭住址,电话,邮箱:",i + 1);
        scanf("%s %d %s %s %s %s %s %s",pnew->name,&pnew->no,pnew->academic,pnew->major,pnew->province,pnew->message.address,pnew->message.phone,pnew->message.email);
        plast->pnext = pnew;
        pnew->pnext = NULL;
        plast = pnew;
    }
    return plast;
}

其中,用malloc为每个节点分配空间,采用尾插法连接链表,将plast指向的节点的pnext字段设置为pnew,然后将pnewpnext字段设置为NULL,表示这是链表的最后一个节点。

再遍历下打印下链表

void traversal(struct address *phead)
{
    struct address *p;
    p = phead->pnext;
    printf("姓名\t学号\t院系\t专业\t籍贯\t家庭住址\t电话\t邮箱\n");
    while (p != NULL)
    {
        printf("%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\n",p->name,p->no,p->academic,p->major,p->province,p->message.address,p->message.phone,p->message.email);
        p = p->pnext;
    }
}

写个主函数和界面测试一下

void printf_body()
{
    printf("\n通讯录管理系统\n");
    printf("1. 添加信息\n");
    printf("2. 修改信息\n");
    printf("3. 删除信息\n");
    printf("4. 显示所有记录\n");
    printf("5. 查询记录\n");
    printf("6. 退出\n");
}
int main()
{
    int choice = 1;
    struct address *plast,*phead = NULL;		//防止野指针
    phead = (struct address *)malloc (sizeof(struct address));		//分配空间
    if (phead  == NULL)		//判断分配是否成功
    {
        printf("出错,请重试");
        exit(-1);
    }
    phead ->pnext = NULL;
    plast = phead;
    while (choice != 0)
    {
        printf_body();
        printf("请输入你的选择:");
        scanf("%d",&choice);
        switch (choice)
        {
        case 1:
            plast = list(plast);
            traversal(phead);
            break;
        case 2:

            break;
        case 3:

            break;
        case 4:

            break;
        case 5:

            break;
        case 6:
            break;
        case 0:
            printf("再见");
            break;
        default:
            printf("出错,请输入有效数字");
            break;
        }

开始写查询模块,要考虑到用人名或电话号码来查询信息:

void search_name(struct address *phead)
{
    struct address *p;
    char name_i[20];
    p = phead;
    printf("输入查询的姓名:");
    scanf("%s",name_i);
    while (strcmp(p->name,name_i) != 0 && p->pnext != NULL)
    {
        p = p->pnext;
    }
    if (strcmp(p->name,name_i) == 0)
    {
        printf("找到如下信息:\n");
        printf("姓名\t学号\t院系\t专业\t籍贯\t家庭住址\t电话\t邮箱\n");
        printf("%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\n",p->name,p->no,p->academic,p->major,p->province,p->message.address,p->message.phone,p->message.email);

    }
    else
    {
        printf("未找到信息\n");
    }
}
void search_phone(struct address *phead)
{
    struct address *p;
    char phone_i[20];
    p = phead;
    printf("输入查询的电话:");
    scanf("%s",phone_i);
    while (strcmp(p->message.phone,phone_i) != 0 && p->pnext != NULL)
    {
        p = p->pnext;
    }
    if (strcmp(p->message.phone,phone_i) == 0)
    {
        printf("找到如下信息:\n");
        printf("姓名\t学号\t院系\t专业\t籍贯\t家庭住址\t电话\t邮箱\n");
        printf("%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\n",p->name,p->no,p->academic,p->major,p->province,p->message.address,p->message.phone,p->message.email);
    }
    else
    {
        printf("未找到信息\n");
    }
}

主函数修改一下:

case 5:
            printf("请输入查询方式:");
            printf("\n1.按姓名查询");
            printf("\n2.按电话号码查询\n");
            int choose = 0;
            scanf("%d",&choose);
            if (choose == 1)
            {
                search_name(phead);
            }
            else if (choose == 2)
            {
                search_phone(phead);
            }
            else
            {
                printf("请输入有效数字\n");
                break;
            }
            system("pause");
            break;

再来写个修改函数模块:

void modify(struct address *phead)
{
    struct address *p;
    char name_i[20];
    printf("请输入你要修改的人的姓名:");
    scanf("%s",name_i);
    p = phead->pnext;
    while (p != NULL){
        if(strcmp(p->name,name_i) == 0)			//strcmp会返回0,所以与0比较如果相同就进行操作
        {
            printf("请输入新的姓名和电话:");
            scanf("%s %s",p->name,p->message.phone);
            printf("修改成功!");
            return;
        }
        p = p->pnext;
    }
    printf("未找到此人,请重试");
}

因为题目只让修改姓名和电话号码,就改俩好了。

接着就是删除函数:

struct address *delete(struct address *phead,struct address *plast)		//通过返回struct address*类型,函数可以返回更新后的尾节点指针plast
{
    struct address *p,*pre;
    p = phead;
    char name_i[20];
    printf("请输入要删除的人员姓名:");
    scanf("%s",name_i);
    pre = phead;
    p = phead->pnext;
    while (p != NULL && strcmp(p->name,name_i) != 0){
        pre = p;
        p = p->pnext;
    }
    if (p != NULL)
    {
        pre->pnext = p->pnext;
        if (p == plast)
        {
            plast = pre;
        }
        free(p);
        printf("删除成功!\n");
    }
    else
        {
            printf("未找到人员\n");
        }
    return plast;
}

然后就是读取和写入:

void save(struct address *phead)
{
    FILE* file = fopen("address.txt","a");
    struct address *p;
    p = phead;
    if (file == NULL)
    {
        printf("出错!");
        return;
    }
    while (p != NULL)
    {
        p = p->pnext;
        fwrite(p,sizeof(struct address),1,file);
    }
    fclose(file);
    printf("保存成功!");
}
void read(void)
{
    FILE* file = fopen("address.txt","r");
    struct address txt;
    if (file == NULL)
    {
        printf("出错!");
        return;
    }
    printf("姓名\t学号\t院系\t专业\t籍贯\t家庭住址\t电话\t邮箱\n");
    while (fread(&txt, sizeof(struct address), 1, file) == 1)
    {
        printf("%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\n",txt.name,txt.no,txt.academic,txt.major,txt.province,txt.message.address,txt.message.phone,txt.message.email);
    }
    if(feof(file))
    {
        printf("读取完毕");
    }
    fclose(file);
}

完成。

主函数部分:

if (phead  == NULL)
    {
        printf("出现错误!");
        exit(-1);
    }
    phead ->pnext = NULL;
    plast = phead;
    while (choice != 0)
    {
        printf_body();
        printf("请输入你的选择:");
        scanf("%d",&choice);
        switch (choice)
        {
        case 1:
            plast = list(plast);
            traversal(phead);
            system("pause") ;
            break;
        case 2:
            modify(phead);
            system("pause") ;
            break;
        case 3:
            delete(phead,phead);
            system("pause") ;
            break;
        case 4:
            save(phead);
            system("pause") ;
            break;
        case 5:
            read();
            system("pause") ;
            break;
        case 6:
            printf("请输入查询方式:");
            printf("\n1.按姓名查询");
            printf("\n2.按电话号码查询\n");
            int choose = 0;
            scanf("%d",&choose);
            if (choose == 1)
            {
                search_name(phead);
            }
            else if (choose == 2)
            {
                search_phone(phead);
            }
            else
            {
                printf("请输入有效数字\n");
                break;
            }
            system("pause");
            break;
        case 0:
            printf("再见");
            break;
        default:
            printf("出错,请输入有效数字");
            break;
        }
    }
}

注意:仅限c语言,c++环境编译需要更改delete与switch(比如DEV C++)

本文作者:Iota @ Iotaの小屋

本文发布时间:2024-12-09 13:13:00

本文版权:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

留言