通讯录——文件读写版本

通讯录最终版本——文件读写

  前面在暴躁小猿给大家分享了通讯录的静态版本和动态版本,但是这两个版本都不能实现文件的读写,每次运行程序都不能保存和读取数据,这样的通讯录是不完善的,根本没有办法去使用,所以为了满足需求,我们需要用对文件可以读写的通讯录,出于这个原因,通讯录最终版本就来了


在这里插入图片描述


一、头文件

代码如下(示例):

#define  _CRT_SECURE_NO_WARNINGS 1
#define max 3
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include <windows.h>

//初始化通讯录
void inicontact(struct contact* pc);
//添加联系人
void addpeople(struct contact* pc);
//删除联系人
void delpeople(struct contact* pc);
//展示联系人
void showpeople(struct contact* pc);
//查找联系人
void searchpeople(struct contact* pc);
//修改联系人
void revisepeople(struct contact* pc);
//联系人排序
void sortpeople(struct contact* pc);
//清除联系人
void deadpeople(struct contact* pc);
//保存联系人到文件
void savecontact(struct contact* pc);
//加载联系人从文件到内存
void Loadcontact(struct contact* pc);
//判断是否通讯录已满
void check(struct contact* pc);
//比较函数
int cmp(struct contact* pc);

struct PeoInfo
{
	char name[10];
	char sex[5];
	int age;
	char tel[15];
	char address[20];
};
struct contact
{
	struct PeoInfo* date;
	int sz;
	int max;
};



  我们这个版本的通讯录是在动态版本通讯录的基础上实现的,所以在头文件中我们就只是多了保存联系人信息到文件和读取联系人信息这个两个函数的声明,其余的代码和动态版本通讯录大同小异,如果有不解的地方可以看小猿之前动态版本通讯录的博客,里面有详细讲解。

二、功能实现模块

#define  _CRT_SECURE_NO_WARNINGS 1
#include "FILE.h"
void menu()
{
	printf("------------------------------------\n");
	printf("--------请选择你要实现的功能--------\n");
	printf("--------1.添加联系人信息------------\n");
	printf("--------2.删除指定联系人信息--------\n");
	printf("--------3.查找指定联系人信息--------\n");
	printf("--------4.修改指定联系人信息--------\n");
	printf("--------5.显示所有联系人信息--------\n");
	printf("--------6.以名字排序所有联系人------\n");
	printf("--------0.      退出         ------\n");
}
void check(struct contact* pc)
{
	if ((pc->sz) >= (pc->max))
	{
		pc = (struct PeoInfo*)realloc(pc->date, (pc->max + 2) * sizeof(struct PeoInfo));
		printf("扩容成功\n");
		pc->max += 2;
	}
}
void Loadcontact(struct contact* pc)
{
	FILE* pf = fopen("contacts.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	struct PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
	{
		check(pc);
		pc->date[pc->sz] = tmp;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
}
	void inicontact(struct contact* pc)
	{
		pc->sz = 0;
		pc->max = 3;
		pc->date = (struct PeoInfo*)calloc(3, sizeof(struct PeoInfo));
		 Loadcontact(pc);
	}
	

	void addpeople(struct contact* pc)
	{
		 check(pc);
		printf("请输入姓名\n");
		scanf("%s", &(pc->date[pc->sz].name));
		printf("请输入性别\n");
		scanf("%s", &(pc->date[pc->sz].sex));
		printf("请输入年龄\n");
		scanf("%d", &(pc->date[pc->sz].age));
		printf("请输入电话\n");
		scanf("%s", &(pc->date[pc->sz].tel));
		printf("请输入住址\n");
		scanf("%s", &(pc->date[pc->sz].address));
		printf("添加联系人完毕\n");
		pc->sz++;
	}
	void delpeople(struct contact* pc)
	{
		char name1[10];
		int input1;
		printf("请输入你要删除的联系人\n");
		scanf("%s", &name1);
		int i;
		for (i = 0; i < (pc->sz); i++)
		{
			if (strcmp(pc->date[i].name, name1) == 0)
			{
				printf("查到到联系人%s是否确认删除\n", name1);
				scanf("%d", &input1);
				if (input1 == 1)
				{
					for (int j = i; j < ((pc->sz) - 1); j++)
					{
						(pc->date[j]) = (pc->date[j + 1]);
						pc->sz--;
					}
					printf("删除成功\n");
				}
				else
				{
					printf("成功取消\n");
				}
			}
		}
		if (i >= (pc->sz))
		{
			printf("联系人%s不存在\n", name1);
		}
	}
	void searchpeople(struct contact* pc)
	{
		char name1[10];
		printf("请输入你要查找的联系人\n");
		scanf("%s", &name1);
		int i;
		for (i = 0; i < (pc->sz); i++)
		{
			if (strcmp(pc->date[i].name, name1) == 0)
			{
				printf("%-10s\t %-15s\t %-3s\t %-15s\t %-20s\t\n",
					"name", "sex", "age", "tel", "address");
				printf("%-10s\t %-15s\t %-3d\t %-15s\t %-20s\t\n",
					pc->date[i].name,
					pc->date[i].sex,
					pc->date[i].age,
					pc->date[i].tel,
					pc->date[i].address);
			}
		}
		if (i > pc->sz)
		{
			printf("不存在此联系人%s\n", name1);
		}
	}

	void revisepeople(struct contact* pc)
	{
		char name1[10];
		printf("请输入你要修改的联系人\n");
		scanf("%s", &name1);
		int i;
		for (i = 0; i < (pc->sz); i++)
		{
			if (strcmp(pc->date[i].name, name1) == 0)
			{
				printf("请输入姓名\n");
				scanf("%s", &(pc->date[i].name));
				printf("请输入性别\n");
				scanf("%s", &(pc->date[i].sex));
				printf("请输入年龄\n");
				scanf("%d", &(pc->date[i].age));
				printf("请输入电话\n");
				scanf("%s", &(pc->date[i].tel));
				printf("请输入住址\n");
				scanf("%s", &(pc->date[i].address));
				printf("修改联系人完毕\n");
			}
		}
		if (i > pc->sz)
		{
			printf("不存在此联系人%s\n", name1);
		}
	}

	void showpeople(struct contact* pc)
	{
		int i;
		printf("%-10s\t %-15s\t %-3s\t %-15s\t %-20s\t\n",
			"name", "sex", "age", "tel", "address");
		for (i = 0; i < (pc->sz); i++)
		{
			printf("%-10s\t %-15s\t %-3d\t %-15s\t %-20s\t\n",
				pc->date[i].name,
				pc->date[i].sex,
				pc->date[i].age,
				pc->date[i].tel,
				pc->date[i].address);
		}

	}
	int cmp(void* e1, void* e2)
	{
		return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
	}

	void sortpeople(struct contact* pc)
	{
		qsort(pc, pc->sz, sizeof(struct PeoInfo), cmp);
	}
	void savecontact(struct contact* pc)
	{
		FILE* pf = fopen("contacts.txt", "w");
		if (pf == NULL)
		{
			perror("fopen");
			return;
		}
		int i = 0;
		for (i = 0; i < pc->sz; i++)
		{
			fwrite(pc->date + i, sizeof(struct PeoInfo), 1, pf);
		}

		fclose(pf);
		pf = NULL;
	}

	void deadpeople(struct contact* pc)
	{
		free(pc->date);
		pc->date = NULL;
		pc->max = 0;
		pc->sz = 0;
	}


  这是我们功能实现总体的代码,也是在动态通讯录上改造的,我们多了两个功能就是保存联系人信息到文件和读取文件中联系人的信息到内存,我们用两个独立的函数来实现这两个功能。

1.保存联系人到文件

代码如下(示例):

	void savecontact(struct contact* pc)
	{
		FILE* pf = fopen("contacts.txt", "w");
		if (pf == NULL)
		{
			perror("fopen");
			return;
		}
		int i = 0;
		for (i = 0; i < pc->sz; i++)
		{
			fwrite(pc->date + i, sizeof(struct PeoInfo), 1, pf);
		}

		fclose(pf);
		pf = NULL;
	}

  我们先对一个contacts.txt文件进行只写操作,如果我们之前没有这个文件系统就会自动创建一个文件,然后我们需要判断一下fopen函数返回的FILE结构的指针是否为NULL,如果为NULL我们就用perror函数显示fopen函数打开错误,如果返回的指针不为NULL,我们就将pc->date内的数据写入到pf这个FILE结构的指针所指向的文件信息区,然后达到写入文件的目的,最后别忘了关闭文件并且将pf指针置为NULL。

2.对文件联系人信息的读取

代码如下(示例):

void check(struct contact* pc)
{
	if ((pc->sz) >= (pc->max))
	{
		pc = (struct PeoInfo*)realloc(pc->date, (pc->max + 2) * sizeof(struct PeoInfo));
		printf("扩容成功\n");
		pc->max += 2;
	}
}
void Loadcontact(struct contact* pc)
{
	FILE* pf = fopen("contacts.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	struct PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(struct PeoInfo), 1, pf))
	{
		check(pc);
		pc->date[pc->sz] = tmp;
		pc->sz++;
	}
	fclose(pf);
	pf = NULL;
}
	void inicontact(struct contact* pc)
	{
		pc->sz = 0;
		pc->max = 3;
		pc->date = (struct PeoInfo*)calloc(3, sizeof(struct PeoInfo));
		 Loadcontact(pc);
	}

  在这里我们为了实现从文件中读取联系人的信息到内存涉及到了三个函数,分别是check函数,它的功能是查询通讯录是否已满,inicontact函数,它的功能是对通讯录进行初始化,我们之前的两个版本都是将创建的空间置为0,但是这里我们要将文件中的信息读入内存中,所以我们要在初始化的时候实现这一功能,Loadcontact函数就是我们加载联系人信息的实现函数,由它来控制加载文件中联系人的信息。
这里的难点在于fread函数,我们先来看一下fread函数的定义:
在这里插入图片描述
  fread函数的作用就是读取文件类型指针所指向空间的count个大小为size的二进制数据放入到ptr的指针所指向的空间中,函数的返回值类型是size_t,也就是无符号整型的数据,如果我们读到一个数据就返回1,两个数据就返回2,所以我们把它写在while循环中作为while循环条件,如果读取结束就返回0,自然会跳出循环。
这就最终实现了通讯录的最终版本——文件读写版本通讯录。

三、测试文件

代码如下(示例):

#define _CRT_SECURE_NO_WARNINGS
#include "FILE.h"
int main()
{
	struct contact c1;
	inicontact(&c1);
	int input = 1;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			system("cls");
			addpeople(&c1);
			break;
		case 2:
			system("cls");
			delpeople(&c1);
			break;
		case 3:
			system("cls");
			searchpeople(&c1);
			break;
		case 4:
			system("cls");
			revisepeople(&c1);
			break;
		case 5:
			system("cls");
			showpeople(&c1);
			break;
		case 6:
			system("cls");
			sortpeople(&c1);
			break;
		case 0:
			system("cls");
			savecontact(&c1);
			free(c1.date);
			exit(1);
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}



总结

  写到这里通讯录的三个版本也就都结束了,后一个版本都是在前一个版本的基础上改进的,逐步让功能完善,成为可以真正满足需求的通讯录,再大的程序我们都可以大而化小,分而治之,逐步实现它的一个一个功能,希望我的博客对大家有所帮助,我们明天见~

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
好的,下面是Python使用Django进行通讯录制作的步骤: 1. 创建Django项目 使用以下命令创建Django项目: ``` django-admin startproject myaddressbook ``` 2. 创建Django应用 使用以下命令创建Django应用: ``` python manage.py startapp contacts ``` 3. 配置数据库 打开myaddressbook/settings.py文件,配置数据库: ```python DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } ``` 这里我们使用sqlite3数据库,如果你想使用其他数据库,需要在此处进行相应的配置。 4. 创建模型 在contacts/models.py文件定义Contact模型: ```python from django.db import models class Contact(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField() phone = models.CharField(max_length=20) def __str__(self): return f'{self.first_name} {self.last_name}' ``` 5. 迁移数据库 运行以下命令迁移数据库: ``` python manage.py makemigrations python manage.py migrate ``` 6. 创建视图 在contacts/views.py文件创建ContactListView视图: ```python from django.views.generic import ListView from .models import Contact class ContactListView(ListView): model = Contact ``` 7. 创建URL 在myaddressbook/urls.py文件创建URL: ```python from django.urls import path from contacts.views import ContactListView urlpatterns = [ path('', ContactListView.as_view(), name='contact_list'), ] ``` 8. 运行服务器 使用以下命令运行Django服务器: ``` python manage.py runserver ``` 现在你可以在浏览器访问http://127.0.0.1:8000/,就可以看到通讯录列表了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴躁小程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值