c语言实现词典(动态、文件储存版)

 

目录

 

前言

需求分析

代码编写

框架搭建

菜单、退出程序

词典的创建和初始化

增删查和展示

背和保存

总体代码


前言

该词典为本人进行日语学习使用,其他语言版本可根据该版本进行修改。这篇文章是我的处女作,若有不足,请各位大佬帮忙指正。

需求分析

作为词典,最主要的功能无非“增删查”。在此基础上,我还添加了“背”的功能。由于是文件储存版本,因此我还在此基础上增加了“保存”的功能。

代码编写

框架搭建

首先先写程序主体。利用do...while循环,当选择“0”时退出程序。再用swicht语句实现程序主题。

在这里,我将程序分成了3部分(程序主体program.c、功能实现func.c和功能头文件func.h)。

小技巧:利用枚举常量“代替”各个功能名,便于后续程序的编写。

enum
{
EXIT,
ADD,
SEARCH,
DEL,
SHOW,
RECITE,
SAVE
}

此时,program.c的代码如下:

#include"fun.h"

  int main()
{
	int input = 0;
	do
	{
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			break;
		case SEARCH:
			break;
		case DEL:
			break;
		case SHOW:
			break;
		case RECITE:
			break;
		case SAVE:
			break;
		case EXIT:
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}

菜单、退出程序

调用多个printf()函数将菜单打印出来。退出程序时,调用一个printf()函数提示已经退出程序。

此时,program.c如下:

#include"fun.h"

int main()
{
	int input = 0;
	do
	{
		menu1();
		switch (input)
		{
		case ADD:
			break;
		case SEARCH:
			break;
		case DEL:
			break;
		case SHOW:
			break;
		case RECITE:
			break;
		case SAVE:
			break;
		case EXIT:
			printf("已退出\n");
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}

func.c如下:

#include"fun.h"

void menu1()//无返回值
{
	printf("**** 1. 添加单词*** 2. 查找单词  ****\n");
	printf("**** 3. 删除单词*** 4. 展示单词表****\n");
	printf("**** 5. 背单词  *** 6. 保存      ****\n");
	printf("*****0. 退出    *********************\n");
	printf("请选择:");
}

func.h如下:

#pragma once
#include<stdio.h>

void menu1();

词典的创建和初始化

首先先创建词典。先用结构体定义一个单词,单词包含单词本体、假名和中文意思。

#define word_length 30//定义单词本体、假名和中文意思的最大长度

typedef struct word
{
	char character[word_length];
	char kana[word_length];
	char chinese[word_length];
}word;

再用另一个结构体定义单词表,单词表包含单词、当前单词数量和当前单词表最大数量。

typedef struct wordlist
{
	word* list;//这里使用指针,便于后续初始化和增容
	int size;//记录目前的单词数量
	int cap;//记录目前的单词表最大数量
	int num;//记录存储的单词数量
}wordlist;

在初始化过程中,使用calloc()函数进行初始化,并将单词都初始化为0。

注意:在程序结束后要调用free()函数将单词表的空间释放。

void InitList(wordlist* ps)
{
	ps->list=(word* )calloc(init_cap, sizeof(word));
	if (ps->list == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->cap = init_cap;
}

此时,program.c如下:

#include"func.h"

int main()
{
	int input = 0;
	wordlist List;
	InitList(&List);//这里将单词表的地址传递进函数,可以节省内存空间,效率更高。后面的功能同理。
	do
	{
		printf("当前单词数量:%d  当前单词最大数量:%d\n", List.size, List.cap);
		menu1();
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			break;
		case SEARCH:
			break;
		case DEL:
			break;
		case SHOW:
			break;
		case RECITE:
			break;
		case SAVE:
			break;
		case EXIT:
			printf("已退出\n");
			break;
		default:
			break;
		}
	} while (input);
	free(List.list);
	List.list == NULL;
	return 0;
}

func.c如下:

#include"func.h"

void menu1()
{
	printf("**** 1. 添加单词*** 2. 查找单词  ****\n");
	printf("**** 3. 删除单词*** 4. 展示单词表****\n");
	printf("**** 5. 背单词  *** 6. 保存      ****\n");
	printf("*****0. 退出    *********************\n");
	printf("请选择:");
}

void InitList(wordlist* ps)
{
	ps->list=(word* )calloc(init_cap, sizeof(word));
	if (ps->list == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->cap = init_cap;
}

fun.h如下:

#pragma once
#include<stdio.h>

#define word_length 30
#define init_cap 3//初始单词表最大容量

typedef struct word
{
	char character[word_length];
	char kana[word_length];
	char chinese[word_length];
}word;

typedef struct wordlist
{
	word* list;
	int size;//记录目前的单词数量
	int cap;//记录目前的单词表最大数量
	int num;//记录存储的单词数量
}wordlist;

enum
{
	EXIT,
	ADD,
	SEARCH,
	DEL,
	SHOW,
	RECITE,
	SAVE
};


void menu1();
void InitList(wordlist* ps);

增删查和展示

再增加之前要进行容量的检查。若单词表已满,则需要扩容。

删除功能和查找功能有相通之处,即先要找到目标的下标,在进行后续操作(删除或显示)。

在这里,我将查找分了三类,但每种查找的思路都相同。

展示功能能将单词表全部打印到屏幕上,因此无需查找。

在增容功能中  调用 realloc()函数,将单词表的容量扩大。

此时,program.c如下:

#include"func.h"

int main()
{
	int input = 0;
	wordlist List;
	InitList(&List);
	do
	{
		printf("当前单词数量:%d  当前单词最大数量:%d\n", List.size, List.cap);
		menu1();
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddWord(&List);
			break;
		case SEARCH:
			SearchWord(&List);
			break;
		case DEL:
			DelWord(&List);
			break;
		case SHOW:
			ShowList(&List);
			break;
		case RECITE:
			break;
		case SAVE:
			break;
		case EXIT:
			printf("已退出\n");
			break;
		default:
			break;
		}
	} while (input);
	free(List.list);
	List.list == NULL;
	return 0;
}

func.c如下:

#include"func.h"

void menu1()
{
	printf("**** 1. 添加单词*** 2. 查找单词  ****\n");
	printf("**** 3. 删除单词*** 4. 展示单词表****\n");
	printf("**** 5. 背单词  *** 6. 保存      ****\n");
	printf("*****0. 退出    *********************\n");
	printf("请选择:");
}

void InitList(wordlist* ps)
{
	ps->list=(word* )calloc(init_cap, sizeof(word));
	if (ps->list == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->cap = init_cap;
}

void AddSpace(wordlist* tmp)
{
	tmp->list = realloc(tmp->list, (tmp->cap + add_cap) * sizeof(word));
	if (tmp->list != NULL)
	{
		printf("增容成功\n");
	}
	else
		perror("增容失败\n");
	tmp->cap = tmp->cap + add_cap;
}
void AddWord(wordlist* ps)
{
	system("cls");
	if (ps->size == ps->cap)
		AddSpace(ps);
	printf("请输入单词:");
	scanf("%s", ps->list[ps->size].character);
	printf("请输入假名:");
	scanf("%s", ps->list[ps->size].kana);
	printf("请输入中文:");
	scanf("%s", ps->list[ps->size].chinese);
	ps->size++;
}

void ShowList(wordlist* ps)
{
	system("cls");
	int i = 0;
	if (ps->size == NULL)
	{
		printf("单词表为空\n");
		return;
	}
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		for (i = 0; i < ps->size; i++)
			printf("%-30s\t%-30s\t%-30s\n", ps->list[i].character, ps->list[i].kana, ps->list[i].chinese);
	}
}

void menu2()
{
	printf("1.通过单词查找\n");
	printf("2.通过假名查找\n");
	printf("3.通过中文查找\n");
	printf("4.返回\n");
}
void search1(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词:");
	char word_tmp[word_length] = { 0 };
	scanf("%s", word_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].character, word_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词的假名\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void search2(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词的中文:");
	char kana_tmp[word_length] = { 0 };
	scanf("%s", kana_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].kana, kana_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void search3(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词:");
	char chinese_tmp[word_length] = { 0 };
	scanf("%s", chinese_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].kana, chinese_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void SearchWord(wordlist* ps)
{
	system("cls");
	int inpu;
	menu2();
	scanf("%d", &inpu);
	switch (inpu)
	{
	case 1:
		search1(ps);
		break;
	case 2:
		search2(ps);
		break;
	case 3:
		search3(ps);
		break;
	case 4:
		return;
		break;
	default:
		break;
	}
	return;
}

void DelWord(wordlist* ps)
{
	system("cls");
	int i = 0;
	printf("请输入要删除的单词:");
	char word_tmp[word_length] = { 0 };
	scanf("%s", word_tmp);
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->list[i].character, word_tmp))
		{
			break;
		}
	}
	for (int j = i; j < ps->size-1; j++)
		ps->list[j] = ps->list[j + 1];
	ps->size--;
}

func.h  如下:

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

#define word_length 30
#define init_cap 3//初始单词表最大容量
#define add_cap 2//每次增容时增加的容量

typedef struct word
{
	char character[word_length];
	char kana[word_length];
	char chinese[word_length];
}word;

typedef struct wordlist
{
	word* list;
	int size;//记录目前的单词数量
	int cap;//记录目前的单词表最大数量
	int num;//记录存储的单词数量
}wordlist;

enum
{
	EXIT,
	ADD,
	SEARCH,
	DEL,
	SHOW,
	RECITE,
	SAVE
};


void menu1();
void InitList(wordlist* ps);
void AddWord(wordlist* ps);
void ShowList(wordlist* ps);
void SearchWord(wordlist* ps);
void DelWord(wordlist* ps);

背和保存

这里我将背也分成了三部分,但每一个部分的内核相同。

关于保存,及要能手动保存,也要能在退出前保存。在程序开始时,要能从文件中读取信息,因此还要在初始化中增加“加载”功能。

这两个功能代码如下:

void menu3()
{
	printf("1.通过单词背中文\n");
	printf("2.通过假名背中文\n");
	printf("3.通过中文背单词\n");
	printf("4.返回\n");
}
void recite1(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].character);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.chinese, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
	    a++;
	    if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
			printf("回答错误,请重试\n");
	} while (a != 3);
}
void recite2(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].kana);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.chinese, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
		a++;
		if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
		printf("回答错误,请重试\n");
	} while (a != 3);
}
void recite3(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].chinese);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.character, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
		a++;
		if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
		printf("回答错误,请重试\n");
	} while (a != 3);
}
void ReciteWord(wordlist* ps)
{
	system("cls");
	int inpu;
	menu3();
	scanf("%d", &inpu);
	switch (inpu)
	{
	case 1:
		recite1(ps);
		break;
	case 2:
		break;
	case 3:
		break;
	case 4:
		return;
		break;
	default:
		break;
	}
}
//可以改成循环的版本
void LoadWordlist(wordlist* ps);
void AddSpace(wordlist* tmp);//读取过程中可能读取的数量大于初始值,因此要增容。
void InitList(wordlist* ps)
{
	ps->list=(word* )calloc(init_cap, sizeof(word));
	if (ps->list == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->cap = init_cap;
	LoadWordlist(ps);
	ps->num = ps->size;
}
void LoadWordlist(wordlist* ps)
{
	word tmp = { 0 };
	FILE* pfRead = fopen("words_list.dat", "rb");//采用“dat“的文件后缀名,防止用记事本打开后乱码。
	if (pfRead == NULL)
	{
		perror("读文件失败");
		return;
	}
	while (fread(&tmp, sizeof(word), 1, pfRead))
	{
		if (ps->size == ps->cap)
		{
			AddSpace(ps);
		}
		ps->list[ps->size] = tmp;
		ps->size++;
	}
	fclose(pfRead);
	pfRead = NULL;
}

void SaveList(wordlist* ps)
{
	FILE* pfWrite = fopen("words_list.dat", "wb");
	if (pfWrite == NULL)
	{
		perror("打开文件失败");
		return;
	}
	for (int i = ps->num; i < ps->size; i++)
	{
		fwrite(&(ps->list[i]), sizeof(word), 1, pfWrite);
		printf("已保存\n");
	}
	fclose(pfWrite);
	pfWrite = NULL;
}

这里我在单词表的结构体中加了一个变量num来记录已存储的单词数,防止重复存储。

总体代码

func.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define word_length 30
#define init_cap 3
#define add_cap 2

typedef struct word
{
	char character[word_length];
	char kana[word_length];
	char chinese[word_length];
}word;

typedef struct wordlist
{
	word* list;
	int size;//记录目前的单词数量
	int cap;//记录目前的单词表最大数量
	int num;//记录存储的单词数量
}wordlist;

enum
{
	EXIT,
	ADD,
	SEARCH,
	DEL,
	SHOW,
	RECITE,
	SAVE
};

void menu1();
void InitList(wordlist* ps);
void AddWord(wordlist* ps);
void ShowList(wordlist* ps);
void SearchWord(wordlist* ps);
void DelWord(wordlist* ps);
void ReciteWord(wordlist* ps);
void SaveList(wordlist* ps);#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define word_length 30
#define init_cap 3
#define add_cap 2

typedef struct word
{
	char character[word_length];
	char kana[word_length];
	char chinese[word_length];
}word;

typedef struct wordlist
{
	word* list;
	int size;//记录目前的单词数量
	int cap;//记录目前的单词表最大数量
	int num;//记录存储的单词数量
}wordlist;

enum
{
	EXIT,
	ADD,
	SEARCH,
	DEL,
	SHOW,
	RECITE,
	SAVE
};

void menu1();
void InitList(wordlist* ps);
void AddWord(wordlist* ps);
void ShowList(wordlist* ps);
void SearchWord(wordlist* ps);
void DelWord(wordlist* ps);
void ReciteWord(wordlist* ps);
void SaveList(wordlist* ps);

func.c

#include"func.h"

void menu1()
{
	printf("**** 1. 添加单词*** 2. 查找单词  ****\n");
	printf("**** 3. 删除单词*** 4. 展示单词表****\n");
	printf("**** 5. 背单词  *** 6. 保存      ****\n");
	printf("*****0. 退出    *********************\n");
	printf("请选择:");
}
void LoadWordlist(wordlist* ps);
void AddSpace(wordlist* tmp);
void InitList(wordlist* ps)
{
	ps->list=(word* )calloc(init_cap, sizeof(word));
	if (ps->list == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->cap = init_cap;
	LoadWordlist(ps);
	ps->num = ps->size;
}
void LoadWordlist(wordlist* ps)
{
	word tmp = { 0 };
	FILE* pfRead = fopen("words_list.dat", "rb");
	if (pfRead == NULL)
	{
		perror("读文件失败");
		return;
	}
	while (fread(&tmp, sizeof(word), 1, pfRead))
	{
		if (ps->size == ps->cap)
		{
			AddSpace(ps);
		}
		ps->list[ps->size] = tmp;
		ps->size++;
	}
	fclose(pfRead);
	pfRead = NULL;
}

void AddSpace(wordlist* tmp)
{
	tmp->list = realloc(tmp->list, (tmp->cap + add_cap) * sizeof(word));
	if (tmp->list != NULL)
	{
		printf("增容成功\n");
	}
	else
		perror("增容失败\n");
	tmp->cap = tmp->cap + add_cap;
}
void AddWord(wordlist* ps)
{
	system("cls");
	if (ps->size == ps->cap)
		AddSpace(ps);
	printf("请输入单词:");
	scanf("%s", ps->list[ps->size].character);
	printf("请输入假名:");
	scanf("%s", ps->list[ps->size].kana);
	printf("请输入中文:");
	scanf("%s", ps->list[ps->size].chinese);
	ps->size++;
}

void ShowList(wordlist* ps)
{
	system("cls");
	int i = 0;
	if (ps->size == NULL)
	{
		printf("单词表为空\n");
		return;
	}
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		for (i = 0; i < ps->size; i++)
			printf("%-30s\t%-30s\t%-30s\n", ps->list[i].character, ps->list[i].kana, ps->list[i].chinese);
	}
}

void menu2()
{
	printf("1.通过单词查找\n");
	printf("2.通过假名查找\n");
	printf("3.通过中文查找\n");
	printf("4.返回\n");
}
void search1(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词:");
	char word_tmp[word_length] = { 0 };
	scanf("%s", word_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].character, word_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词的假名\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void search2(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词的中文:");
	char kana_tmp[word_length] = { 0 };
	scanf("%s", kana_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].kana, kana_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void search3(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词:");
	char chinese_tmp[word_length] = { 0 };
	scanf("%s", chinese_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].kana, chinese_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void SearchWord(wordlist* ps)
{
	system("cls");
	int inpu;
	menu2();
	scanf("%d", &inpu);
	switch (inpu)
	{
	case 1:
		search1(ps);
		break;
	case 2:
		search2(ps);
		break;
	case 3:
		search3(ps);
		break;
	case 4:
		return;
		break;
	default:
		break;
	}
	return;
}

void DelWord(wordlist* ps)
{
	system("cls");
	int i = 0;
	printf("请输入要删除的单词:");
	char word_tmp[word_length] = { 0 };
	scanf("%s", word_tmp);
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->list[i].character, word_tmp))
		{
			break;
		}
	}
	for (int j = i; j < ps->size-1; j++)
		ps->list[j] = ps->list[j + 1];
	ps->size--;
}

void menu3()
{
	printf("1.通过单词背中文\n");
	printf("2.通过假名背中文\n");
	printf("3.通过中文背单词\n");
	printf("4.返回\n");
}
void recite1(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].character);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.chinese, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
	    a++;
	    if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
			printf("回答错误,请重试\n");
	} while (a != 3);
}
void recite2(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].kana);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.chinese, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
		a++;
		if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
		printf("回答错误,请重试\n");
	} while (a != 3);
}
void recite3(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].chinese);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.character, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
		a++;
		if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
		printf("回答错误,请重试\n");
	} while (a != 3);
}
void ReciteWord(wordlist* ps)
{
	system("cls");
	int inpu;
	menu3();
	scanf("%d", &inpu);
	switch (inpu)
	{
	case 1:
		recite1(ps);
		break;
	case 2:
		break;
	case 3:
		break;
	case 4:
		return;
		break;
	default:
		break;
	}
}

void SaveList(wordlist* ps)
{
	FILE* pfWrite = fopen("words_list.dat", "wb");
	if (pfWrite == NULL)
	{
		perror("打开文件失败");
		return;
	}
	for (int i = ps->num; i < ps->size; i++)
	{
		fwrite(&(ps->list[i]), sizeof(word), 1, pfWrite);
		printf("已保存\n");
	}
	fclose(pfWrite);
	pfWrite = NULL;
}#include"func.h"

void menu1()
{
	printf("**** 1. 添加单词*** 2. 查找单词  ****\n");
	printf("**** 3. 删除单词*** 4. 展示单词表****\n");
	printf("**** 5. 背单词  *** 6. 保存      ****\n");
	printf("*****0. 退出    *********************\n");
	printf("请选择:");
}
void LoadWordlist(wordlist* ps);
void AddSpace(wordlist* tmp);
void InitList(wordlist* ps)
{
	ps->list=(word* )calloc(init_cap, sizeof(word));
	if (ps->list == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->cap = init_cap;
	LoadWordlist(ps);
	ps->num = ps->size;
}
void LoadWordlist(wordlist* ps)
{
	word tmp = { 0 };
	FILE* pfRead = fopen("words_list.dat", "rb");
	if (pfRead == NULL)
	{
		perror("读文件失败");
		return;
	}
	while (fread(&tmp, sizeof(word), 1, pfRead))
	{
		if (ps->size == ps->cap)
		{
			AddSpace(ps);
		}
		ps->list[ps->size] = tmp;
		ps->size++;
	}
	fclose(pfRead);
	pfRead = NULL;
}

void AddSpace(wordlist* tmp)
{
	tmp->list = realloc(tmp->list, (tmp->cap + add_cap) * sizeof(word));
	if (tmp->list != NULL)
	{
		printf("增容成功\n");
	}
	else
		perror("增容失败\n");
	tmp->cap = tmp->cap + add_cap;
}
void AddWord(wordlist* ps)
{
	system("cls");
	if (ps->size == ps->cap)
		AddSpace(ps);
	printf("请输入单词:");
	scanf("%s", ps->list[ps->size].character);
	printf("请输入假名:");
	scanf("%s", ps->list[ps->size].kana);
	printf("请输入中文:");
	scanf("%s", ps->list[ps->size].chinese);
	ps->size++;
}

void ShowList(wordlist* ps)
{
	system("cls");
	int i = 0;
	if (ps->size == NULL)
	{
		printf("单词表为空\n");
		return;
	}
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		for (i = 0; i < ps->size; i++)
			printf("%-30s\t%-30s\t%-30s\n", ps->list[i].character, ps->list[i].kana, ps->list[i].chinese);
	}
}

void menu2()
{
	printf("1.通过单词查找\n");
	printf("2.通过假名查找\n");
	printf("3.通过中文查找\n");
	printf("4.返回\n");
}
void search1(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词:");
	char word_tmp[word_length] = { 0 };
	scanf("%s", word_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].character, word_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词的假名\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void search2(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词的中文:");
	char kana_tmp[word_length] = { 0 };
	scanf("%s", kana_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].kana, kana_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void search3(wordlist* tmp)
{
	int i = 0;
	printf("请输入要查找的单词:");
	char chinese_tmp[word_length] = { 0 };
	scanf("%s", chinese_tmp);
	for (i = 0; i < tmp->size; i++)
	{
		if (0 == strcmp(tmp->list[i].kana, chinese_tmp))
		{
			break;
		}
	}
	if (i == tmp->size)
		printf("未找到所查单词\n");
	else
	{
		printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
		printf("%-30s\t%-30s\t%-30s\n", tmp->list[i].character, tmp->list[i].kana, tmp->list[i].chinese);
	}
}
void SearchWord(wordlist* ps)
{
	system("cls");
	int inpu;
	menu2();
	scanf("%d", &inpu);
	switch (inpu)
	{
	case 1:
		search1(ps);
		break;
	case 2:
		search2(ps);
		break;
	case 3:
		search3(ps);
		break;
	case 4:
		return;
		break;
	default:
		break;
	}
	return;
}

void DelWord(wordlist* ps)
{
	system("cls");
	int i = 0;
	printf("请输入要删除的单词:");
	char word_tmp[word_length] = { 0 };
	scanf("%s", word_tmp);
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->list[i].character, word_tmp))
		{
			break;
		}
	}
	for (int j = i; j < ps->size-1; j++)
		ps->list[j] = ps->list[j + 1];
	ps->size--;
}

void menu3()
{
	printf("1.通过单词背中文\n");
	printf("2.通过假名背中文\n");
	printf("3.通过中文背单词\n");
	printf("4.返回\n");
}
void recite1(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].character);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.chinese, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
	    a++;
	    if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
			printf("回答错误,请重试\n");
	} while (a != 3);
}
void recite2(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].kana);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.chinese, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
		a++;
		if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
		printf("回答错误,请重试\n");
	} while (a != 3);
}
void recite3(wordlist* tmp)
{
	int i = rand() % (tmp->size);
	printf("%s\n", tmp->list[i].chinese);
	int a = 0;
	word ret = tmp->list[i];
	char word_tmp[word_length];
	do
	{
		printf("请输入中文意思(错误3次直接看答案):");
		scanf("%s", word_tmp);
		if (0 == strcmp(ret.character, word_tmp))
		{
			printf("回答正确\n");
			break;
		}
		a++;
		if (a == 3)
		{
			printf("%-30s\t%-30s\t%-30s\n", "单词", "假名", "中文意思");
			printf("%-30s\t%-30s\t%-30s\n", ret.character, ret.kana, ret.chinese);
			break;
		}
		printf("回答错误,请重试\n");
	} while (a != 3);
}
void ReciteWord(wordlist* ps)
{
	system("cls");
	int inpu;
	menu3();
	scanf("%d", &inpu);
	switch (inpu)
	{
	case 1:
		recite1(ps);
		break;
	case 2:
		break;
	case 3:
		break;
	case 4:
		return;
		break;
	default:
		break;
	}
}

void SaveList(wordlist* ps)
{
	FILE* pfWrite = fopen("words_list.dat", "wb");
	if (pfWrite == NULL)
	{
		perror("打开文件失败");
		return;
	}
	for (int i = ps->num; i < ps->size; i++)
	{
		fwrite(&(ps->list[i]), sizeof(word), 1, pfWrite);
		printf("已保存\n");
	}
	fclose(pfWrite);
	pfWrite = NULL;
}

program.c

#include"func.h"

int main()
{
	int input = 0;
	wordlist List;
	InitList(&List);
	srand((unsigned int)time(NULL));
	do
	{
		printf("当前单词数量:%d  当前单词最大数量:%d\n", List.size, List.cap);
		menu1();
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddWord(&List);
			break;
		case SEARCH:
			SearchWord(&List);
			break;
		case DEL:
			DelWord(&List);
			break;
		case SHOW:
			ShowList(&List);
			break;
		case RECITE:
			ReciteWord(&List);
			break;
		case SAVE:
			SaveList(&List);
			break;
		case EXIT:
			SaveList(&List);
			printf("已退出\n");
			break;
		default:
			break;
		}
	} while (input);
	free(List.list);
	List.list == NULL;
	return 0;
}

我已经将源码发到我的Github上了。链接:xwz639-739/worddictionary (github.com)

可能与当前代码有出入,以这一版为准。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xwz639_739

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

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

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

打赏作者

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

抵扣说明:

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

余额充值