由于本实验主要是理解文件操作,这里先不把问题负责化。通常,词典中的词条包含单词、音标、解释、例句、短语等项目,电子词典还可能会提供朗读等信息。这里,只保留了其中最主要的两项:单词和解释。
效果如下:
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define DEFAULT_FILENAME "mydict.dat"
/*宏定义*/
#define FIND_WORD_CMD 1
#define ADD_WORD_CMD 2
#define HELP_CMD 3
#define EXIT_CMD 4
#define UNKNOWN_CMD -1
/*函数的定义*/
void FileReadLine(FILE *file, char *buf);
void FileWriteLine(FILE *file, char *buf);
int DictFindWord(FILE *file, char *word, char *exp);
void DictAddWord(FILE *file, char *word, char *exp);
int DecodeCommand(char *cmdbuf, char *wordbuf, char *expbuf, int bufsize);
int GetCommandCatagory(char cmdcatach);
void PrintHelpInfo();
/*主函数,程序入口*/
int main(int argc, char *argv[]){
int res, i;
char *dictfilename;
FILE *dictfile;
char nowch;
char cmdbuf[100], wordbuf[80], expbuf[80];
/*确定字典文件的文件名*/
if(argc < 2){
dictfilename = DEFAULT_FILENAME;
}else{
dictfilename = argv[1];
}
/*打开字典文件*/
dictfile = fopen(dictfilename, "a+");
/*如果打开失败,输出错误信息*/
if(dictfile == NULL){
printf("Error:Cannot open the dictionary file.\n");
return 1;
}
printf("\n *** Little Console Dictionary ***\n\n");
while(1){
/*输出提示符,等待用户输入命令*/
printf("? ");
i = res = 0;
/*接收用户输入的命令。采用这种方式主要是为了避免scanf函数不支持*/
/*空格键的问题*/
while((nowch = getchar())!= '\n'){
/*命令最长为1000个字符,超过这个长度则不再接收,并记录*/
if(i < 99){
cmdbuf[i++] = nowch;
}else{
res = -1;
}
}
/*如果输入的命令过长,则打印错误信息,并返回重新接收命令*/
if(res == -1){
printf("Too long command. \n");
continue;
}
/*接收的字符串末尾添加"\0",以便程序正常处理*/
cmdbuf[i] = '\0';
/*对命令进行译码,得到命令类型和参数*/
res = DecodeCommand(cmdbuf, wordbuf, expbuf, 80);
/*根据不同命令。进行不同的操作*/
switch(res){
/*处理查询单词的命令处理*/
case FIND_WORD_CMD:
/*用户未输入要查询的单词则输出错误信息*/
if(strlen(wordbuf) < 1){
printf("Too few parameters : 1 [word]\n");
break;
}
/*进行单词查找,否则输出错误信息*/
res = DictFindWord(dictfile, wordbuf, expbuf);
if(res == 1){
printf("Word: %s\n",wordbuf);
printf("Expression: %s\n",expbuf);
}else{
printf("No such word \'%s\'\n", wordbuf);
}
break;
/*增加词典词条的命令处理*/
case ADD_WORD_CMD:
if(strlen(wordbuf) < 1 || strlen(expbuf) < 1){
printf("Too few parameters: a [word] [exp]\n");
break;
}
/*添加单词到词典*/
DictAddWord(dictfile, wordbuf, expbuf);
printf("Add word \'%s\' into dictionary successfully.\n", wordbuf);
break;
/*输出帮助信息的命令处理*/
case HELP_CMD:
PrintHelpInfo();
break;
/*退出命令的处理*/
case EXIT_CMD:
/*输出结束信息*/
printf("Goodbye\n");
/*关闭词典文件*/
fclose(dictfile);
return 0;
break;
default:
/*对非法命令的处理*/
printf("Unknown Command\n");
break;
}
}
/*虽然不会执行该语句,但是有时可以避免编译器输出警告信息。*/
return 0;
}
/*读取文件file中的一行文本,放到buf中。*/
void FileReadLine(FILE *file, char *buf)
{
char nowch;
nowch = fgetc(file);
while(nowch != '\n' && nowch != EOF)
{
*(buf++) = nowch;
nowch = fgetc(file);
}
*buf = '\0';
}
/*向文件file中写入一行文本,写入的内容为buf。*/
void FileWriteLine(FILE *file, char *buf)
{
fputs(buf, file);
fputc('\n', file);
}
/*在词典文件file中查找单词word,然后将解释放到exp中。*/
int DictFindWord(FILE *file, char *word, char *exp)
{
/*将流指针移动到文件开头。*/
fseek(file, 0, SEEK_SET);
/*搜索至文件尾。*/
while(!feof(file))
{
/*搜索文件中的单词行。*/
FileReadLine(file, exp);
/*比较是否与被查询的单词相同,若相同,则读出解释行并返回。*/
if(strcmp(word, exp) == 0)
{
FileReadLine(file, exp);
return 1;
}
/*其他情况忽略解释行。*/
FileReadLine(file, exp);
}
return 0;
}
/*添加单词work,解释exp到单词词典文件file中。*/
void DictAddWord(FILE *file, char *word, char *exp)
{
/*将流指针移动到文件尾。*/
fseek(file, 0, SEEK_END);
/*分别添加单词行,和解释行*/
FileWriteLine(file,word);
FileWriteLine(file, exp);
}
/*命令译码,输入命令为cmdbuf,输出的第一个参数放到wordbuf中,第二个参数
放到expbuf中,命令的类型由返回值返回,各个缓冲区的大小有bufsize确定。*/
int DecodeCommand(char *cmdbuf, char *wordbuf, char *expbuf, int bufsize)
{
char cmdcata, nowch;
int i, j;
/*寻找命令中的第一个字母,该字符作为命令的类型*/
nowch = *(cmdbuf++);
/*忽略之前所有的非字母字符。*/
while(nowch != '\0' && !isalpha(nowch))
nowch = *(cmdbuf++);
/*如果命令行为空字符串,则返回失败。*/
if(nowch == '\0')
return UNKNOWN_CMD;
/*记录这个类型字符。*/
cmdcata = nowch;
/*忽略这个字符后面的空白字符。*/
nowch = *(cmdbuf++);
while(nowch != '\0' && isspace(nowch))
nowch = *(cmdbuf++);
/*读取到后面的空白字符,将这些字符读取到wordbuf中。*/
i = 0;
while(nowch != '\0' && !isspace(nowch))
{
if(i < bufsize - 1)
{
wordbuf[i++] = nowch;
}
nowch = *(cmdbuf++);
}
wordbuf[i++] = '\0';
/*忽略到wordbuf之后的空白字符。*/
while(nowch != '\0' && isspace(nowch))
nowch = *(cmdbuf++);
/*将后面所有字符读取到expbuf中。*/
j = 0;
while(nowch != '\0')
{
if(j < bufsize -1)
{
expbuf[j++] = nowch;
}
nowch = *(cmdbuf++);
}
expbuf[j++] = '\0';
/*解释命令类型字符的命令类型。*/
return GetCommandCatagory(cmdcata);
}
/*将命令类型字符翻译成命令类型*/
int GetCommandCatagory(char cmdcatach)
{
switch (cmdcatach)
{
case 'l':
return FIND_WORD_CMD;
break;
case 'a':
return ADD_WORD_CMD;
break;
case 'h':
return HELP_CMD;
break;
case 'q':
return EXIT_CMD;
break;
default:
return UNKNOWN_CMD;
break;
}
}
/*输出帮助信息。*/
void PrintHelpInfo()
{
printf("Help:\n");
printf("l [word] Look up the dictionary for some word.\n");
printf("a [word] [exp] Add the new word into dictionary.\n");
printf("h Show the help information.\n");
printf("q Quit.\n");
}