【C言語】ファイル操作・アドレス帳変更(バージョンアップ版)データ保存可能

以上でファイル操作の内容を学習しましたので、分からない場合はこの記事を読んでください。

【C言語】Xiao Wangがファイル操作を実現します(簡単な図解説)_Xiao Wangのコード学習ブログ - CSDNブログ

アドレス帳 私たちは以前、静的および動的アドレス帳の実装方法も学びました。

【C言語】C言語を使って静的・動的アドレス帳を実現する(シンプルでわかりやすい) - プログラマー募集


目次

序文

1. ファイル操作のアイデアを使用する

2. ステップを使用する

1. 改造を終了する

2. 変換を初期化する

3. コードデモ

3. ファイル操作アドレス帳の完全なコード

1.連絡先.h

2.連絡先.c

3.テスト.c

要約する


序文

静的データベースと動的データベースを実装する場合、一連のデータを入力し、一連の追加、削除、変更、チェックを完了するとプログラムが閉じられ、次にプログラムを開くと、以前のデータが残っていることがわかります。これは、私たちのデータがすべてメモリに保存されているためです。プログラムが終了すると、自然なメモリは解放され、再度開くと、データは失われます。

では、プログラム内のデータをファイル操作でハードディスクに転送した場合、次回からは取り出すことができるのでしょうか?

もちろん可能ですので、その方法をご紹介します。

1. ファイル操作のアイデアを使用する

元のアドレス帳の何を変更したいのでしょうか?

1. データを保存するために終了します。        したがって、0 を入力して終了すると、データを対応するファイルに保存するファイル操作を追加します。

2. プログラムを開いて以前のデータを抽出し、         初期化するときにファイル操作を使用して、

上記2点を修正することでアドレス帳を改善し、より実用的なデータアクセス可能なアドレス帳を実現できます。

2. ステップを使用する

1. 改造を終了する

写真が示すように:

コードは以下のように表示されます:

void SaveContact(Contact* pc) {
	//存入数据
	//使用fwrite 二进制存储吧

	//fopen打开文件
	FILE* pf = fopen("Contact.txt", "wb");
	//判断是否存在文件Contact.txt
	if (NULL == pf) {
		perror("SaveContact::fopen");
	}
	else {
		fwrite(pc->data, sizeof(PeopleInfo), pc->sz, pf);
		//输出之后提示输出完成到Contact.txt中
		printf("保存完成\n");
		//关闭流 并pf置为NULL 防止野指针
		fclose(pf);
		pf = NULL;
	}

}

2. 変換を初期化する

元のデータを最初から取得したいので、初期化するときにContact.txtファイルのデータを読み込むだけで済みます。

回路図は以下の通りです:

コードは以下のように表示されます:

//新增代码,读取文件中的数据
void read_Contact(Contact* pc) {
	//读取的时候先进行判断是否
	FILE* pf = fopen("Contact.txt", "r");
	if (NULL == pf) {
		perror("read_Contact::open");
	}
	else {
		PeopleInfo ptr={0};
		int i = 0;
		while (fread(&ptr, sizeof(PeopleInfo), 1, pf)) {
			check_capacity(pc);
			//不够就扩容
			pc->data[i] = ptr;
			pc->sz++;
			i++;
		}
	}
}
void check_capacity(Contact* pc) {
	if (pc->sz == pc->capacity) {
		//使用realloc函数 进行扩容
		PeopleInfo* ptr = (PeopleInfo*)realloc(pc->data, sizeof(PeopleInfo) * (pc->capacity + MAX2));
		if (ptr == NULL) {
			perror("check_capacity");
			return;
		}
		else {
			pc->data = ptr;
			pc->capacity = pc->capacity + MAX2;
			printf("扩容完成\n");
		}
	}
}
//这是动态通讯录的初始化
void InitContact(Contact* pc) {
	//进行初始化的时候,我们当然可以直接
	assert(pc);//断言
	pc->sz = 0;
	PeopleInfo *ptr=(PeopleInfo*)calloc(MAX1,sizeof(PeopleInfo));
	if (ptr == NULL) {
		perror("malloc::data");
		return;
	}
	pc->data = ptr;
	pc->capacity=MAX1;

	read_Contact(pc);
}

3. コードデモ

図に示すように、このようにして、実際のニーズに適したハードディスク ファイル内のデータの入力と読み取りが可能になります。これは、ファイル操作と処理後の動的アドレス帳です。静的な場合は、より単純です。動的、静的が実現できることを知っています。


3. ファイル操作アドレス帳の完全なコード

Contact.h Contact.c test.c の3 つの部分に分かれています。

Contact.h は、test.c で必要な関数をヘッダー ファイルとして宣言します。

Contact.c は Contact.h で宣言された関数を実装します。

test.c アドレス帳の本文。バックボーンはアドレス帳のロジックを実装します。

1.連絡先.h

#define _CRT_SECURE_NO_WARNINGS

//Contact 实现通讯录 头文件
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<malloc.h>
#include<stdlib.h>
#include<search.h>

#define MAX 100
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 20
#define TELE_MAX 12


//下面两个define是用于动态通讯录的
#define MAX1 3	//表示第一次容积是多少
#define MAX2 2  //表示一次扩容多少




//构建通讯录所需的结构体
typedef struct PeopleInfo {
	char name[NAME_MAX];//姓名
	int age;//年龄
	char sex[NAME_MAX];//性别
	char addr[ADDR_MAX];//地址
	char tele[TELE_MAX];//电话号码
}PeopleInfo;

//这是静态通讯录  就是data这个数组是固定死的MAX
//typedef struct Contact {
//	PeopleInfo data[MAX];//表示存储的通讯录最大人员数
//	int sz;//表示当前Contact通讯录人员个数
//}Contact;

//实现动态通讯录
typedef struct Contact {
	PeopleInfo *data;//表示存储的通讯录最大人员数
	int sz;//表示当前Contact通讯录人员个数
	int capacity; //表示当前容量  作为扩容的依据
}Contact;

//初始化通讯录
void InitContact(Contact* pc);
//添加通讯录的信息
void addContact(Contact* pc);
//删除通讯录中的信息
void delContact(Contact* pc);
//查找通讯录成员信息
int searchContact(Contact* pc);
//打印
void showContact(Contact* pc);
//改变指定元素
void changeContact(Contact* pc);
//排序,按照名字排序
void sortContact(Contact* pc);

//保存通讯录
void SaveContact(Contact*pc);

//读取通讯录
void read_Contact(Contact*pc);

2.連絡先.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"
//用来实现头文件的代码
//
这是静态初始化
//void InitContact(Contact* pc) {
//	//进行初始化的时候,我们当然可以直接
//	pc->sz = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//	//memset 函数  这样的话,从data这个数组的地址开始 sizeof(pc->data)个字节,都赋值为0
//}

//这是动态通讯录的初始化
void InitContact(Contact* pc) {
	//进行初始化的时候,我们当然可以直接
	assert(pc);//断言
	pc->sz = 0;
	PeopleInfo *ptr=(PeopleInfo*)calloc(MAX1,sizeof(PeopleInfo));
	if (ptr == NULL) {
		perror("malloc::data");
		return;
	}
	pc->data = ptr;
	pc->capacity=MAX1;

	read_Contact(pc);
}
静态通讯录
//void addContact(Contact* pc) {
//	assert(pc);
//	if (pc->sz == MAX) {
//		printf("通讯录已满,无法添加\n");
//		return;
//	}
//	printf("请输入名字:>");
//	scanf("%s", pc->data[pc->sz].name);
//	printf("请输入年龄:>");
//	scanf("%d", &(pc->data[pc->sz].age));
//	printf("请输入性别:>");
//	scanf("%s", pc->data[pc->sz].sex);
//	printf("请输入地址:>");
//	scanf("%s", pc->data[pc->sz].addr);
//	printf("请输入电话:>");
//	scanf("%s", pc->data[pc->sz].tele);
//	printf("添加完成,请继续操作\n");
//	pc->sz++;
//}
//动态通讯录
void check_capacity(Contact* pc) {
	if (pc->sz == pc->capacity) {
		//使用realloc函数 进行扩容
		PeopleInfo* ptr = (PeopleInfo*)realloc(pc->data, sizeof(PeopleInfo) * (pc->capacity + MAX2));
		if (ptr == NULL) {
			perror("check_capacity");
			return;
		}
		else {
			pc->data = ptr;
			pc->capacity = pc->capacity + MAX2;
			printf("扩容完成\n");
		}
	}
}
	
void addContact(Contact* pc) {
	assert(pc);
	check_capacity(pc);
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->sz].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->sz].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	printf("添加完成,请继续操作\n");
	pc->sz++;
}
void delContact(Contact* pc) {
	assert(pc);
	printf("请选择删除的目标:>");
	if (pc->sz == 0) {
		return;
	}
	//删除的话只需要找到对应的要删除的数据,比如以名字为准,先找到,然后再讲其后面的元素覆盖前面的
	int pos = searchContact(pc);
	//换位置
	if (pos == -1) {
		printf("没有查找到该成员\n");
		return;
	}
	for (int i = pos; i < pc->sz - 1; i++) {
		pc->data[i] = pc->data[i + 1];
	}

	pc->sz--;//直接--不用管换位置之后最后一个数字的问题
	printf("删除完成\n");
}


int  searchContact(Contact* pc) {
	assert(pc);
	char name[20];
	int pos = -1;
	scanf("%s", name);
	//查询
	for (int i = 0; i < pc->sz; i++) {
		if (strcmp(pc->data[i].name, name) == 0) {
			pos = i;
		}
	}
	
	return pos;
}

void showContact(Contact* pc) {
	assert(pc);
	if (pc->sz == 0) {
		return;
	}//可以有可无
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话");
	for (int i = 0; i < pc->sz; i++) {
		printf("%-20s\t%-5d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);
	}
	printf("打印完成\n");
}



void changeContact(Contact* pc) {
	assert(pc);
	//先找到
	int pos = searchContact(pc);
	printf("请输入名字:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("更改完成, 请继续操作\n");
}


void sortContact(Contact* pc) {
	assert(pc);
	if (pc->sz == 0) {
		printf("通讯录中暂无元素\n");
		return;
	}
	Contact s;
	InitContact(&s);
	for (int i = 0; i < pc->sz-1; i++) {
		for (int j = 0; j < pc->sz-1-i; j++) {
			if (strcmp(pc->data[j].name, pc->data[j + 1].name)==1) {
				s.data[j] = pc->data[j];
				pc->data[j] = pc->data[j + 1];
				pc->data[j + 1] = s.data[j];
			}
		}
	}
}

int compare(const void* e1, const void* e2) {
	return *((int*)e1) - *((int*)e2);
}
void sort(Contact*pc) {
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), compare);
}
//int main()
//
//{
//	qsort()
//	return 0;
//}

void SaveContact(Contact* pc) {
	//存入数据
	//使用fwrite 二进制存储吧

	//fopen打开文件
	FILE* pf = fopen("Contact.txt", "wb");
	//判断是否存在文件Contact.txt
	if (NULL == pf) {
		perror("SaveContact::fopen");
	}
	else {
		fwrite(pc->data, sizeof(PeopleInfo), pc->sz, pf);
		//输出之后提示输出完成到Contact.txt中
		printf("保存完成\n");
		//关闭流 并pf置为NULL 防止野指针
		fclose(pf);
		pf = NULL;
	}

}
void read_Contact(Contact* pc) {
	//读取的时候先进行判断是否
	FILE* pf = fopen("Contact.txt", "r");
	if (NULL == pf) {
		perror("read_Contact::open");
	}
	else {
		PeopleInfo ptr={0};
		int i = 0;
		while (fread(&ptr, sizeof(PeopleInfo), 1, pf)) {
			check_capacity(pc);
			//不够就扩容
			pc->data[i] = ptr;
			pc->sz++;
			i++;
		}
	}
}

3.テスト.c

#define _CRT_SECURE_NO_WARNINGS
#include"Contact.h"

//这边进行主要的通讯录流程操作

void menu() {
	printf("***********************************************\n");
	printf("******      1.add           2.del        ******\n");
	printf("******      3.search        4.change     ******\n");
	printf("******      5.show          6.sort       ******\n");
	printf("******      0.exit                       ******\n");
	printf("***********************************************\n");

}
void test() {
	//打印选择菜单

	int input = 0;
	int pos = 0;
	Contact pc;
	//Contact pc={0};
	//当然可以这样初始化,但是不一定后来初始化都这样,所以有InitContact()
	InitContact(&pc);
	
	do {
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
			case 1:
				addContact(&pc);
				break;
			case 2:
				delContact(&pc);
				break;
			case 3:
				pos = searchContact(&pc);
				if (pos == -1) {
					printf("没有查找到该成员\n");
				}
				else {
					printf("%-20s\t%-5d\t%-5s\t%-20s\t%-12s\n", pc.data[pos].name, pc.data[pos].age, pc.data[pos].sex, pc.data[pos].addr, pc.data[pos].tele);
				}
				break;
			case 4:
				changeContact(&pc);
				break;
			case 5:
				showContact(&pc);
				break;
			case 6:
				sort(&pc);
				break;
			case 0:
				SaveContact(&pc);
				printf("退出通讯录\n");
				free(pc.data);
				break;
			default:
				break;
			}
	} while (input);
}
int main()
{
	test();
	return 0;
}

要約する

この記事ではファイル操作で実現しています。アドレス帳のデータはハードディスク上に保存されており、ハードディスクからプログラムにデータを読み込むことができるので、より実際のニーズに適しています。主なファイル操作を紹介します。とアプリケーション、実装方法、および完全なコードが添付されているので、友人がそのようなプログラムを理解して理解できることを願っています。

Xiao Wang は、2023 年のウサギ年の新年を皆様に祝福するためにここにいます。

おすすめ

転載: blog.csdn.net/qq_63319459/article/details/128723542