首页 > 其他分享 >C语言小项目-通讯录

C语言小项目-通讯录

时间:2023-11-30 21:32:38浏览次数:45  
标签:ps name 项目 struct C语言 通讯录 printf data size

对C语言的学习研究也有一段时间了,今天做一个小项目“通讯录”,来回顾之前所学。

文件结构

通讯录这个项目需要三个文件:

1.test.c 用于测试

2.contact.c 用于实现

3.contact.h 声明函数

需求描述

1.该通讯录要能存放1000个好友的信息

2.信息要包含:姓名、电话、性别、住址、年龄

3.增加好友信息

4.删除指定名字的好友信息

5.修改好友信息

6.打印好友信息

7.排序

。。。

实现

实现菜单界面

第一步我们先搭建一个框架。这个框架主要包括一些菜单的选择,类似于一个界面。

我们要在test.c实现菜单


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


}
int main(){
    int input=0;
    do {
        menu();
        printf("please select:>");
        scanf("%d",&input);
        switch (input) {
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            case 4:
                break;
            case 5:
                break;
            case 6:
                break;
            case 0:
                printf("exit\n");
                break;
            default:
                printf("input error\n");
                break;
        }
    } while (input);
}

我们执行一次运行输入0试一下:

C语言小项目-通讯录_C

但是这上面代码是有些需要优化的。比如switch case语句。随着实现的功能增加,操作增加。那么这些case的数组会增加很多,代码的可读性就比较差,后续我们会对这里进行优化。

创建通讯录

创建通讯录需要记录每个通讯录中每个用户的信息。所以需要用到结构体。这个结构体声明我们放在contact.h中。

struct PeoInfo
{
    char name[20];
    int age;
    char sex[5];
    char tele[12];
    char addr[30];
};

然后再test.c中创建结构体变量

    //创建通讯录
    struct PeoInfo con[1000];

但是我们发现上面代码有很多数字,20 5 12 1000等等,这样后续修改不是很方便。所以我们用宏定义来替换。

#define  MAX 1000
#define  NMAE 20
#define  SEX 5
#define  TELE 12
#define  ADDR 30

struct PeoInfo
{
    char name[NMAE];
    int age;
    char sex[SEX];
    char tele[TELE];
    char addr[ADDR];
};


    //创建通讯录
    struct PeoInfo con[MAX];

这样代码可读性就好一点,也便于维护

接下来我们要有一些个函数、初始化通讯录、增加通讯录等等

//初始化通讯录
InitContact(con);
//增加
AddContact(con,&size);

但是这样我们发现,这个通讯录在增加成员删除成员的时候,不仅仅要传入通讯录还要传入当前通讯录有多少个信息,所以我们能不能把通讯录和当前存储的个数进行封装

struct Contact{
    struct  PeoInfo data[MAX];//存放一个信息
    int size;//记录当前个数
};

放在contact.h中

初始化通讯录

在.h文件中声明InitContact

//声明函数
void InitContact(struct  Contact* ps);

然后在.c文件中实现这个函数

void InitContact(struct  Contact* ps){
    //置0
    memset(ps->data,0, sizeof (ps->data));
    ps->size=0;
}

另外这里需要注意的是 test.c文件引用头文件不能直接引用 contact.h要去引用contact.c然后contact.c在去引用头部文件contact.h

这里我们调试一次,在初始化通讯录结构体之前,成员的值为:

C语言小项目-通讯录_C_02

看到并不是全部都是0,在执行了初始化函数InitContact之后,所有成员都变成了0;

C语言小项目-通讯录_通讯录_03

C语言小项目-通讯录_C_04

这也就意味着我们初始化功能写好了。

增加通讯录成员

还是先在.h文件中声明函数


void AddContact(struct  Contact* ps);

然后去.c文件中去实现

void AddContact(struct  Contact* ps){
 //判断通讯录是否满
    if(ps->size==MAX){
        printf("error , full of contact");
    } else{
        printf("please input name");
        scanf("%s",ps->data[ps->size].name);
        printf("please input ege");
        scanf("%d",&(ps->data[ps->size].age));
        printf("please input sex");
        scanf("%s",ps->data[ps->size].sex);
        printf("please input tele");
        scanf("%s",ps->data[ps->size].tele);
        printf("please input addr");
        scanf("%s",ps->data[ps->size].addr);
        ps->size++;
        printf("add sucessfully\n");
    }
}

增加通讯录成员第一件事要判断通讯录是否满了。如果满了则返回一条信息。

如果未满则按照每个信息进行填写即可。最后要记得对size增加1 。

另外要注意在添加age的时候 因为是int类型所以一定要取到age的地址来添加。

那么这个写完我们运行一下看是否添加成功

执行这个添加之前我们看到成员都初始化好了:

C语言小项目-通讯录_C_05

输入完毕之后

C语言小项目-通讯录_结构体_06

我们看一下成员信息是否已经有了(变量视图)

C语言小项目-通讯录_结构体_07

这里我们可以看到我们输入的信息已经被记录进去了。这就说明增加功能没有问题了。

这里最好是增加完之后自动打印出来看一下最好,所以我们就实现打印功能。

打印输出通讯录

还是先在.h文件中声明函数

void ShowContact(struct  Contact* ps);

然后去.c文件中去实现


void ShowContact(struct  Contact* ps){
    if(ps->size==0){
        printf("contact null");
    } else{
        int i=0;
        printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n",
               "name",
               "age",
               "sex",
               "tele",
               "addr");
        for (int j = 0; j < ps->size; ++j) {

            printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
                   ps->data[j].name,
                   ps->data[j].age,
                   ps->data[j].sex,
                   ps->data[j].tele,
                   ps->data[j].addr);
        }
    }
}

 注意,输出的时候%加数字是指保留多少宽度,二者中间的-指的是左对齐

随便写点测试一下:

C语言小项目-通讯录_C_08

最下面就是输出的结果。可以看到像一个列表一样,都是左对齐。

优化 switch case语句

我们在上面实现菜单的时候,提到了纯数字的switch语句不方便阅读和维护。所以我们在这里对其进行优化,怎么优化呢?我们可以使用枚举类型。

我们可以在头文件中创建枚举类型

enum Option{
    EXIT,
    ADD,
    DEL,
    SEARCH,
    MODIFY,
    SHOW,
    SORT
};

然后修改菜单中的switch case语句

int main(){
    int input=0;
    //创建通讯录
    struct Contact con;//通讯录,包含1000个元素和size
    //初始化通讯录
    InitContact(&con);


    do {
        menu();
        printf("please select:>");
        scanf("%d",&input);
        switch (input) {
            case ADD:
                AddContact(&con);
                break;
            case DEL:
                DelContact(&con);
                break;
            case SEARCH:
                break;
            case MODIFY:
                break;
            case SHOW:
                break;
            case SORT:
                break;
            case EXIT:
                 printf("exit\n");
                break;
            default:
                printf("input error\n");
                break;
        }
    } while (input);
}

这样一来代码可读性就好了,后期需要加什么操作,只需要继续往枚举类型加就行了。

根据姓名删除指定通讯录成员

还是先在.h文件中声明函数

void DelContact(struct  Contact* ps);

然后去.c文件中去实现

   void DelContact(struct  Contact* ps){
    char name[NAME];
    printf("please input del name");
    scanf("%s",name);
    //查找要删除的成员的位置
    int i;
    for (i=0; i < ps->size; ++i) {
        if(0==strcmp(ps->data[i].name,name)){
            break;
        }
    }
         //删除
    if(i==ps->size){
        printf("member is null");
    }else{
        int  j;
        for ( j = 0; j < ps->size-1; ++j) {
            ps->data[j]=ps->data[j+1];
        }
        ps->size--;
        printf("delete successfully");
    }
 
} 

当然删除的方法不止这一个,这个只是把要删除的成员的后一个成员将其覆盖掉,后面依次循环执行覆盖操作。还有个方法是直接将最后一个成员的位置覆盖掉要删除的位置的成员。只不过这样size的序号就乱了。

查找成员

在写这个方法的时候我们很容易发现,查找似乎我们刚刚才写过,对就是在删除指定成员的时候我们写过,因为删除就需要先去查找,当然除了删除,修改也需要。所以我们这里可以将查找功能提前封装出来,封装出一个单独的查找函数。

static int FindByNme(struct  Contact* ps,char name[NAME]){
        int i;
    for (i=0; i < ps->size; ++i) {
        if(0==strcmp(ps->data[i].name,name)){
            return i;
        }
    }
    //找不到的情况
    return -1;
}

修改一下删除功能

void DelContact(struct  Contact* ps){
    char name[NAME];
    printf("please input del name");
    scanf("%s",name);
    //查找要删除的成员的位置
    //找到了返回名字所在元素下标
    //找不到返回-1
    int pos= FindByNme(ps,name);
//    int i;
//    for (i=0; i < ps->size; ++i) {
//        if(0==strcmp(ps->data[i].name,name)){
//            break;
//        }
//    }
    if(pos==-1){
        printf("member is null");
    }else{
        int  j;
        for ( j = pos; j < ps->size-1; ++j) {
            ps->data[j]=ps->data[j+1];
        }
        ps->size--;
        printf("delete successfully");
    }
    //删除
}

修改通讯录成员

还是先在.h文件中声明函数

void ModifyContact(const struct  Contact* ps);

然后去.c文件中去实现

void ModifyContact(const struct  Contact* ps){
    char name[NAME];
    printf("please input name for modify:>");
    scanf("%s",name);
    int pos= FindByNme(ps,name);
    if(pos==-1) {
        printf("member is null");
    } else{
        printf("please input modify name");
        scanf("%s",ps->data[pos].name);
        printf("please input modify ege");
        scanf("%d",&(ps->data[pos].age));
        printf("please input modify sex");
        scanf("%s",ps->data[pos].sex);
        printf("please input modify tele");
        scanf("%s",ps->data[pos].tele);
        printf("please input modify addr");
        scanf("%s",ps->data[pos].addr);
        printf("modify sucessfully\n");

        printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n","name","age","sex","tele","addr");
        //打印出来查找到的结果
        printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
               ps->data[pos].name,
               ps->data[pos].age,
               ps->data[pos].sex,
               ps->data[pos].tele,
               ps->data[pos].addr);
    }

}

修改的话比较简单,根据输入的名字先执行查询,然后查询到的话 重新执行一遍插入的时候执行的代码即可,然后打印一下该结果。

排序(根据年龄升序)

还是先在.h文件中声明函数

void SortContact(struct  Contact* ps);

然后去.c文件中去实现

最简单的就是用冒泡排序即可


void SortContact(struct  Contact* ps){
    for (int i = 0; i < ps->size; ++i) {
        for (int j = i+1; j < ps->size; ++j) {
            if(ps->data[i].age>ps->data[j].age){
                //交换位置
                struct  PeoInfo tmp;
                tmp=ps->data[i];
                ps->data[i]=ps->data[j];
                ps->data[j]=tmp;
            }
        }
    }
    printf("sort successfully");
    ShowContact(ps);
}

最后排序完成在输出一下,其他的排序可以自行实现一下,包括排序算法也可以读着自己进行修改去实现。


全套代码

1.test.c 用于测试

//
// Created by leslieSu79 on 2023/11/30.
//
#include "contact.c"

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


}
int main(){
    int input=0;
    //创建通讯录
    struct Contact con;//通讯录,包含1000个元素和size
    //初始化通讯录
    InitContact(&con);


    do {
        menu();
        printf("please select:>");
        scanf("%d",&input);
        switch (input) {
            case ADD:
                AddContact(&con);
                break;
            case DEL:
                DelContact(&con);
                break;
            case SEARCH:
                SearchContact(&con);
                break;
            case MODIFY:
                ModifyContact(&con);
                break;
            case SHOW:
                ShowContact(&con);
                break;
            case SORT:
                SortContact(&con);
                break;
            case EXIT:
                 printf("exit\n");
                break;
            default:
                printf("input error\n");
                break;
        }
    } while (input);
}

2.contact.h 声明函数

//
// Created by leslieSu79 on 2023/11/30.
//

#ifndef C_CONTACT_H
#define C_CONTACT_H
#include "stdio.h"
#include "string.h"

#define  MAX 1000
#define  NAME 20
#define  SEX 5
#define  TELE 12
#define  ADDR 30

struct PeoInfo
{
    char name[NAME];
    int age;
    char sex[SEX];
    char tele[TELE];
    char addr[ADDR];
};
struct Contact{
    struct  PeoInfo data[MAX];//存放一个信息
    int size;//记录当前个数
};

enum Option{
    EXIT,
    ADD,
    DEL,
    SEARCH,
    MODIFY,
    SHOW,
    SORT
};

//声明函数
void InitContact(struct  Contact* ps);
void AddContact(struct  Contact* ps);
void ShowContact(const struct  Contact* ps);
void DelContact(struct  Contact* ps);
void ModifyContact(const struct  Contact* ps);
void SortContact(struct  Contact* ps);

#endif //C_CONTACT_H

3.contact.c 定义函数

//
// Created by leslieSu79 on 2023/11/30.
//

#include "contact.h"

void InitContact(struct  Contact* ps){
    //置0
    memset(ps->data,0, sizeof (ps->data));
    ps->size=0;

}

void AddContact(struct  Contact* ps){
    //判断通讯录是否满
    if(ps->size==MAX){
        printf("error , full of contact");
    } else{
        printf("please input name");
        scanf("%s",ps->data[ps->size].name);
        printf("please input ege");
        scanf("%d",&(ps->data[ps->size].age));
        printf("please input sex");
        scanf("%s",ps->data[ps->size].sex);
        printf("please input tele");
        scanf("%s",ps->data[ps->size].tele);
        printf("please input addr");
        scanf("%s",ps->data[ps->size].addr);
        ps->size++;
        printf("add sucessfully\n");
        ShowContact(ps);
    }
}

void ShowContact(const struct  Contact* ps){
    if(ps->size==0){
        printf("contact null\n");
    } else{
//        int i=0;
        printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n","name","age","sex","tele","addr");
        for (int j = 0; j < ps->size; ++j) {

            printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
                   ps->data[j].name,
                   ps->data[j].age,
                   ps->data[j].sex,
                   ps->data[j].tele,
                   ps->data[j].addr);
        }
    }
}

static int FindByNme(const struct  Contact* ps,char name[NAME]){
        int i;
    for (i=0; i < ps->size; ++i) {
        if(0==strcmp(ps->data[i].name,name)){
            return i;
        }
    }
    //找不到的情况
    return -1;
}

void DelContact(struct  Contact* ps){
    char name[NAME];
    printf("please input del name");
    scanf("%s",name);
    //查找要删除的成员的位置
    //找到了返回名字所在元素下标
    //找不到返回-1
    int pos= FindByNme(ps,name);
//    int i;
//    for (i=0; i < ps->size; ++i) {
//        if(0==strcmp(ps->data[i].name,name)){
//            break;
//        }
//    }
    if(pos==-1){
        printf("member is null");
    }else{
        int  j;
        for ( j = pos; j < ps->size-1; ++j) {
            ps->data[j]=ps->data[j+1];
        }
        ps->size--;
        printf("delete successfully\n");
        ShowContact(ps);
    }
    //删除
}

void SearchContact(struct  Contact* ps){
    char name[NAME];
    printf("please input name for select:>");
    scanf("%s",name);
    int pos= FindByNme(ps,name);
    if(pos==-1) {
        printf("member is null");
    } else{
        printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n","name","age","sex","tele","addr");
        //打印出来查找到的结果
        printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
               ps->data[pos].name,
               ps->data[pos].age,
               ps->data[pos].sex,
               ps->data[pos].tele,
               ps->data[pos].addr);
    }

}

void ModifyContact(const struct  Contact* ps){
    char name[NAME];
    printf("please input name for modify:>");
    scanf("%s",name);
    int pos= FindByNme(ps,name);
    if(pos==-1) {
        printf("member is null");
    } else{
        printf("please input modify name");
        scanf("%s",ps->data[pos].name);
        printf("please input modify ege");
        scanf("%d",&(ps->data[pos].age));
        printf("please input modify sex");
        scanf("%s",ps->data[pos].sex);
        printf("please input modify tele");
        scanf("%s",ps->data[pos].tele);
        printf("please input modify addr");
        scanf("%s",ps->data[pos].addr);
        printf("modify sucessfully\n");

        printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n","name","age","sex","tele","addr");
        //打印出来查找到的结果
        printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
               ps->data[pos].name,
               ps->data[pos].age,
               ps->data[pos].sex,
               ps->data[pos].tele,
               ps->data[pos].addr);
    }

}

void SortContact(struct  Contact* ps){
    for (int i = 0; i < ps->size; ++i) {
        for (int j = i+1; j < ps->size; ++j) {
            if(ps->data[i].age>ps->data[j].age){
                //交换位置
                struct  PeoInfo tmp;
                tmp=ps->data[i];
                ps->data[i]=ps->data[j];
                ps->data[j]=tmp;
            }
        }
    }
    printf("sort successfully");
    ShowContact(ps);
}


总计两百多行吧是个比较简单小程序。主要是复习回顾结构体和枚举类型的使用。

标签:ps,name,项目,struct,C语言,通讯录,printf,data,size
From: https://blog.51cto.com/u_16160587/8634112

相关文章

  • 在eclipse中拖动项目到Tomcat服务器中报错:Project facet Java version 16 is not supp
    ......
  • 映客马甲包项目沉淀
    一、立项映客业务遇到瓶颈,能守好自己的护城河已经很难,但是产品团队得找方法实现增长。按产品的原话说:在这种业务上,不进就等于倒退,最后慢性死亡。想要用户增长,就得不断获取新用户,而这种体量的APP投放广告获取用户的成本是巨大的,人均100+了,为了能降低获取用户的成本,立项了映客的马......
  • 《初学C语言第11天》
    ////求定积分-----------已给函数接口//#include<stdio.h>//#include<stdlib.h>//#include<math.h>//doublesquare(doublex)//平方//{//  returnx*x;//x^2//}//doublecube(doublex)//立方//{//  returnx*x*x;//x^3//}///*你编写的积分函数嵌入在这里开始*//......
  • CentOS安装node环境,并编译前端项目
    https://www.jianshu.com/p/a0e0311d62591.centos安装node环境1.下载nodejs最新的tar包可以在下载页面https://nodejs.org/en/download/中找到下载地址。然后执行指令$wgethttps://nodejs.org/dist/v9.3.0/node-v9.3.0-linux-x64.tar.xz2,解压包$tar-xvfnod......
  • 大屏项目的搭建心得,使用img的填充模式来实现大屏自适应。
    借鉴了图片的两种填充模式cover和contain文档介绍https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fitcontain:被替换的内容将被缩放,以在填充元素的内容框时保持其宽高比。整个对象在填充盒子的同时保留其长宽比。cover:被替换的内容在保持其宽高比的同时填充......
  • Vue 项目配置自动更新,自动刷新页面
    今天用户反馈使用页面的时候,有时候点击没反应,排查下来,是因为发布版本的时候,用户那边没有加载最新的文导致的,然后根据思路,做了这个自动更新的功能效果预览http://demo.webwlx.cn/#/update实现思路1.把当前版本的编译时间,通过环境变量的方式保存起来打开vite.config.jsim......
  • 项目冲刺D1
    成员分配任务学号姓名工作20211111刘海涛数据库20211117祁昱霖功能整合20211105李宜时前端设计20211121杨博川数据库链接20211126李浩瑞后端设计今日任务学号姓名工作20211111刘海涛jdknginxmysqlnavicatidea的安装2021......
  • Apple开发_Xcode项目中找不到Products文件、无法找到.ipa文件、无法找到打包后的静态
    1、困扰造成的困扰就是找不到.ipa文件了,如果是运行程序用来生成静态库的话,也无法找到.a后或者.framework文件了;编译出的ipa包想直接拿来用,找不到输出的ipa文件。2、解决办法2.1方法一找到项目文件.xcodeproj右击「显示包内容」打开project.pbxproj文件搜索到如下内容:mainGroup=......
  • 夜莺项目发布 v6.4.0 版本,新增全局宏变量功能
    大家好,夜莺项目发布v6.4.0版本,新增全局宏变量功能,本文为大家简要介绍一下相关更新内容。全局宏变量功能像SMTP的配置中密码类型的信息,之前都是以明文的方式在页面展示,夜莺支持全局宏变量之后,可以在变量管理配置一个smtp_password的密码类型的变量,在SMTP配置页面,密码的......
  • 基于Python的BlackJack游戏项目设计与实现——LW
    本篇论文介绍了基于Python的Blackjack游戏的设计和实现。该游戏是一款经典的赌博游戏,玩家可以在游戏中与电脑进行对战。在系统设计方面,本文首先对需求进行了分析,并采用了面向对象的方法进行了系统的设计。在客户端模块设计中,使用了Pygame库进行图形界面的实现,同时采用了多线程技术......