C语言通过三种方法实现属于你的通讯录

目录
  • 一、基础版本
    • 1.1 通讯录的个人信息(结构体来实现)
    • 1.2通讯录名单
    • 1.3人员初始化
    • 1.4菜单
    • 1.5主函数
  • 二、功能的实现
    • 2.1、增加人数
    • 2.2、删除人数
    • 2.3、查找
    • 2.4、展示
    • 2.5、排序(这里我是通过名字)
  • 三、通讯录进阶(设置动态存储)
    • 3.1通讯录从静态改为动态
    • 3.2通讯录的初始化
    • 3.3通讯录的增加需要判断是否满了
  • 四、文件的形式存储通讯录
    • 4.1人员信息的保存
    • 4.2人员信息的流入

一、基础版本

前提准备:

1、通讯录里面的人的个人信息(姓名、性别、年龄、手机号、地址)。

2、通讯录名单(来实现人员的增删插改)。

3、人员的初始化。

4、菜单。

1.1 通讯录的个人信息(结构体来实现)

typedef struct peoInfo     //重定义
{
     char name[20]; //姓名
     int age ;        //年龄
     char sex[10];    //性别
     char tele[12];    //手机号
     char addr[30];     //地址
 }peoInfo;

1.2通讯录名单

typedef struct Contact
{
    peoInfo data[100]; //人员名单 结构体数组
    int count;         //人员数量
}Contact;

1.3人员初始化

void InitContact(Contact* con)
{
    assert(con);
    con->count=0; //初始人数为0
    memset(con->data,0,sizeof(con->data)); //这是一个c语言的库函数把数组里面的数全部初始化为0

}

1.4菜单

void menu(void)
{
    printf("===============================\n");
    printf("====1.add  2. del  3.serch=====\n");
    printf("=====4.modify      5.show======\n");
    printf("=====6.sort        0.exit======\n");
    printf("===============================\n");
    printf("===============================\n");

}

1.5主函数

enum a
{
    ext, //这里用了简单的枚举的方法 枚举的初始值为0
    add,
    del,
    serch,
    modify,
    show,
    sort
};
int main()
{
    int choice;
    Contact con; //通讯录
    do
    {
        menu();
        printf("请选择功能\n");
        scanf("%d",&choice);
        switch(choice)
        {
            case add:
                AddContact(&con); //实现增加功能的函数
                break ;
            case del:
                DelContanct(&con); //实现删除功能的函数
                break ;
            case serch:
                SerContact(&con); //实现查找功能的函数
                break ;
            case modify:
                ModContact(& con); //实现修改功能的函数
                break ;
            case show:
                ShowContact(&con); //实现展示功能的函数
                break ;
            case sort:
                SorContact(&con);     //实现排序功能的函数
                break ;
            case ext :
                printf("程序结束\n");
                break;
            default :
                printf("输入有误请重新输入\n");
        }
    }while(choice);
    return 0;

}

二、功能的实现

2.1、增加人数

void AddContact(Contact* con)
{
    assert(con); //指针不能为空
    if(con->count==Max)
    {
        printf("存放已满\n");
        return ;
    }
    printf("请输入名字");
    scanf("%s",con->data[con->count].name);
    printf("请输入年龄");
    scanf("%d",&(con->data[con->count].age));
    printf("请输入性别");
    scanf("%s",con->data[con->count].sex);
    printf("请输入电话");
    scanf("%s",con->data[con->count].tele);
    printf("请输入地址");
    scanf("%s",con->data[con->count].addr);
    con->count++;
    printf("增加成功\n");

}

2.2、删除人数

 static int xiaomafind(Contact* con,char name[])
{

     assert(con);
     int i=0;

     for(i=0;i<con->count;i++)
     {
         if(0==strcmp(con->data[i].name,name))  //通过名字来查找看是否存在 ,如果有返回下标。
         {
         return i;
         }
    else
        {
            return -1;
        }
     }
 void DelContanct(Contact* con)
{
    char name[20]={0};
    printf("请输入你想删除的名字\n");
    assert(con);
    int i;
    scanf("%s",name);
    int pos=xiaomafind(con,name);
    if(pos==-1)
    {
        printf("没有你要删除的人\n");
    }
    else
    {
        for(i=pos;i<con->count;i++)
        {
            con->data[i]=con->data[i+1]; //通过数组后一个覆盖前一个来完成删除功能
        }
        con->count--;  //删除完成后人员减一
        printf("删除成功\n");
    }
}

2.3、查找

static int xiaomafind(Contact* con,char name[])
{

     assert(con);
     int i=0;

     for(i=0;i<con->count;i++)
     {
         if(0==strcmp(con->data[i].name,name))
         {
         return i;
         }
     }

         return -1;
 }
void SerContact(Contact *con)
{
    char name[20]={0};
    printf("请输入你想查找的名字\n");
    assert(con);
    scanf("%s",name);
    int find =xiaomafind(con,name);
    if(find==-1)
    {
        printf("没有你要查找的用户\n");
    }
    else{
        printf("查找成功\n");

    }
}

2.4、展示

void ShowContact( const Contact* con)
{
    assert(con);
    int i;
    for(i=0;i<con->count;i++)
    {
        printf("%2s\t%3d\t%5s\t%12s\t%30s\n",con->data[i].name,con->data[i].age,con->data[i].sex,con->data[i].tele,con->data[i].addr);  //这里是为了打印好看
    }
}

2.5、排序(这里我是通过名字)

^ _ ^用qsort 函数发现很很容的都能进行排序,我们只需要告诉他我们的排序方法是什么就可以很容易的进行一下排序

int cmp_stu_by_name(const void*e1,const void*e2)
{
    return strcmp(((peoInfo*)e1)->name,((peoInfo*)e2)->name);
    } //如不不理解的看我指针讲解中回调函数
void SorContact(Contact* con)
{
    assert(con);

    qsort(con->data, con->count, sizeof(peoInfo), cmp_stu_by_name); //这里运用了一个c语言的库函数qsort函数,在指针进阶中我也讲述了如何使用,如果不会的可以看一下指针的进阶。
}

三、通讯录进阶(设置动态存储)

动态版本只需要改三个位置就行啦

3.1通讯录从静态改为动态

//静态版本
//typedef struct Contact
//{
 //   peoInfo data[100]; //人员名单 结构体数组
  //  int count;         //人员数量
//}Contact;

//动态版本
​​​​​​​typedef struct Contact
{
    peoInfo *data; //人员名单 结构体指针
    int count;         //人员数量
    int capicity;  //通讯录容量
}Contact;

3.2通讯录的初始化

 //静态版本
//void InitContact(Contact* con)
//{
  //  assert(con);
  //  con->count=0; //初始人数为0
 //   memset(con->data,0,sizeof(con->data)); //这是一个c语言的库函数把数组里面的数全部初始化为0
//}
  //动态版本
void  InitContact(Contact* con)
{
    assert(con);
    con->count=0;
    con->data=(PeoInf0*)calloc(3,sizeof(peoInfo*));
    if(con->data=NULL)
    {
        perrror("con->data"); //如果空指针打印错误原因
    }
    con->capicity=3; //这里我们设置的初始容量为3

}

3.3通讯录的增加需要判断是否满了

void AddContact(Contact* con)
{
    assert(con); //指针不能为空
    if(con->count==con->capicity)
    {
        (peoInfo*)ptr=(PeoInfo*)realloc(con->data,(con->capicity)*2*sizeof(peoInfo)). //增加人数前先进行判断是否满了,如果满了扩大2倍。
    if(ptr==NULL)
        {
            perror("peoInof");
            return ;
        }
        else{
            con->data=ptr;
        }
    }
    printf("请输入名字");
    scanf("%s",con->data[con->count].name);
    printf("请输入年龄");
    scanf("%d",&(con->data[con->count].age));
    printf("请输入性别");
    scanf("%s",con->data[con->count].sex);
    printf("请输入电话");
    scanf("%s",con->data[con->count].tele);
    printf("请输入地址");
    scanf("%s",con->data[con->count].addr);
    con->count++;
    printf("增加成功\n");

}

^ - ^这样我们就实现通讯录的动态化,就不怕通讯录人数会存满了。

四、文件的形式存储通讯录

前面的通讯录在程序结束后发现人员没有办法进行一个保存,而通过文件的形式我们可以很好的做到这一点,在结束之前进行对文件的保存,在再一次执行程序是输入保存的文件,但是文件操作也有自己的不足之处,后面用数据库来实现更好,当前我们先用文件的形式来进行实现数据的保存,而实现这个只需要在结束时对文件保存,在初始化的时候时文件信息流入。

4.1人员信息的保存

void SaveContact(Contact*con)
{
    assert(con);
     //通过二进制写的形式把人员数据写入当中
    FILE* pfWrite=fopen("Contact.txt","wb"); 

    if(pfWrite==NULL)
    {
        perror("SaveContact");
        return ;
    }
    int i=0;
    for(i=0;i<con->count;i++)
    {
        fwrite(con->data+i,sizeof(peoInfo),1,pfWrite); //一次写一个人员
    }
    fclose(pfWrite);
    pfWrite=NULL;
}

4.2人员信息的流入

void LoadContact(Contact* con)
{
    assert(con);
    FILE*pfread =fopen("/Users/mamenghao/Desktop/Contact.txt","rb"); //二进制来读取文件信息
    if(pfread==NULL)
    {
        perror("LoadContact");
        return ;
    }
    peoInfo tmp={0}; //创建一个人员结构体变量先做临时的保存
   while( fread(&tmp,sizeof(peoInfo),1,pfread)==1)
   {
       if(con->count==con->capicity)
       {
           peoInfo* ptr=(peoInfo*)realloc(con->data,((con->capicity)*2*sizeof(peoInfo)));
           if(ptr==NULL)
           {
               perror("peoInof");
               return ;
           }
           else{
               con->data=ptr;
           }
       } //在增加前先判断是否容量已经满了

       con->data[con->count]=tmp;
       con->count++;
   }
    fclose(pfread);
    pfread=NULL;

}

总结:

通讯录本身实现它并不是特别的难,运用的知识就是顺序表的增删插改功能,而进一步的优化只需要大家熟练掌握文件的操作和动态内存存储就能很好的实现啦!!

到此这篇关于C语言通过三种方法实现属于你的通讯录的文章就介绍到这了,更多相关C语言通讯录内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解C语言之实现通讯录

    目录 基本思路和代码实现 其他探讨 总结 基本思路和代码实现 为了代码清晰易读,我们创建一个Main.c源文件用来实现代码的基本逻辑.创建一个Contact.h源文件用于封装实现功能的函数,创建Contact.h头文件用于函数的声明. 首先就是构架代码基本框架,在主函数中实现打印菜单和循环的功能 (这里为了好截图switch里的语句缩进得比较紧凑) 基本逻辑实现后开始考虑创建通讯录,通讯录里会记录人的信息.所以要先能够描述人的信息: 创建表达人的信息的结构体类型,在Contact.h中定义: 而

  • C语言实现简单的通讯录管理系统

    本文实例为大家分享了C语言实现通讯录管理系统的具体代码,供大家参考,具体内容如下 要实现一个通讯录管理系统,需要用到结构体.指针.文件操作.动态管理等内容. 效果展示: 实现思路 通讯录中的联系人包括姓名.年龄.性别.电话.住址,因此可以定义一个结构体PeoInfo来存储这些信息. 同时,由于通讯录需要记录当前的大小,以此来方便我们对通讯录realloc进行扩容,所以需要定义通讯录结构体Contact来保存这些信息,其中该结构体中可以嵌套一个PeoInfo类型的指针. 当定义完结构体以后,就可以

  • C语言通讯录管理系统完整代码

    本文实例为大家分享了C语言实现通讯录管理系统的具体代码,供大家参考,具体内容如下 设计内容: 设计一个通讯录管理系统,以实现以下功能:信息添加.查询.修改.删除.排序等功能. 设计要求: 1) 每条信息至包含 :姓名.电话.工作单位等信息2) 作为一个完整的系统,应具有友好的界面和较强的容错能力 预览: 代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <windows.

  • C语言实现通讯录的示例代码

    目录 一.Contact.h文件 二.Contact.c文件 三.test.c文件 一.Contact.h文件 包含函数的声明 #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #define MAX 100 #define MAX_NAME 20 #defi

  • C语言代码实现通讯录管理系统

    目录 一.需求分析 二.程序结构 三.头文件内容的介绍 四.模块化实现各个功能 (1)主函数实现 (2)初始化通讯录 (3)添加联系人信息 (4)删除联系人信息 (5)查找联系人信息 (6)更改联系人信息 (7)显示所有联系人信息 (8)对联系人信息进行排序 (9)退出时销毁通讯录 本文实例为大家分享了C语言实现通讯录管理系统,供大家参考,具体内容如下 一.需求分析 运用C语言实现一个简单的通讯录管理系统,要求对数据有 增删改查清排显 等功能的实现(这里由于还没学到文件,所以下面所有的存储都是在

  • C语言通过三种方法实现属于你的通讯录

    目录 一.基础版本 1.1 通讯录的个人信息(结构体来实现) 1.2通讯录名单 1.3人员初始化 1.4菜单 1.5主函数 二.功能的实现 2.1.增加人数 2.2.删除人数 2.3.查找 2.4.展示 2.5.排序(这里我是通过名字) 三.通讯录进阶(设置动态存储) 3.1通讯录从静态改为动态 3.2通讯录的初始化 3.3通讯录的增加需要判断是否满了 四.文件的形式存储通讯录 4.1人员信息的保存 4.2人员信息的流入 一.基础版本 前提准备: 1.通讯录里面的人的个人信息(姓名.性别.年龄.

  • Java语言通过三种方法实现队列的示例代码

    目录 队列 图解 数组模拟队列 队列优化—循环队列 代码 使用java内部队列 代码 队列 队列是一种特殊的线性表,只允许在表的前端进行删除操作,在表的后端进行插入操作. 队列是一个有序列表,可以用数组或是链表来实现. 遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的要后取出. 就相当于我们日常生活中的排队,先来先服务,后来的只能在后面进行排队等待. 图解 数组模拟队列 通过对定义的了解,发现队列很像我们的数组,那我们是不是可以通过数组来模拟队列,下面我们来实践一下. 首先先分析一下

  • 详解C语言快速排序三种方法的单趟实现

    目录 交换排序的思想 冒泡排序的思想 快速排序的整体框架 快速排序单趟实现逻辑 1. hoare版本单趟实现(左右指针法) 2.挖坑法单趟排序实现 3.前后指针法 交换排序的思想 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排 序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 冒泡排序的思想 冒泡排序比较简单,我们之前使用也很多,简单讲解,就是比较两个数,如果比他大就交换,没有他大就接着向后比,一直到数组结束,这是单趟

  • Ubuntu系统安装Ruby语言的三种方法

    Ruby是一个开源的动态编程语言,它有优美的语法,可用于构建可伸缩的Web应用程序.ruby gems可以很好地增强Ruby开发者的开发效率. 要在Ubuntu系统上安装Ruby,有几种方法,每种方法都只需几步就能搞定. 方法一:使用apt-get安装 可以直接使用两个命令完成Ruby的安装. 复制代码 代码如下: # sudo apt-get update # sudo apt-get install ruby 或者 复制代码 代码如下: # sudo apt-get install ruby

  • C语言实现求最大公约数的三种方法

    目录 题目描述 问题分析 代码实现 方法一:穷举法 方法二:辗转相除法 方法三:更相减损法 题目描述 求任意两个正整数的最大公约数 问题分析 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约数记为(a,b,c),多个整数的最大公约数也有同样的记号.求最大公约数有多种方法,常见的有质因数分解法.短除法.辗转相除法.更相减损法.与最大公约数相对应的概念是最小公倍数,a,b的最小公倍数记为[a,b]. --百度

  • C语言三种方法解决轮转数组问题

    目录 题目 1.题目描述 2.要求 3.原题链接 二.相关知识点 三.解决思路 旋转法 直接法 空间换取时间 题目 1.题目描述 给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数. 示例 1: 输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4] 2.要求 进阶

  • Go语言实现超时的三种方法实例

    目录 前言 方法一:用两个通道 + A协程sleep 方法二:使用Timer(定时器) 方法三:使用context.WithTimeout 附:go 实现超时退出 总结 前言 超时,指一个协程A开启另一个协程B,A会阻塞等待B一段指定的时间,例如:5秒,A通知B结束(也有可能不通知,让B继续运行).也就是说,A就不愿意阻塞等待太久. Go语言有多种方法实现这种超时,我总结出3种: 方法一:用两个通道 + A协程sleep 一个通道用来传数据,一个用来传停止信号. package main imp

  • C语言实现短字符串压缩的三种方法详解

    目录 前言 一.通用算法的短字符压缩 二.短字符串压缩 (1)Smaz (2)Shoco (3)Unisox2 三.总结 前言 上一篇探索了LZ4的压缩和解压性能,以及对LZ4和ZSTD的压缩.解压性能进行了横向对比.文末的最后也给了一个彩蛋:任意长度的字符串都可以被ZSTD.LZ4之类的压缩算压缩得很好吗? 本篇我们就来一探究竟. 一.通用算法的短字符压缩 开门见山,我们使用一段比较短的文本:Narrator: It is raining today. So, Peppa and George

  • Go语言拼接URL路径的三种方法

    目录 JoinPath ResolveReference path.Join 参考 Go语言拼接URL路径有多种方法建议用ResolveReference. JoinPath JoinPath会把多个多个路径合并成一个路径,并且处理../和./,多个//合并成单个/. package main import (     "fmt"     "net/url" ) func main() {     u1 := "http://example.com/dir

  • JavaScript中定义函数的三种方法

    在JavaScript的世界里,定义函数的方法多种多样,这正是JavaScript灵活性的体现,但是正是这个原因让初学者摸不着头脑,尤其对于没有 语言基础的同学.正所谓条条大道通罗马,但是如果道路太多,会让行路者不知所措,因为不知道走那条路才是正途,呵呵,废话一大篇,闲言少叙,先看代码: 复制代码 代码如下: /*第一种方法,使用function语句,格式如下*/ function fn(){ alert("这是使用function语句进行函数定义"); } fn(); /*第二种方法

随机推荐