C小项目——电子词典
来源:互联网 发布:php json数组 编辑:程序博客网 时间:2024/06/06 09:02
C语言项目——查字典
宗旨:技术的学习是有限的,分享的精神是无限的。
【项目需求描述】
一、单词查询
给定文本文件“dict.txt”,该文件用于存储词库。词库为“英-汉”,“汉-英”双语词典,每个单词和其解释的格式固定,如下所示:
#单词
Trans:解释1@解释2@…解释n
每个新单词由“#”开头,解释之间使用“@”隔开。一个词可能有多个解释,解释均存储在一行里,行首固定以“Trans:”开头。下面是一个典型的例子:
#abyssinian
Trans:a. 阿比西尼亚的@n. 阿比西尼亚人;依索比亚人
该词有两个解释,一个是“a. 阿比西尼亚的”;另一个是“n. 阿比西尼亚人;依索比亚人”。
要求编写程序将词库文件读取到内存中,接受用户输入的单词,在字典中查找单词,并且将解释输出到屏幕上。用户可以反复输入,直到用户输入“exit”字典程序退出。
程序执行格式如下所示:
./app –text
-text表示使用文本词库进行单词查找。
二、建立索引,并且使用索引进行单词查询
要求建立二进制索引,索引格式如下图所示。将文本文件“dict.txt”文件转换为上图所示索引文件“dict.dat”,使用索引文件实现单词查找。程序执行格式如下:
./app –index
-index表示使用文本词库dict.txt建立二进制索引词库dict.dat
./app –bin
-bin表示使用二进制索引词库进行单词查找。
//================================================================================================================
一、文本文件单词查询
1、单词结构:
#单词
Trans:解释1@解释2@…解释n
在dict.txt文件中,单词占一行,以“#”开头;解释以“Trans:”开头,内容以“@”分隔。结构我采用链表。具体结构定义如下:
// 单词链表 ---- 单词名称,翻译的个数,单词翻译的结果
typedef struct dict
{
char word[TARGET_WORD_MAX_SIZE]; // 要输入的单词,如"#superstar"
uint8_t mean_count; // 单词解释的个数,如既可以做名词也可以做动词,
char trans[TARGET_WORD_MEANING_COUNT][TARGET_WORD_MAX_TRANSLATION]; // 翻译结果,用@分开(strtok分割函数)
struct dict *next;
} word_t, *dict_t;
2、接口定义
2.1、文件中单词的总数:要建立单链表,就要知道单链表的长度,因此,要知道文件中单词的总个数,定义如下接口:
uint32_t ListCount(FILE *fp); // 词典里面单词的个数,即是要创建链表的长度
2.2、创建单链表:从文件中一项一项读出单词及其解释,填充到单词结构体中,创建单链表就是分配内存并连接节点的过程,定义接口如下(count是单词的总数):
dict_t CreateList(dict_t head, FILE *fp, uint32_t count); // 创建单链表,返回首节点。分配内存。
2.3、查找单词:从链表中匹配要查找的单词,找到了就输出单词解释,定义接口如下:
void SearchList(dict_t head, uint32_t count); // 查找输入的单词
2.4、释放内存:创建链表分配的内存在结束时释放,定义接口如下:
void DestroyList(dict_t head); // 释放内存
二、建立索引文件dict.data
1、索引结构
如上图所示,包含如下内容:索引头单词个数(4字节),单词1的单词长度(4字节),单词1的内容(单词长度个字节),单词1的解释个数(4字节),解释1的长度(4字节),解释1的内容(解释1的长度),解释2的长度(4字节),解释2的内容(解释2的长度)...按照这个格式将dict.txt文件的内容写到dict.dat的索引文件中。结构和上面文本查询的结构一样。
2、接口定义
将链表的节点按上面的格式一个一个写到索引文件dict.dat中,用fwrite函数写,定义接口如下:
// 链表头结点head,文件名,链表长度
void WriteIndexFile(dict_t head, const char *filename, uint32_t count);
三、索引文件查找单词
上面建立了索引文件,并按协议的格式将文本文件的内容写到了索引文件中,通过索引查找单词就是从索引文件读出要查找的单词,用fread函数读,接口定义如下:
void ReadIndexFile(dict_t head, const char *filename, uint32_t *count);
具体实现:
#ifndef _TARGET_H_#define _TARGET_H_#include <stdlib.h>#include <stdio.h>#include <string.h>typedef unsigned char uint8_t;typedef unsigned int uint32_t;#define TARGET_TEXT_NAME "./dict.txt"#define TARGET_INDEX_NAME "./dict.dat"#define TARGET_WORD_MAX_SIZE 60#define TARGET_WORD_MEANING_COUNT 20#define TARGET_WORD_MAX_TRANSLATION 100#define TARGET_WORD_BUFFER 1024// 单词链表 ---- 单词名称,单词有几种翻译,单词翻译的结果typedef struct dict{ char word[TARGET_WORD_MAX_SIZE]; // 要输入的单词,如"#superstar" uint8_t mean_count; // 单词解释的个数,如既可以做名词也可以做动词,用@分开 char trans[TARGET_WORD_MEANING_COUNT][TARGET_WORD_MAX_TRANSLATION]; // 翻译结果 struct dict *next;} word_t, *dict_t;uint32_t ListCount(FILE *fp); // 词典里面单词的个数,即是要创建链表的长度dict_t CreateList(dict_t head, FILE *fp, uint32_t count); // 创建单链表,返回首节点。分配内存。void SearchList(dict_t head, uint32_t count); // 查找输入的单词void DestroyList(dict_t head); // 释放内存void WriteIndexFile(dict_t head, const char *filename, uint32_t count);void ReadIndexFile(dict_t head, const char *filename, uint32_t *count);void Process(int argc, char **argv); // 主进程,main函数主要调用接口#endif /* _TARGET_H_ */
main.c
#include "target.h"int main(int argc, char **argv){ if(argc < 2) { fprintf(stderr, "input params is too few!\n"); return 1; } Process(argc, argv); return 0;}
process.c:
#include "target.h"static const char params[][15] = {"-text", "-index", "-bin", "-test1 -f", "-test2 -f"};voidProcess(int argc, char **argv){ FILE *fp; dict_t head; uint32_t count; if((fp = fopen(TARGET_TEXT_NAME, "r")) == NULL) { fprintf(stderr, "open file failure!\n"); exit(1); } count = ListCount(fp); printf("count: %d\n", count); printf("open sucess!\n"); if((strcmp(argv[1], params[0])) == 0) { head = CreateList(head, fp, count); SearchList(head, count); fclose(fp); DestroyList(head); } if((strcmp(argv[1], params[1])) == 0) { head = CreateList(head, fp, count); fclose(fp); WriteIndexFile(head, TARGET_INDEX_NAME, count); DestroyList(head); } if(strcmp(argv[1], params[2]) == 0) { head = CreateList(head, fp, count); ReadIndexFile(head, TARGET_INDEX_NAME, &count); SearchList(head, count); fclose(fp); DestroyList(head); }}
find_word_from_text.c
#include "target.h"static char file_exist;uint32_tListCount(FILE *fp) // 单词的个数即是链表的长度{ uint32_t count = 0; char buffer[100]; while(fgets(buffer, sizeof(buffer), fp)) { if('#' == buffer[0]) { ++count; } } rewind(fp); // 这一步一定要做,使文件指针指向文件头 return count;}dict_tCreateList(dict_t head, FILE *fp, uint32_t count) // 创建链表,返回头结点{ dict_t new, pointer; char buf[TARGET_WORD_BUFFER]; uint8_t word_size, trans_size, mean_count = 1, *str; uint32_t i, j = 0; head = (dict_t)malloc(sizeof(word_t)); //分配节点空间 if(NULL == head) { fprintf(stderr, "malloc failure!\n"); exit(1); } printf("head success!\n"); if(count > 0) { memset(buf, 0, sizeof(buf)); fgets(buf, sizeof(buf), fp); word_size = strlen(buf); buf[word_size - 1] = '\0'; strcpy(head->word, buf); memset(buf, 0, sizeof(buf)); fgets(buf, sizeof(buf), fp); trans_size = strlen(buf); buf[trans_size - 1] = '\0'; str = strtok(buf, "@"); strcpy(head->trans[j++], str + 6); while(str = strtok(NULL, "@")) { strcpy(head->trans[j++], str); ++mean_count; } head->mean_count = mean_count; head->next = NULL; // 到这里为止填充了首节点,并将首节点的下一个节点指向空 pointer = head; for(i = 0; i < count - 1; ++i) // 将后面(count-1)个依次链接到首节点后面 { mean_count = 1; new = (dict_t)malloc(sizeof(word_t)); //分配节点空间 memset(buf, 0, sizeof(buf)); fgets(buf, sizeof(buf), fp); word_size = strlen(buf); buf[word_size - 1] = '\0'; strcpy(new->word, buf); memset(buf, 0, sizeof(buf)); fgets(buf, sizeof(buf), fp); trans_size = strlen(buf); buf[trans_size - 1] = '\0'; for(j = 0; j < count;) { str = strtok(buf, "@"); strcpy(new->trans[j++], str + 6); while(str = strtok(NULL, "@")) { strcpy(new->trans[j++], str); ++mean_count; } } new->mean_count = mean_count; new->next = NULL; pointer->next = new; pointer = new; } } rewind(fp); return head;}voidPrintList(dict_t head){ dict_t pointer; pointer = head; while(pointer != NULL) { printf("pointer->word = %s, pointer->mean_count = %d\n", pointer->word, pointer->mean_count); pointer = pointer->next; }}voidSearchList(dict_t head, uint32_t count) // 从链表中查找单词{ dict_t pointer; char str[TARGET_WORD_MAX_SIZE]; uint32_t i; while(1) { file_exist = 0; pointer = head; printf("Please input a word:"); fgets(str, TARGET_WORD_MAX_SIZE, stdin); str[strlen(str) - 1] = '\0'; if(strcmp(str, "exit") == 0) { exit(1); } while(pointer != NULL) { if((strcmp(pointer->word, str)) == 0) { for(i = 0; i < pointer->mean_count; ++i) { file_exist = 1; fprintf(stdout, "Trans%d: %s\n", i + 1, pointer->trans[i]); } break; } pointer = pointer->next; } if(file_exist == 0) {
// 这里判断了该单词不存在,可以选择添加,也可以选择退出;/* printf("no find!\n"); printf("Do you want to add a new word?:(Y/N)\n"); scanf("%c", &new_word); if(new_word == 'Y' || new_word == 'y') { AddWordToText(head, TARGET_CUSTOM_TEXT); }*/ exit(1); } }}voidDestroyList(dict_t head) { dict_t pointer; while(pointer != NULL) { pointer = head; head = head->next; free(pointer); }}
find_word_from_index.c
#include "target.h"voidWriteIndexFile(dict_t head, const char *filename, uint32_t count) // 建立索引,按协议格式写入文件{ FILE *stream; uint32_t i, word_size, trans_size, mean_count; uint8_t j; dict_t pointer = head; if((stream = fopen(filename, "wb")) == NULL) { fprintf(stderr, "Cannot open output file.\n"); exit(1); } fwrite(&count, 4, 1, stream); while(pointer != NULL) { word_size = strlen(pointer->word); mean_count = pointer->mean_count; fwrite(&word_size, 4, 1, stream); fwrite(pointer->word, 1, word_size, stream); fwrite(&mean_count, 4, 1, stream); for(j = 0; j < mean_count; ++j) { trans_size = strlen(pointer->trans[j]); fwrite(&trans_size, 4, 1, stream); fwrite(pointer->trans[j], 1, trans_size, stream); } pointer = pointer->next; } fclose(stream);}voidReadIndexFile(dict_t head, const char *filename, uint32_t *count) // 从文件中读出单词内容{ FILE *stream; uint8_t i; uint32_t word_size, trans_size, mean_count; dict_t pointer = head; printf("enter...\n"); if((stream = fopen(filename, "rb")) == NULL) { fprintf(stderr, "Cannot open output file.\n"); exit(1); } // printf("read file success!...\n"); fread(count, 4, 1, stream); printf("count = %d\n", *count); while(pointer != NULL) { fread(&word_size, 4, 1, stream); // printf("word_size = %d\n", word_size); fread(pointer->word, 1, word_size, stream); pointer->word[word_size] = '\0'; fread(&pointer->mean_count, 4, 1, stream); //printf("pointer->word = %s\n", pointer->word); //printf("pointer->mean_count = %d\n", pointer->mean_count); for(i = 0; i < pointer->mean_count; ++i) { memset(pointer->trans[i], 0, sizeof(pointer->trans[i])); fread(&trans_size, 4, 1, stream); fread(pointer->trans[i], 1, trans_size, stream); pointer->trans[i][trans_size] = '\0'; printf("trans_size = %d\n", trans_size); printf("pointer->trans = %s\n", pointer->trans[i]); } pointer = pointer->next; } //fclose(stream); printf("read over!\n");}
先用gcc编译生成可执行文件app,再分别执行文本查询,索引建立和索引查询。
- C小项目——电子词典
- 第十九周—c语言 电子词典项目
- 英汉电子词典小项目总结
- 第十四周项目四——电子词典
- 第十四周项目四——电子词典
- 第十四周项目四—电子词典
- 第十七周项目七—电子词典
- 第十六周实践项目3————电子词典
- C++第15周项目5——-电子词典
- 15周项目五。电子词典——这是咋回事?
- 第14周上机实践项目4——电子词典
- 第十四周项目——电子词典(一般方法)
- 第十四周项目4:电子词典——二分法查找
- 第14周上机实践项目3——电子词典
- 15第十四周项目三——OOP版电子词典
- 第十六周上机实践——项目3-电子词典
- 电子词典项目
- 课程设计—电子词典
- cf#186-C. Mr. Kitayuta, the Treasure Hunter-dp(预推断+offset)
- Rectangle Area-带有交差集矩形面积
- 单链表的反转
- regex_iterator()的使用sregex_iterator(),cregex_iterator()
- 多线程 线程的创建方式和多线程共享资源
- C小项目——电子词典
- 位运算符基础
- 挑战密室(化学方程式)
- 静变量static、全局变量extern、局部变量、实例变量
- Oracle学习笔记——1、基本的SQL语句
- java/android基础总结2
- BootStrap——Start
- Django数据模型动态增删字段(更改数据库模式)
- POJ--3187--Backward Digit Sums