通讯录-第三版

Posted 午饭要阳光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通讯录-第三版相关的知识,希望对你有一定的参考价值。

第一版中:

        我们开辟了一个有1000个元素的结构体数组来保存通讯录的信息,这种方式有一个缺点,当通讯录中存储的联系人比较少时会造成内存资源的浪费。


第二版中:

        我们采用动态内存的方式去开辟数组,并且根据联系人个数的增加,而不断的增长这块存储空间,这样就避免了内存浪费的现象。但是这个版本还是有一些问题,就是当程序运行起来保存的信息到程序结束就被销毁,下一次程序运行起来的时候我们又要重新输入。

       

        为此我们引入第三个版本,使用文件的方式去保存这些信息。当程序运行起来时,会自动从文件中读取这些信息并加载到结构体数组中,当程序结束时,又将结构体数组中的信息写入文件中

#define _CRT_SECURE_NO_WARNINGS 1

#ifndef  __ADDRESSBOOK_H__           //使用条件编译,防止重复引入头文件

#define  __ADDRESSBOOK_H__

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define  NAME_MAX 20
#define  SEX_MAX 6
#define  TELE_MAX 20
#define  ADDR_MAX 40
#define INIT_SIZE 2
#define ADD_SIZE 10


typedef enum choice
{
	EXIT,
	ADD,
	DELETE,
	CHANGE,
	FIND,
	INIT,
	OUTPUT,
	SORT
}choice;


typedef struct                     //定义一个信息的结构体类型
{
	char name[NAME_MAX];
	char sex[SEX_MAX];
	int age;
	char tele[TELE_MAX];
	char address[ADDR_MAX];

}infor;

typedef struct                           //创建一个顺序表
{
	infor *data;
	int i;                               //表示联系人个数
	int size;                            //表示开辟空间的容量
}sequence;


void Add(sequence *book);
void delete(sequence *book, char *names);
void change(sequence *book, char *names);
void output(sequence const *book);
void init(sequence *book);
void sort(sequence *book);
void find(sequence *book, char *names);
void save_addressbook(sequence *book);         //向文件里面写入信息
void load_addressbook(sequence *book);         //从文件中读取信息
void memory(sequence *book);                   //动态内存开辟函数

#endif







//函数实现
#include"addressbook.h"

int find_place(sequence *book, char *names)
{
	int n = 0;
	while (n < book->i)
	{
		if (strcmp(book->data[n].name, names) == 0)
			break;
		n++;
	}
	if (n != book->i)
		return n;                       //如果找到则返回这个位置
	return -1;                           //没找到返回-1
}

void find(sequence *book, char *names)
{
	int ret = find_place(book, names);
	if (ret == -1)
		printf("查询无果\n");
	else
		printf("名字:%s 性别: %s 年龄: %d 电话: %s 地址: %s\n",
		book->data[ret].name,
		book->data[ret].sex,
		book->data[ret].age,
		book->data[ret].tele,
		book->data[ret].address);
}

void memory(sequence *book)
{
	infor *p = NULL;
	if (book->size == 0)                  //如果当前没有开辟空间,则开辟一块空间
	{
		p = (infor *)malloc(INIT_SIZE*sizeof(infor));
		if (p == NULL)
			exit(1);
		else
			book->data = p;
		book->size = INIT_SIZE;             
	}
	if (book->i == (book->size - 1))          //如果空间不够,则进行扩容
	{

		p = (infor *)realloc(book->data, (book->size = +ADD_SIZE)*sizeof(infor));
		if (p== NULL)
			exit(1);
		else
			book->data = p;
	}
}
void Add(sequence *book)
{
	memory(book);
	printf("请输入名字:");
	scanf("%s", book->data[book->i].name);
	printf("请输入性别:");
	scanf("%s", book->data[book->i].sex);
	printf("请输入年龄:");
	scanf("%d", &book->data[book->i].age);
	printf("请输入电话:");
	scanf("%s", book->data[book->i].tele);
	printf("请输入地址:");
	scanf("%s", book->data[book->i].address);
	++book->i;
	printf("添加成功\n");
}


void delete(sequence *book, char *names)
{
	if (book->i <= 0)
	{
		printf("通讯录已空\n");
	}
	else
	{
		int n = 0;
		n = find_place(book, names);                       //根据名字查找
		if (n< 0)
		{
			printf("没有此人\n");
		}
		else
		{
			book->data[n] = book->data[book->i - 1];//如果找到,则将最后一条记录放到这个位置
			book->i--;                     //删除一个,则记录位置的book->i也要减一
			printf("删除成功\n");
		}
	}
}

void change(sequence *book, char *names)
{
	int ret = 0;
	ret = find_place(book, names);              //先找到这个人的位置
	if (ret == -1)
	{
		printf("没有此人\n");
	}
	else
	{
		printf("请输入名字:");
		scanf("%s", book->data[ret].name);
		printf("请输入性别:");
		scanf("%s", book->data[ret].sex);
		printf("请输入年龄:");
		scanf("%d", &book->data[ret].age);
		printf("请输入电话:");
		scanf("%s", book->data[ret].tele);
		printf("请输入地址:");
		scanf("%s", book->data[ret].address);
		printf("修改成功\n");
	}
}


void output(sequence const *book)
{
	if (book->i <= 0)
	{
		printf("通讯录为空\n");
	}
	else
	{
		int n = 0;
		printf("%5s %5s %5s %11s %11s\n", "名字", "性别", "年龄", "电话", "地址");
		while (n < book->i)
		{
			printf("%5s %5s %5d %11s %11s\n",
				book->data[n].name,
				book->data[n].sex,
				book->data[n].age,
				book->data[n].tele,
				book->data[n].address);
			n++;
		}

	}
}



void init(sequence *book)
{
	book->i = 0;            //只要将记录位置的book->i置0
	printf("初始化成功\n");
}



void sort(sequence *book)
{
	if (book->i >1)                  //当通讯录中有1个以上记录再进行排序
	{
		int i = 0;
		int j = 0;
		int flag = 0;
		for (i = 0; i < book->i - 1; i++)
		{
			flag = 1;
			for (j = 0; j < book->i - i - 1; j++)
			{
				if (strcmp(book->data[j].name, book->data[j + 1].name) > 0)  //根据名字进行排序
				{
					infor tmp = book->data[j];
					book->data[j] = book->data[j + 1];
					book->data[j + 1] = tmp;
					flag = 0;
				}        //if 结束
			}
			if (flag)     //如果已经有序,则flag为真
				break;
		}
	}
	printf("排序成功\n");
}




void save_addressbook(sequence *book)
{
	int i = 0;
	FILE *pfwrite = fopen("test.txt","w");  //首先打开文件 
	if (pfwrite == NULL)
	{
		perror("open file pfwrite");
		exit(EXIT_FAILURE);
	}
	for (i = 0; i < book->i; i++)                                //将当前结构体数组中的信息全部写入
	{
		fwrite(&(book->data[i]), sizeof(infor), 1, pfwrite);     //使用二进制流的方式写入
	}
	fclose(pfwrite);                                              //关闭文件
}


void load_addressbook(sequence *book)
{
	int n = 0;
	infor tmp = { 0 };                           //创建临时变量用来保存每次读取的信息
	FILE *pfread = fopen("test.txt", "r");       //首先打开文件 (test.txt 自己在当前目录底下创建)
	if (pfread == NULL)
	{
		perror("open file pfread");
		exit(EXIT_FAILURE);
	}
	while (fread(&tmp, sizeof(infor), 1, pfread))  //每次读取一条信息,当读取完成后,fread返回0
	{
		memory(book);                              //要加载信息首先要开辟内存,或者内存不够时就要扩容
		book->data[n] = tmp;
		n++;
		book->i++;                              //同时book->i也要增长
	}
	fclose(pfread);
}










#include"addressbook.h"

void meau()
{
	printf("*******************************\n");
	printf("*0.exit              1.Add    *\n");
	printf("*2.deletel           3.change *\n");
	printf("*4.find              5.init   *\n");
	printf("*6.output            7.sort   *\n\n");
}
void execute(sequence *book)
{
	load_addressbook(book);
	char name[20];
	while (1)
	{
		int n = 0;
		meau();
		printf("请选择:");
		scanf("%d", &n);
		switch (n)
		{
		case EXIT:
			save_addressbook(book);
			free(book->data);
			exit(1);
			break;
		case ADD:
			Add(book);
			break;
		case DELETE:
			printf("请输入姓名:");
			scanf("%s", name);
			delete(book, name);
			break;
		case CHANGE:
			printf("请输入姓名:");
			scanf("%s", name);
			change(book, name);
			break;
		case FIND:
			printf("请输入姓名:");
			scanf("%s", name);
			find(book, name);
			break;
		case INIT:
			init(book);
			break;
		case OUTPUT:
			output(book);
			break;
		case SORT:
			sort(book);
			break;
		default:
			printf("选择无效\n");
			break;
		}
	}

}

int main()
{
	sequence book;
	book.i = 0;
	book.size = 0;
	book.data = NULL;
	execute(&book);
	system("pause");
	return 0;
}

以上是关于通讯录-第三版的主要内容,如果未能解决你的问题,请参考以下文章

关于阮一峰老师es6(第三版)中管道机制代码的理解浅析

《第一行代码》 第三版 - 第三章(笔记)

第一行代码 Android 第三版读后感

《unix环境高级编程·第三版》源代码编译及使用

unix网络编程第三版源代码ubuntu下配置的问题解决

笨办法学 Python(第三版)习题 18: 命名变量代码函数