《通讯录》开发用到得知识点
常量、变量的使用
全局变量
分支语句
函数
宏
循环语句
scanf和printf
数据
结构体
文件
指针*
《通讯录》中解决的经典问题
- 数组元素如何删除(不使用链表)
开发调试环境:Mac os x10.10 + xcode6.1
通讯录主界面:
添加联系人界面
删除联系人界面
修改联系人界面
搜索联系人
#include <stdio.h>
#include <string.h>
/****** 宏定义 *******/
#define NAME_LEN 21
#define TEL_LEN 12
#define N 1000
/****** 函数的声明 *******/
void doAdd();
void doDelete();
void doUpdate();
void doList();
void searchPersonByName();
void init();
void writeFile();
/****** 变量定义 *******/
typedef struct Linker{
//联系人的姓名
char name[NAME_LEN];
//联系人电话
char mobileNum[TEL_LEN];
}Person;
//定义联系人数组
Person contacts[N];
//定义一个变量,用于存放当前联系人的个数
int totalCount=0;
//文件路径的变量
char *filePath="telbook.data";
int main(int argc, const char * argv[]) {
int flag = 1;
int num =-1;
//进行初始化
init();
printf("数据初始化成功!...\n");
while (flag) {
printf("**************************\n");
printf("****** 欢迎使用通讯录 ******\n");
printf("****** 1、添加联系人 ******\n");
printf("****** 2、删除联系人 ******\n");
printf("****** 3、修改联系人 ******\n");
printf("****** 4、查看所有联系人 ****\n");
printf("****** 5、搜索联系人 ******\n");
printf("****** 6、退出系统 ******\n");
printf("**************************\n\n");
printf("请选择1-6之间的一个操作\n");
scanf("%d",&num);
if (num<=0 || num >6) {
printf("非法输入\n");
}else{
//判断用户选择了哪个功能
switch (num) {
case 1:
doAdd();
break;
case 2:
doDelete();
break;
case 3:
doUpdate();
break;
case 4:
doList();
break;
case 5:
searchPersonByName();
break;
case 6:
printf("正在退出系统...\n");
printf("退出完成!\n");
flag = 0;
break;
default:
break;
}
}
}
return 0;
}
/**
* 添加联系人
思路:
1)提示用户输入姓名和电话号码
2)接收用户输入的内容
3)保存到联系人数组
4)写入到文件中
*/
void doAdd(){
printf("您选择的是添加联系,请按提示操作\n");
//1)提示用户输入姓名和电话号码
printf("请输入联系人姓名:*联系人姓名不能有空格\n");
//2)接收用户输入的内容
// 0 0
// 1 1 contacts[1]
//3)保存到联系人数组
scanf("%s",contacts[totalCount].name);
printf("请输入联系人电话:*联系人电话不能有空格\n");
scanf("%s",contacts[totalCount].mobileNum);
//联系人的总数要+1
totalCount++;
//4)写入到文件中
writeFile();
}
/**
* 删除联系人的函数
思路:
1)让用户输入要删除的数据的编号
2)判断编号是否合法
3)让用户再次确认删除
4)开始删除数组元素
5)删除文件内容
*/
void doDelete(){
printf("您选择的是删除联系,请按提示操作\n");
doList();
//1)让用户输入要删除的数据的编号
int no;
printf("请输入要删除的联系人的编号:\n");
scanf("%d",&no);
//2)判断编号是否合法
if (no<=0 || no >totalCount) {
printf("编号不存在!\n");
return;
}
//3)让用户再次确认删除
int no1;
printf("请再次确认要删除的信息: 0.取消 1.确定\n");
scanf("%d",&no1);
if (no1) {
//4)开始删除数组元素
// 1)删除的元素是数组的最后一个元素
if (no==totalCount) {
totalCount --;
}else{
// 2) 删除的不是最后一个元素
for (int i=no; i<totalCount; i++) {
//后一个元素覆盖前一个元素
contacts[no-1] = contacts[no];
}
totalCount--;
//5)删除文件内容
writeFile();
}
}
}
/**
* 更新联系人信息
思路:
1)提示输入要修改的联系人编号
2)判断编号是否合法
3)让用户输入新的姓名、电话
4)让用户再次确认修改
5)开始修改用户信息
6)更新到文件中
*/
void doUpdate(){
printf("您选择的是修改联系人,请按提示操作\n");
doList();
//1)让用户输入要修改的数据的编号
int no;
printf("请输入要修改的联系人的编号:\n");
scanf("%d",&no);
//2)判断编号是否合法
if (no<=0 || no >totalCount) {
printf("编号不存在!\n");
return;
}
//3)让用户输入新的姓名和电话号码
char name[NAME_LEN];
char tel[TEL_LEN];
printf("请输入新的用户名:\n");
scanf("%s",name);
printf("请输入新的电话号码:\n");
scanf("%s",tel);
//4)让用户再次确认修改
int no1;
printf("请再次确认要修改的信息: 0.取消 1.确定\n");
scanf("%d",&no1);
if (no1) {
//5)开始修改用户信息
strcpy(contacts[no-1].name, name);
strcpy(contacts[no-1].mobileNum, tel);
//6)更新到文件中
writeFile();
}
}
/**
* 查看所有的联系人
思路:
1)先判断联系人是否为空
2)如果不为空,遍历数组,显示所有的联系人
*/
void doList(){
if (totalCount==0) {
printf("您的通讯录还空无一人!\n");
}else{
printf("所有的联系人信息如下:\n");
printf("编号\t姓名\t\t电话\n");
for (int i=0; i<totalCount; i++) {
printf("%d\t%s\t\t%s\n",i+1,contacts[i].name,contacts[i].mobileNum);
}
}
printf("\n");
}
/**
* 根据联系人的姓名查找联系人
思路:
1)提示用户输入要查找的人的姓名
2)遍历联系人数组,查找有没有这个人
3)查找到了,把电话号码显示出来
4)没有查找到,提示没有这个联系人
*/
void searchPersonByName(){
printf("您选择的是搜索联系人,请按提示操作:\n");
char name[NAME_LEN];
//1)提示用户输入要查找的人的姓名
printf("请输入要查找的用户名:\n");
scanf("%s",name);
int i;
//2)遍历联系人数组,查找有没有这个人
for (i=0; i<totalCount; i++) {
//3)查找到了,把电话号码显示出来
if (strcmp(contacts[i].name, name)==0) {
printf("您查找的 %s 的电话号码是:%s\n",contacts[i].name,contacts[i].mobileNum);
//停止循环
break;
}
}
//4)没有查找到,提示没有这个联系人
if (i==totalCount) {
printf("你的通讯录没有这个人!\n");
}
printf("\n");
}
/**
初始化方法,用于初始化数据
思路:
1)尝试性的读取文件
2)如果成功了,说明文件存在,则读取文件内容
3)不成功,说明文件不存在,
1)创建文件
2)写入联系人数量
*/
void init(){
//读取数据文件
FILE *fp = fopen(filePath, "rb");
if (fp!=NULL) {
//读取到,fread读文件到数组中
//printf("通讯录文件已经存在!\n");
//先读取联系人的个数
fread(&totalCount, sizeof(int), 1, fp);
// printf("totalCount = %d",totalCount);
for (int i=0; i<totalCount; i++) {
//循环读取每一块数据
fread(&contacts[i], sizeof(Person), 1, fp);
}
}else{
//不存在,创建文件
fp = fopen(filePath, "w");
//当前联系人的数量保存到文件中
// int count=1;
// 4 1
fwrite(&totalCount, sizeof(int), 1, fp);
printf("通讯录文件创建成功!\n");
}
fclose(fp);
}
/**
* 普通的写文件操作(把联系人写入到文件中)
思路:
1)先写联系人的长度,占用的时文件的头4个字节
2)然后遍历数组,把数组的每一个元素都写入到文件中
*/
void writeFile(){
FILE *fp = fopen(filePath, "wb");
if (fp!=NULL) {
// 1)先写联系人的长度,占用的时文件的头4个字节
fwrite(&totalCount, sizeof(int), 1, fp);
// 2)然后遍历数组,把数组的每一个元素都写入到文件中
for (int i=0; i<totalCount; i++) {
fwrite(&contacts[i], sizeof(Person), 1, fp);
}
printf("文件更新成功!\n");
}
fclose(fp);
}