首页 > 其他分享 >C语言-静态通讯录(全功能)(详略版)

C语言-静态通讯录(全功能)(详略版)

时间:2024-06-20 23:58:28浏览次数:25  
标签:count Contacts 联系人 C语言 pc 通讯录 printf data 详略

目录

前言:        

基本功能:

游戏主体: 

定义结构体:

初始化结构体:

添加联系人:

 显示通讯录:

修改联系人信息:

查找联系人:

删除联系人:

排序通讯录:

清空联系人:


前言:        

        大家好,今天写了一个通讯录系统,本程序也是对结构体的考察,我会尽可能阐述出自己的思路以及重要的知识点,大家也可以看看注释!

设计思路:

        1.添加联系人

        2.删除联系人

        3.修改联系人信息

        4.查找指定联系人

        5.显示通讯录

        6.排序通讯录

        7.清除所有联系人

这是我封装的一些函数:

// 显示菜单
void Show_menu(void);
// 初始化通讯录
void Init_Contacts(contacts *pc);
// 添加联系人
void Add_Contacts(contacts *pc);
// 显示通讯录
void Show_Contacts(contacts *pc);
// 修改联系人信息
void Modifly_Contacts(contacts *pc);
// 查找指定联系人
int Find_Contacts(contacts *pc, char *name_t, int pos[MAX]);
// 删除联系人
void Del_Contacts(contacts *pc);
// 查找联系人
void Seek_Contacts(contacts *pc);
// 排序通讯录
void Sort_Contacts(contacts *pc);
// 清空联系人
void Clear_Contacts(contacts *pc);

基本功能:

游戏主体: 

int main()
{
    int choose = 0;
    contacts con;
    Init_Contacts(&con);    //初始化通讯录
    do
    {
        Show_menu();         //显示菜单
        printf("Your choose is -->");
        scanf("%d",&choose);
        switch(choose)
        {
            case 1:     //添加联系人
                Add_Contacts(&con);         break;
            case 2:    //删除联系人
                Del_Contacts(&con);         break;
            case 3:   //修改联系人
                Modifly_Contacts(&con);     break;
            case 4:  //查找联系人
                Seek_Contacts(&con);        break;
            case 5: //显示通讯录
                Show_Contacts(&con);        break;
            case 6: //排序通讯录
                Sort_Contacts(&con);        break;
            case 7://清空所有联系人
                Clear_Contacts(&con);       break;
            case 0:
                printf("Exit Successful!"); break;
            default:    //输入错误,请重新输入
                printf("Input error!");     break;
        }
    } while (choose);

    system("pause");
    return 0;
}

首先,初始化了结构体,然后不断的在循环里选择自己所需的操作,在使用函数时,我们应当将结构体的地址作为参数传入,以便更好的修改

显示菜单:

// 显示菜单
void Show_menu()
{
    printf("**************************************\n");
    printf("*****  1.add             2.del   *****\n");
    printf("*****  3.modifly         4.seek  *****\n");
    printf("*****  5.show            6.sort  *****\n");
    printf("*****  0.exit                    *****\n");
    printf("**************************************\n");
}

定义结构体:

//最大字节空间
#define MAX_NAME 9
#define MAX_SEX  5
#define MAX_TELE 12
#define MAX_ADDER 30

// 类型声明
typedef struct PeoInfo
{
    char name[MAX_NAME];  // 名字
    int age;       // 年龄
    char sex[MAX_SEX];   // 性别
    char tele[MAX_TELE]; // 电话
    char addr[MAX_ADDER]; // 地址
} PeoInfo;

这是在.h文件中创建的一个完整的通讯录结构体,这里使用define定义的常量,方便以后的修改。

初始化结构体:

#define MAX 100 //最多人数
typedef struct contacts
{
    PeoInfo data[MAX]; // 存储信息
    int count;         // 记录人数
} contacts;

count表示当前存储的人数,他会随着增加或减少,PeoInfo date里面存放着通讯录的一些信息,这样写的好处在于方便管理和引用

// 初始化通讯录
void Init_Contacts(contacts *pc)
{
    assert(pc);
    pc->count = 0;
    memset(pc->data, 0, sizeof(pc->data)); // 全部初始化
}

在添加联系人信息之前,需要把data和sz全都初始化为0

assert是防止pc为NULL(空指针)它的头文件是<assert.h>,我们在使用指针时应该判断一下,这是一个很好的习惯

memset是字符串函数它的头文件是<string.h>,这里的作用是把data [MAX] 里面的空间全部设置为0

这里你也可以用循坏来初始化,都可以

这两个东西你们也可以自行查询一下,以下不在过多赘述

添加联系人:

// 添加联系人
void Add_Contacts(contacts *pc)
{
    assert(pc);
    if (pc->count == MAX) // 当联系人已满时,打印信息直接结束
    {
        printf("No Vacancies!\n");
        printf("Please afrsh choose!\n");
        return;
    }
    else
    {
        // 输入信息
        printf("Please input name->");
        scanf("%s", pc->data[pc->count].name);
        printf("Please input age->");
        scanf("%d", &(pc->data[pc->count].age));
        printf("Please input sex->");
        scanf("%s", pc->data[pc->count].sex);
        printf("Please input telephone->");
        scanf("%s", pc->data[pc->count].tele);
        printf("Please input address->");
        scanf("%s", pc->data[pc->count].addr);
    }
    pc->count++; // 输入成功,人数+1
    printf("added successfully!\n");
}

我们在添加之前,应该先判断人数是否已满,没有满我们再让其输入信息

count是作为接收人的个数,所以直接可以拿来当下标,当全部输入完信息后,再对人数count + 1

 显示通讯录:

// 显示通讯录
void Show_Contacts(contacts *pc)
{
    assert(pc);
    if (pc->count == 0) // 如果通讯录为空,则直接返回
    {
        printf("This contacts is empty!\n");
        return;
    }
    int i = 0;
    //列标题
    printf("%-15s\t%-15s\t%-15s\t%-15s\t%-15s\n", "name", "age", "sex", "tele", "addr");
    for (i = 0; i < pc->count; i++)
    {
        printf("%-15s\t%-15d\t%-15s\t%-15s\t%-15s\n",
               pc->data[i].name,  // 名字
               pc->data[i].age,   // 年龄
               pc->data[i].sex,   // 性别
               pc->data[i].tele,  // 电话
               pc->data[i].addr); // 地址
    }
}

这里我们打印了列标题以及各个信息为了美观我们可以将它们占位符统一一下,这里的 '-'表示左对齐,如果没有就是右对齐

利用循环遍历,将所有已经录入的信息打印出来

修改联系人信息:

// 修改联系人信息
void Modifly_Contacts(contacts *pc)
{
    assert(pc);
    char name_t[10] = {'\0'};
    printf("Please input your want modifly name->");
    scanf("%s", name_t); // 提供所修改信息的名称
    // gets(name_t);    *需要清除缓冲区

    int pos[MAX] = {0};                              // 存储的所要修改数据的下标
    int same_count = Find_Contacts(pc, name_t, pos); // 计算与输入的名称相同的个数(考虑重复情况)
    int select = 1;                                  // 当出现重复数据时为用户提供选择,select=1防止没有重复时,无法正确修改信息
    if (same_count == 0)                             // 输入要修改名称没有时,意味输入错误程序结束
    {
        printf("This contacts is empty,please afrsh choose!\n");
        return;
    }
    else if (same_count > 1) // 当出现多个相同名称时,再进一步提供选择第几个
    {
        printf("Detected multiple players before making further choices->");
        scanf("%s", &select);
        while (select > same_count) // 在循环中,所做选择序号不能超过出现的个数
        {
            printf("Input error!!!\n");
            printf("Please afrsh input->");
            scanf("%d", &select);
        }
    }
    // 修改数据-->pos数组里存储的是所出现数的下标
    printf("Please input name->");
    scanf("%s", pc->data[pos[select - 1]].name);
    printf("Please input age->");
    scanf("%d", &(pc->data[pos[select - 1]].age));
    printf("Please input sex->");
    scanf("%s", pc->data[pos[select - 1]].sex);
    printf("Please input telephone->");
    scanf("%s", pc->data[pos[select - 1]].tele);
    printf("Please input address->");
    scanf("%s", pc->data[pos[select - 1]].addr);
}

首先判断源数据里是否有所输入的数据,如果没有则返回,否则继续

定义一个数组name_t,用来接收用户所要修改的名称

(注意,这里如果用gets()函数来接收的话,需要清楚一个缓冲区,不然上一回的’\n‘就会直接当成这一回的输入内容)

Find_Conatsts()函数就是判断所输入的数据,源数据里有多少,然后用pos数组来存放各个相同名称的下标,后面我们会详细展开Find_Conatcts()函数

当有多个相同名称的数据时,我们将它打印出来,用户做选择,是比实际下标多1的,所以下面我们在输入时用的是select -  1这样就能定位到所指派的pos下标,此时pos数组存放的刚好是相同数据在结构体里的下标,这样就能完成正确赋值

当有多个相同名称数据时,用户做选择,然后再一一赋值,没有多个相同名称就给select初始化为1,这样也能正确访问到该位置的数组

查找联系人:

// 排查联系人
int Find_Contacts(contacts *pc, char *name_t, int pos[MAX])
{
    assert(pc);
    int i = 0;
    int tag = 0;
    printf("Find the follwing content for you :\n");
    for (i = 0; i < pc->count; i++)
    {
        // 如果所要修改数据与源数据相同时,输出出来并将下标存放到pos数组
        if (strcmp(pc->data[i].name, name_t) == 0)
        {
            printf("%-15s\t%-15d\t%-15s\t%-15s\t%-15s\n",
                    pc->data[i].name,
                    pc->data[i].age,
                    pc->data[i].sex,
                    pc->data[i].addr);
                    pc->data[i].tele,
            pos[tag++] = i; // 存储下标位置
        }
    }
    return tag; // 返回个数
}

因为我们考虑了多条相同数据的情况,所以这里的Find_Contacts()函数可能复杂些

这里的功能是:所传入的输入name_t遍历整个源数组,当有相同时,我们将其输出出来(以供用户进一步选择)

然后将下标存放到pos数组中(为了我们后期能够准确找到所选择数据在源结构体中的位置)

然后将其个数返回(为了判断是否要供用户选择这一条件),我们在修改联系人信息删除联系人信息都提供了极大的帮助

删除联系人:

// 删除联系人
void Del_Contacts(contacts *pc)
{
    assert(pc);
    char name_t[10] = {'\0'};
    printf("Please input your want modifly name->");
    scanf("%s", name_t); // 提供所修改信息的名称

    int pos[MAX] = {0};
    int same_count = Find_Contacts(pc, name_t, pos);
    int select = 1;

    if (same_count == 0) // 当源数据中没有要删除的数据时
    {
        printf("This contacts is empty,please afrsh choose!\n");
        return;
    }
    else if (same_count > 1) // 当出现多个相同名称时,再进一步提供选择第几个
    {
        printf("Detected multiple players before making further choices->");
        scanf("%d", &select);
        while (select > same_count) // 再循环中,所做选择序号不能超过出现的个数
        {
            printf("Input error!!!\n");
            printf("Please afrsh input->");
            scanf("%s", &select);
        }
    }
    // 删除数据
    int i = 0;
    for (i = pos[select - 1]; i < pc->count - 1; i++) // count - 1 避免越界
        pc->data[i] = pc->data[i + 1];
    printf("Delete Successful!\n"); // 打印成功信息,人数 - 1
    pc->count--;
}

删除数据与前面的修改数据大致是一模一样的,都是简单的对它进行一下判断,唯一不同的是最后一点->如何删除

我们可以用所要删除的数据为其实下标,让后面的数据不断覆盖前面的数据,这样就实现了删除功能,最后再将人数 - 1

但是中间的判断条件为pc->count - 1 避免出现越界访问情况

排序通讯录:

// 排序通讯录
void Sort_Contacts(contacts *pc)
{
    assert(pc);
    if (pc->count == 0) // 通讯录为空,直接结束
    {
        printf("This contacts is empty,please afrsh choose!\n");
        return;
    }
    // 不为空,则使用qsort排序
    else
        qsort(pc, pc->count, sizeof(PeoInfo), cmp_peo_name);
    printf("Sorting Successful!\n"); // 排序成功
}
// qsort排序所用函数(升序)
int cmp_peo_name(const void *e1, const void *e2)
{
    return strcmp(((PeoInfo *)e1)->name, ((PeoInfo *)e2)->name);
}

先进行判断是否为空,为空则打印提示信息结束,不为空则用qsort()函数进行排序,它的头文件是<stdilb.h>有兴趣的可以详细学习一个这个函数,当然你也可以用两重for循环那种方法,定义一个结构体作为中间变量来交换,方法不唯一

本程序使用的升序,如果想用降序则将第二块代码中的两个参数调换一个位置

清空联系人:

// 清空联系人
void Clear_Contacts(contacts *pc)
{
    if(pc->count == 0)  //如果通讯录本身为空则打印提示信息返回
        {
            printf("This contacts is empty,please afrsh choose!\n");
            return;
        }
    printf("Are you sure you want to clear all ?\n");
    printf("Yes->1   exit->other\n");
    printf("Your choose is->");
    int flag = 1;
    scanf("%d",&flag);
    if(flag == 1)
    {
        Init_Contacts(pc);
        printf("Clear successful!\n");
    }
}

很简单,就是再次调用一下初始化函数!

GitHub - HackerActivists/Contacts: Static_Contacts_C

这是我的一个源代码,大家可以去看看!

标签:count,Contacts,联系人,C语言,pc,通讯录,printf,data,详略
From: https://blog.csdn.net/2301_81590110/article/details/139833805

相关文章

  • 请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度
    /*请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度的函数)函数返回较长的字符串。若两个字符串长度相同,则返回第一个字符串。*/#include<stdio.h>char*fun(char*buff,char*str){intbuff_len=0,str_len=0;while(bu......
  • HMAC与Hash算法——C语言实现
    hash算法是HMac的Mac hmacsha256.h1/**2*@filehmacsha256.h3*@authoryourname([email protected])4*@brief5*@version0.16*@date2024-06-207*8*@copyrightCopyright(c)20249*10*/1112#ifndef_HMAC_SHA_256_H_13#......
  • 【C语言】自定义类型
    目录一、结构体:1、结构体的声明:2、结构体的自引用:3、结构体变量的定义和初始化:4、结构体内存对齐:5、结构体传参:6、位段:二、枚举类型:三、联合体:一、结构体:1、结构体的声明:首先要了解什么是结构:结构是一些值的集合,与数组不同的是结构的每一个成员变量可以使不同......
  • 探究C语言函数栈帧的创建和销毁
    引言在C语言程序中,每当一个函数被调用时,系统都会在栈上为该函数分配一块内存空间,这块内存空间就被称为栈帧。栈帧中包含了函数执行所需的所有信息,如局部变量、参数、返回地址等。栈帧的创建和销毁是函数调用的核心部分,它们确保了函数能够正确地执行和返回。本文将在VS2013环......
  • C语言基础入门 -1
    一.计算机中单位bit -比特位(最小单位);byte-字节kb-千字节mb-兆字节gb-千兆字节tb-太字节1字节=8比特位;其他单位之间换算为1024;二.数据类型与所占字节char//字符型   1字节short//短整型   2字节int  //整型   4字节long//长整型  ......
  • C语言----自定义类型:联合和枚举
     1.联合体联合体的特点像结构体一样,联合体也是一个或者多个成员构成的,这些成员可以是不同的类型联合体的关键字:union结构体的关键字:struct枚举的关键字:enum但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共......
  • 【C语言】初识C语言 - 数组
    一、一维数组的创建和初始化1.1一维数组的创建数组的定义:是一种线性数据结构,用于存储相同数据类型的元素的集合。数组中的元素在内存中是连续存储的,并且通过索引来访问。#include<stdio.h>intmain(){ intarr[1]={2}; //数组数据类型为:int //数组名为:arr //......
  • C语言期末复习笔记
    目录一,基础介绍。二,标识符起名规范。三,数据类型。四,变量。五,运算符和表达式1,加减乘除​编辑  /为整除,%为余数,*为乘号2,关系运算符3,逻辑运算符4,运算符优先级5,前自增,后自增6,三目运算符。7,符合运算符。六,控制语句。1,if判断2,多重判断。3,for循环4,while循环5,d......
  • C语言程序设计-11 结构体与共用体
    11.1定义一个结构的一般形式11.2结构类型变量的说明1.先定义结构,再说明结构变量。2.在定义结构类型的同时说明结构变量。3.直接说明结构变量。11.3结构变量成员的表示方法11.4结构变量的赋值结构变量的赋值就是给各成员赋值。可用输入语句或赋值语句来完成。......
  • C语言程序设计-10 指针
    指针是C语言中广泛使用的一种数据类型。运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构;能很方便地使用数组和字符串;并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。学习指针是学习C语言中最重要的一环,能......