【C语言】小型通讯录实现
C语言实现相关小型通讯录,可以做到对通讯录里面的内容进行增删查改,排序(以名字为依据),由于实现的代码相对较多,可以通过多个程序文件来编写程序,涉及的知识点主要有结构体类型及其操作,枚举类型的使用等。这里主要有三个文件:
test.c(主要通讯录各个函数的功能);
Contact.h(用于存放通讯录各个功能函数的声明,以及程序所用库函数的声明);
Contact.h(存放通讯录各类功能函数)。
通讯录实现部分(test.c):
#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
int main()
{
int input = 0;
struct Contact con;
InitContact(&con);
do
{
menu();
printf("please choose:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case DISPLAY:
ShowContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case EXIT:
break;
case SORT:
SortContact(con.data, con.sz);
break;
default:
printf("an error appeared: \n");
break;
}
} while(input);
printf("exit the contact successfully !\n");
return 0;
}
在 test.c 中 首先创建个通讯录 con,并对其进行初始化,将其所有元素均置为0,在接下来,通过do…while方式循环实现各类操作,在switch语句中选择执行哪类通讯录功能;需要注意的是,可以通过枚举变量实现将数字与具有实际意义的变量名联系起来,使得代码可读性提高。
通讯录函数声明(Contact.h)
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <search.h>
#define NAME_MAX 15
#define SEX_MAX 6
#define TELE_MAX 13
#define ADDR_MAX 20
#define MAX 1000
void menu(void);
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
DISPLAY,
SORT
};
struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
struct Contact
{
struct PeoInfo data[MAX];
int sz;
};
void InitContact(struct Contact* pc);
void AddContact(struct Contact* pc);
void ShowContact(struct Contact* pc);
void DelContact(struct Contact* pc);
int FindContactByName(const struct Contact* pc, const char* name);
void SearchContact(const struct Contact* pc);
void ModifyContact(struct Contact* pc);
void SortContact(struct PeoInfo* pc, int size);
在 Contact.h 中,主要存放各种自定义结构体类型以及通讯录各类功能函数的声明,以及在以后用到的库函数,在 test.c 中,只要通过
#include "Contact.h"
即可将所需的所有模块导入到 test.c 中。
通讯录功能实现( Contact.c )
打印菜单:
void menu(void)
{
printf("**************************************\n");
printf("*********** 1.add 2.del *****\n");
printf("*********** 3.search 4.modify *****\n");
printf("*********** 5.display 6.sort *****\n");
printf("************0.exit *****\n");
printf("**************************************\n");
}
这个函数相对比较简单,只是在窗口显示一个菜单,引导用户如何操作;
初始化菜单(将菜单置空)
void InitContact(struct Contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, MAX * sizeof(struct PeoInfo));
}
开辟变量空间后,空间中存放的都是随机值,对之后的增删查改的操作造成不利影响,因此需要对所创建的结构体进行初始化;将sz和其他成员变量值为0。
增(向通讯录里添加元素)
void AddContact(struct Contact* pc)
{
if (pc->sz == MAX)
{
printf("contact is full, can't increase");
return;
}
else
{
struct PeoInfo tmp;
printf("Enter name:>");
scanf("%s", tmp.name);
printf("Enter age:>");
scanf("%d", &(tmp.age));
printf("Enter sex:>");
scanf("%s", tmp.sex);
printf("Enter telephone:>");
scanf("%s", tmp.tele);
printf("Enter address:>");
scanf("%s", tmp.addr);
pc->data[pc->sz] = tmp;
pc->sz++;
}
}
首先创建一个临时的个人信息的结构体,将数据输入进去,之后将其输入进 con 结构体中的 data 数组中,然后 sz 自加后 变为1,表明通讯录中已经有了 sz 个元素,在之后的各类操作中可以用到;
在删查改操作中,都需要依据一定线索对某一元素进行查找,需要设计查找函数
int FindContactByName(const struct Contact* pc, const char* name)
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (!strcmp(pc->data[i].name, name))
return i;
}
return -1;
}
此函数通过对通讯录成员的name进行遍历,直到匹配到特定元素,并返回其序号,便于操作,如果未找到,则返回整数-1;
删(删除通讯录中指定的元素)
void DelContact(struct Contact* pc)
{
int i = 0;
char del_name[NAME_MAX] = { 0 };
if (!(pc->sz))
{
printf("contact is empty. can't delete\n");
return;
}
printf("Enter name as delete clue :>");
scanf("%s", del_name);
int position = FindContactByName(pc, del_name);
if (-1 == position)
printf(" the specific people can't be found!!\n");
else
{
int j = 0;
for (j = position;j<pc->sz-1; j++)
{
pc->data[j] = pc->data[j + 1];
}
pc->sz--;
printf("deletion is successfully!!\n");
}
if (i == pc->sz)
printf("can't search it!!");
}
如果通讯录为空或者未找到,则直接退出;如果找到,通过后面元素覆盖前面元素的方式“删除”指定元素,删除后要注意元素总个数减去1;
查(查找指定元素)
void SearchContact(const struct Contact* pc)
{
char find_name[NAME_MAX] = { 0 };
printf("Enter the specific element's name:>");
scanf("%s", &find_name);
int position = FindContactByName(pc, find_name);
if (-1 == position)
{
printf("can't find this people!!\n");
return;
}
else
{
printf("%-15s\t%-5s\t%-8s\t%-15s\t%-30s\t\n",
"NAME", "AGE", "SEX", "TELE", "ADDR");
printf("%-15s\t%-5d\t%-8s\t%-15s\t%-30s\t\n",
pc->data[position].name,
pc->data[position].age,
pc->data[position].sex,
pc->data[position].tele,
pc->data[position].addr);
}
}
在找到指定元素后将其打印出即可;
改(寻找到指定元素并将其变更)
void ModifyContact(struct Contact* pc)
{
char find_name[NAME_MAX] = { 0 };
printf("Enter the specific element's name:>");
scanf("%s", &find_name);
int position = FindContactByName(pc, find_name);
if (-1 == position)
{
printf("can't find this people!!\n");
return;
}
else
{
struct PeoInfo tmp;
printf("Enter new name:>");
scanf("%s", tmp.name);
printf("Enter new age:>");
scanf("%d", &(tmp.age));
printf("Enter new sex:>");
scanf("%s", tmp.sex);
printf("Enter new telephone:>");
scanf("%s", tmp.tele);
printf("Enter new address:>");
scanf("%s", tmp.addr);
pc->data[position] = tmp;
}
printf(" the modification is fuccessful!!\n");
}
其本质上就是 增 和 查 的结合。
排(依据特定方式将元素排序)
int compare(const void* p1, const void* p2)
{
return strcmp(((struct PeoInfo*)p1)->name, ((struct PeoInfo*)p2)->name);
}
void SortContact(struct PeoInfo* pc, int size)
{
qsort(pc, size, sizeof(struct PeoInfo), compare);
printf("the sort is successful! \n");
}
在 test.c 中,传递通讯录结构体中的 data 数组,也将 sz 传递过来,使用sqort函数排序,可以通过更改排序时所比较的成员变量来改变排序的依据;
显(显示现在的通讯录)
void ShowContact(struct Contact* pc)
{
int i = 0;
printf("%-15s\t%-5s\t%-8s\t%-15s\t%-30s\t\n",
"NAME","AGE","SEX","TELE","ADDR");
for (i = 0; i < pc->sz; i++)
{
printf("%-15s\t%-5d\t%-8s\t%-15s\t%-30s\t\n",
pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].tele,
pc->data[i].addr);
}
printf("\n");
}
在设计过程中,注意对齐方式,***"%-30s"*** 表示以字符串的方式打印(%s),30 表示该字符串所占的空间, - 表示左对齐
同样的设计方法还可以用在成绩表的制作等,加油🤣🤣
|