目录
一.简介
现在通讯录系统非常多,网上一找一大堆。但是写法却有不同,我这个通讯录是采用动态内存开辟的方式将信息存入文件中,下次进入系统可以从文件中读取信息,系统包含插入,删除,查找,修改,排序,打印等功能。非常适合初学者练手。
二.详解
为了增强代码可读性我将项目分为三个模块,头文件,函数实现,主函数三部分。头文件主要是包含头文件,定义全局变量,函数声明。函数实现部分只写函数的实现。主函数就只有主函数。
所谓的通讯录说简单点就是一个结构体数组,这个结构体包含一个人的信息。所以首先要定义好结构体。
typedef struct PeoInfo {//一个人的信息
char stunum[10];
char name[10];
int age;
char sxe[3];
char tell[12];
char QQ[10];
} PeoInfo;
typedef struct Contact {
PeoInfo* data;//结构体数组
int sz;
int capacity;
}Contact;
主函数部分也就是实现一个菜单,能够实现功能选择。我采用枚举加do循环的方式实现菜单功能的选择。没什么可说的。下面我将重点介绍接口的实现。
1.通讯录初始化
初始化实现的功能就是动态开辟空间给通讯录结构体内的变量赋初值然后加载文件中存储的信息需要调用加载接口。
//初始化
void InitContact(Contact* pc) {
pc->data = (PeoInfo*)calloc(sizeof(PeoInfo) * 3,sizeof(PeoInfo));
pc->capacity = 3;
pc->sz = 0;
if (pc->data == NULL) {
perror("InitContact::calloc");
return;
}
LoodPeoInfo(pc);
}
2.加载信息
因为信息存储在文件中,所以需要打开文件然后fscanf读出文件中的信息放入结构体数组中同时要考虑容量问题。判断读取结束就是看fscanf的返回值,这个返回值是读取的有效元素 的个数。
//加载文件中信息
void LoodPeoInfo(Contact* pc) {
int count = 0;
FILE* p = fopen("test.txt", "r");
if (p == NULL) {
perror("open file for read");
return;
}
else {
while (1) {
if ((pc->sz) == (pc->capacity)) {
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + 2));
pc->capacity += 2;
if (ptr != NULL) {
pc->data = ptr;
}
else {
perror("AddInfor::realloc");
return;
}
}
count = fscanf(p, "%10s%5s%5d%5s%12s%12s\n", pc->data[pc->sz].stunum, pc->data[pc->sz].name,
&(pc->data[pc->sz].age), pc->data[pc->sz].sxe, pc->data[pc->sz].tell, pc->data[pc->sz].QQ);
if (count != 6) {
break;
}
(pc->sz)++;
}
}
fclose(p);
p = NULL;
}
3.添加
添加信息首先要判断通讯录的容量,不够了要增容,然后再scanf从键盘输入要存储的信息存入结构体数组中。
//增加信息
void AddInfor(Contact* pc) {
if ((pc->sz) == (pc->capacity)) {
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + 2));
pc->capacity += 2;
if (ptr != NULL) {
pc->data = ptr;
}
else {
perror("AddInfor::realloc");
return;
}
}
else {
printf("请输入学号:");
scanf("%s", (pc->data[pc->sz]).stunum);
printf("请输入姓名:");
scanf("%s", (pc->data[pc->sz]).name);
printf("请输入年龄:");
scanf("%d", &((pc->data[pc->sz]).age));
printf("请输入性别:");
scanf("%s", (pc->data[pc->sz]).sxe);
printf("请输入电话:");
scanf("%s", (pc->data[pc->sz]).tell);
printf("请输入QQ:");
scanf("%s", (pc->data[pc->sz]).QQ);
pc->sz++;
printf("添加成功\n");
}
}
4.查找
查找你先要输入查找人的一些信息,然后再在结构体数组中找符合条件的元素。
//查找
int Search(Contact* pc) {
char stu[10] = { 0 };
int k = pc->sz;
if (k == 0) {
printf("通讯录为空\n");
return 1;
}
else {
printf("请输入要查找的人的编号:");
scanf("%s", stu);
while (k) {
if (strcmp((pc->data[k - 1]).stunum, stu) == 0) {
printf("%10s %5s %5s %5s %12s %12s\n", "学号", "姓名", "年龄", "性别", "电话", "QQ");
printf("%10s %5s %5d %5s %12s %12s\n",
pc->data[k - 1].stunum, pc->data[k - 1].name,
pc->data[k - 1].age, pc->data[k - 1].sxe,
pc->data[k - 1].tell, pc->data[k - 1].QQ);
/*ShowInfor(pc);*/
return k;
}
k--;
}
if (k == 0) {
printf("查无此人\n");
return 0;
}
}
return 1;
}
5.删除
删除首先要找到要删除的人的信息,然后在删除。所以要写一个子函数专门查找,也可以复用上面的查找函数。
int MySearchForDel(Contact* pc) {
char stu[10] = { 0 };
int k = pc->sz;
if (k == 0) {
printf("通讯录为空\n");
return 1;
}
else {
printf("请输入要删除的人的编号:");
scanf("%s", stu);
while (k) {
if (strcmp((pc->data[k - 1]).stunum, stu) == 0) {
return k;
}
k--;
}
if (k == 0) {
printf("无此人\n");
return 0;
}
}
return 1;
}
//删除
void DelInfor(Contact* pc) {
int S = MySearchForDel(pc);
if (S != 0) {
for (int i = S - 1; i < pc->sz - 1; i++) {
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
ShowInfor(pc);
}
}
6.打印
代码如下
//打印
void ShowInfor(Contact* pc) {
int i = 0;
printf("%10s %5s %5s %5s %12s %12s\n", "学号", "姓名", "年龄", "性别", "电话", "QQ");
for (i = 0; i < pc->sz; i++) {
printf("%10s %5s %5d %5s %12s %12s\n",
pc->data[i].stunum, pc->data[i].name,
pc->data[i].age, pc->data[i].sxe,
pc->data[i].tell, pc->data[i].QQ);
}
}
7.修改
修改和删除差不多都要先找到要修改的人的信息,然后再从新输入这个人的信息,达到修改的目的。
int MySearchForMod(Contact* pc) {
char stu[10] = { 0 };
int k = pc->sz;
if (k == 0) {
printf("通讯录为空\n");
return 1;
}
else {
printf("请输入要修改的人的编号:");
scanf("%s", stu);
while (k) {
if (strcmp((pc->data[k - 1]).stunum, stu) == 0) {
return k;
}
k--;
}
if (k == 0) {
printf("无此人\n");
return 0;
}
}
return 1;
}
//修改
void ModifyInfor(Contact* pc) {
int S = MySearchForMod(pc);
if (S != 0) {
printf("请输入学号:");
scanf("%s", (pc->data[S - 1]).stunum);
printf("请输入姓名:");
scanf("%s", (pc->data[S - 1]).name);
printf("请输入年龄:");
scanf("%d", &((pc->data[S - 1]).age));
printf("请输入性别:");
scanf("%s", (pc->data[S - 1]).sxe);
printf("请输入电话:");
scanf("%s", (pc->data[S - 1]).tell);
printf("请输入QQ:");
scanf("%s", (pc->data[S - 1]).QQ);
printf("修改成功\n");
ShowInfor(pc);
}
}
8.排序
首先你要确定按什么排序,怎么排。我是调用了qsort函数按编号给结构体数组排升序。比较的方法要自己写。
int compare(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->stunum, ((PeoInfo*)p2)->stunum);
}
//排序
void SortInfor(Contact* pc) {
if (pc->sz != 0) {
qsort((pc->data), pc->sz, sizeof(pc->data[0]), compare);
ShowInfor(pc);
}
else {
printf("通讯录为空\n");
}
}
9.保存信息
在退出之前把信息保存至文件中去。fprintf函数写入信息也可以用fwrite函数。
//退出之前把信息保存在文件
void SaveInfor(Contact* pc) {
FILE* p = fopen("test.txt", "w");
int i = 0;
if (p == NULL) {
perror("open file for write");
return;
}
else {
/*fwrite(pc->data, sizeof(PeoInfo), pc->sz, p);*/
for ( i = 0; i < pc->sz; i++) {
fprintf(p, "%10s%5s%5d%5s%12s%12s\n", pc->data[i].stunum,
pc->data[i].name, pc->data[i].age,
pc->data[i].sxe, pc->data[i].tell,
pc->data[i].QQ);
}
}
fclose(p);
p = NULL;
}
三.代码
1.memos.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include <assert.h>
typedef struct PeoInfo {
char stunum[10];
char name[10];
int age;
char sxe[3];
char tell[12];
char QQ[10];
} PeoInfo;
//typedef struct Contact {
// PeoInfo data[1000];
// int sz;
//}Contact;
typedef struct Contact {
PeoInfo* data;
int sz;
int capacity;
}Contact;
//增加信息
void AddInfor(Contact* pc);
//查找
int Search(Contact* pc);
//删除
void DelInfor(Contact* pc);
//打印
void ShowInfor(Contact* pc);
//修改
void ModifyInfor(Contact* pc);
//排序
void SortInfor(Contact* pc);
//初始化
void InitContact(Contact* pc);
//保存信息
void SaveInfor(Contact* pc);
2.test.c
#define _CRT_SECURE_NO_WARNINGS
#include "memos.h"
void menu() {
printf("******************************\n");
printf("****** 1.add 2.del *****\n");
printf("****** 3.search 4.modify***\n");
printf("****** 5.sort 6.show ****\n");
printf("****** 0.exit ****\n");
printf("******************************\n");
}
//枚举选择菜单的情况
enum IN {
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
SHOW
};
int main() {
menu();
Contact Con = { 0 };//创建通讯录
InitContact(&Con);//初始化
int input = 0;
do {
printf("请输入:");
scanf("%d", &input);
switch (input) {
case ADD:
AddInfor(&Con);
break;
case DEL:
DelInfor(&Con);
break;
case SEARCH:
Search(&Con);
break;
case MODIFY:
ModifyInfor(&Con);
break;
case SORT:
SortInfor(&Con);
break;
case SHOW:
ShowInfor(&Con);
break;
case EXIT:
SaveInfor(&Con);
break;
default:
printf("输入错误,请从新输入:");
break;
}
} while (input);
free(Con.data);
Con.data = NULL;
return 0;
}
3.body.c
#define _CRT_SECURE_NO_WARNINGS
#include "memos.h"
//加载文件中信息
void LoodPeoInfo(Contact* pc) {
int count = 0;
FILE* p = fopen("test.txt", "r");
if (p == NULL) {
perror("open file for read");
return;
}
else {
while (1) {
if ((pc->sz) == (pc->capacity)) {
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + 2));
pc->capacity += 2;
if (ptr != NULL) {
pc->data = ptr;
}
else {
perror("AddInfor::realloc");
return;
}
}
count = fscanf(p, "%10s%5s%5d%5s%12s%12s\n", pc->data[pc->sz].stunum, pc->data[pc->sz].name,
&(pc->data[pc->sz].age), pc->data[pc->sz].sxe, pc->data[pc->sz].tell, pc->data[pc->sz].QQ);
if (count != 6) {
break;
}
(pc->sz)++;
}
}
fclose(p);
p = NULL;
}
//初始化
void InitContact(Contact* pc) {
pc->data = (PeoInfo*)calloc(sizeof(PeoInfo) * 3,sizeof(PeoInfo));
pc->capacity = 3;
pc->sz = 0;
if (pc->data == NULL) {
perror("InitContact::calloc");
return;
}
LoodPeoInfo(pc);
}
//增加信息
void AddInfor(Contact* pc) {
if ((pc->sz) == (pc->capacity)) {
PeoInfo* ptr = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo) * (pc->capacity + 2));
pc->capacity += 2;
if (ptr != NULL) {
pc->data = ptr;
}
else {
perror("AddInfor::realloc");
return;
}
}
else {
printf("请输入学号:");
scanf("%s", (pc->data[pc->sz]).stunum);
printf("请输入姓名:");
scanf("%s", (pc->data[pc->sz]).name);
printf("请输入年龄:");
scanf("%d", &((pc->data[pc->sz]).age));
printf("请输入性别:");
scanf("%s", (pc->data[pc->sz]).sxe);
printf("请输入电话:");
scanf("%s", (pc->data[pc->sz]).tell);
printf("请输入QQ:");
scanf("%s", (pc->data[pc->sz]).QQ);
pc->sz++;
printf("添加成功\n");
}
}
//查找
int Search(Contact* pc) {
char stu[10] = { 0 };
int k = pc->sz;
if (k == 0) {
printf("通讯录为空\n");
return 1;
}
else {
printf("请输入要查找的人的编号:");
scanf("%s", stu);
while (k) {
if (strcmp((pc->data[k - 1]).stunum, stu) == 0) {
printf("%10s %5s %5s %5s %12s %12s\n", "学号", "姓名", "年龄", "性别", "电话", "QQ");
printf("%10s %5s %5d %5s %12s %12s\n",
pc->data[k - 1].stunum, pc->data[k - 1].name,
pc->data[k - 1].age, pc->data[k - 1].sxe,
pc->data[k - 1].tell, pc->data[k - 1].QQ);
/*ShowInfor(pc);*/
return k;
}
k--;
}
if (k == 0) {
printf("查无此人\n");
return 0;
}
}
return 1;
}
int MySearchForDel(Contact* pc) {
char stu[10] = { 0 };
int k = pc->sz;
if (k == 0) {
printf("通讯录为空\n");
return 1;
}
else {
printf("请输入要删除的人的编号:");
scanf("%s", stu);
while (k) {
if (strcmp((pc->data[k - 1]).stunum, stu) == 0) {
return k;
}
k--;
}
if (k == 0) {
printf("无此人\n");
return 0;
}
}
return 1;
}
//删除
void DelInfor(Contact* pc) {
int S = MySearchForDel(pc);
if (S != 0) {
for (int i = S - 1; i < pc->sz - 1; i++) {
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
ShowInfor(pc);
}
}
//打印
void ShowInfor(Contact* pc) {
int i = 0;
printf("%10s %5s %5s %5s %12s %12s\n", "学号", "姓名", "年龄", "性别", "电话", "QQ");
for (i = 0; i < pc->sz; i++) {
printf("%10s %5s %5d %5s %12s %12s\n",
pc->data[i].stunum, pc->data[i].name,
pc->data[i].age, pc->data[i].sxe,
pc->data[i].tell, pc->data[i].QQ);
}
}
int MySearchForMod(Contact* pc) {
char stu[10] = { 0 };
int k = pc->sz;
if (k == 0) {
printf("通讯录为空\n");
return 1;
}
else {
printf("请输入要修改的人的编号:");
scanf("%s", stu);
while (k) {
if (strcmp((pc->data[k - 1]).stunum, stu) == 0) {
return k;
}
k--;
}
if (k == 0) {
printf("无此人\n");
return 0;
}
}
return 1;
}
//修改
void ModifyInfor(Contact* pc) {
int S = MySearchForMod(pc);
if (S != 0) {
printf("请输入学号:");
scanf("%s", (pc->data[S - 1]).stunum);
printf("请输入姓名:");
scanf("%s", (pc->data[S - 1]).name);
printf("请输入年龄:");
scanf("%d", &((pc->data[S - 1]).age));
printf("请输入性别:");
scanf("%s", (pc->data[S - 1]).sxe);
printf("请输入电话:");
scanf("%s", (pc->data[S - 1]).tell);
printf("请输入QQ:");
scanf("%s", (pc->data[S - 1]).QQ);
printf("修改成功\n");
ShowInfor(pc);
}
}
int compare(const void* p1, const void* p2) {
return strcmp(((PeoInfo*)p1)->stunum, ((PeoInfo*)p2)->stunum);
}
//排序
void SortInfor(Contact* pc) {
if (pc->sz != 0) {
qsort((pc->data), pc->sz, sizeof(pc->data[0]), compare);
ShowInfor(pc);
}
else {
printf("通讯录为空\n");
}
}
//退出之前把信息保存在文件
void SaveInfor(Contact* pc) {
FILE* p = fopen("test.txt", "w");
int i = 0;
if (p == NULL) {
perror("open file for write");
return;
}
else {
/*fwrite(pc->data, sizeof(PeoInfo), pc->sz, p);*/
for ( i = 0; i < pc->sz; i++) {
fprintf(p, "%10s%5s%5d%5s%12s%12s\n", pc->data[i].stunum,
pc->data[i].name, pc->data[i].age,
pc->data[i].sxe, pc->data[i].tell,
pc->data[i].QQ);
}
}
fclose(p);
p = NULL;
}