查看: 5098|回复: 6

c语言,结构体配合链表做的一个通讯录管理系统。待改进。

[复制链接]
发表于 2016-10-25 13:29:35 | 显示全部楼层 |阅读模式


#include"stdio.h"
#include"stdlib.h"
#include"string.h"
struct stucontact
{

        char  stuname[20];    //姓名
        char  stunum[20];     //电话号码
        char  stubirth[20];       //生日
        char  stuhome[20];           //籍贯
        struct stucontact *next;
};
#define LEN sizeof(struct stucontact)
#define n 3   
struct stucontact *creat(void)                       //初始化通讯录
{
        int i = 0;
        struct stucontact *p1 = NULL, *p2 = NULL, *head = NULL;
        char   a[20], b[20], c[20], d[20];
        printf("请输入%d组学生信息(用空格分开)(姓名,手机号,生日,籍贯): \n",n);
        while (i<n)                              
        {        scanf("%s%s%s%s", a,b,c,d);
                i++;
                p1 = (struct stucontact *)malloc(LEN);              //分配新结点
                strcpy(p1->stuname, a);                              //字符串的赋值
                strcpy(p1->stunum, b);
                strcpy(p1->stubirth , c);
                strcpy(p1->stuhome , d);
                if (head == NULL)head = p1;
                else
                        p2->next = p1;         
                p2 = p1;
               
        }
        p2->next = NULL;
        return (head);
}
void  list(struct stucontact *head){                             //输出
        struct stucontact *p;
        if (head == NULL) printf("通讯录为空!");
        else
        {
                printf("通讯录为:\n");
                p = head;
                while (p != NULL)
                {
                        printf("%s  %s  %s  %s\n", p->stuname, p->stunum, p->stubirth, p->stuhome);
                        p = p->next;                     
                }
        }
}
struct stucontact *add(struct stucontact *head)
{
        char ch='y',h;
        while(ch=='y'||ch=='Y'){
                struct stucontact  *p0, *p1, *p2 = NULL;
        p0 = (struct stucontact *)malloc(LEN);
        p0->next = NULL;        
        printf("请输入要填加的学生信息(用空格分开)(姓名,手机号,生日,籍贯): \n");
        scanf("%s%s%s%s", p0->stuname,p0->stunum,p0->stubirth, p0->stuhome);
        getchar();         //空读
        if (head == NULL) head = p0;
        else
        {

                p1 = head;
                while ((strcmp(p0->stuname , p1->stuname)>0) && (p1->next != NULL))  //字符串的比较
                {
                        p2 = p1;
                        p1 = p1->next;

                }
                if (strcmp(p0->stuname , p1->stuname)<=0)
                {
                        if (head == p1){ head = p0;
                        printf("已添加");
                        printf("是否继续添加?确认请输入 y/Y    ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;        }
                        else {p2->next = p0;
                        p0->next = p1;
                        printf("已添加");
                        printf("是否继续添加?确认请输入 y/Y    ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;        }
                }
                else {        p1->next = p0;
        printf("已添加删除");
                        printf("是否继续删除添加?确认请输入 y/Y   ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;}       
        }
        }return (head);

}
struct stucontact *del(struct stucontact *head)
{
        char ch='y',h;
        while(ch=='y'||ch=='Y'){
        char a[20];                    //a就已经是一个首地址
        char b[20];
        struct stucontact *p1 = NULL, *p2 = NULL;
        if (head == NULL)  printf("通讯录为空,无法进行删除操作");
        else
        {
                printf("请输入要删除的学生名字及电话号码(用空格分开):  \n");
                scanf("%s%s", a, b);
                p1 = head;
                while ((strcmp(a, p1->stuname) != 0) && (strcmp(b, p1->stunum) != 0) && (p1->next != NULL))   //查找
                {
                        p2 = p1;
                        p1 = p1->next;
                }
                if ((strcmp(a, p1->stuname) == 0) && (strcmp(b, p1->stunum) == 0))           //姓名和电话号码必须都满足
                {
                        if (head == p1) { head=head->next;}            //  删除不了头结点。。。。望各位大神指导
                        else p2->next = p1->next;                    //链表问题最好画图,多画几次就能基本了解
                        printf("已删除");
                        printf("是否继续删除?确认请输入 y/Y    ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;       
                }
                else {printf("不存在");
                printf("是否继续删除?确认请输入 y/Y    ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;        }

        }
        }
        return (head);
}

struct stucontact *search(struct stucontact *head)
{char ch='y',h;
        while(ch=='y'||ch=='Y'){
        if (head == NULL)  printf("通讯录为空,无法进行查询操作");
        else
        {
                char a[20];
                printf("请输入要查询的学生名字:     ");
                scanf("%s", a);
                struct stucontact *p1 = NULL, *p2 = NULL;
                p1 = head;
                while ((strcmp(a, p1->stuname) != 0) && (p1->next != NULL))
                {
   
                        p2 = p1;
                        p1=p1->next;
                }
                if ((strcmp(a, p1->stuname) == 0))
                {
                        printf("该学生信息为:  姓名:%s 电话:%s  生日:%s  籍贯:%s \n", p1->stuname, p1->stunum, p1->stubirth, p1->stuhome);
            printf("是否继续查询?确认请输入 y/Y     ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;        }
                else  printf("通讯录中不存在您要查找的信息。\n");
        }
        }
        return (head);
}

struct stucontact   *change(struct stucontact  *head)
{
        char ch='y',h;
        while(ch=='y'||ch=='Y'){
        if (head == NULL)  printf("通讯录为空,无法进行查询操作");
        else
        {
                char a[20];
                printf("请输入要修改的学生名字:     ");
                scanf("%s", a);
                struct stucontact  *p1 = NULL, *p2 = NULL;
                p1 = head;
                while ((strcmp(a , p1->stuname) !=0) && (p1->next != NULL))
                {
         
                        p2 = p1;                       //存放
                        p1=p1->next;                      //p1指向下一个
                }
                if ((strcmp(a, p1->stuname)==0))
                {
                printf("请输入修改的信息:  \n");
                scanf("%s%s%s%s", p1->stuname, p1->stunum, p1->stubirth, p1->stuhome);              //执行完上边的循环之后,p2是要删除的结点的上一个,要删除的结点是p1,p1->next是要删除的结点的后一个结点,所以这样赋值就可以直接跳过要删的结点。
             printf("已修改,是否继续修改?确认请输入 y/Y    ");
                scanf("%s",&h);             //单个字符需要加&
                getchar();
                if(h=='y'||h=='Y')
                ch=h;
                else break;}
                else  printf("通讯录中不存在您要查找的信息。\n");
        }
        }
        return(head);
}


void main()
{
        struct stucontact *head;
        head = creat();
        list(head);
        int select;
        while (1)
        {
                printf("\n");
                printf("\n");
                printf("\n");
                printf("\n");
                printf("\t\t\t------------------------\n");
                printf("\t\t\t                       \n");
                printf("\t\t\t    学生通讯录管理系统  \n");
                printf("\t\t\t                        \n");
                printf("\t\t\t------------------------\n");
                printf("\n");
                printf("\t\t\t         1.增加         \n");
                printf("\t\t\t         2.删除         \n");
                printf("\t\t\t         3.搜索         \n");
                printf("\t\t\t         4.修改         \n");
                printf("\t\t\t         5.输出         \n");
                printf("\t\t\t         0.退出         \n");
                printf("请输入您接下来的操作:   ");
                scanf("%d", &select);
                switch (select)
                {
                case 1:add(head); break;
                case 2:del(head); break;
                case 3:search(head); break;
                case 4:change(head); break;
                case 5:list(head); break;
                case 0:printf("谢谢使用,再见!"); exit(1);
                default:printf("\n   按键错误,请重新选择  \n"); break;
                }
        }


}




回复

使用道具 举报

发表于 2016-10-26 16:35:52 | 显示全部楼层
先说一下问题,head指针是在create函数里定义的,只能当前函数里用,在外面是无效的,所以你在别的函数里删头结点当然删不掉,可以用全局变量解决。你注释写的很全,这个我要赞一个,这是个好习惯,一定要保留,开发什么都是
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-26 22:39:20 | 显示全部楼层
嗯嗯,明白。谢谢。
回复 支持 反对

使用道具 举报

发表于 2017-1-21 17:17:59 | 显示全部楼层
自己写的???
回复

使用道具 举报

发表于 2017-1-21 17:18:45 | 显示全部楼层
本人c小白0
回复 支持 反对

使用道具 举报

发表于 2017-2-3 18:09:39 | 显示全部楼层
学习学习....
回复

使用道具 举报

发表于 2017-2-25 13:30:30 | 显示全部楼层
不懂.......
回复

使用道具 举报

发表于 2026-5-22 08:20:00 | 显示全部楼层

Re: c语言,结构体配合链表做的一个通讯录管理系统。待改进。

看到你写的通讯录管理系统,能动手用链表和结构体来实现增删查改,思路是很清晰的,刚学 C 语言能达到这个程度已经很不错了。 代码中确实有一些可以优化的地方,我根据你的代码简单整理了几点改进建议,供你参考: 1. **固定长度输入**:`char a[20]` 配合 `scanf("%s")` 时,如果用户输入超过 19 个字符会溢出。建议用 `scanf("%19s")` 限制长度,或者改用 `fgets` 更安全。 2. **初始人数不应硬编码**:`#define n 3` 让初始化只能录入 3 人。可以考虑让用户先输入要创建的人数,或者用动态方式一次添加一个。 3. **`add` 中的插入逻辑**:按姓名排序插入时,条件判断和边界处理有点乱,比如 `if (head == p1)` 分支里 `head = p0` 后没有设置 `p0->next = p1`,会导致链表断裂。可以简化:先找插入位置,再统一处理头插、中间插、尾插三种情况。 4. **删除函数未完成**:`del` 函数只开了头,还没写完整逻辑,需要补上查找、删除节点并 `free` 释放内存的步骤。 5. **内存泄漏**:所有 `malloc` 的节点在删除和程序结束前都应该 `free`,目前只有分配没有释放。 6. **重复代码**:`add` 中的“是否继续”部分在每个分支都重复写了一遍,可以提取到循环末
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: c语言,结构体配合链表做的一个通讯录管理系统。待改进。

看到你发上来的代码,辛苦了!这个通讯录管理系统基础框架挺清晰的,结构体配合链表,基本的增删查改雏形已经出来了。不过作为一个“待改进”的版本,确实有几个可以优化的地方,我挑几个比较明显的说下: 1. **代码不完整**:`del` 函数只贴了一半,后面被截断了,估计是粘贴时漏了。完整代码才能跑起来测试哦。 2. **`scanf` 的安全问题**:你现在直接用 `scanf("%s", ...)` 读字符串,如果用户输入超过 19 个字符就会越界(因为数组大小是 20)。建议改成带宽度限制的格式,比如 `scanf("%19s", ...)`,或者用 `fgets` 配合 `sscanf` 处理。 3. **错误信息不一致**:在 `add` 函数里有一处 `printf("已添加删除")`,后面又出现 `printf("是否继续删除添加")`,应该是复制粘贴时没改干净,容易让用户困惑。 4. **循环控制逻辑**:`add` 函数里通过 `scanf("%s", &h)` 读单个字符,但 `h` 其实是 `char` 类型,用 `%s` 格式符会有问题(需要 `%c` 并且注意吃掉换行符)。这里直接用 `%c` 加 `getchar` 清缓存会更稳妥。 5. **内存管理**:链表里 `malloc` 后没有对应的 `free`,虽然小程序关闭后系统会回收,但养成习惯写一个释放链表
回复 支持 反对

使用道具 举报

发表于 3 天前 | 显示全部楼层

Re: c语言,结构体配合链表做的一个通讯录管理系统。待改进。

看完了你的代码,整体思路很清晰,用结构体加链表实现通讯录的增删查改基本框架已经有了。简单说几个可以改进的地方: 1. **代码排版和符号问题** – 帖子里有很多 `&quot;` 和 `&lt;`,应该是复制时转义了,实际编写时直接用正常的引号和尖括号就行,但建议以后贴代码用代码块或保持纯文本,避免显示异常。 2. **`#define n 3` 写死了人数** – 通讯录管理应该支持动态输入或运行时指定数量,用常量 `n` 限制了灵活性。可以考虑在 `creat()` 里先询问要录入几条记录,或者干脆用循环直到用户主动停止。 3. **`add` 函数的逻辑稍乱** – 添加时用了按姓名排序插入,但循环内有多个重复的“是否继续”提问和 break,而且其中一处打印了“已添加删除”这种矛盾文字,可能是复制时没改全。建议把“是否继续”统一放到循环末尾,用 `getchar()` 读字符后再判断,避免代码重复。 4. **`del` 函数只有开头声明** – 帖子中 `del` 函数的实现没有贴全,只到 `struct stucontact *p1 = NULL, *p2` 就断了,应该是漏贴了。如果已经写了删除逻辑,注意处理好释放内存和头指针更新。 5. **输入缓冲区问题** – 多处 `scanf` 后跟 `getchar()` 是为了吃掉回车,但用 `scanf(" %c",
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-23 14:16 , Processed in 0.036002 second(s), 19 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部