要想实现一个通讯录,首先,我们要知道 我们要想实现的是通讯录都有哪些功能,
首先 要思考这个通讯录 是干什么的,最关键的是——存放显示联系人;存放显示它的姓名;年龄;性别;地址;还有? 电话号码;没有电话号码;怎么练习别人呢;怎么能叫通讯录呢?
除了存放显示联系人 我们还要有最起码的 增删查找改;最后我们还希望能有一个 排序的功能。
知道了这么多,我们就有了 一个大致的方向了
首先
要有个简易的初始界面 像这样:
#include<stdio.h>
void Add()
{}
void Del()
{}
void Search()
{}
void Show()
{}
void Modify()
{}
void Sort()
{}
void menu()
{
printf("***1.(Add) ***\n");
printf("***2.(Del) ***\n");
printf("***3.(Search)***\n");
printf("***4.(Modify)***\n");
printf("***5.(Show) ***\n");
printf("***6.(Sort) ***\n");
printf("***0.(Exit) ***\n");
}
int main()
{
int input = 0;
do
{
menu(); //给个菜单 提示所执行的功能
printf("请输入要执行的功能: ");
scanf("%d", &input);
switch(input)
{
case 1:Add();
break;
case 2:Del();
break;
case 3:Search();
break;
case 4:Modify();
break;
case 5:Show();
break;
case 6:Sort();
break;
case 0: printf("退出通讯录\n");
break;
default:printf("输入错误\n");
break;
}
} while (input);
}
以下是运行结果:
这样我们就已经完成了第一步;
这第二步呢 就是创建变量 ;
我们用结构体来创建变量比较方便:
struct People
{
char name[10];
int age; // age为整形变量
char sex[10];
char tele[11];
char address[10];
};
struct Contact
{
people date[100]; //初始我们存放100个人的信息 所以我们给people类型
int count; // 记录当前通讯录中的人数
};
//——————————————————————————
typedef struct People
{
char name[10];
int age[10];
char sex[10];
char tele[11];
char address[10];
}People;
typedef struct Contact
{
int date[100];
int count;
}Contact;
为了方便后来对结构体引用 我们利用typedef 来将结构体重命名。
以上才算完成了这个通讯录的基本框架 现在 我们一步一步对函数进行构造来实现我们的功能。
提到函数;我们先不着急去直接写那些功能函数
想一想 我们的 Contact 是不是还没有初始化;
先构建一个 Contact变量
Contact con; // 构建一个Contact变量
initContact(&con); // 初始化
然后开始写初始化函数
void initContact(Contact*pc) // 初始化 pc 的类型是Contact*
{
assert(pc); //防止pc为空指针
pc->count = 0;
memset(pc->date, 0, sizeof(pc->date));
//memset 复制字符 0)(一个无符号字符)到参
//数 pc->date所指向的字符串的前 sizeof(pc->date)个字符。
}
初始化结束,我们先写Add函数
case 1:Add(&con);
break;
这里打印的时候尤其要注意? 稍不注意就错了(惨疼的教训)
// name是数组名 本身就是地址 // age 是整形变量 ?需要取地址
void Add(Contact* pc)
{
assert(pc);
// 首先要 对pc 判断 是否是空指针 空指针不能解引用
// 判断 count 是否已经超过了date可以存储的范围
if (pc->count == 100)
{
printf("人数已满,请处理后重试");
return;
}
printf("请输入名字:");
scanf("%s", pc->date[pc->count].name); // name是数组名 本身就是地址
printf("请输入年龄:");
scanf("%d", &(pc->date[pc->count].age)); // age 是整形变量 需要取地址
printf("请输入性别:");
scanf("%s", &pc->date[pc->count].sex);
printf("请输入电话:");
scanf("%s", pc->date[pc->count].tele);
printf("请输入地址:");
scanf("%s", pc->date[pc->count].address);
pc->count = pc->count + 1; // count 记录存储人数的个数 记得加1
printf("增加成功\n");
}
下面是Del函数
case 2:Del(&con);
break;
int find_name(Contact* pc,char name1[])
{
assert(pc);
int i = 0; // for 循环遍历寻找
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(name1, pc->date[i].name))
return i; //返回 i 方便删除
}
return -1;
}
void Del(Contact* pc)
{
assert(pc);
//首先要判断 通讯录是否为空
if(pc->count == 0)
{
printf("通讯录为空,不可删除\n");
}
printf("请输入要删除联系人的名字:");
char name1[20] = { 0 };
scanf("%s", &name1);
// 要知道删除之前 我们是知道这个联系人的位置在哪
// 不能直接申请删除
// 所以我们要先找到 这个联系人的位置 并且判断是否存在
// 我们假设 这个联系人里没有人重名
// 我们先按照 名字来查找
int ret = find_name(pc, name1); // 给个 ret 来接受返回值
//采用覆盖删除
if (ret == 0)
{
printf("无该联系人,请核验后重试\n");
return 0;
}
else if (ret != -1)
{
int i = 0;
for (i = ret; i < pc->count - 1; i++)
{
pc->date[ret] = pc->date[ret + 1];
}
}
pc->count = pc->count - 1;
printf("删除成功\n");
}
接下来就是 Search函数
case 3:Search(&con);
break;
同样的查找之前 我们是知道这个联系人的位置在哪? ?
我们要先找到 这个联系人的位置 并且判断是否存在
?我们假设 这个联系人里没有人重名??我们先按照 名字来查找
仍然用find_name这个函数
void Search(Contact* pc)
{
assert(pc);
printf("请输入要查找的人的名字:");
//老规矩 我们要首先要判断查找的联系人是否存在
char name1[20] = { 0 };
scanf("%s", &name1);
int ret = find_name(pc, name1); // 给个 ret 来接受返回值
if (ret == -1)
{
printf("无该联系人,请核验后重试\n");
return ;
}
//按每个字符的宽度,左对齐输出它们。
printf("%-20s\t%-10s\t%-10s\t%-11s\t%-10s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s\t%-10d\t%-10s\t%-11s\t%-10s\n",
pc->date[ret].name,
pc->date[ret].age,
pc->date[ret].sex,
pc->date[ret].tele,
pc->date[ret].address);
}
再然后就是Modify函数
case 4:Modify(&con);
break;
同样的修改之前 我们是知道这个联系人的位置在哪? ?
我们要先找到 这个联系人的位置 并且判断是否存在
?我们仍然假设 这个联系人里没有人重名??我们先按照 名字来查找
仍然用find_name这个函数
void Modify(Contact* pc)
{
assert(pc);
printf("请输入要修改的人的名字:");
//老规矩 我们要首先要判断修改的联系人是否存在
char name1[20] = { 0 };
scanf("%s", &name1);
int ret = find_name(pc, name1); // 给个 ret 来接受返回值
if (ret == -1)
{
printf("无该联系人,请核验后重试\n");
return;
}
printf("请输入名字:");
scanf("%s", pc->date[ret].name);
printf("请输入年龄:");
scanf("%d", pc->date[ret].age);
printf("请输入性别:");
scanf("%s", &pc->date[ret].sex);
printf("请输入电话:");
scanf("%s", pc->date[ret].tele);
printf("请输入地址:");
scanf("%s", pc->date[ret].address);
printf("修改成功\n");
}
下面是 Show函数
case 5:Show(&con);
break;
void Show(Contact* pc)
{
assert(pc);
int i = 0; // for 循环遍历打印
printf("%-20s\t%-10s\t%-10s\t%-11s\t%-10s\n", "名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-10d\t%-10s\t%-11s\t%-10s\n",
pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].address);
}
}
最后一个 函数?
case 6:Sort(&con);
break;
要用到qsort函数 不知道用法的点?这里
int com_by_name(const void* e1,const void*e2)
{
strcmp(((People*)e1)->name, ((People*)e2)->name);
}
void Sort(Contact* pc)
{
assert(pc);
// 我们还是按照名字来排序
qsort(pc->date,pc->count, sizeof(People),com_by_name);
printf("排序成功\n");
}
———————————————————————————————————————————
手动分割线
以上我们就将简易版的通讯录 完成了
下面附上完整的代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
typedef struct People
{
char name[10];
int age;
char sex[10];
char tele[11];
char address[100];
}People;
typedef struct Contact
{
People date[100];
int count; // 记录当前通讯录中的人数
}Contact;
void initContact(Contact*pc) // 初始化 pc 的类型是Contact*
{
assert(pc); //防止pc为空指针
pc->count = 0;
memset(pc->date, 0, sizeof(pc->date));
//memset 复制字符 0)(一个无符号字符)到参数 pc->date所指向的字符串的前 sizeof(pc->date)个字符。
}
void Add(Contact* pc)
{
assert(pc);
// 首先要 对pc 判断
// 判断 count 是否已经超过了date可以存储的范围
if (pc->count == 100)
{
printf("人数已满,请处理后重试\n");
return;
}
printf("请输入名字:");
scanf("%s", pc->date[pc->count].name); // name是数组名 本身就是地址
printf("请输入年龄:");
scanf("%d", &(pc->date[pc->count].age)); // age 是整形变量 需要取地址
printf("请输入性别:");
scanf("%s", pc->date[pc->count].sex);
printf("请输入电话:");
scanf("%s", pc->date[pc->count].tele);
printf("请输入地址:");
scanf("%s", pc->date[pc->count].address);
pc->count = pc->count + 1;
printf("增加成功\n");
return;
}
int find_name(Contact* pc,char name1[])
{
assert(pc);
int i = 0; // for 循环遍历寻找
for (i = 0; i < pc->count; i++)
{
if (0 == strcmp(name1, pc->date[i].name))
return i; //返回 i 方便删除
}
return -1;
}
void Del(Contact* pc)
{
assert(pc);
//首先要判断 通讯录是否为空
if(pc->count == 0)
{
printf("通讯录为空,不可删除\n");
}
printf("请输入要删除联系人的名字:");
char name1[20] = { 0 };
scanf("%s", &name1);
// 要知道删除之前 我们是知道这个联系人的位置在哪
// 不能直接申请删除
// 所以我们要先找到 这个联系人的位置 并且判断是否存在
// 我们假设 这个联系人里没有人重名
// 我们先按照 名字来查找
int ret = find_name(pc, name1); // 给个 ret 来接受返回值
//采用覆盖删除
if (ret == -1)
{
printf("无该联系人,请核验后重试\n");
return ;
}
else if (ret != -1)
{
int i = 0;
for (i = ret; i < pc->count - 1; i++)
{
pc->date[ret] = pc->date[ret + 1];
}
}
pc->count = pc->count - 1;
printf("删除成功\n");
}
void Search(Contact* pc)
{
assert(pc);
printf("请输入要查找的人的名字:");
//老规矩 我们要首先要判断查找的联系人是否存在
char name1[20] = { 0 };
scanf("%s", name1);
int ret = find_name(pc, name1); // 给个 ret 来接受返回值
if (ret == -1)
{
printf("无该联系人,请核验后重试\n");
return ;
}
//按每个字符的宽度,左对齐输出它们。
printf("%-20s\t%-3s\t%-10s\t%-11s\t%-10s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s\t%-3d\t%-10s\t%-11s\t%-10s\n",
pc->date[ret].name,
pc->date[ret].age,
pc->date[ret].sex,
pc->date[ret].tele,
pc->date[ret].address);
}
void Show(Contact* pc)
{
assert(pc);
int i = 0; // for 循环遍历打印
printf("%-20s\t%-3s\t%-10s\t%-11s\t%-10s\n", "名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pc->count; i++)
{
printf("%-20s\t%-3d\t%-10s\t%-11s\t%-10s\n",
pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].address);
}
}
void Modify(Contact* pc)
{
assert(pc);
printf("请输入要修改的人的名字:");
//老规矩 我们要首先要判断修改的联系人是否存在
char name1[20] = { 0 };
scanf("%s", &name1);
int ret = find_name(pc, name1); // 给个 ret 来接受返回值
if (ret == -1)
{
printf("无该联系人,请核验后重试\n");
return;
}
printf("请输入名字:");
scanf("%s", pc->date[ret].name);
printf("请输入年龄:");
scanf("%d", &(pc->date[ret].age));
printf("请输入性别:");
scanf("%s", pc->date[ret].sex);
printf("请输入电话:");
scanf("%s", pc->date[ret].tele);
printf("请输入地址:");
scanf("%s", pc->date[ret].address);
printf("修改成功\n");
}
int com_by_name(const void* e1,const void*e2)
{
strcmp(((People*)e1)->name, ((People*)e2)->name);
}
void Sort(Contact* pc)
{
assert(pc);
// 我们还是按照名字来排序
qsort(pc->date,pc->count, sizeof(People),com_by_name);
printf("排序成功\n");
}
void menu()
{
printf("***1.(Add) ***\n");
printf("***2.(Del) ***\n");
printf("***3.(Search)***\n");
printf("***4.(Modify)***\n");
printf("***5.(Show) ***\n");
printf("***6.(Sort) ***\n");
printf("***0.(Exit) ***\n");
}
int main()
{
int input = 0;
Contact con; // 构建一个Contact变量
initContact(&con); // 初始化
do
{
menu(); //给个菜单 提示所执行的功能
printf("请输入要执行的功能: ");
scanf("%d", &input);
switch(input)
{
case 1:Add(&con);
break;
case 2:Del(&con);
break;
case 3:Search(&con);
break;
case 4:Modify(&con);
break;
case 5:Show(&con);
break;
case 6:Sort(&con);
break;
case 0: printf("退出通讯录\n");
break;
default:printf("输入错误\n");
break;
}
} while (input);
}
|