功能展示
通讯录用到的知识点
常量,变量的使用
全局变量
分支语句
函数
宏
循环语句
scanf和printf
数据
结构体
文件
指针*
经典的问题(难点)
数组元素的删除(涉及数据结构)
功能分析及实现步骤
//
// main.c
// End_project
// 通讯录
// Created by 自超 陈 on 15/8/31.
// Copyright (c) 2015 年 自超 陈 . All rights reserved.
//
#include <stdio.h>
#include <string.h>
// 宏定义 *******************************************************************
#define N 100 // 通讯录容量
#define NAMELEN 22 // 姓名长度
#define NUMLEN 12 // 号码长度
//********* 定义部分 ********************************************************
// 定义联系人的结构体
typedef struct {
// 联系人
char name[ NAMELEN ];
// 号码
char telNum[ NUMLEN ];
}Person;
// 存储所有联系人,联系人数组
Person contacts[ N ]; // 能够存储 100 个联系人
// 定义联系人个数
int totalContactCount = 0 ;
// 接收用户输入的编号
int fno;
// 定义数据文件保存的位置
char *filePath = "telbook.data" ;
//*********** 函数声明部分 ***************************************************
int valitataInput( int num, int min, int max); // 合法输入
void doAdd(); // 添加
void doDelete(); // 删除
void doUpdata(); // 修改
void doList(); // 显示联系人
void doSearchByName(); // 搜索
void init(); // 初始化
void writeFile(); // 写数据到文件
// 主函数 *******************************************************************
int main( int argc, const char * argv[]) {
/*
1 、引入头文件
2 、进行必要的宏定义
3 、定义文件名称变量、联系人数组、联系人结构体
4 、定义函数,并进行声明
5 、编写循环控制程序
6 、现实操作界面
7 、根据编号执行不同的函数
*/
init ();
printf ( " 通讯录初始化完成! \n" );
while ( 1 ) {
printf ( "\n" );
// 软件的界面显示出来,死循环控制不停地输入
printf ( "**************************\n" );
printf ( "****** 欢迎使用通讯录 ******\n" );
printf ( "****** 1 、添加联系人 ******\n" );
printf ( "****** 2 、删除联系人 ******\n" );
printf ( "****** 3 、修改联系人 ******\n" );
printf ( "****** 4 、查看所有联系人 ****\n" );
printf ( "****** 5 、搜素联系人 ******\n" );
printf ( "****** 6 、退出系统 ******\n" );
printf ( "**************************\n" );
// 提示用户选择一个序号
printf ( " 请选择 1~6 之间的功能编号: \n" );
scanf ( "%d" , & fno );
// 判断编号是否合法,最好写个函数
valitataInput ( fno , 1 , 6 );
// 做不同的事情,定义不同的函数
switch ( fno ) {
case 1 :
// 执行添加
doAdd ();
break ;
case 2 :
// 执行删除
doDelete ();
break ;
case 3 :
// 执行修改
doUpdata ();
break ;
case 4 :
// 执行显示所有联系人
doList ();
break ;
case 5 :
// 执行搜索联系人
doSearchByName ();
break ;
case 6 :
printf ( " 系统正在退出 ...\n" );
printf ( " 系统已经退出! " );
return 0 ;
break ;
default :
break ;
}
}
return 0 ;
}
// 判断编号合法函数 **********************************************************
//min-1,max-6
int valitataInput( int num, int min, int max) {
if (num < min || num > max) {
// main.c
// End_project
// 通讯录
// Created by 自超 陈 on 15/8/31.
// Copyright (c) 2015 年 自超 陈 . All rights reserved.
//
#include <stdio.h>
#include <string.h>
// 宏定义 *******************************************************************
#define N 100 // 通讯录容量
#define NAMELEN 22 // 姓名长度
#define NUMLEN 12 // 号码长度
//********* 定义部分 ********************************************************
// 定义联系人的结构体
typedef struct {
// 联系人
char name[ NAMELEN ];
// 号码
char telNum[ NUMLEN ];
}Person;
// 存储所有联系人,联系人数组
Person contacts[ N ]; // 能够存储 100 个联系人
// 定义联系人个数
int totalContactCount = 0 ;
// 接收用户输入的编号
int fno;
// 定义数据文件保存的位置
char *filePath = "telbook.data" ;
//*********** 函数声明部分 ***************************************************
int valitataInput( int num, int min, int max); // 合法输入
void doAdd(); // 添加
void doDelete(); // 删除
void doUpdata(); // 修改
void doList(); // 显示联系人
void doSearchByName(); // 搜索
void init(); // 初始化
void writeFile(); // 写数据到文件
// 主函数 *******************************************************************
int main( int argc, const char * argv[]) {
/*
1 、引入头文件
2 、进行必要的宏定义
3 、定义文件名称变量、联系人数组、联系人结构体
4 、定义函数,并进行声明
5 、编写循环控制程序
6 、现实操作界面
7 、根据编号执行不同的函数
*/
init ();
printf ( " 通讯录初始化完成! \n" );
while ( 1 ) {
printf ( "\n" );
// 软件的界面显示出来,死循环控制不停地输入
printf ( "**************************\n" );
printf ( "****** 欢迎使用通讯录 ******\n" );
printf ( "****** 1 、添加联系人 ******\n" );
printf ( "****** 2 、删除联系人 ******\n" );
printf ( "****** 3 、修改联系人 ******\n" );
printf ( "****** 4 、查看所有联系人 ****\n" );
printf ( "****** 5 、搜素联系人 ******\n" );
printf ( "****** 6 、退出系统 ******\n" );
printf ( "**************************\n" );
// 提示用户选择一个序号
printf ( " 请选择 1~6 之间的功能编号: \n" );
scanf ( "%d" , & fno );
// 判断编号是否合法,最好写个函数
valitataInput ( fno , 1 , 6 );
// 做不同的事情,定义不同的函数
switch ( fno ) {
case 1 :
// 执行添加
doAdd ();
break ;
case 2 :
// 执行删除
doDelete ();
break ;
case 3 :
// 执行修改
doUpdata ();
break ;
case 4 :
// 执行显示所有联系人
doList ();
break ;
case 5 :
// 执行搜索联系人
doSearchByName ();
break ;
case 6 :
printf ( " 系统正在退出 ...\n" );
printf ( " 系统已经退出! " );
return 0 ;
break ;
default :
break ;
}
}
return 0 ;
}
// 判断编号合法函数 **********************************************************
//min-1,max-6
int valitataInput( int num, int min, int max) {
if (num < min || num > max) {
printf("非法输入!");
return 1;
//
返回值
1
,使
while
继续执行
}
else
{
return 0 ;
}
}
// 添加联系人函数 ************************************************************
/*
1 、提示用户输入联系人姓名
2 、接收联系人
3 、提示用户输入电话号码
4 、接收电话号码
5 、确认添加
6 、联系人个数 +1
7 、把联系人信息写入文件中
*/
void doAdd() {
printf ( " 您选择的是添加联系人,请按提示操作: \n" );
// 1 、提示用户输入联系人姓名
printf ( " 请输入联系人姓名 : ( * 联系人姓名之间不能有空格) \n" );
// 2 、接收联系人
scanf ( "%s" , contacts [ totalContactCount ]. name );
// 3 、提示用户输入电话号码
printf ( " 请输入联系人号码 : ( * 联系人号码之间不能有空格) \n" );
// 4 、接收电话号码
scanf ( "%s" , contacts [ totalContactCount ]. telNum );
// 5 、确认添加
int flag;
printf ( " 您确认添加吗? 1. 确认 0. 取消 \n" );
scanf ( "%d" , &flag);
if (flag) {
// 6 、联系人个数 +1
totalContactCount ++;
// 7 、把联系人信息写入文件中
writeFile ();
}
}
// 删除联系人函数 ************************************************************
/*
1 、提示输入删除的联系人编号
2 、判断编号是否合法,编号不能大于联系人个数
3 、提示用户再次确认删除
4 、开始数组元素
1) 删除的元素正好是数组的最后一个元素
只需让联系人数量 -1
2 )如果删除的元素不是数组的最后一个元素
需移动元素
联系人数量 -1
5 、同步到文件中
*/
void doDelete() {
printf ( " 您选择的是删除联系人,请按提示操作: \n" );
doList ();
// 1 、提示输入删除的联系人编号
int no;
printf ( " 请输入要删除的联系人编号: \n" );
scanf ( "%d" , &no);
// 2 、判断编号是否合法,编号不能大于联系人个数
if ( valitataInput (no, 1 , totalContactCount )) {
return ;
}
// 3 、提示用户再次确认删除
int flag;
printf ( " 删除联系人后,数据无法恢复,您确认要删除吗? 1. 确认 0. 取消 \n" );
scanf ( "%d" , &flag);
if (flag) {
// 4 、开始删除数组元素
// 1) 删除的元素正好是数组的最后一个元素
// 只需让联系人数量 -1
if (no == totalContactCount ) {
totalContactCount --;
} else {
// 2 )如果删除的元素不是数组的最后一个元素
// 需移动元素
// 联系人数量 -1
for ( int i = no; i < totalContactCount ; i++) {
// 元素的移动和覆盖
contacts [no - 1 ] = contacts [no];
}
}
// 5 、同步到文件中
writeFile ();
}
}
// 修改联系人函数 ************************************************************
/*
1 、提示用户输入修改的信息编号
2 、验证编号是否合法
3 、输入新的用户名和新的电话号码
4 、让用户确认
5 、更新数组信息
*/
void doUpdata() {
printf ( " 您选择的是修改联系人,请按提示操作: \n" );
doList ();
// 1 、提示输入修改的联系人编号
int no;
printf ( " 请输入要修改的联系人编号: \n" );
scanf ( "%d" , &no);
// 2 、判断编号是否合法,编号不能大于联系人个数
if ( valitataInput (no, 1 , totalContactCount )) {
return ;
}
// 3 、输入新的用户名和新的电话号码
char newName[ NAMELEN ];
char newTel[ NAMELEN ];
printf ( " 请输入联系人新的姓名:( * 注意联系人姓名之间不能有空格) \n" );
scanf ( "%s" , newName);
printf ( " 请输入联系人心的电话:( * 注意联系人电话之间不能有空格) \n" );
scanf ( "%s" , newTel);
// 4 、让用户确认
int flag;
printf ( " 确认后,信息将永久修改,您确认要修改吗? 1. 确认 0. 取消 \n" );
scanf ( "%d" , &flag);
if (flag) {
// 5 、更新数组信息
strcpy ( contacts [no - 1 ]. name , newName);
strcpy ( contacts [no - 1 ]. telNum , newTel);
// 6 、写入到文件中
writeFile ();
}
}
// 显示联系人函数 ************************************************************
/*
如果文件存在则读取文件中的所有数据,遍历
1 、判断
totalContactCount == 0 表示没有联系人
2 、如果不等于 0
开始遍历,并且输出联系人的信息
*/
void doList() {
printf ( " 显示所有联系人,请按提示操作: \n" );
if ( totalContactCount == 0 ) {
printf ( " 您的通讯录还没有小伙伴 ~ 请添加小伙伴! \n" );
} else {
// 输出格式
printf ( " 编号 \t 姓名 \t 电话 \t\n" );
// 遍历联系人数组
for ( int i = 0 ; i < totalContactCount ; i++) {
printf ( "%d\t %s\t %s\t \n" , i+ 1 , contacts [i]. name , contacts [i]. telNum );
}
}
}
// 搜索联系人函数 ************************************************************
/*
根据联系人的姓名查找联系人
1 、提示用户输入要查找的联系人姓名
2 、遍历数组,查找此人
1 )输入的姓名和 contacts[i].name 比较
3 、查找到了,显示电话号码
4 、查找不到,提示查无此人
*/
void doSearchByName() {
printf ( " 您选择的是搜索联系人,请按提示操作: \n" );
//1 、提示用户输入要查找的联系人姓名
char searchName[ NAMELEN ];
printf ( " 请输入要查找的联系人姓名: \n" );
scanf ( "%s" , searchName);
// 遍历数组,查找此人
int i;
for (i = 0 ; i < totalContactCount ; i++) {
// 比较输入的姓名和 contacts[i].name 是否相等 返回值 ==0
if ( strcmp (searchName, contacts [i]. name ) == 0 ) {
// 打印此联系人对应的电话号
printf ( " 您搜索的联系人 %s 电话是: %s\n" , searchName, contacts [i]. telNum );
break ; // 查找到了,循环结束
}
}
// 查找不到,提示查无此人
if (i == totalContactCount ) {
printf ( " 查无此人!请看看是否输错! \n" );
}
}
// 通讯录初始化函数 **********************************************************
/*
1 、尝试性读取数据文件
2 、如果读取成功,说明文件存在
如果存在,要读取联系人数据,保存到联系人数组中 contacts
3 、如果读取失败,说明我们是第一次使用通讯录
如果第一次使用
1 )创建联系人数据文件
2 )把当前联系人的个数写入文件中 totalContactCount = 0
*/
void init() {
// 定义文件指针,并打开
FILE *fp = fopen ( filePath , "r" );
// 判断
if (fp != NULL ) {
// 第一步:读取联系人个数
fread (& totalContactCount , sizeof ( totalContactCount ), 1 , fp);
// 读取每一个联系人
for ( int i = 0 ; i < totalContactCount ; i++) {
// 读取每个联系人保存到联系人数组
fread (& contacts , sizeof ( Person ), 1 , fp);
}
} else {
// 创建文件
fp = fopen ( filePath , "wb" );
// 写入联系人个数
fwrite (& totalContactCount , sizeof ( totalContactCount ), 1 , fp);
printf ( " 通讯录文件创建成功 ~\n" );
}
fclose (fp);
}
// 写数据到文件 **************************************************************
/*
1 、以 wb 的方式打开
2 、先写联系人个数
3 、写每个联系人数据
*/
void writeFile() {
// 1 、以 wb 的方式打开
FILE *fp = fopen ( filePath , "wb" );
if (fp != NULL ) {
// 2 、先写联系人个数
fwrite (& totalContactCount , sizeof ( totalContactCount ), 1 , fp);
// 3 、写每个联系人数据
for ( int i = 0 ; i < totalContactCount ; i++) {
// 每次都写入一个数据的元素
fwrite (& contacts [i], sizeof ( Person ), 1 , fp);
}
printf ( " 写文件数据更新成功! \n" );
}
// 关闭文件指针
fclose (fp);
return 0 ;
}
}
// 添加联系人函数 ************************************************************
/*
1 、提示用户输入联系人姓名
2 、接收联系人
3 、提示用户输入电话号码
4 、接收电话号码
5 、确认添加
6 、联系人个数 +1
7 、把联系人信息写入文件中
*/
void doAdd() {
printf ( " 您选择的是添加联系人,请按提示操作: \n" );
// 1 、提示用户输入联系人姓名
printf ( " 请输入联系人姓名 : ( * 联系人姓名之间不能有空格) \n" );
// 2 、接收联系人
scanf ( "%s" , contacts [ totalContactCount ]. name );
// 3 、提示用户输入电话号码
printf ( " 请输入联系人号码 : ( * 联系人号码之间不能有空格) \n" );
// 4 、接收电话号码
scanf ( "%s" , contacts [ totalContactCount ]. telNum );
// 5 、确认添加
int flag;
printf ( " 您确认添加吗? 1. 确认 0. 取消 \n" );
scanf ( "%d" , &flag);
if (flag) {
// 6 、联系人个数 +1
totalContactCount ++;
// 7 、把联系人信息写入文件中
writeFile ();
}
}
// 删除联系人函数 ************************************************************
/*
1 、提示输入删除的联系人编号
2 、判断编号是否合法,编号不能大于联系人个数
3 、提示用户再次确认删除
4 、开始数组元素
1) 删除的元素正好是数组的最后一个元素
只需让联系人数量 -1
2 )如果删除的元素不是数组的最后一个元素
需移动元素
联系人数量 -1
5 、同步到文件中
*/
void doDelete() {
printf ( " 您选择的是删除联系人,请按提示操作: \n" );
doList ();
// 1 、提示输入删除的联系人编号
int no;
printf ( " 请输入要删除的联系人编号: \n" );
scanf ( "%d" , &no);
// 2 、判断编号是否合法,编号不能大于联系人个数
if ( valitataInput (no, 1 , totalContactCount )) {
return ;
}
// 3 、提示用户再次确认删除
int flag;
printf ( " 删除联系人后,数据无法恢复,您确认要删除吗? 1. 确认 0. 取消 \n" );
scanf ( "%d" , &flag);
if (flag) {
// 4 、开始删除数组元素
// 1) 删除的元素正好是数组的最后一个元素
// 只需让联系人数量 -1
if (no == totalContactCount ) {
totalContactCount --;
} else {
// 2 )如果删除的元素不是数组的最后一个元素
// 需移动元素
// 联系人数量 -1
for ( int i = no; i < totalContactCount ; i++) {
// 元素的移动和覆盖
contacts [no - 1 ] = contacts [no];
}
}
// 5 、同步到文件中
writeFile ();
}
}
// 修改联系人函数 ************************************************************
/*
1 、提示用户输入修改的信息编号
2 、验证编号是否合法
3 、输入新的用户名和新的电话号码
4 、让用户确认
5 、更新数组信息
*/
void doUpdata() {
printf ( " 您选择的是修改联系人,请按提示操作: \n" );
doList ();
// 1 、提示输入修改的联系人编号
int no;
printf ( " 请输入要修改的联系人编号: \n" );
scanf ( "%d" , &no);
// 2 、判断编号是否合法,编号不能大于联系人个数
if ( valitataInput (no, 1 , totalContactCount )) {
return ;
}
// 3 、输入新的用户名和新的电话号码
char newName[ NAMELEN ];
char newTel[ NAMELEN ];
printf ( " 请输入联系人新的姓名:( * 注意联系人姓名之间不能有空格) \n" );
scanf ( "%s" , newName);
printf ( " 请输入联系人心的电话:( * 注意联系人电话之间不能有空格) \n" );
scanf ( "%s" , newTel);
// 4 、让用户确认
int flag;
printf ( " 确认后,信息将永久修改,您确认要修改吗? 1. 确认 0. 取消 \n" );
scanf ( "%d" , &flag);
if (flag) {
// 5 、更新数组信息
strcpy ( contacts [no - 1 ]. name , newName);
strcpy ( contacts [no - 1 ]. telNum , newTel);
// 6 、写入到文件中
writeFile ();
}
}
// 显示联系人函数 ************************************************************
/*
如果文件存在则读取文件中的所有数据,遍历
1 、判断
totalContactCount == 0 表示没有联系人
2 、如果不等于 0
开始遍历,并且输出联系人的信息
*/
void doList() {
printf ( " 显示所有联系人,请按提示操作: \n" );
if ( totalContactCount == 0 ) {
printf ( " 您的通讯录还没有小伙伴 ~ 请添加小伙伴! \n" );
} else {
// 输出格式
printf ( " 编号 \t 姓名 \t 电话 \t\n" );
// 遍历联系人数组
for ( int i = 0 ; i < totalContactCount ; i++) {
printf ( "%d\t %s\t %s\t \n" , i+ 1 , contacts [i]. name , contacts [i]. telNum );
}
}
}
// 搜索联系人函数 ************************************************************
/*
根据联系人的姓名查找联系人
1 、提示用户输入要查找的联系人姓名
2 、遍历数组,查找此人
1 )输入的姓名和 contacts[i].name 比较
3 、查找到了,显示电话号码
4 、查找不到,提示查无此人
*/
void doSearchByName() {
printf ( " 您选择的是搜索联系人,请按提示操作: \n" );
//1 、提示用户输入要查找的联系人姓名
char searchName[ NAMELEN ];
printf ( " 请输入要查找的联系人姓名: \n" );
scanf ( "%s" , searchName);
// 遍历数组,查找此人
int i;
for (i = 0 ; i < totalContactCount ; i++) {
// 比较输入的姓名和 contacts[i].name 是否相等 返回值 ==0
if ( strcmp (searchName, contacts [i]. name ) == 0 ) {
// 打印此联系人对应的电话号
printf ( " 您搜索的联系人 %s 电话是: %s\n" , searchName, contacts [i]. telNum );
break ; // 查找到了,循环结束
}
}
// 查找不到,提示查无此人
if (i == totalContactCount ) {
printf ( " 查无此人!请看看是否输错! \n" );
}
}
// 通讯录初始化函数 **********************************************************
/*
1 、尝试性读取数据文件
2 、如果读取成功,说明文件存在
如果存在,要读取联系人数据,保存到联系人数组中 contacts
3 、如果读取失败,说明我们是第一次使用通讯录
如果第一次使用
1 )创建联系人数据文件
2 )把当前联系人的个数写入文件中 totalContactCount = 0
*/
void init() {
// 定义文件指针,并打开
FILE *fp = fopen ( filePath , "r" );
// 判断
if (fp != NULL ) {
// 第一步:读取联系人个数
fread (& totalContactCount , sizeof ( totalContactCount ), 1 , fp);
// 读取每一个联系人
for ( int i = 0 ; i < totalContactCount ; i++) {
// 读取每个联系人保存到联系人数组
fread (& contacts , sizeof ( Person ), 1 , fp);
}
} else {
// 创建文件
fp = fopen ( filePath , "wb" );
// 写入联系人个数
fwrite (& totalContactCount , sizeof ( totalContactCount ), 1 , fp);
printf ( " 通讯录文件创建成功 ~\n" );
}
fclose (fp);
}
// 写数据到文件 **************************************************************
/*
1 、以 wb 的方式打开
2 、先写联系人个数
3 、写每个联系人数据
*/
void writeFile() {
// 1 、以 wb 的方式打开
FILE *fp = fopen ( filePath , "wb" );
if (fp != NULL ) {
// 2 、先写联系人个数
fwrite (& totalContactCount , sizeof ( totalContactCount ), 1 , fp);
// 3 、写每个联系人数据
for ( int i = 0 ; i < totalContactCount ; i++) {
// 每次都写入一个数据的元素
fwrite (& contacts [i], sizeof ( Person ), 1 , fp);
}
printf ( " 写文件数据更新成功! \n" );
}
// 关闭文件指针
fclose (fp);
}