【无标题】

这是随便在网上找的一个通讯录,主要是想复习一下c语言,我在不理解或者觉得重要的地方会加上注释。

这是一个多文件程序,由三个文件组成的通讯录程序,要注意需要将这些文件放到一个工程里才行。

一个.c文件会对应生成一个.obj文件(编译之后生成的文件)最后会生成.exe文件​​​​​​​

推荐一下我现在读的书《手把手教你写c语言》这本书用大白话讲的很透彻,像网上推荐的c primer plus确实太青涩。我觉得看书引起共鸣是最重要的,边看书边实践,你在现实遇到过很容易让思想运动起来和引起兴趣,也会加深你的记忆。Simple is not simple

//  contact.h
//.h文件是头文件,内含函数声明、宏定义、结构体定义等
//在头文件定义的函数作用范围是整个工程,就比如我在contact.h里声明a=2,那么在contact.c里a的值也是2.一般来说.h文件里只有声明,

#include<stdio.h>//stdio.h这个文件的内容就是基本输入输出函数的声明,比如输入函数scanf()和输出函数printf()
#include<string.h>//string.h在使用到字符数组时需要使用
 
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 6
#define ADDR_MAX 30
#define TELE_MAX 13
//typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名。,预处理是指在进行编译的第一遍扫描之前所作的工作。typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

 
typedef struct peoinfo//定义一个结构体struct peoinfo,一种自定义的数据类型
{
    char name[NAME_MAX];//字符串或串(String)是由数字、字母、下划线组成的一串字符。1个字节
    int age;//int占4个字节,当没有前缀long 或short时系统会自动识别,其实这里应该限制的准确一点,也不会出现后边的对齐的其中的一个问题了
    char sex[SEX_MAX];
    char addr[ADDR_MAX];
    char tele[TELE_MAX];//这些在开头已经被预处理命令下了宏定义,比如TELE电话最多可以占13个字节
    //这些限制并没有什么用,实际是可以超过这些限制
 
}peoinfo;//在结尾添上peoinfo;的作用是:struct peoinfo是结构体的名的在结尾写上peoinfo是结构体起别名,以便在后续代码中使用。在没有使用typedef时这里的作用是定义一个变量
 
typedef struct contact
{
    peoinfo data[MAX];//总内存占1000字节
    int sz;
}contact;
 
void Initcontact(contact* p);//指针变量指向contact的地址
 
void Addcontact(contact* p);
 
void Showcontact(contact*p);
 
void Delcontact(contact*p);
 
void Searchcontact(contact*p);
 
void Modifycontact(contact* p);
 
void Sortcontact(contact* p);//这些函数在contact.c文件里

//  contact.c
//.c文件是程序文件,内含函数实现,变量定义等内容
//  Created by apple on 2023/2/19
#define _CRT_SECURE_NO_WARNINGS  1//这条预处理的作用是有一些老的.c文件使用了strcpy,scanf等不安全的函数,而报警告和错误,而导致无法编译通过。
 
#include"contact.h"//调用contact.h文件
 
int find_by_name(contact*p,char name[])//contact*p指向contact的指针,在存储contact的内存中查找联系人,char name用于你输入的内容
{
    int i = 0;
    for (i = 0; i < p->sz; i++)//for循环中括号里的第一个先将0赋给a,然后执行判断i < p->sz,满足i小于p所指向的结构体中的变量sz,运行for嵌入语句,里面的语句运行完了i+1
    {
        if (strcmp(name, p->data[i].name) == 0)//strcmp是一个函数,作用是比较name和p->data[i].name是否相等,如果相等返回值为0,0==0开始运行内部代码
        {
            return i;//返回值为i表示找到了联系人
        }
    }
    return -1;//返回值为—1代表没找到
}//(*p).data[i].name == p -> data[i].name
 
void Initcontact(contact* p)
{
    p->sz = 0;//将sz里面的数据清空。可以试一试把这一段代码删除会发生什么
    memset(p->data, 0, sizeof(p->data));//将指针指向的data数据清空,第三个表达式的意思是设置为指向p->data的内存大小,就算我把值设置成1,它也照样能正常运行,c语言的危险性不可忽视🙅♂️.sizeof的作用是求出对象在计算机内存中所占字节数
    
}
 
 
void Addcontact(contact* p)
{
    if (p->sz == 1000)//
    {
        printf("通讯录已满,无法再添加\n");
        return ;//只是表示从函数中返回,不返回任何值,运行到这程序就结束了。
    }
    printf("请输入名字:");
    scanf("%s", p->data[p->sz].name);//%s字符串类型,整个意思是将输入的字符串存入p指向data结构体中的sz变量里的name中
    printf("请输入年龄:");//在年龄这里可以试一试输入非整形是会发生什么
    scanf("%d", &p->data[p->sz].age);//%d整形类型
    printf("请输入性别:");
    scanf("%s", p->data[p->sz].sex);
    printf("请输入地址:");
    scanf("%s", p->data[p->sz].addr);
    printf("请输入电话:");
    scanf("%s", p->data[p->sz].tele);
    
    p->sz++;//将p指向sz的值加一
}
 


void Showcontact(contact* p)//展示所有的联系人
{
    int i = 0;
    printf("%-10s\t%-4s\t%-6s\t%-30s\t%-13s\n", "名字", "年龄", "性别", "地址", "电话");//t就是水平制表符,作用是使输出结果对齐,怎么对齐是按照这个公式(num = |n-8|%8)来输出空格的。这样写还麻烦了,s前面的数字是限制宽度
    for (i = 0; i < p->sz; i++)
    {
        printf("%-10s\t%-4d\t%-6s\t%-30s\t%-13s\n", p->data[i].name,
            p->data[i].age,
            p->data[i].sex,
            p->data[i].addr,
            p->data[i].tele);
    }//
}
//void Showcontact(contact* p)//自己改了一下
//{
//    int i = 0;
//        for (i = 0; i < p->sz; i++)
//    {
//        printf("%s\%s\n\%s\%s\n\%s\%s\n\%s\%s\n\%s\%s\n", "名字:", p->data[i].name,
//            "年龄:",p->data[i].age,
//            "性别:",p->data[i].sex,
//            "地址:",p->data[i].addr,
//            "电话:",p->data[i].tele);
//        printf("*****************************************\n");
//    }
//}


void Delcontact(contact* p)
{
    char name[NAME_MAX] = { 0 };//对于一个没有传入任何数据的name数组为什么还要再清空我也不清楚,上网搜了一下说是防止name数组中出现垃圾数据,影响到程序的运行结果,在C语言中,定义的变量(包括数组)的值都是存储在内存中的,而缓存中的数据则是从内存中读取的。因此,清除name中的数据时,只需要清除缓存中的数据即可。
    printf("删除人姓名:");
    scanf("%s", name);
    int ret=find_by_name(p,name);
    if (ret == -1)//负一代表没找到
    {
        printf("删除的人不存在\n");
        return;
    }
    int i = 0;
    for (i = ret; i < p->sz - 1; i++)//这里用的了冒泡排序,后面的就不说了,用的方法都一样
    {
        p->data[i] = p->data[i + 1];
    }
    p->sz--;
    printf("删除成功\n");
}
 
void Searchcontact(contact* p)
{
    char name[NAME_MAX] = { 0 };
    int i = 0;
    printf("查找人姓名:");
    scanf("%s", name);
    int ret=find_by_name(p,name);
    if (ret == -1)
    {
        printf("查找的人不存在\n");
        return;
    }
    printf("%-20s\t%-4s\t%-6s\t%-30s\t%-13s\n", "名字", "年龄", "性别", "地址", "电话");
    printf("%-20s\t%-4d\t%-6s\t%-30s\t%-13s\n", p->data[ret].name,
            p->data[ret].age,
            p->data[ret].sex,
            p->data[ret].addr,
            p->data[ret].tele);
    
}
 
void Modifycontact(contact* p)
{
    char name[NAME_MAX] = { 0 };
    int i = 0;
    printf("修改人姓名:");
    scanf("%s", name);
    int ret = find_by_name(p, name);
    if (ret == -1)
    {
        printf("修改的人不存在\n");
        return;
    }
    printf("请输入名字:");
    scanf("%s", p->data[ret].name);
    printf("请输入年龄:");
    scanf("%d", &p->data[ret].age);
    printf("请输入性别:");
    scanf("%s", p->data[ret].sex);
    printf("请输入地址:");
    scanf("%s", p->data[ret].addr);
    printf("请输入电话:");
    scanf("%s", p->data[ret].tele);
    printf("修改成功\n");
}
 
void Sortcontact(contact* p)
{
    if (p->sz == 0)
    {
        printf("联系人为空,无法排序");
    }
    int i = 0;
    peoinfo tmp ;
    for (i = 0; i < p->sz-1; i++)
    {
        int j = 0;
        for (j = 0; j < p->sz - i-1; j++)
        {
            if (p->data[i].age > p->data[i + 1].age)
            {
                tmp = p->data[i];
                p->data[i] = p->data[i + 1];
                p->data[i + 1] = tmp;
            }
        }
    }
    printf("排序完成\n");
}


//  main.c
//main函数是整个C程序的入口。
//  Created by apple on 2023/2/19.
#define _CRT_SECURE_NO_WARNINGS  1
 
 
#include"contact.h"
 
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;
    contact con;//在结构体后面创建的是变量
    Initcontact(&con);
    do//先执行一次,再判断要不要再执行
    {
        menu();
        printf("请选择:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            Addcontact(&con);
            break;
        case 2:
            Delcontact(&con);
            break;
        case 3:
            Searchcontact(&con);
            break;
        case 4:
            Modifycontact(&con);
            break;
        case 5:
            Showcontact(&con);
            break;
        case 6:
            Sortcontact(&con);
            break;
        case 0:
            printf("已退出");
            break;
        default:
            printf("选择错误,重新选择\n");
            break;
        }
    } while (input);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值