制作特定书单词手册

来源:互联网 发布:开淘宝网需要垫资金吗 编辑:程序博客网 时间:2024/04/29 21:40

前段时间,看Dan Simons的海伯利安系列,但是到Endmion时,海峡两岸均未引进。没办法,就先下个Sample看,看了四章,觉得很好看。后来,又找了个pdf格式的全本,不认识的单词实在太多,就想制份单词表。下面是步骤:

1.先要从文件里提取出单词。这里有一个简单的C程序可以完成这个任务,代码如下:

 
/**wordCount.h*/                                                 #ifndef _ZPZ_TRIE_H#define _ZPZ_TRIE_H#include <stdio.h>#include <stdlib.h>                                                 typedef int (*trie_char_to_index)(charc);typedef char (*trie_index_to_char)(inti);                                                 typedef struct _trie_node{    intcount;    intdepth;    struct_trie_node ** list;} trie_node;                                                 typedef struct _trie_tree{    intchar_width;    intmax_depth;    trie_node * root;    trie_char_to_index char_to_index;    trie_index_to_char index_to_char;} trie_tree;                                                 inlinetrie_node * trie_node_new(intdepth){    trie_node * node = (trie_node *)malloc(sizeof(trie_node));    if(NULL != node){        memset(node, 0,sizeof(trie_node));        node->depth = depth;    }    returnnode;}                                                 static inline trie_node ** trie_node_alloc_children(intchar_width){    trie_node ** nodes = (trie_node **)malloc(char_width *sizeof(trie_node *));    if(NULL != nodes){        memset(nodes, 0, char_width *sizeof(trie_node *));    }    return nodes;}                                                 inline trie_tree * trie_init(    trie_tree * tree,    intchar_width,    trie_char_to_index char_to_index,    trie_index_to_char index_to_char){    memset(tree, 0,sizeof(trie_tree));    tree->char_to_index = char_to_index;    tree->index_to_char = index_to_char;    tree->root = trie_node_new(0);    tree->char_width = char_width;    if(NULL != tree->root){        tree->root->list = trie_node_alloc_children(tree->char_width);    }}                                                 int trie_add(trie_tree * tree, char* word, int len){    char* p = word, * end = p + len;    trie_node * trie =  tree->root;    int index, depth = 0;    if(NULL == p || end == p){        return0;    }    while(p < end){        index = tree->char_to_index(*p);        if(NULL == trie->list){            trie->list = trie_node_alloc_children(tree->char_width);        }        if(NULL == trie->list){            return0;        }        depth++;        if(NULL == trie->list[index]){            trie->list[index] = trie_node_new(depth);        }        if(NULL == trie->list[index]){            return0;        }        trie = trie->list[index];        p++;    }    if(depth > tree->max_depth + 1){        tree->max_depth = depth - 1;    }    trie->count++;    return 1;}                                                 #define trie_add_ex(tree,word) trie_add((tree), (word), strlen(word))                                                 static int trie_node_release(trie_node * node,int char_width){    int i;    if(NULL != node->list){        for(i = 0; i < char_width; i++){            if(NULL != node->list[i]){                trie_node_release(node->list[i], char_width);            }        }        free(node->list);    }    free(node);}                                                 #define trie_release(tree)  \    trie_node_release((tree)->root, (tree)->char_width);\                                                 trie_node * trie_find(trie_tree * tree,char * word, int len){    intindex;    char* p = word, * end = p + len;    trie_node * trie =  tree->root;    if(NULL == p || p == end){        return NULL;    }    while('\0'!= *p){        if(NULL == trie->list){            return NULL;        }        index = tree->char_to_index(*p);        if(NULL == trie->list[index]){            return NULL;        }        trie = trie->list[index];        p++;    }    return trie;                                                 }#define trie_find_ex(tree,word) trie_find((tree),(word),strlen(word))                                                 static inline void trie_node_dump(    trie_tree * tree,    trie_node * node,    char* word){    int i = 0;    if(node->count > 0){        printf("%-8d %s\n", node->count, word);    }    if(NULL != node->list){        for(; i < tree->char_width; i++){            if(NULL != node->list[i]){                word[node->depth] = tree->index_to_char(i);                word[node->depth + 1] ='\0';                trie_node_dump(tree, node->list[i], word);            }        }    }}                                                 void trie_dump(trie_tree * tree){    char* word = (char*)malloc(tree->max_depth + 1);    memset(word, 0, tree->max_depth + 1);    trie_node_dump(tree, tree->root, word);}                                                 static inline int char_to_index(char c){    if('0'<= c && c <= '9'){        return c - '0';    }    elseif('a'<= c && c <= 'z'){        return 10 + c - 'a';    }    elseif('A'<= c && c <= 'Z'){        return 10 + 26 + c - 'A';    }    return 10 + 26 + 26;}                                                 static inline char index_to_char(int index){    if(0 <= index && index < 10){        return'0' + index;    }    else if(10 <= index && index < (10 + 26)){        return 'a' + (index - 10);    }    else if((10 + 26) <= index && index < (10 + 26 + 26)){        return 'A' + (index - 10 - 26);    }    return' ';}                                                 inline trie_init_alnum(trie_tree * tree){    trie_init(tree, 26 + 26 + 10 + 1, char_to_index, index_to_char);}                                                 #endif

然后是一个具体实现代码:


 
/* * ===================================================================================== * *       Filename:  countWord.c * *    Description: * *        Version:  1.0 *        Created:  2013年01月04日 07时41分15秒 *       Revision:  none *       Compiler:  gcc * *         Author:  YOUR NAME (), *        Company: * * ===================================================================================== */#include "countWord.h"                                              typedef void (*word_handler)(char* start, char* end);                                              #define is_digit_or_letter(c) (((c) >='a' && (c) <= 'z') || ((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'Z'))                                              void find_word_in_buffer(    char* start,    int len,    word_handler handler){    int stat = 0;    char* end = start + len, * last = start;                                                  while(start < end){        //printf("%c", *start);        if(is_digit_or_letter(*start)){            if(0 == stat){                last = start;                stat = 1;            }        }        else{            if(1 == stat){                //word                handler(last, start);                stat = 0;            }        }        start++;    }    if(1 == stat && last < start){        handler(last, start);    }}                                              void count_words_of_file(    FILE* file,    word_handler handler){    int line = 1,  words = 1;    long file_size = 0;    char* buffer;                                                  fseek(file, 0 , SEEK_END);    file_size =ftell(file);    rewind(file);                                                  buffer = (char*)malloc(file_size);                                                  if(NULL == buffer){        printf("Alloc failed");        return;    }                                                  fread(buffer, file_size, 1, file);    find_word_in_buffer(buffer, file_size, handler);}                                              static trie_tree tree;                                              void count_words_handler(char* begin, char* end){    trie_add(&tree, begin, end - begin);}                                              int main(int argc, char ** argv){    if(argc < 2){        printf("parameter 2 must be the file name.\n");        return1;    }    FILE* file = fopen(argv[1],"r");    if(NULL == file){        printf("File %s not exitst.", argv[1]);        return2;    }    trie_init_alnum(&tree);    count_words_of_file(file, count_words_handler);    fclose(file);    trie_dump(&tree);    trie_release(&tree);    return0;}

然后编译就可以用了。

2.获得书中的单词

1
./a.out Endmion.txt > wordsOfEndmion.csv

其中a.out是编译的可执行程序,Endmion.txt是小说文件,而wordsOfEndmion.csv是小说中所有出现的单词


3.排个序

 
sort-n wordsOfEndmion.csv > wordsOfEndmion_sort.csv

排序的作用是把那些高频词筛选出来,因为那些高频词都是认识的。我是把频率60以上的基本都删除了。其余的就是一些出现频率小的词,里面有太多不认识的。我们的目标就是这些词。

4.整理词典文件

现在这个 词典文件的基本格式是 "1 abort"这样的,为了获得翻译结果,需要把前面的这个频率数字去除。用任何 方法均可,我是用的Gvim中的块操作。操作完成后,文件的格式就是每行一个单词了。

5.获得单词释义

在Linux中,有一个命令行词典非常好用,其名字叫 sdcv ,是stardict的一个命令行实现。我们要获得释义,就靠它了。写一个Shell脚本:

 
#!/bin/bash#name getMean.sh# Usage: $0 <FILENAME                   whileread line  # 提供和输入文件一样多的行...do        echo"$line">>$0.mean   # 输入所读入的行本身.        sdcv -n"$line">>$0.meandone                   exit0


非常简单,就是读取每一行,然后把单词和释义写入到另一个文件中。用法示例:

 
./getMean.sh < wordsOfEndmion_sort.csv

把前一步整理好的文件用< 符号传送给脚本 文件即可。会在脚本目录生成一个名为"getMean.sh.eman"的文件,其格式类似于:


Soya
Found 1 items, similar to Soya.
-->朗道英汉字典5.0
-->soya

【医】 大豆

Aenea
Found 10 items, similar to Aenea.
-->朗道英汉字典5.0
-->aedea

【医】 外生殖器

-->朗道英汉字典5.0
-->Aegean

*[i:'dʒi:әn]
a. 爱琴海的
n. 爱琴海


好,大功告成。现在,把其扩展名修改为txt,然后发送给Amazon,一份专属于Endmion的词典就制作 成功了。可以随时在Kindle上观看了。