c ++与可混淆字符的Unicode字符串比较。示例(U 0054)应为==(U03A4)等

时间:2012-09-18 15:14:16

标签: c++ unicode

我有Unicode字符串,我想与以下要求进行比较。

可混淆的s [1]字符应该被认为是相同的字符,  例如:T(LATIN CAPITAL LETTER T U 0054)应为== T(希腊大写字母TAU U03A4)等

(* [1]示例http://unicode.org/cldr/utility/confusables.jsp?a=TESTt&r=None *)

http://www.unicode.org/Public/security/revision-03/confusablesSummary.txt

我将使用上面的文件来制作代码,但是如果已经有任何免费库我宁愿使用它。

我认为代码会创建一个临时的ustring,其中每个可混淆的字符都会被相应的拉丁字符替换。

在实际程序中,我将测试10x5000x10000个字符串,每个字符串包含一个单词。

测试程序:

 std::locale::global(std::locale(""));

 std::cout.imbue(std::locale());

 Glib::ustring s1,s2;

 s1="TEST";

 s2="TΕST";

 s1.normalize(Glib::NORMALIZE_NFKD    );

 s2.normalize(Glib::NORMALIZE_NFKD   );

 std::cout<<"1->true, 0->false  (s1==s2) =>  "<<(s1==s2)<<"\n";

测试程序输出:

1->true, 0->false  (s1==s2) =>  0

Ubuntu 区域设置命令输出:

Ubuntu 12.04 64 bit>$ locale  
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

感谢您的时间!

2 个答案:

答案 0 :(得分:2)

正如user1675224所说,你应该使用ICU,而不是试图推出自己的算法。

例如,要使用uspoof_areConfusable

UErrorCode status = 0;
USpoofChecker *sc = uspoof_open(&status);
int result = uspoof_areConfusable(sc, s1.data(), s1.length(), s2.data(), s2.length(), &status);
uspoof_close(sc);

如果您要将大量字符串相互比较,则应使用uspoof_getSkeleton将它们转换为骨架,并将其放入集合或哈希集中。

答案 1 :(得分:0)

 std::string s1,s2;
    s1="TEst";
    s2="TΕst";
    std::cout<<" s1.length()="<<s1.length()<<"\n";
    std::cout<<" s2.length()="<<s2.length()<<"\n";

 UErrorCode status = U_ZERO_ERROR ;
 USpoofChecker *sc = uspoof_open(&status);
 char p[100];
 int result = uspoof_getSkeletonUTF8    (sc,USPOOF_ANY_CASE, s1.data(),s1.length(),p,100,&status);
 std::string skeleton1(p,result);
 std::cout<<" result in bytes="<<result<<" status="<<status<<"\n";
 std::cout<<" skeleton1="<<skeleton1<<"\n";
 std::cout<<"1->true, 0->false  (s1==skeleton1) =>  "<<(s1==skeleton1)<<"\n";
 //
 char p2[100];
 int result2 = uspoof_getSkeletonUTF8   (sc,USPOOF_ANY_CASE , s2.data(),s2.length(),p2,100,&status);
 std::string skeleton2(p2,result2);
 std::cout<<" result2 in bytes="<<result2<<" status="<<status<<"\n";
 std::cout<<" skeleton2="<<skeleton2<<"\n";
 std::cout<<"1->true, 0->false  (s2==skeleton2) =>  "<<(s2==skeleton2)<<"\n";
 std::cout<<"1->true, 0->false  (s1==s2) =>  "<<(s1==s2)<<"\n";
 std::cout<<"1->true, 0->false  (skeleton1==skeleton2) =>  "<<(skeleton1==skeleton2)<<"\n";
 //
 uspoof_close(sc);

输出

 s1.length()=4
 s2.length()=5
 result in bytes=4 status=0
 skeleton1=TEst
 1->true, 0->false  (s1==skeleton1) =>  1
 result2 in bytes=4 status=0
 skeleton2=TEst
 1->true, 0->false  (s2==skeleton2) =>  0
 1->true, 0->false  (s1==s2) =>  0
 1->true, 0->false  (skeleton1==skeleton2) =>  1

谢谢。