C语言实现通讯录——有关文件操作介绍

目录

1.前言

2.部分重点解析

3.具体代码


1.前言

提到通讯录管理系统,想必各位如果是计算机相关专业的同学都曾经被这个结课作业或多或少的支配过,那么今天我们就透过这个通讯录管理系统来为大家简单剖析一下有关文件的操作。

2.部分重点解析

在介绍文件操作之前,我们先简单实现一下不含文件操作版本的通讯录。

(1):简易菜单逻辑实现

在实现通讯录的具体各项功能前,我们应当先把他的“骨架”实现,这样才有利于我们建立一个清晰的项目逻辑,更有利于后续功能的有序实现。基于我们之前提到过的模块化设计思想,我们将以下代码放在test.c文件中实现

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
void meum()
{
	printf("******************************\n");
	printf("** 1. add   2. del **\n");
	printf("** 3. search 4. modify **\n");
	printf("** 5. show  6. clear **\n");
	printf("** 7. sort  0. exit **\n");
	printf("******************************\n");
}

int main()
{
	int input = 0;
	Contact con;
	IntiContact(&con);
	do
	{
		meum();
		printf("请选择\n");
		scanf("%d", &input);
		switch (input)
		{
		case ADD://添加
			AddContact(&con);
			break;
		case DEL://删除
			DeleteContact(&con);
			break;
		case SEARCH://查找
			FindContact(&con);
			break;
		case MODIFY://修改
			ModifyContact(&con);
			break;
		case SHOW://展示
			ShowContact(&con);
			break;
		case CLEAR://清空
			ClearContact(&con);
			break;
		case SORT://排序
			SortContact(&con);
			break;
		case EXIT://退出
			printf("退出程序\n");
		    DestroyContact(&con);
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	}
	while (input);
	return 0;
}

有关以上代码我们还要结合contact.h这个头文件来看

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<errno.h>
#include<malloc.h>
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 20
#define ADDR_MAX 20
#define TELE_MAX 12
#define DEFAULT_SZ 3
enum Option//定义操作的枚举,比起用数字更直观
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	CLEAR,
	SORT
};
typedef struct PeoInfo//定义联系人信息的结构体
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char addr[ADDR_MAX];
	char tele[TELE_MAX];
}PeoInfo;

typedef struct Contact//嵌套定义通讯录结构体
{
	//PeoInfo data[MAX];
	PeoInfo* data;
	int sz;//当前人数
	int capacity;//最大容量
}Contact;

void IntiContact(Contact* pc);
void AddContact(Contact* pc);
void ShowContact(const Contact* pc);
void DeleteContact(Contact* pc);
void FindContact(Contact* pc);
void ModifyContact(Contact* pc);
void ClearContact(Contact* pc);
void SortContact(Contact* pc);
void DestroyContact(Contact* pc);

为什么我们需要这个头文件呢?答案是为了代码的后期维护,这样我们所实现的函数或者有关宏定义只需要全部存放在这里面,我们需要用到的时候就只需要引这一个我们自己的头文件就好,不需要重复引用,减少了代码冗余,同时我们如果需要修改某些定义时也可以直接在此修改,更利于我们的代码维护。

接下来我们进入最关键的核心函数实现,该代码我们存放于contact.c文件下

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h";

void CheckCapacity(Contact* pc)//检测通讯录是否已满
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity * 2) * (sizeof(PeoInfo)));//增容操作
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity *= 2;
			printf("增容成功\n");
		}
	}
}

void IntiContact(Contact* pc)//初始化
{
	assert(pc);
	pc->sz = 0;
	pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (pc->data == NULL) //检查分配是否成功
	{
		printf("%s\n", strerror(errno));
		return;
	}
	pc->capacity = DEFAULT_SZ;
}


void AddContact(Contact* pc)
{
	assert(pc);
	CheckCapacity(pc);
	printf("请输入姓名\n");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄\n");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别\n");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话\n");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址\n");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("添加成功\n");
}

void ShowContact(const Contact* pc)
{
	assert(pc);//确保传入参数有效
	if (pc->sz == 0)
	{
		printf("当前通讯录为空\n");
		return;
	}
	int i = 0;
	printf("%-10s\t%-5s\t%-5s\t%-13s\t%-20s\t\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5d\t%-5s\t%-13s\t%-20s\t\n", 
			pc->data[i].name,pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

int FindByname(const Contact* pc,char name[])//搜索
{
	for(int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DeleteContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录已空,删除失败\n");
		return;
	}
	printf("请输入待删除联系人姓名\n");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("该联系人不存在\n");
	}
	else
	{
		for (int j = 0; j < pc->sz - 1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("删除成功\n");
	}
}

void FindContact(Contact* pc)
{
	int i = 0;
	char name[NAME_MAX] = { 0 };
	int pos = 0;
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录已空,无法查找\n");
		return;
	}
		printf("请输入要查找人的名字:>");
	    scanf("%s", name);
		pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要查找的条目不存在\n");
		return;
	}
	printf("%15s\t%5s\t%5s\t%12s\t%20s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%15s\t%5d\t%5s\t%12s\t%20s\n", pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);
}

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	int pos = 0;
	if (pc->sz == 0)
	{
		printf("通讯录已空,无法修改\n");
		return;
	}
	printf("请输入要修改的联系人姓名\n");
	scanf("%s", name);
	pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要修改的联系人不存在,修改失败\n");
		return;
	}
	printf("请输入要修改什么信息(1-名字,2-年龄,3-性别,4-电话,5-住址):>");
	int msg = 0;
	scanf("%d", &msg);
	switch (msg)
	{
	case 1:
		printf("请输入新的姓名:>");
		scanf("%s", pc->data[pos].name);
		break;
	case 2:
		printf("请输入新的年龄:>");
		scanf("%d", &pc->data[pos].age);
		break;
	case 3:
		printf("请输入新的性别:>");
		scanf("%s", pc->data[pos].sex);
		break;
	case 4:
		printf("请输入新的电话:>");
		scanf("%s", pc->data[pos].tele);
		break;
	case 5:
		printf("请输入新的地址:>");
		scanf("%s", pc->data[pos].addr);
		break;
	default:
		printf("输入有误,修改失败\n");
		return;
	}
	printf("修改成功\n");
}

void ClearContact(Contact* pc)
{
	assert(pc);
	IntiContact(pc);
	printf("初始化成功\n");
}

void SortContact(Contact* pc)//通讯录排序
{
	PeoInfo tmp;
	for (int i = 0; i < pc->sz - 1; i++)//此处采用冒泡排序,也可换用效率更高的快排
	{
		for (int j = 0; j < pc->sz - i - 1; j++)
		{
			if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
			{
				tmp = pc->data[j];
				pc->data[j] = pc->data[j + 1];
				pc->data[j + 1] = tmp;
			}
		}
	}
	printf("排序完成\n");
}

void DestroyContact(Contact* pc)//退出通讯录后释放内存,避免内存泄漏
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

有关核心函数的实现大家可参照上述参考代码和注释,但是在上述通讯录完成后,我们可以发现一个问题,在退出程序后通讯录内的信息也随着内存的释放被销毁了,那么我们该如何令他在退出程序后依然存储有关信息呢?这时我们就需要用到文件操作了。

首先我们需要实现一个保存函数在程序退出之前执行

void SaveContact(Contact* pc)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return ;
	}
	for (int i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
	}
	fclose(pf);//关闭文件
	pf = NULL;//防止野指针
}

我们先看到fopen函数的参数

FILE *fopen(char *filename, *type);

首先关于他的返回值:

如果成功的打开一个文件, fopen()函数返回文件指针,   否则返回空指针 (NULL)。由此可判断文件打开是否成功,所以这里我们要先判断指针是否为空。

然后看到第一个参数:

fopen()函数中第一个形式参数表示文件名, 可以包含路径和文件名两部分。

第二个参数:

 第二个形式参数表示打开文件的类型。关于文件类型的规定参见下表。

  1. 表   文件操作类型

  2. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  3. 字符                含义

  4. ────────────────────────────

  5. "r"           打开文字文件只读

  6. "w"           创建文字文件只写

  7. "a"           增补, 如果文件不存在则创建一个

  8. "r+"          打开一个文字文件读/写

  9. "w+"          创建一个文字文件读/写

  10. "a+"          打开或创建一个文件增补

  11. “rb+”        为了读和写打开一个二进制文件
  12. “wb+”      为了读和写,新建一个新的二进制文件
  13. “ab+”       打开一个二进制文件,在文件尾进行读和写

接下来我们看到fwrite函数

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 

他的四个参数含义如下:

第一个ptr是要写入的数据的头指针,无符号类型;

第二个参数size是大小,表示每个写入元素的大小,单位是字节;

第三个参数nmemb是个数,以上一个参数为单位的个数;

第四个参数stream就是文件指针,表示往哪里写。

至于返回值,如果成功执行,则返回写入元素的个数,如果不和nmemb相等,则表示出错。

 

之后我们又面临一个问题,在我们重新打开通讯录时,我们如何读取已保存的数据,这个过程我们通常称之为加载,其实我们只需要在原初始化函数稍加改造即可。

void IntiContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (pc->data == NULL) //检查分配是否成功
	{
		printf("%s\n", strerror(errno));
		return;
	}
	pc->capacity = DEFAULT_SZ;
//_____________________________________//

	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return;
	}
	PeoInfo buf = { 0 };
	while (fread(&buf, sizeof(PeoInfo), 1, pf))
	{
		CheckCapacity(pc);
		pc->data[pc->sz] = buf;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
	
}

 同样的我们看到fread函数

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

fread函数的作用是从文件里读内容到程序中,它的参数意思是:

第一个参数ptr表示盛放内容的首地址

第二个参数size表示每个元素的大小,单位还是字节

第三个参数nmem表示要读取的元素个数

第四个参数stream表示的是文件指针,即从哪个文件中读取

返回值则是表示读取元素的个数,与nmemb一致表示读取成功,否则失败

由于该函数操作与fread类似这里就不过多赘述了。

3.具体代码 

由于大部分代码在之前已经展示过,大家只需稍加改动即可,所以我们只放出最后的contact.c的文件代码。

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h";

void CheckCapacity(Contact* pc)
{
	if (pc->sz == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity * 2) * (sizeof(PeoInfo)));
		if (ptr != NULL)
		{
			pc->data = ptr;
			pc->capacity *= 2;
			printf("增容成功\n");
		}
	}
}

void IntiContact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
	if (pc->data == NULL) //检查分配是否成功
	{
		printf("%s\n", strerror(errno));
		return;
	}
	pc->capacity = DEFAULT_SZ;

	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return;
	}
	PeoInfo buf = { 0 };
	while (fread(&buf, sizeof(PeoInfo), 1, pf))
	{
		CheckCapacity(pc);
		pc->data[pc->sz] = buf;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
	
}


void AddContact(Contact* pc)
{
	assert(pc);
	CheckCapacity(pc);
	printf("请输入姓名\n");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄\n");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别\n");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话\n");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入地址\n");
	scanf("%s", pc->data[pc->sz].addr);

	pc->sz++;
	printf("添加成功\n");
}

void ShowContact(const Contact* pc)
{
	assert(pc);
	if (pc->sz == 0)
	{
		printf("当前通讯录为空\n");
		return;
	}
	int i = 0;
	printf("%-10s\t%-5s\t%-5s\t%-13s\t%-20s\t\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-10s\t%-5d\t%-5s\t%-13s\t%-20s\t\n", 
			pc->data[i].name,pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
	}
}

int FindByname(const Contact* pc,char name[])
{
	for(int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DeleteContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录已空,删除失败\n");
		return;
	}
	printf("请输入待删除联系人姓名\n");
	scanf("%s", name);
	int pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("该联系人不存在\n");
	}
	else
	{
		for (int j = 0; j < pc->sz - 1; j++)
		{
			pc->data[j] = pc->data[j + 1];
		}
		pc->sz--;
		printf("删除成功\n");
	}
}

void FindContact(Contact* pc)
{
	int i = 0;
	char name[NAME_MAX] = { 0 };
	int pos = 0;
	assert(pc);
	if (pc->sz == 0)
	{
		printf("通讯录已空,无法查找\n");
		return;
	}
		printf("请输入要查找人的名字:>");
	    scanf("%s", name);
		pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要查找的条目不存在\n");
		return;
	}
	printf("%15s\t%5s\t%5s\t%12s\t%20s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%15s\t%5d\t%5s\t%12s\t%20s\n", pc->data[pos].name,
		pc->data[pos].age,
		pc->data[pos].sex,
		pc->data[pos].tele,
		pc->data[pos].addr);
}

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	int pos = 0;
	if (pc->sz == 0)
	{
		printf("通讯录已空,无法修改\n");
		return;
	}
	printf("请输入要修改的联系人姓名\n");
	scanf("%s", name);
	pos = FindByname(pc, name);
	if (pos == -1)
	{
		printf("要修改的联系人不存在,修改失败\n");
		return;
	}
	printf("请输入要修改什么信息(1-名字,2-年龄,3-性别,4-电话,5-住址):>");
	int msg = 0;
	scanf("%d", &msg);
	switch (msg)
	{
	case 1:
		printf("请输入新的姓名:>");
		scanf("%s", pc->data[pos].name);
		break;
	case 2:
		printf("请输入新的年龄:>");
		scanf("%d", &pc->data[pos].age);
		break;
	case 3:
		printf("请输入新的性别:>");
		scanf("%s", pc->data[pos].sex);
		break;
	case 4:
		printf("请输入新的电话:>");
		scanf("%s", pc->data[pos].tele);
		break;
	case 5:
		printf("请输入新的地址:>");
		scanf("%s", pc->data[pos].addr);
		break;
	default:
		printf("输入有误,修改失败\n");
		return;
	}
	printf("修改成功\n");
}

void ClearContact(Contact* pc)
{
	assert(pc);
	IntiContact(pc);
	printf("初始化成功\n");
}

void SortContact(Contact* pc)
{
	PeoInfo tmp;
	for (int i = 0; i < pc->sz - 1; i++)
	{
		for (int j = 0; j < pc->sz - i - 1; j++)
		{
			if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
			{
				tmp = pc->data[j];
				pc->data[j] = pc->data[j + 1];
				pc->data[j + 1] = tmp;
			}
		}
	}
	printf("排序完成\n");
}

void DestroyContact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
}

void SaveContact(Contact* pc)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return ;
	}
	for (int i = 0; i < pc->sz; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
	}
	fclose(pf);
	pf = NULL;
}

那么本文到此结束,作者能力有限,文章如有纰漏请在评论区下方指正。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通讯录管理系统的设计与实现可以分成以下几个步骤: 1. 定义通讯录结构体 首先需要定义一个结构体来存储通讯录的信息,包括编号、姓名、性别、电话和公司名称等信息。可以定义如下结构体: ``` typedef struct AddressBook { char num[10]; char name[10]; char sex[10]; char phone[20]; char address[50]; } AddressBook; ``` 2. 编写主函数main() 主函数的功能是根据选单的选项调用各函数,并完成相应的功能。可以使用switch语句来实现: ``` int main() { int option; while(1) { Menu(); printf("请选择您要进行的操作:"); scanf("%d", &option); switch(option) { case 1: Create(); break; case 2: Add(); break; case 3: Find(); break; case 4: Alter(); break; case 5: Delete(); break; case 6: List(); break; case 7: Quit(); return 0; default: printf("请输入正确的选项!\n"); break; } } return 0; } ``` 3. 编写菜单函数Menu() 菜单函数的功能是显示提示选单,可以使用printf语句来实现: ``` void Menu() { 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("7. 退出系统\n"); } ``` 4. 编写退出函数Quit() 退出函数的功能是退出选单,可以使用exit()函数来实现: ``` void Quit() { printf("感谢使用通讯录管理系统!\n"); exit(0); } ``` 5. 编写创建函数Create() 创建函数的功能是创建新的数据记录,可以使用fopen()函数打开文件,并使用fwrite()函数写入数据: ``` void Create() { FILE *fp; fp = fopen("addressbook.dat", "wb"); if(fp == NULL) { printf("无法创建文件!\n"); return; } printf("创建成功!\n"); fclose(fp); } ``` 6. 编写增加函数Add() 增加函数的功能是增加新的数据记录,可以使用fopen()函数打开文件,并使用fwrite()函数写入数据: ``` void Add() { FILE *fp; AddressBook ab; fp = fopen("addressbook.dat", "ab"); if(fp == NULL) { printf("无法打开文件!\n"); return; } printf("请输入通讯者信息:\n"); printf("编号:"); scanf("%s", ab.num); printf("姓名:"); scanf("%s", ab.name); printf("性别:"); scanf("%s", ab.sex); printf("电话:"); scanf("%s", ab.phone); printf("公司名称:"); scanf("%s", ab.address); fwrite(&ab, sizeof(AddressBook), 1, fp); printf("添加成功!\n"); fclose(fp); } ``` 7. 编写查询函数Find() 查询函数的功能是按要求查询相关的信息,可以使用fopen()函数打开文件,并使用fread()函数读取数据,使用strcmp()函数比较字符串: ``` void Find() { FILE *fp; AddressBook ab; char name[10]; int flag = 0; fp = fopen("addressbook.dat", "rb"); if(fp == NULL) { printf("无法打开文件!\n"); return; } printf("请输入要查询的姓名:"); scanf("%s", name); while(fread(&ab, sizeof(AddressBook), 1, fp)) { if(strcmp(ab.name, name) == 0) { printf("编号:%s\n", ab.num); printf("姓名:%s\n", ab.name); printf("性别:%s\n", ab.sex); printf("电话:%s\n", ab.phone); printf("公司名称:%s\n", ab.address); flag = 1; break; } } if(flag == 0) { printf("文件中没有该信息!\n"); } fclose(fp); } ``` 8. 编写修改函数Alter() 修改函数的功能是修改某条记录的信息,可以使用fopen()函数打开文件,并使用fread()函数读取数据,使用strcmp()函数比较字符串,使用fseek()函数定位文件指针,使用fwrite()函数写入数据: ``` void Alter() { FILE *fp; AddressBook ab; char name[10]; int flag = 0; long offset; fp = fopen("addressbook.dat", "rb+"); if(fp == NULL) { printf("无法打开文件!\n"); return; } printf("请输入要修改的姓名:"); scanf("%s", name); while(fread(&ab, sizeof(AddressBook), 1, fp)) { if(strcmp(ab.name, name) == 0) { printf("请输入新的通讯者信息:\n"); printf("编号:"); scanf("%s", ab.num); printf("姓名:"); scanf("%s", ab.name); printf("性别:"); scanf("%s", ab.sex); printf("电话:"); scanf("%s", ab.phone); printf("公司名称:"); scanf("%s", ab.address); offset = ftell(fp) - sizeof(AddressBook); fseek(fp, offset, SEEK_SET); fwrite(&ab, sizeof(AddressBook), 1, fp); printf("修改成功!\n"); flag = 1; break; } } if(flag == 0) { printf("文件中没有该信息!\n"); } fclose(fp); } ``` 9. 编写删除函数Delete() 删除函数的功能是删除某条记录,可以使用fopen()函数打开文件,并使用fread()函数读取数据,使用strcmp()函数比较字符串,使用fseek()函数定位文件指针,使用fwrite()函数写入数据: ``` void Delete() { FILE *fp, *temp; AddressBook ab; char name[10]; int flag = 0; fp = fopen("addressbook.dat", "rb"); if(fp == NULL) { printf("无法打开文件!\n"); return; } temp = fopen("temp.dat", "wb"); if(temp == NULL) { printf("无法创建临时文件!\n"); return; } printf("请输入要删除的姓名:"); scanf("%s", name); while(fread(&ab, sizeof(AddressBook), 1, fp)) { if(strcmp(ab.name, name) == 0) { printf("删除成功!\n"); flag = 1; } else { fwrite(&ab, sizeof(AddressBook), 1, temp); } } if(flag == 0) { printf("文件中没有该信息!\n"); } fclose(fp); fclose(temp); remove("addressbook.dat"); rename("temp.dat", "addressbook.dat"); } ``` 10. 编写显示函数List() 显示函数的功能是显示所有记录,可以使用fopen()函数打开文件,并使用fread()函数读取数据: ``` void List() { FILE *fp; AddressBook ab; fp = fopen("addressbook.dat", "rb"); if(fp == NULL) { printf("无法打开文件!\n"); return; } printf("编号\t姓名\t性别\t电话\t\t\t公司名称\n"); while(fread(&ab, sizeof(AddressBook), 1, fp)) { printf("%s\t%s\t%s\t%s\t%s\n", ab.num, ab.name, ab.sex, ab.phone, ab.address); } fclose(fp); } ``` 11. 统计男女比例 统计男女比例的方法是在显示函数List()中添加统计代码: ``` void List() { FILE *fp; AddressBook ab; int male = 0, female = 0; fp = fopen("addressbook.dat", "rb"); if(fp == NULL) { printf("无法打开文件!\n"); return; } printf("编号\t姓名\t性别\t电话\t\t\t公司名称\n"); while(fread(&ab, sizeof(AddressBook), 1, fp)) { printf("%s\t%s\t%s\t%s\t%s\n", ab.num, ab.name, ab.sex, ab.phone, ab.address); if(strcmp(ab.sex, "男") == 0) { male++; } else if(strcmp(ab.sex, "女") == 0) { female++; } } printf("男性:%d人,女性:%d人\n", male, female); fclose(fp); } ``` 12. 显示同一公司中的人的信息 显示同一公司中的人的信息的方法是在查询函数Find()中添加统计代码: ``` void Find() { FILE *fp; AddressBook ab; char address[50]; int flag = 0; fp = fopen("addressbook.dat", "rb"); if(fp == NULL) { printf("无法打开文件!\n"); return; } printf("请输入要查询的公司名称:"); scanf("%s", address); while(fread(&ab, sizeof(AddressBook), 1, fp)) { if(strcmp(ab.address, address) == 0) { printf("编号:%s\n", ab.num); printf("姓名:%s\n", ab.name); printf("性别:%s\n", ab.sex); printf("电话:%s\n", ab.phone); printf("公司名称:%s\n", ab.address); flag = 1; } } if(flag == 0) { printf("文件中没有该信息!\n"); } fclose(fp); } ``` 至此,C语言通讯录管理系统的设计与实现就完成了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值