一.这一部曲是紧接第二部没有介绍完的内容,主要是函数接口实体的实现,代码比较多,如果没有看前两部曲的先去看看,再来看这里,不然不好理解,话不说多上代码,

 #define  _CRT_SECURE_NO_WARNINGS
#include "dict.h" /**************函数实现************************/
/*统计文件中单词数量,返回单词数量*/
int statWordCount(char *filaename)
{
FILE *F = fopen(filaename, "r");
if (F == NULL)
{
printf("文件打开失败");
return -;
}
else
{
int num = ;
while (!feof(F))
{
char buf[];
fgets(buf, , F);
num++;
}
fclose(F);
return num / ;//两行对应一个单词 }
}
/*加载文本词库文件*/
void loadTextFile(char *filename)
{
LEN = statWordCount(filename);//计算单词数量
mallocForSArra(LEN);//为单词结构体数组分配内存
FILE *F = fopen(filename, "r");
if (F == NULL)
{
printf("加载文件失败");
return;
}
createInitArray(F);//创建并初始化结构体数组
printf("OK\n"); }
/*加载二进制词库文件*/
void loadBinFile(char *filename)
{
FILE *F = fopen(filename, "rb");
if (F == NULL)
{
printf("打开文件失败");
return;
} createInitBinArr(F); }
/*为长度为len的结构体数组分配内存*/
void mallocForSArra(int len)
{
DICT = (SWORD *)malloc(sizeof(SWORD)*len);
}
/*对结构体dict数组进行排序,使用插入排序*/
void sortStructArr(SWORD * dict)
{
SWORD SW;
int j;
int i;
for (i = ; i < LEN; i++)
{
SW = dict[i];
for (j = i; j> && wordcmp(dict[j-],SW) > ; j--)
{
dict[j] = dict[j - ];
}
dict[j] = SW;
}
printf("ok"); }
/*输入模块,返回输入字符串*/
char *getInput(char *p)
{ scanf("%s",p);
//printf("%s", p);
return p;
}
/*输出模块,输出一个结构体*/
void setOutput(SWORD *word)
{
if (word == NULL)
{
printf("没有找到您输入的单词\n");
return;
}
printf("\n%s", word->key);
int len = word->count_trans;
printf("\n解释:\n");
for (int i = ; i < len; i++)
{
printf("\n\t%s", word->trans[i]);
} }
/*查询模块,使用二分法,据关键词key在词库里查询,找到返回这个结构体位置,否则返回NULL*/
SWORD *searchWord(char *key)
{
//printf("%s\n",key);
//int low = 0;
//int high = LEN;
//while (low < high)
//{
// int mid = (low + high) / 2; // if (strcmp(key,DICT[mid].key) == 0)
// {
// printf("%s", DICT[mid].key);
// return DICT + mid; // }
// else if (strcmp(key, DICT[mid].key) > 0)
// {
// low = mid + 1;
// }
// else
// {
// high = mid - 1;
// printf("%s*********", DICT[mid].key);
//
// }
//}
//int len = strlen(key);
//int dictlen = strlen(DICT[0].key);
//printf("%d\t%d", len, dictlen);
//printf("%s*********", DICT[0].key);
for (int i = ; i < LEN; i++)
{
if (strcmp(key, DICT[i].key) == )
{
return DICT + i;
} } return NULL; }
/*从输入获取要添加的单词*/
void getWord(SWORD *word)
{ printf("请输入要添加的单词(输入#over结束添加):");
scanf("%s", word->key); printf("%s", word->key); printf("请输入解释数量:");
scanf("%d", &(word->count_trans));
for (int i = ; i < word->count_trans; i++)
{
printf("请输入第%d条解释:",i+);
scanf("%s", (word->trans)[i]);
}
printf("hello"); } /*添加单词word到结构体数组,弃用*/
void addWordToArr(SWORD *word)
{
//给词库添加单词
//int len = (*word).count_trans; //puts((*word).key);
//for (int i = 0; i < len; i++)
//{
// puts((*word).trans[i]);
//} //printf("%d\n", LEN);
//printf("%s\n", DICT[LEN - 1].key);
//printf("%d\n", DICT[LEN - 1].count_trans);
//for (size_t i = 0; i < DICT[LEN - 1].count_trans; i++)
//{
// printf("%s\n", DICT[LEN - 1].trans[i]);
//}
LEN = LEN + ;
DICT = (SWORD *)realloc(DICT, LEN);
DICT[ - ] = *word; //puts((*word).key);
//for (int i = 0; i < len; i++)
//{
// puts((*word).trans[i]);
//}
//printf("%d\n", (*word).count_trans); //int keylen = strlen((*word).key)+1;
//分配单词空间并填充
//DICT[LEN - 1].key = (char *)malloc(sizeof(char) * keylen);
//strcpy(DICT[LEN - 1].key, word->key);
//DICT[LEN - 1].key[keylen - 1] = '\0';
////解释长度
//int transnum = word->count_trans;
//DICT[LEN - 1].count_trans = transnum; //DICT[LEN - 1].trans = (char **)malloc(sizeof(char *)*transnum);
////解释空间分配与填充
//for (int i = 0; i < transnum; i++)
//{
// int trlen = strlen(word->trans[i])+1;
// DICT[LEN - 1].trans[i] = (char *)malloc(sizeof(char)* trlen);
// strcpy(DICT[LEN - 1].trans[i], word->trans[i]);
// DICT[LEN - 1].trans[i][trlen - 1] = '\0';
//} }
/*保存一个单词到文件*/
void saveWord(char *filename,SWORD *sw)
{
FILE *F = NULL;
if (!_access(filename, ))//如果文件存在
{
F = fopen(filename, "a");
if (F == NULL)
{
printf("保存词库到文件失败");
return;
} char str[];
sprintf(str, "#%s", sw->key);
fputs(str, F); char trans[] = "";
for (int i = ; i < sw->count_trans; i++)
{
char strs[];
if (i == )
{
sprintf(strs, "Trans:%s", sw->trans[i]);
}
else
{
sprintf(strs, "@%s", sw->trans[i]);
}
strcat(trans, str); }
fputs(trans, F);//将解释写入文件 fclose(F); }
else
{
F = fopen(filename, "w");
if (F == NULL)
{
printf("保存词库到文件失败");
return;
} char str[];
sprintf(str, "#%s", sw->key);
fputs(str, F); char trans[] = "";
for (int i = ; i < sw->count_trans; i++)
{
char strs[];
if (i == )
{
sprintf(strs, "Trans:%s", sw->trans[i]);
}
else
{
sprintf(strs, "@%s", sw->trans[i]);
}
strcat(trans, str); }
fputs(trans, F);//将解释写入文件 fclose(F);
} }
/*生成二进制的词库文件,30位字符块大小*/
void createBinFile(SWORD *word)
{
FILE *F = fopen(dictbitname, "wb");
if (F == NULL)
{
printf("打开文件失败");
return;
}
printf("打开文件成功");
fwrite(&LEN, sizeof(int), , F);//前四个字节存储单词个数
printf("写入长度成功");
for (; word <= DICT+LEN-; word += )
{
fwrite(word->key, sizeof(char),, F);
//printf("写入单词成功");
fwrite(&(word->count_trans), sizeof(int),, F); //printf("写入解释数量%d成功", word->count_trans);
for (int i = ; i < word->count_trans; i++)
{ fwrite(word->trans+i, sizeof(char), , F);
//printf("\n写入解释成功"); }
}
fclose(F); } /*计算一个字符串里某个ch字符的个数*/
int calcNumber(char *str,char ch)
{
int num = ;
for (char *p =str; *p != '\0'; p++)
{
if (*p == ch)
{
num++;
}
}
return num;
}
/*从字符串str中取出字符ch后面的字符串*/
char *rearstr(char *str, char ch,int *pos)
{
char *p = strrchr(str, ch);
*pos = p - str;
p = p + ;
return p;
} /*创建并初始化词库结构体数组*/
void createInitArray(FILE *F)
{
for (int i = ; i < LEN; i++)
{
char str[] = { };
fgets(str, , F);
char *temp = str + ;
int length = strlen(temp);//分配空间长度排除#号
DICT[i].key = (char *)malloc(sizeof(char)*length);//一条关键字分配内存
strcpy(DICT[i].key, temp);
DICT[i].key[length - ] = '\0';//关键词 char strtrans[] = { };
fgets(strtrans, , F); int len = strlen(strtrans) + ;//加1是考虑到'\0'
char *ch = (char *)malloc(sizeof(char)*len);//给每一个指针所指的字符串分配内存
strcpy(ch, strtrans);//将数组里的字符串拷贝到ch中但不带'\0'
ch[len - ] = '\0';//添加字符串结束标记 int number = calcNumber(strtrans, '@') + ;
DICT[i].count_trans = number;//解释的数量 DICT[i].trans = (char **)malloc(sizeof(char *)*number); char *transtemp = strtrans + ;
char *tok = strtok(transtemp, "@");
int j = ;
while (tok != NULL)
{
int translen = strlen(tok)+;
DICT[i].trans[j] = (char *)malloc(sizeof(char)*translen);//给每一条解释分配存储空间
strcpy(DICT[i].trans[j], tok);
DICT[i].trans[j][translen - ] = '\0'; tok = strtok(NULL, "@");
j++;
} }
} /*比较两个SWORD单词的大小,前一个大于后一个返回1,前一个小于后一个返回-1,前一个等于后一个返回0*/
int wordcmp(SWORD wordf, SWORD wordr)
{
if (strcmp(wordf.key, wordr.key) == )
{
return ;
}
else if (strcmp(wordf.key, wordr.key) > )
{
return ;
}
else
{
return -;
}
} /*创建并初始化二进制加载文件对应的的数组,30为写入块大小*/
void createInitBinArr(FILE *F)
{
fread(&LEN, sizeof(int), , F);//先读取四个字节初始化词库长度
mallocForSArra(LEN);//为词库数组分配内存
SWORD *TEMP = DICT;
while (!feof(F))//不在文件末尾
{ TEMP->key = (char *)malloc(sizeof(char)* );//一条关键字分配内存
fread(TEMP->key, sizeof(char), , F); fread(&(TEMP->count_trans), sizeof(int), , F);//读取解释数量
TEMP->trans = (char **)malloc(sizeof(char *)*(TEMP->count_trans)); for (int i = ; i < TEMP->count_trans; i++)
{
TEMP->trans[i] = (char *)malloc(sizeof(char)*);//给每一条解释分配存储空间
fread(TEMP->trans[i], sizeof(char), , F);
} }
}
/*查询模块函数*/
void searchModel()
{ //开始查询
char p[] = { };
printf("请输入要查找的单词:");
char *instr = getInput(p);
while (strcmp(instr, "#exit") != )//不等于#exit就一直查找
{
/* printf("%s", instr);*/ SWORD *wd = searchWord(instr); setOutput(wd);
printf("请输入要查找的单词(输入#exit退出查询):");
instr = getInput(p);
} }
/*添加单词模块函数*/
void addWordModel()
{ SWORD word;
word.key = (char *)malloc(sizeof(char)* );//开辟单词输入缓冲区 word.trans = (char **)malloc(sizeof(char *)* );//开辟解释输入缓冲区 for (int i = ; i < ; i++)
{
word.trans[i] = (char *)malloc(sizeof(char)* );
}
//char key[100] = {0};
//char trans[10][50] = {0};
//word.key = key;
//word.trans = trans;
// getWord(&word); //int len = word.count_trans;
//puts(word.key);
//for (int i = 0; i < len; i++)
//{
// puts(word.trans[i]);
//} do
{ getWord(&word);//获取单词 printf("是否保存词库数组到文件(输入0退出程序,1保存,2不保存):0/1/2?\n"); int yesorno;
scanf("%d", &yesorno);
if (yesorno == )
{
saveWord(dicttxtname, &word);/*保存词库结构数组到文件*/
}
else if (yesorno == )
{
exit();
}
else
{ } } while (strcmp(word.key, "#over") != ); }

二.至此整个电子词典项目介绍完了,在加载二进制文件和读取时有些小bug,运行结果在第二部曲中有描述,本人目前换有一个计划,那就是监听键盘输入以及获取聊天信息,有意的朋友们欢迎一起交流,再次感谢大家。

c语言项目流程开发三部曲的更多相关文章

  1. 基于Linux下的C语言项目实战--本地账号管理系统

    C语言开发项目实战: C语言是一门通用计算机编程语言,广泛应用于底层开发.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言.尽 ...

  2. Atitit 项目管理 提升开发效率的项目流程方法模型 哑铃型  橄榄型 直板型

    Atitit 项目管理 提升开发效率的项目流程方法模型 哑铃型  橄榄型 直板型 项目主体三个部分 ui界面,中间层,数据库 按照不同的比重可以分为一下三个模型  哑铃型  橄榄型 直板型 哑铃型 开 ...

  3. iOS开发项目之一 [ 项目流程]

    项目流程 *人员配置 *客户端(iOS工程师,Android工程师) *前端 h5 *后台人员(php,java,net) *提供接口(请求地址.请求参数,请求方式,接口文档) *UI UE * 效果 ...

  4. django搭建简单开发项目流程(一)

    1 搭建环境 sudo apt-get install python3-pip 安装pip3 sudo pip3 install virtualenv 安装虚拟环境 virtualenv -p pyt ...

  5. 【C语言项目】贪吃蛇游戏(上)

    目录 00. 目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) 3.5 欢迎界面函 ...

  6. 基于ABP开发框架的技术点分析和项目快速开发实现

    在我们开发各种项目应用的时候,往往都是基于一定框架进行,同时配合专用的代码生成工具,都是为了快速按照固定模式开发项目,事半功倍,本篇随笔对基于ABP开发框架的技术点进行分析和ABP框架项目快速开发实现 ...

  7. AI全流程开发难题破解之钥

    摘要:通过对ModelArts.盘古大模型.ModelBox产品技术的解读,帮助开发者更好的了解AI开发生产线. 本文分享自华为云社区<[大厂内参]第16期:华为云AI开发生产线,破解AI全流程 ...

  8. K2 blackpearl 流程开发(一)

    转:http://blog.csdn.net/gxiangzi/article/details/8444060 郁闷,今天K2的license过期了,很多东西都没法用了,还得去找PM大大帮忙申请一个. ...

  9. Go语言项目的错误和异常管理 via 达达

    Go语言项目的错误和异常管理 最近连续遇到朋友问我项目里错误和异常管理的事情,之前也多次跟团队强调过错误和异常管理的一些概念,所以趁今天有动力就赶紧写一篇Go语言项目错误和异常管理的经验分享. 首先我 ...

随机推荐

  1. 如何编写单元测试-基于Spring

    单元测试 首先单元测试真的算是一种"脏活累活",但是我个人感觉还是有必要,至少本人最近开始写单元测试后还是能发现一些"bug"的. 如何写单元测试 单元测试的要 ...

  2. less简述

       什么是less? 一种 动态 样式 语言. LESS 将 CSS 赋予了动态语言的特性,如 变量, 继承, 运算, 函数. LESS 既可以在 客户端 上运行 (支持IE 6+, Webkit, ...

  3. SQL Server 结构分解

    关系引擎和存储引擎是SQL Server 的两大组件,其中关系引擎也叫查询处理器,它包括查询优化器.命令解析器.查询执行器.存储引擎管理所有的数据及涉及的IO,它包括事务管理器和数据访问方法和缓冲区管 ...

  4. 深度解析continue,break和return

    continue,break和return是Java中的关键字,在方法体内的流程控制中使用频率较高. 在现实中,经常会有同学在使用中产生混淆,从而使得流程控制语句发生混乱.在这里,我结合个人的使用经历 ...

  5. MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作)

    MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作): a.创建2张表 create table userinfo(nid int not nul ...

  6. Qt颜色下拉框

    上周为了用Qt写一个类似颜色下拉框的东西,查阅了网上的多数相关资料,依然没有我想要的.终于在周四的时候下定决心重写QCombobox类来实现功能,现在把它贴出来,望看到的人,批评指正.废话不多说,先上 ...

  7. DOM操作中,getElementByXXXX 和 querySelector 的区别

    1. 返回值:     getElements返回动态集合:       优: 首次查找效率高      缺: 可能造成反复查找DOM树    querySelector返回非动态集合:      优 ...

  8. static,final,包,访问修饰符,内部类

    static 关键字可以修饰成员变量,被static修饰的成员变量归属于类static关键字可以修饰成员方法:被static修饰的成员方法可以直接使用类名调用,也可以通过对象调用,建议使用类名.非静态 ...

  9. JavaScript:彻底理解同步、异步和事件循环(Event Loop)

    一. 单线程 我们常说"JavaScript是单线程的". 所谓单线程,是指在JS引擎中负责解释和执行JavaScript代码的线程只有一个.不妨叫它主线程. 但是实际上还存在其他 ...

  10. JAVA基础-JDBC二(常用的开源工具)

    一.连接池 在实际的开发应用中,我们常常会对数据库进行大量的高并发的访问,而最原始的连接和操作方式并不能满足这种大量的访问,程序员为了追求更方便.更快捷.更科学安全的开发.第三方的工具类和Dao层的框 ...