From 8ee053a8fb8c7186e9b5a0c45a37e1e59f860821 Mon Sep 17 00:00:00 2001 From: hikarupsp Date: Wed, 13 Mar 2013 21:14:01 +0900 Subject: [PATCH] =?utf8?q?AI003:AI=5FThink=5FSlideLookUpWordByHistory?= =?utf8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=E4=B8=AD=E3=80=82=20chnlib:chnlib.hC?= =?utf8?q?HNLIB=5FSTRUCTURE=5FSIGNATURE=E3=81=AE=E5=80=A4=E3=82=92?= =?utf8?q?=E4=BF=AE=E6=AD=A3=E3=80=82=20CHNLIB=5FString=5FGetReferencePoin?= =?utf8?q?terOfCString=E3=81=AB=E3=81=8A=E3=81=84=E3=81=A6=E3=80=81?= =?utf8?q?=E5=86=85=E9=83=A8=E5=8F=82=E7=85=A7=E3=81=8CNULL=E3=81=AE?= =?utf8?q?=E6=99=82=E3=81=AB=E3=80=81=E7=A9=BA=E6=96=87=E5=AD=97=E3=81=B8?= =?utf8?q?=E3=81=AE=E3=83=9D=E3=82=A4=E3=83=B3=E3=82=BF=E3=82=92=E8=BF=94?= =?utf8?q?=E3=81=99=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F=E3=80=82?= =?utf8?q?=20UTF-8=E6=96=87=E5=AD=97=E5=88=97=E9=96=A2=E9=80=A3=E9=96=A2?= =?utf8?q?=E6=95=B0=E3=81=AE=E5=BC=B7=E5=8C=96=E3=80=82=20UTF-8=E5=AF=BE?= =?utf8?q?=E5=BF=9C=E9=96=A2=E6=95=B0=E3=81=AF=E3=80=81=E3=82=B3=E3=83=A1?= =?utf8?q?=E3=83=B3=E3=83=88=E3=81=AB[UTF-8]=E3=81=AE=E8=A1=A8=E8=A8=98?= =?utf8?q?=E3=81=8C=E3=81=82=E3=82=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CHNOSProject/AI003/AI003/main.c | 56 +++++----- CHNOSProject/chn/chnlib.h | 9 +- CHNOSProject/chn/chnlib01.c | 34 ++---- CHNOSProject/chn/chnlib02.c | 52 +++------ CHNOSProject/chn/chnlib04.c | 205 ++++++++++++++++++++++++++++++++++++ CHNOSProject/libtest/libtest/main.c | 16 ++- 6 files changed, 280 insertions(+), 92 deletions(-) diff --git a/CHNOSProject/AI003/AI003/main.c b/CHNOSProject/AI003/AI003/main.c index 7401c6c..10775b5 100755 --- a/CHNOSProject/AI003/AI003/main.c +++ b/CHNOSProject/AI003/AI003/main.c @@ -84,45 +84,51 @@ int main(int argc, const char * argv[]) CHNLIB_UIPArray *AI_Think_SlideLookUpWordByHistory(CHNLIB_String *input) { //入力文字列と履歴文字列を照らし合わせ、単語の候補を抜き出す。 + //候補単語は、新たに確保されたUIPArrayに格納され、そのArrayへのポインタを返す。 + //data32=入力文字列中に含まれる候補単語の数。 + //pointer=候補単語を示すCHNLIB_String. + //[UTF-8] CHNLIB_UIPArray *candidatewordlist; int i, i_max; int j, j_max; int k, k_max; + const char *cstr_input, *cstrp_input; + const char *cstr_history, *cstrp_history; int candidatelength, templength; - const char *cstr_input, *cstr_history; + int cstrp_input_length; candidatewordlist = CHNLIB_UIPArray_Initialize(); - i_max = CHNLIB_UIPArray_GetNumberOfDatas(WorkingSet.InputHistory); cstr_input = CHNLIB_String_GetReferencePointerOfCString(input); - k_max = CHNLIB_CString_GetLength(cstr_input); - + k_max = CHNLIB_UTF8_GetStringLengthByCharacter(cstr_input); + cstrp_input = cstr_input; + for(k = 0; k < k_max; k++){ - //**UTF-8 only - //UTF-8のマルチバイト部分でないことを確認 - if(CHNLIB_UTF8_GetCharacterType(cstr_input[k]) != 0){ - //**** - candidatelength = 0; - for(i = 0; i < i_max; i++){ - cstr_history = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(WorkingSet.InputHistory, i)); - j_max = CHNLIB_CString_GetLength(cstr_history); - for(j = 0; j < j_max; j++){ - templength = CHNLIB_CString_CompareString_LeftHand(&cstr_history[j], &cstr_input[k]); - if(templength > candidatelength && templength != (k_max - k)){ - //前方一致の長さが、 - //これまで見つかった単語よりも長く、かつ - //入力文字列の検索部分の全長ではない場合、 - //単語の候補とする。 - candidatelength = templength; - } + //input character loop + candidatelength = 0; + cstrp_input_length = CHNLIB_UTF8_GetStringLengthByCharacter(cstrp_input); + for(i = 0; i < i_max; i++){ + //history entry loop + cstr_history = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(WorkingSet.InputHistory, i)); + j_max = CHNLIB_UTF8_GetStringLengthByCharacter(cstr_history); + cstrp_history = cstr_history; + + for(j = 0; j < j_max; j++){ + //history character loop + templength = CHNLIB_UTF8_CompareString_LeftHand(cstrp_history, cstrp_input); + if(templength > candidatelength && templength != cstrp_input_length){ + //前方一致の長さが、これまで見つかった単語よりも長く、かつ入力文字列の検索部分の全長ではない場合、 + //単語の候補とする。 + candidatelength = templength; } + CHNLIB_UTF8_GetNextUnicodeOfCharacter(cstrp_history, &cstrp_history); } - if(candidatelength > 0){ - //AI_Memory_AddRootWordData(CHNLIB_String_ExtractByLength(input, k, candidatelength)); - CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(&candidatewordlist, 0, CHNLIB_String_ExtractByLength(input, k, candidatelength), &AI_Memory_AddRootWordData_IsDuplicated); - } } + if(candidatelength > 0){ + CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(&candidatewordlist, 0, CHNLIB_String_ExtractByLength(input, CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(cstr_input, 0, k - 1), CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(cstrp_input, 0, candidatelength - 1)), &AI_Memory_AddRootWordData_IsDuplicated); + } + CHNLIB_UTF8_GetNextUnicodeOfCharacter(cstrp_input, &cstrp_input); } //各候補単語が入力文字列にいくつ含まれているかをdata32に保存する。 diff --git a/CHNOSProject/chn/chnlib.h b/CHNOSProject/chn/chnlib.h index ec5a027..4356011 100755 --- a/CHNOSProject/chn/chnlib.h +++ b/CHNOSProject/chn/chnlib.h @@ -48,7 +48,7 @@ struct CHNLIB_STRUCTURE_HEADER { //Define library values // -#define CHNLIB_STRUCTURE_SIGNATURE ((uint)0x43484E4C) //"CHNL" +#define CHNLIB_STRUCTURE_SIGNATURE ((uint)0x4C4E4843) //"CHNL"(Little Endian) #define False 0 #define True 1 @@ -112,7 +112,6 @@ char *CHNLIB_CString_ExtractByLength(const char s[], int start, int len); int CHNLIB_CString_CompareString(const char s[], const char search[]); int CHNLIB_CString_CompareString_Strict(const char s[], const char search[]); int CHNLIB_CString_CompareString_LeftHand(const char s[], const char search[]); -uint CHNLIB_CString_GetCountOfContain(const char s[], const char search[]); //@chnlib02.c int CHNLIB_String_Search_UIPArrayStringLocation(const CHNLIB_String *s, int s_start, const CHNLIB_UIPArray *list, int *location); int CHNLIB_UIPArray_GetSeparatedStringByUIPArray(CHNLIB_UIPArray **separated, const CHNLIB_UIPArray *list, const CHNLIB_String *s); @@ -125,5 +124,11 @@ const char *CHNLIB_Environment_GetFilenameFromPath(const char path[]); //@chnlib05.c int CHNLIB_UTF8_GetCharacterType(char c); +int CHNLIB_UTF8_GetStringLengthByCharacter(const char s[]); +uint CHNLIB_UTF8_GetNextUnicodeOfCharacter(const char s[], const char **next); +int CHNLIB_UTF8_CompareString(const char s[], const char search[]); +int CHNLIB_UTF8_CompareString_LeftHand(const char s[], const char search[]); +int CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(const char s[], int start, int end); +uint CHNLIB_UTF8_GetCountOfContain(const char s[], const char search[]); #endif diff --git a/CHNOSProject/chn/chnlib01.c b/CHNOSProject/chn/chnlib01.c index 76df884..b47f3d0 100644 --- a/CHNOSProject/chn/chnlib01.c +++ b/CHNOSProject/chn/chnlib01.c @@ -22,6 +22,11 @@ // // +//Define static values +// +char *CHNLIB_String_Intenal_NullCString = ""; + +// //Declare internal functions // @@ -58,7 +63,6 @@ CHNLIB_String *CHNLIB_String_Initialize(const char str[]) void CHNLIB_String_Free(CHNLIB_String *strtag) { //strtagを解放する。 - if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){ return; } @@ -115,11 +119,15 @@ int CHNLIB_String_Print(CHNLIB_String *strtag) const char *CHNLIB_String_GetReferencePointerOfCString(const CHNLIB_String *strtag) { //strtagが格納している文字列へのポインタを返す。 - //strtag==Invalidの場合、NULLを返す。 + //strtag->str==NULLの場合、constな空文字へのポインタを返す。 if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){ return NULL; } + if(strtag->str == NULL){ + return CHNLIB_String_Intenal_NullCString; + } + return (const char *)strtag->str; } @@ -176,7 +184,7 @@ int CHNLIB_String_CompareString_Strict(const CHNLIB_String *s, const CHNLIB_Stri uint CHNLIB_String_GetCountOfContain(const CHNLIB_String *s, const CHNLIB_String *search) { - return CHNLIB_CString_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(search)); + return CHNLIB_UTF8_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(search)); } // @@ -334,26 +342,6 @@ int CHNLIB_CString_CompareString_LeftHand(const char s[], const char search[]) return i; } - -uint CHNLIB_CString_GetCountOfContain(const char s[], const char search[]) -{ - //[Not implemented] - uint count; - int i; - - if(s == NULL || search == NULL){ - CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS); - return 0; - } - - count = 0; - for(i = 0; s[i] != '\0'; i++){ - if(CHNLIB_CString_CompareString(&s[i], search)){ - count++; - } - } - return count; -} // //Internal functions diff --git a/CHNOSProject/chn/chnlib02.c b/CHNOSProject/chn/chnlib02.c index 459ed8d..a175006 100644 --- a/CHNOSProject/chn/chnlib02.c +++ b/CHNOSProject/chn/chnlib02.c @@ -95,58 +95,34 @@ int CHNLIB_UIPArray_GetSeparatedStringByUIPArray(CHNLIB_UIPArray **separated, co return 0; } -int CHNLIB_UIPArray_GetSeparatedUTF8Character(CHNLIB_UIPArray **separated, const CHNLIB_String *s){ +int CHNLIB_UIPArray_GetSeparatedUTF8Character(CHNLIB_UIPArray **separated, const CHNLIB_String *s) +{ //文字列sを、UTF-8の一文字ごとに分割し、その文字のUnicodeをdata32、その一文字に該当するStringをpointerに格納し、separatedに追加する形で返す。 //不完全なUTF-8文字列は無視される。 - const char *refstr; - int i, i_max, type; - int phase, start; - uint unicode; + //[UTF-8] + const char *p, *q, *p_base; + uint u; if(separated == NULL || CHNLIB_StructureHeader_GetTypeID(s) != CHNLIB_STRUCT_ID_String){ return 1; } - refstr = CHNLIB_String_GetReferencePointerOfCString(s); - i_max = CHNLIB_String_GetLength(s); + p_base = CHNLIB_String_GetReferencePointerOfCString(s);; + p = p_base; - phase = 0; - unicode = 0; - for(i = 0; i < i_max; i++){ - type = CHNLIB_UTF8_GetCharacterType(refstr[i]); - switch (type) { - case 1: - CHNLIB_UIPArray_AppendLast(separated, refstr[i], CHNLIB_String_ExtractByLength(s, i, 1)); - phase = 0; - unicode = 0; - break; - - case 0: - if(phase > 0){ - unicode <<= 6; - unicode |= (refstr[i] & 0x3f); - phase--; - if(phase == 0){ - //一文字完成 - CHNLIB_UIPArray_AppendLast(separated, unicode, CHNLIB_String_ExtractByLength(s, start, i - start + 1)); - } - } - break; - - case 2: - case 3: - case 4: - start = i; - unicode = (refstr[i] << (type + 1)) >> (type + 1); - phase = type - 1; - break; + for(;;){ + u = CHNLIB_UTF8_GetNextUnicodeOfCharacter(p, &q); + if(u == 0){ + //終端文字 + break; } + CHNLIB_UIPArray_AppendLast(separated, u, CHNLIB_String_ExtractByLength(s, (int)(p - p_base), (int)(q - p))); + p = q; } return 0; } - CHNLIB_String *CHNLIB_ReadLine(FILE *fp) { char s[CHNLIB_MAX_STRING_LENGTH]; diff --git a/CHNOSProject/chn/chnlib04.c b/CHNOSProject/chn/chnlib04.c index 9500088..417d1d8 100644 --- a/CHNOSProject/chn/chnlib04.c +++ b/CHNOSProject/chn/chnlib04.c @@ -22,6 +22,11 @@ int CHNLIB_UTF8_GetCharacterType(char c) { //UTF-8文字列中の1バイトcが、UTF-8文字列中でどのような役割を持つのかを返す。 + //0:マルチバイト文字の後続バイト + //1:1バイト文字 + //2以上の数値n:nバイト文字の最初のバイト。後続のn個のマルチバイト後続バイトと組み合わせて一つの文字を示す。 + //判断不能な場合は-1を返す。 + //[UTF-8] if(((c >> 6) & 3) == 2){ //マルチバイト後続バイト //10xxxxxx @@ -48,8 +53,208 @@ int CHNLIB_UTF8_GetCharacterType(char c) return 4; } + return -1; +} + +int CHNLIB_UTF8_GetStringLengthByCharacter(const char s[]) +{ + //sをUTF-8文字列として解釈し、文字としては何文字で構成された文字列かを返す。 + //無効な(マルチバイトの一部が欠けているような)文字はカウントしない。 + //[UTF-8] + int i, mbsize, n; + int count; + + if(s == NULL){ + return 0; + } + + count = 0; + mbsize = 0; + for(i = 0; s[i] != '\0'; i++){ + n = CHNLIB_UTF8_GetCharacterType(s[i]); + switch(n){ + case -1: + //無効なバイト + mbsize = 0; + break; + case 0: + //マルチバイト後続バイト + if(mbsize > 0){ + mbsize--; + if(mbsize == 0){ + count++; + } + } + break; + case 1: + //1バイト文字 + count++; + if(mbsize > 0){ + mbsize = 0; + } + break; + default: + //nバイト文字の最初のバイト + mbsize = n - 1; + break; + } + } + return count; +} + +uint CHNLIB_UTF8_GetNextUnicodeOfCharacter(const char s[], const char **next) +{ + //sをUTF-8文字列として解釈し、その文字列の最初の文字のUnicodeを返す。 + //また、nextがNULLでないとき、*nextに、この文字列中で次の文字にあたる部分へのポインタを格納する。 + //s==NULLの時、*nextの値は変更されない。 + //次の文字が存在しない場合は、*nextはs中の終端文字へのポインタとなる。また、戻り値は0となる。 + //無効な(マルチバイトの一部が欠けているような)文字は無視する。 + //[UTF-8] + int i, n, mbsize; + uint unicode; + + if(s == NULL){ + return 0; + } + + unicode = 0; + for(i = 0; s[i] != '\0'; i++){ + n = CHNLIB_UTF8_GetCharacterType(s[i]); + switch(n){ + case -1: + //無効なバイト + mbsize = 0; + break; + case 0: + //マルチバイト後続バイト + if(mbsize > 0){ + mbsize--; + unicode <<= 6; + unicode |= (0x3f & s[i]); + if(mbsize == 0){ + return unicode; + } + } + break; + case 1: + //1バイト文字 + if(next != NULL){ + *next = (char *)(s + 1); + } + return s[i]; + default: + //nバイト文字の最初のバイト + unicode = (((s[i]) << (n + 1)) >> n + 1); + mbsize = n - 1; + if(next != NULL){ + *next = (char *)(s + n); + } + break; + } + } + if(next != NULL){ + *next = &s[i]; + } return 0; } +int CHNLIB_UTF8_CompareString(const char s[], const char search[]) +{ + //s,searchをUTF-8文字列として解釈し、s[]の先頭からsearch[]と比較し、searchの終端まで一致したらTrue, 一致しなかったらFalseを返す。 + //終端文字は比較せず、search[]に含まれる文字(終端文字除く)がすべて入っていれば一致とみなす。 + //ただし、searchの先頭文字が終端文字、つまり空文字列だった場合は、常にFalseを返す。 + //[UTF-8] + int i, i_max; + + if(s == NULL || search == NULL){ + CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS); + return False; + } + if(search[0] == '\0'){ + //空文字はいかなる文字列とも一致しない。 + return False; + } + + i_max = CHNLIB_UTF8_GetStringLengthByCharacter(search); + for(i = 0; i < i_max; i++){ + if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) != CHNLIB_UTF8_GetNextUnicodeOfCharacter(search, &search)){ + return False; + } + } + return True; +} + +int CHNLIB_UTF8_CompareString_LeftHand(const char s[], const char search[]) +{ + //s,searchをUTF-8文字列として解釈し、二つの文字列がどの程度一致するか調べる。前方一致。 + //戻り値は、終端文字を除く、同一だった文字数。 + //[UTF-8] + int i, i_max; + + if(s == NULL || search == NULL){ + CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS); + return 0; + } + + i_max = CHNLIB_UTF8_GetStringLengthByCharacter(search); + for(i = 0; i < i_max; i++){ + if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) != CHNLIB_UTF8_GetNextUnicodeOfCharacter(search, &search)){ + break; + } + } + return i; +} +int CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(const char s[], int start, int end) +{ + //sをUTF-8文字列として解釈し、start番目の文字からend番目の文字までの占めるバイト数を返す。 + //start番目の文字が終端文字以降の文字を指している場合は0を返す。 + //end番目の文字が + //[UTF-8] + int i; + const char *p; + + if(s == NULL){ + CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS); + return 0; + } + if(end < start){ + CHNLIB_ReportError("Invalid index.\n", CHNLIB_DEBUG_ARGUMENTS); + return 0; + } + + for(i = 0; i < start; i++){ + if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) == 0){ + return 0; + } + } + p = s; + for(; i <= end; i++){ + CHNLIB_UTF8_GetNextUnicodeOfCharacter(p, &p); + } + + return (int)(p - s); +} +uint CHNLIB_UTF8_GetCountOfContain(const char s[], const char search[]) +{ + //文字列s中に、文字列searchがいくつ含まれているかを返す。 + //[UTF-8] + uint count; + + if(s == NULL || search == NULL){ + CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS); + return 0; + } + + count = 0; + for(;;){ + if(CHNLIB_UTF8_CompareString(s, search)){ + count++; + } + if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) == 0){ + break; + } + } + return count; +} diff --git a/CHNOSProject/libtest/libtest/main.c b/CHNOSProject/libtest/libtest/main.c index 3031303..b8b196d 100644 --- a/CHNOSProject/libtest/libtest/main.c +++ b/CHNOSProject/libtest/libtest/main.c @@ -11,14 +11,22 @@ int main(int argc, const char * argv[]) { - CHNLIB_String *s; + CHNLIB_String *s, *t; CHNLIB_UIPArray *separated; separated = CHNLIB_UIPArray_Initialize(); - s = CHNLIB_String_Initialize("あいうえお漢字。test  aa"); + s = CHNLIB_String_Initialize("このたけやぶにたけたてかけたかったのは、たけたてかけたてたかったからです。"); + t = CHNLIB_String_Initialize("た"); - CHNLIB_UIPArray_GetSeparatedUTF8Character(&separated, s); - CHNLIB_Debug_PrintStructureData(separated, 0); + printf("%d bytes, %d characters\n", CHNLIB_String_GetLength(s), CHNLIB_UTF8_GetStringLengthByCharacter(CHNLIB_String_GetReferencePointerOfCString(s))); + printf("%d bytes, %d characters\n", CHNLIB_String_GetLength(t), CHNLIB_UTF8_GetStringLengthByCharacter(CHNLIB_String_GetReferencePointerOfCString(t))); + + printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(t))); + printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(t), CHNLIB_String_GetReferencePointerOfCString(s))); + printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(s))); + printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(t), CHNLIB_String_GetReferencePointerOfCString(t))); + + printf("%d\n", CHNLIB_UTF8_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(t))); return 0; } -- 2.11.0