批处理之家's Archiver

happy886rr 发表于 2017-5-31 02:47

跨平台的命令行字典外壳 dic.exe

[i=s] 本帖最后由 happy886rr 于 2017-7-10 11:59 编辑 [/i]

下载:城通网盘[url]https://page37.ctfile.com/fs/14274637-204821002[/url]
[quote] DIC.EXE是一款字典外壳第三方,已做多平台延伸,代码支持多平台编译,可在windows、linux、安卓、ios等多种设备上运行。查词核心采用自主研发的RODB内存数据库,迄今为止最快的查询速度,查询任何单词耗时都小于1毫秒。RODB意在通过最简短的代码实现最高速的数据查询。
(图片均为外链)(MFC版) 5KB, [attach]10660[/attach]

(安卓版)下载地址:[url]https://page37.ctfile.com/fs/14274637-204820983[/url]
[img]http://i1.piimg.com/1949/7731e9ba0046f705.png[/img]

[/quote]

跨平台源码:[code]/*
        CONSOLE ENGLISH-CHINESE DICTIONARY, COPYRIGHT@2017~2019 BY LEO, VERSION 1.0
        DIC.EXE
*/

#include   <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include    <time.h>

#if !defined(_MSC_VER) && !defined(bool)
#include <stdbool.h>
#endif

/***************定义宏变量***************/
//标准行长
#define BUFF_SIZE 1024

//标准基长
#define UINT_SIZE 4

//索引阈值
#define INDX_SIZE 255*255*UINT_SIZE*4

/***************定义宏函数***************/
//字符串转索引值
#define CHARARRAY2UINT(x) (unsigned int)(((unsigned char)(x)[0]<<24)|((unsigned char)(x)[1]<<16)|((unsigned char)(x)[2]<<8)|((unsigned char)(x)[3]))

//索引值转字符串
#define UINT2CHARARRAY(inSTAINER,uINNUM) \
        (inSTAINER)[0] = (char)(((uINNUM)&0xFF000000)>>24),\
        (inSTAINER)[1] = (char)(((uINNUM)&0x00FF0000)>>16),\
        (inSTAINER)[2] = (char)(((uINNUM)&0x0000FF00)>> 8),\
        (inSTAINER)[3] = (char)( (uINNUM)&0x000000FF     );

/***************设全局变量***************/
//微型容器
char          Keyic[UINT_SIZE];
unsigned char Brray[UINT_SIZE * 4];

//行存容器
char Input[BUFF_SIZE];
char Line [BUFF_SIZE];
char lineCACHE[BUFF_SIZE*16];

//定义RODB数据类型
typedef struct
{
        const char* data;
        const char* index;
        const unsigned int indexnum;
} RODB, *PRODB;

/***************WIN32兼容 ***************/
#if defined(WIN32) || defined(__WIN32__)

//引入WIN32头文件
#include <windows.h>
#include  <locale.h>

//缓存容器
wchar_t wcsCACHE[BUFF_SIZE * 32];
char    outCACHE[BUFF_SIZE * 32];

//ANSI、UTF8互转函数
char* ANSIteUTF8(const char* inputSTR, int inPAGE, int outPAGE, wchar_t* wcsCACHE, char* outCACHE)
{
        //输入代码页 过渡到 UNICODE中转代码页
        int wlEN=MultiByteToWideChar(inPAGE, 0, inputSTR,-1, NULL, 0);
        MultiByteToWideChar(inPAGE, 0, inputSTR, -1, wcsCACHE, wlEN);
        wcsCACHE[wlEN]=L'\0';

        //UNICODE中转代码页 过渡到 输出代码页
        int uLEN=WideCharToMultiByte(outPAGE, 0, wcsCACHE, -1, NULL, 0, NULL, NULL);
        WideCharToMultiByte(outPAGE, 0, wcsCACHE, -1, outCACHE, uLEN, NULL, NULL);
        outCACHE[uLEN]='\0';

        //返回结果
        return outCACHE;
}
#endif

/***************功能函数群***************/
//快排回调
int CompUINT(const void* a, const void* b)
{
        unsigned int leftINDEX=CHARARRAY2UINT((unsigned char*)a), rightINDEX=CHARARRAY2UINT((unsigned char*)b);
       
        //布尔比较 化解 UINT溢出漏洞
        if(leftINDEX <rightINDEX)
        {
                return -1;
        }
        return (int)(leftINDEX >rightINDEX);
}

//创建 RODB 内存数据库
RODB CreatRODB(const char* dicDATA_FILE, const char demilCHAR, unsigned char* pBRRAY)
{
        //读取字典文件
        FILE* fp=fopen(dicDATA_FILE, "rb");
        if(fp == NULL)
        {
                fprintf(stdout, "[ERROR]: read dictionary error\n");
                exit(1);
        }

        //获取字典文件尺寸
        fseek(fp, 0, SEEK_END);
        int fsize= ftell(fp);
        fseek(fp, 0, SEEK_SET);

        //动态分配字典容器
        char* dicDATA=(char*)malloc(fsize+2);

        //将字典文件读入内存
        fread(dicDATA, sizeof(char), fsize, fp);
        fclose(fp);
        dicDATA[fsize]='\n', dicDATA[fsize+1]='\0';

        //动态分配索引容器
        char* fastINDEX=(char*)malloc(INDX_SIZE), *fastp=fastINDEX;

        int lpHEAD, indexCOUNT=0, preINDEX_OFFSET=0, perINDEX_OFFLEN=0;
        unsigned int preINDEX=(unsigned int)0, curINDEX=(unsigned int)0;

        bool needsQSORT=false;
        char* lp=NULL, *cp=(char*)dicDATA;
        while(*cp != '\0')
        {
                lpHEAD=(int)(char*)cp, lp=(char*)Line;

                //读取关键词KEY:分隔符前字串
                while((*cp != '\n') && (*cp != demilCHAR))
                {
                        *lp++ = *cp++;
                };
                *lp='\0';

                //数据指针 置 流位 换行符
                while(*cp++ != '\n');

                //提取 关键词KEY 前4字符
                strncpy((char*)pBRRAY, Line, UINT_SIZE);

                //根据 KEY前4字符 创建索引
                curINDEX=CHARARRAY2UINT(pBRRAY);

                //效验索引可行性
                if(curINDEX < preINDEX)
                {
                        //如果逆序,则启用QSORT快排
                        needsQSORT=true;
                }

                //比对索引
                if(curINDEX != preINDEX)
                {
                        //打印索引值
                        //fprintf(stdout, "%u %s\n", curINDEX, Line);

                        int ILEN=lpHEAD-preINDEX_OFFSET, IOFFSET=lpHEAD-(int)(char*)dicDATA;
                        if(fastp != fastINDEX)
                        {
                                //尺度码块
                                UINT2CHARARRAY(fastp, (unsigned int)ILEN);
                                fastp+=4;
                        }

                        //索引码块
                        UINT2CHARARRAY(fastp, (unsigned int)curINDEX);
                        indexCOUNT++;
                        fastp+=4;

                        //效验码块
                        UINT2CHARARRAY(fastp, (unsigned int)0);
                        fastp+=4;

                        //偏移码块
                        UINT2CHARARRAY(fastp, (unsigned int)IOFFSET);
                        fastp+=4;

                        preINDEX=curINDEX;
                        preINDEX_OFFSET=lpHEAD;
                }
        }

        int lastOFFSET=(int)(char*)dicDATA+fsize-preINDEX_OFFSET;

        if(fastp != fastINDEX)
        {
                //追加结尾尺度码块
                UINT2CHARARRAY(fastp, (unsigned int)lastOFFSET);
                fastp+=4;
        }

        //置结束符
        *fastp='\0';

        //启用快排索引
        if(needsQSORT)
        {
                qsort((void*)fastINDEX, (size_t)indexCOUNT, (size_t)UINT_SIZE * 4, CompUINT);
        }

        RODB ret = {(const char*)dicDATA, (const char*)fastINDEX, (const unsigned int)indexCOUNT};

        //返回RODB指针
        return ret;
}

//高速查询核心
bool SearchResultCharArray(PRODB prodb, unsigned int uSEARCH_INDEX, unsigned char* pBRRAY, char* lineCACHE, char* Line, char* srcKEY)
{
        //使用闭区间
        int i, minIDX = -1, maxIDX = (unsigned int)(prodb->indexnum);
        unsigned iSEARCH_INDEX;
        bool bret=false;

        while(maxIDX - minIDX > 1)
        {
                i = (maxIDX + minIDX)>>1;

                //读取字典索引值
                memcpy(pBRRAY, &((prodb->index)[UINT_SIZE * 4 * i]), UINT_SIZE * 4);
                iSEARCH_INDEX = CHARARRAY2UINT(pBRRAY);

                //找到目标索引
                if(iSEARCH_INDEX == uSEARCH_INDEX)
                {
                        break;
                }

                //更新搜索范围
                (iSEARCH_INDEX  < uSEARCH_INDEX) ?(minIDX = i) :(maxIDX = i);
        }

        //如果搜索不到,则退出
        if(iSEARCH_INDEX != uSEARCH_INDEX)
        {
                //查询失败
                return bret;
        }

        //获取 KEY 在字典数据库中的偏移
        unsigned int keyOFFSET = CHARARRAY2UINT(pBRRAY+UINT_SIZE*2), keyOFFLEN=CHARARRAY2UINT(pBRRAY+UINT_SIZE*3);

        //转到KEY偏移位置,复制 keyOFFLEN长度数据 至 行缓存容器
        memcpy(lineCACHE, &((prodb->data)[keyOFFSET]), keyOFFLEN);

        //置容器结束符
        lineCACHE[keyOFFLEN]='\0';

        //显示查询结果
        char* bp = (char*)lineCACHE;
        int keyLEN = strlen(srcKEY);

        while(*bp)
        {
                char* p=Line;
                while((*p++ = *bp++) != '\n');
                *p='\0';

                if(strncmp(Line, srcKEY, keyLEN) == 0)
                {
                        //设置查询真值
                        bret = true;

                        //行显查询结果
#if defined(WIN32) || defined(__WIN32__)

                        fprintf(stdout, "%s", ANSIteUTF8(Line, CP_UTF8, CP_ACP, wcsCACHE, outCACHE));

#else

                        fprintf(stdout, "%s", Line);

#endif
                }
        }

        //返还查询真值
        return bret;
}

//*************MAIN主函数入口*************/
int main(int argc, char** argv)
{
        if(argc != 2)
        {
                fprintf(stdout, "Usage: dic [Dictionary file]\n");
                return 1;
        }

        //打印字典标题
        fprintf(stdout, "[English-Chinese dictionary] --- use \"q\" to exit");

        //构建RODB内存数据库
        unsigned char* pBRRAY=(unsigned char*)Brray;
        RODB rodb=CreatRODB(argv[1], '\t', pBRRAY);

        //构建字典查询 SHELL
        while(printf("\n>>"), fgets(Input, BUFF_SIZE-1, stdin)!=NULL)
        {
                //将输入转化为字符串
                char *p =strchr(Input,'\n');
                if(p != NULL)
                {
                        *p='\0';
                }

                //判断输入是否为空
                if (p!=Input)
                {
                        //使用按键 小写q 退出
                        if(!strcmp(Input, "q"))
                        {
                                fputs("[EXIT]: thanks for use, bye!", stdout);
                                break;
                        }

#if defined(WIN32) || defined(__WIN32__)
                        //对WIN32控制台 代码页 兼容
                        char* srcKEY=ANSIteUTF8(Input, CP_ACP, CP_UTF8, wcsCACHE, outCACHE);

#else

                        char* srcKEY=Input;

#endif

                        //将被查询字符串转化为索引值
                        strncpy(Keyic, srcKEY, UINT_SIZE);
                        unsigned int uSEARCH_INDEX = CHARARRAY2UINT(Keyic);

                        //执行查询
                        if(! SearchResultCharArray(&rodb, uSEARCH_INDEX, pBRRAY, lineCACHE, Line, srcKEY) )
                        {
                                fprintf(stdout, "[SORRY]: can not find it\n");
                        }

                }
        }
        return 0;
}
[/code]补充:附带几个移植到手机上的第三方,手机上的控制台一样精彩。包括:bse、choice、dic、equation、revpolish。下载地址:[url]https://page37.ctfile.com/fs/14274637-204820983[/url]

老刘1号 发表于 2017-5-31 12:25

[i=s] 本帖最后由 老刘1号 于 2017-6-2 22:57 编辑 [/i]

希望出GUI版

happy886rr 发表于 2017-5-31 13:29

[i=s] 本帖最后由 happy886rr 于 2017-6-2 12:51 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=199971&ptid=44336]2#[/url] [i]老刘1号[/i] [/b]已更新MFC版,窗口取词,更加速度。

老刘1号 发表于 2017-6-2 13:17

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=199973&ptid=44336]3#[/url] [i]happy886rr[/i] [/b]


    命令行版提示找不到词典,在程序目录或者工作目录下都不行,词典的名称没有更改

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.