1

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

易混淆的 s [1] 字符应视为相同字符,例如:T (LATIN CAPITAL LETTER TU 0054) 应为 == T (GREEK CAPITAL LETTER 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=

感谢您的时间!

4

2 回答 2

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,并将其放入集合或散列集合中。

于 2012-09-18T16:33:34.793 回答
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

谢谢你。

于 2012-09-19T08:43:13.970 回答