题目:通讯录管理程序

问题描述

编写一个简单的通讯录管理程序。通讯录记录有姓名,地址(省、市(县)、街道),电话号码,邮政编码等四项。

基本要求

程序应提供的基本基本管理功能有:

1) 添加:即增加一个人的记录到通信录中

2) 显示:即在屏幕上显示所有通信录中的人员信息,应能分屏显示。

3) 存储:即将通讯录信息保存在一个文件中。

4) 装入:即将文件中的信息读入程序。

5) 查询:可根据姓名查找某人的相关信息,若找到显示其姓名、地址、电话号码和邮政编码。

6) 修改:可修改一个人的除姓名外其它信息。

测试数据

程序应输入不少于10个人员的通讯录信息,应考虑到人员可以同名的情况。

实现提示

程序可用一个结构体数组、单向链表或对象数组来管理人员信息,每个人员的姓名,地址,电话号码和邮政编码用一个结构体或类实现。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define CHARMAX 30 typedef struct record {
char name[CHARMAX];
char phonenumber[11];
char address[3][CHARMAX]; //0-省 1-市 2-街道
char postcode[6];
struct record *next;
} RECORD; void PrintMenu(); void AlterString(RECORD *head); RECORD *InputRecord(RECORD *head, int *total); void PrintAllRecords(RECORD *head, const int *total); RECORD *DeleteRecord(RECORD *head,int *total); RECORD *ReviseRecord(RECORD *head); RECORD *SearchRecord(RECORD *head, int onlyOneRecord) ; RECORD *ImportRecords(RECORD *head, int *total); RECORD *ExportRecords(RECORD *head); int main() {
int total = 0, selection;
RECORD *head = NULL;
printf("Welcome to Directory Management System!\n");
printf("By XZ&YYM\n");
printf("---------------------------------------------\n"); do {
PrintMenu();
scanf("%d", &selection);
system("cls");
switch (selection) {
case 0:
break;
case 1:
head = InputRecord(head, &total);
break;
case 2:
PrintAllRecords(head, &total);
break;
case 3:
head = DeleteRecord(head,&total);
break;
case 4:
head = ReviseRecord(head);
break;
case 5:
SearchRecord(head,0);
break;
case 6:
head = ImportRecords(head,&total);
break;
case 7:
ExportRecords(head);
break;
default:
printf("\n\n-- Sorry!Please input 0-10!\n");
};
} while (selection != 0);
return 0;
} void PrintMenu() {
printf("\n");
printf("|1.Input record\n");
printf("|2.List all records\n");
printf("|3.Delete record\n");
printf("|4.Revise record\n");
printf("|5.Search record\n");
printf("|6.Import records from file\n");
printf("|7.Export records to file\n");
printf("|0.Exit\n");
printf("|Please input 0-7 to select function :");
} //功能:将字符串后的回车删掉
//入参:链表首地址
//出参:无
void AlterString(RECORD *head) {
int m;
RECORD *p1 = head; while (p1 != NULL) {
for (m = 0; m < CHARMAX; m++) {
if (*((p1->name) + m) == '\n') {
*((p1->name) + m) = '\0';
}
}
for (m = 0; m < 11; m++) {
if (*((p1->phonenumber) + m) == '\n') {
*((p1->phonenumber) + m) = '\0';
}
}
for (m = 0; m < CHARMAX; m++) {
if (*((p1->address[0]) + m) == '\n') {
*((p1->address[0]) + m) = '\0';
}
}
for (m = 0; m < CHARMAX; m++) {
if (*((p1->address[1]) + m) == '\n') {
*((p1->address[1]) + m) = '\0';
}
}
for (m = 0; m < CHARMAX; m++) {
if (*((p1->address[2]) + m) == '\n') {
*((p1->address[2]) + m) = '\0';
}
}
for (m = 0; m < 6; m++) {
if (*((p1->postcode) + m) == '\n') {
*((p1->postcode) + m) = '\0';
}
}
p1 = p1->next;
}
} //功能:连续输入数据
//入参:链表首地址,数据总数地址
//出参:链表首地址
RECORD *InputRecord(RECORD *head, int *total) {
int i = *total;
char inputChar;
RECORD *p = head, *input = (RECORD *) malloc(sizeof(RECORD)); printf("\n-- Start to Input Record\n"); //如果拥有数据,则输出现有数据总数
if (*total) {
printf("-- You have had %d records\n\n", *total);
} do {
//输入数据
printf("Input NO.%d Record`s Name:", i + 1);
fflush(stdin);
fgets(input->name, CHARMAX + 1, stdin);
printf("Input NO.%d Record`s Phone Number:", i + 1);
fflush(stdin);
fgets(input->phonenumber,CHARMAX + 1, stdin);
printf("Input NO.%d Record`s Address:\n", i + 1);
printf("- Input NO.%d Record`s Province:", i + 1);
fflush(stdin);
fgets(input->address[0], CHARMAX + 1, stdin);
printf("- Input NO.%d Record`s City:", i + 1);
fflush(stdin);
fgets(input->address[1], CHARMAX + 1, stdin);
printf("- Input NO.%d Record`s Street:", i + 1);
fflush(stdin);
fgets(input->address[2], CHARMAX + 1, stdin);
printf("- Input NO.%d Record`s Postcode:", i + 1);
fflush(stdin);
fgets(input->postcode, 7, stdin);
input->next = NULL; //插入时放于链表的最后 //插入数据,分为首数据和非首数据
if (head == NULL) {
head = input;
p = input;
} else {
while (p->next != NULL) {
p = p->next;
}
p->next = input;
} //增加数据计数
(*total)++; //询问是否继续
printf("\nDo you want to continue?(Y/N):");
scanf(" %c", &inputChar);
if (inputChar == 'Y' || inputChar == 'y') { //直接用getchar必须输入大写Y才能继续
//创建新的空间
input = (RECORD *) malloc(sizeof(RECORD));
i++;
} else {
break;
}
} while (1); //将字符串后面的回车删除
AlterString(head);
return head; } //功能:打印全部数据
//入参:链表首地址,数据总数地址
//出参:无
void PrintAllRecords(RECORD *head, const int *total) {
int page = 1, firstIndex = 0, i, pageAmount = *total / 10 + 1;
RECORD *p = head;
do {
system("cls"); //处理输入的数字过大或过小
if (page > pageAmount) {
printf("-- Sorry! The MAX of pages is %d\n", pageAmount);
} else if (page < 0) {
printf("-- Sorry! The number have to be positive\n");
} else {
//处理分页
firstIndex = 10 * (page - 1); printf("NO.\tName\tPhonenumber\tProvince\tCity\tStreet\tPostcode\t\n"); //处理前置数据
p = head;
for (i = 0; i < firstIndex; ++i) {
p = p->next;
} i = 0; //输出数据
while (p != NULL && i < 10) { //todo 大量数据可能出现问题
i++;
printf("NO.%d\t%s\t%s\t\t%s\t\t%s\t%s\t%s\t\n", i+firstIndex,p->name, p->phonenumber, p->address[0], p->address[1],
p->address[2],
p->postcode);
p = p->next;
}
printf("-- Page %d (Total %d pages)\n ", page, pageAmount);
} printf("-- Jump to page number (Input 0 to finish):");
scanf("%d", &page);
} while (page);
} //功能:删除某条数据
//入参:链表首地址
//出参:链表首地址
RECORD *DeleteRecord(RECORD *head,int *total) {
RECORD *p1 = head, *p2,*searchResult;
searchResult = SearchRecord(head, 1); while (p1 != NULL && p1 != searchResult) {
p2 = p1; //p2上一个节点
p1 = p1->next; //p1下一个节点
} if (p1 == head) {
head = p1->next;
free(p1);
(*total)--; //todo
printf("\n-- Success!\n");
} else if (p1 != NULL) {
p2->next = p1->next;
free(p1);
(*total)--;
printf("\n-- Success!\n");
} else {
printf("\n-- Do not find this id!\n");
}
return head; } //功能:输出某条数据
//入参:数据地址
//出参:无
void PrintOneRecord(RECORD *p) {
printf("Name:%s\tPhonenumber:%s\tProvince:%s\tCity:%s\tStreet::%s\tPostcode:%s\t\n", p->name, p->phonenumber,
p->address[0], p->address[1], p->address[2], p->postcode);
} //功能:更改数据
//入参:数据地址
//出参:无
RECORD *ReviseRecord(RECORD *head){
RECORD *p1 = head, *p2,*searchResult,*input = (RECORD *) malloc(sizeof(RECORD));
//返回需要更改的数组地址
searchResult = SearchRecord(head, 1);
if (!searchResult){
return head;
}
//输入数据
printf("\nInput the newRecord`s Name:");
fflush(stdin);
fgets(input->name, CHARMAX + 1, stdin);
printf("Input the newRecord`s Phone Number:");
fflush(stdin);
fgets(input->phonenumber,CHARMAX + 1, stdin);
printf("Input the Record`s Address:\n");
printf("- Input the newRecord`s Province:");
fflush(stdin);
fgets(input->address[0], CHARMAX + 1, stdin);
printf("- Input the newRecord`s City:");
fflush(stdin);
fgets(input->address[1], CHARMAX + 1, stdin);
printf("- Input the newRecord`s Street:");
fflush(stdin);
fgets(input->address[2], CHARMAX + 1, stdin);
printf("- Input the newRecord`s Postcode:");
fflush(stdin);
fgets(input->postcode, 7, stdin);
//插入时放于链表的最后
input->next = NULL; while (p1 != NULL && p1 != searchResult) {
p2 = p1; //p2上一个节点
p1 = p1->next; //p1下一个节点
}
if (p1 == head) {
head = input;
input->next = p1->next;
free(p1); //是否要释放?
printf("\n-- Success the Revise!\n");
} else if (p1 != NULL) {
p2->next = input;
input->next = p1->next;
free(p1);
printf("\n-- Success Revise!\n");
} else {
printf("\n-- Do not find this id!\n");
}
AlterString(head);
return head;
} //功能:搜索数据,并返回唯一搜索结果
//入参:链表首地址,是否要求返回唯一结果
//出参:数据地址
RECORD *SearchRecord(RECORD *head, int onlyOneRecord) {
int amount = 0, i = 0, selection = 0; //i,p1循环变量
char input[CHARMAX];
RECORD *p1 = head, *results[100] = {NULL}; //result是RECORD类型的指针数组 printf("\n-- Search the record:");
setbuf(stdin, NULL);
fgets(input, CHARMAX + 1, stdin); //去除字符串回车
for (i = 0; i < CHARMAX; ++i) {
if (*((input) + i) == '\n') {
*((input) + i) = '\0';
}
} //遍历搜索
while (p1 != NULL) {
if (strstr(p1->name, input) || //strstr()判断是否为子串
strstr(p1->phonenumber, input) ||
strstr(p1->address[0], input) ||
strstr(p1->address[1], input) ||
strstr(p1->address[2], input) ||
strstr(p1->postcode, input)) {
results[amount] = p1;
amount++;
}
p1 = p1->next;
} //若有多个结果,提示用户选择
if (amount > 1) {
printf("\n-- Search Result:\n");
for (i = 0; i < amount; i++) {
printf("NO.%d\t", i + 1);
PrintOneRecord(results[i]);
}
if (!onlyOneRecord) {
return NULL; //如果不需要去重,则返回NULL
}
printf("\n-- Input the number you want to change: ");
scanf("%d", &selection);
//处理输入数据不正确,默认返回第一个
if (selection - 1 > amount || selection < 0) {
printf("\n-- Wrong input (Choose the first record automatically)");
return results[0];
}
return results[selection - 1];
} else if (!amount) {
printf("\n-- Sorry! No result!");
return NULL;
} else {
printf("\n-- Search Result:\n");
PrintOneRecord(results[0]);
return results[0];
} } //功能:导入文件中的数据
//入参:链表首地址,总条数
//出参:数据地址
RECORD *ImportRecords(RECORD *head, int *total) {
int i = *total,m=3;
FILE *fpRead;
RECORD *p = head, *input; fpRead = fopen("stu.txt","r");
if(fpRead==NULL){
printf("can't open file\n");
return 0;
}
do {
//输入数据
input = (RECORD *) malloc(sizeof(RECORD));
fread(input, sizeof(struct record),1,fpRead);
input->next = NULL; //插入时放于链表的最后 //插入数据,分为首数据和非首数据
if (head == NULL) {
head = input;
p = input;
} else {
while (p->next != NULL) {
p = p->next;
}
p->next = input;
} //增加数据计数
(*total)++;
m--; } while (m); return head; } //功能:搜索数据,并返回唯一搜索结果
//入参:链表首地址,是否要求返回唯一结果
//出参:数据地址
RECORD *ExportRecords(RECORD *head){
FILE *fp;
struct record *p=head;
if((fp=fopen("stu.txt","wb"))==NULL)
{
printf("Fail to open the stu.txt!\n");
exit(0);
}
while(p != NULL)
{
fwrite(p, sizeof(struct record),1,fp);
p=p->next;
}
fclose(fp);
printf("you have save correctly!\n");
return 0;
}

  

C实现通讯录管理系统(亮点:纯链表实现、子串匹配,文件读写)的更多相关文章

  1. c语言实现通讯录管理系统(c课程设计)

    工具:Visual C++6.0 说明: 本系统基于C语言实现班级通讯录管理系统,为大一时学习C语言刚入门所做的课程设计.功能包括增.删.查.改等,非常适合初学者练手.通讯录包括的个人信息有姓名.学号 ...

  2. C++课程设计 通讯录管理系统 原码及解析

    设计题目:通信录管理系统 用C++设计出模拟手机通信录管理系统,实现对手机中的通信录进行管理. (一)功能要求 查看功能:选择此功能时,列出下列三类选择. A 办公类B 个人类C 商务类,当选中某类时 ...

  3. iOS学习之Object-C语言简单的通讯录管理系统

    用这几天学的OC的知识,写了一个实现简单功能的通讯录管理系统,在这里分享给大家: 通讯录管理系统 *  需求: 1.定义联系人类Contact.实例变量:姓名(拼音,首字母大写).性别.电话号码.住址 ...

  4. c++实现通讯录管理系统(控制台版)

    c++实现通讯录管理系统(控制台版) 此项目适合c++初学者,针对c++基础知识,涉及到变量.结构体定义使用.数组定义使用.指针定义使用等. 运行之后的结果如下: 代码: #include <i ...

  5. C++入门-控制台版的通讯录管理系统

    通讯录管理系统 1.系统需求 通讯录是一个可以记录亲人.好友信息的工具. 本教程主要利用C++来实现一个通讯录管理系统 系统中需要实现的功能如下: 添加联系人:向通讯录中添加新人,信息包括(姓名.性别 ...

  6. C++通讯录管理系统(添加联系人,显示联系人,删除联系人,查找联系人,修改联系人,清空联系人,退出通讯录)

    1 /** 2 * ProjectNmae:通讯录管理系统 3 * 功能: 4 * 添加联系人:向通讯录添加新人 5 * 显示联系人:显示通讯录中的所有联系人信息 6 * 删除联系人:按照姓名进行删除 ...

  7. c++—通讯录管理系统

    一.运用所学的结构体.地址指针等基础知识,完成通讯录管理系统 二.系统主要有以下6个功能: 1.添加联系人2.显示联系人 3.删除联系人 4.查找联系人5.修改联系人 6.清空联系人 1 #inclu ...

  8. ASP.NET MVC5+EF6+EasyUI 后台管理系统(56)-插件---单文件上传与easyui使用fancybox

    系列目录 https://yunpan.cn/cZVeSJ33XSHKZ  访问密码 0fc2 今天整合lightbox插件Fancybox1.3.4,发现1.3.4版本太老了.而目前easyui 1 ...

  9. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(32)-swfupload多文件上传[附源码]

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(32)-swfupload多文件上传[附源码] 文件上传这东西说到底有时候很痛,原来的asp.net服务器 ...

  10. 纯前端导出pdf文件

    纯前端js导出pdf,已经用于生产环境. 工具: 1.html2canvas,一种让html转换为图片的工具. 2.pdfmake或者jspdf ,一种生成.编辑pdf,并且导出pdf的工具. pdf ...

随机推荐

  1. linux tty终端个 pts伪终端 telnetd伪终端

    转:http://blog.sina.com.cn/s/blog_735da7ae0102v2p7.html 终端tty.虚拟控制台.FrameBuffer的切换过程详解 Framebuffer Dr ...

  2. cpp编码规范要求

    1.所有头文件使用#ifndef #define #endif来防止文件被多重包含,命名格式当是: <PROJECT>_<PATH>_<FILE>_H_ 2.只有当 ...

  3. java线程基础巩固---多线程与JVM内存结构的关系及Thread构造函数StackSize的理解

    继续学习一下Thread的构造函数,在上次[http://www.cnblogs.com/webor2006/p/7760422.html]已经对如下构造都已经学习过了: 多线程与JVM内存结构的关系 ...

  4. ogg12c 配置

    环境:source 192.168.2.182 : 系统:Windows Server 2012 oracle: Release 12.1.0.2.0 ogg: 12.2.0.2.3 target 1 ...

  5. 手摸手教你使用vue-cli脚手架-详细步骤图文解析[vue入门]

    写在前面: 使用 vue-cli 可以快速创建 vue 项目,vue-cli很好用,但是在最初搭建环境安装vue-cli及相关内容的时候,对一些人来说是很头疼的一件事情,本人在搭建vue-cli的项目 ...

  6. Hadoop-No.14之文件传输的特点

    文件传输特点 这是一种all-or-nothing批处理方法,所以如果文件传输过程中出现错误,则不会写入或读取任何数据.这种方法与Flume,Kafka之类的采集方法不同,后者提供一定程度的错误处理功 ...

  7. Python模拟浏览器前进后退操作

    # 模拟浏览器前进后退操作 # 代码中引入selenium版本为:3.4.3 # 通过Chrom浏览器访问发起请求 # Chrom版本:59 ,chromdriver:2.3 # 需要对应版本的Chr ...

  8. 常用NoSql数据库比较

    1. CouchDB 所用语言: Erlang 特点:DB一致性,易于使用 使用许可: Apache 协议: HTTP/REST 双向数据复制, 持续进行或临时处理, 处理时带冲突检查, 因此,采用的 ...

  9. Linux下nc或scp命令来实现文件传输

    很实用的小技巧, 可以使用nc或者是scp nc命令,转载自:https://www.cnblogs.com/xuybin/archive/2013/09/27/3343098.html 发送端:ca ...

  10. Confluence 6 评论一个文件

    无论是一个图片 —— 例如一个模拟的新市场计划需要反馈,还是一个 PDF 文件,一个演讲稿,或者任何你可以在 Confluence 中预览的文件.你可以在预览的的任何位置放置一个热点然后添加你的评论后 ...