乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 222|回复: 14

挑战:优化函数 MatchCharInString

[复制链接]

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-26 07:48:01 | 显示全部楼层 |阅读模式
修改-添加的源代码项目文件
下面列出的函数MatchCharInString(还附加了测试工具的项目文件)可以工作,但没有我希望的那么有效。如果你除了,你的任务是让它更快。请注意,字符串是UTF-16多字节的。这意味着“for and time循环”可能是错误的优化,因为它需要与不同的Unicode本地文件一起使用。一个明显的优化是不要复制pcszSource和pcszMatchChars中的字符串。这里有一些基本规则,MatchCharsInString参数不能更改,CString和/或AString不是可行的选项。TIA,玩得开心。
包含的项目文件的示例输出。
在这里,第一个测试将字符'B''B''O'与字符串“这是一个测试”进行比较,并且没有找到匹配项,因为没有找到'B'。
第二行测试'B'B''O'反对“Bob说,“Hello World!”并在位置0-'B',2-'B',15-'O'找到匹配项。
'B''B''O'的每个字符在字符串中只匹配一次,如果找到,则继续搜索下一个字符串位置的下一个字符。
  1. Testing -- BBO
  2.    Does not match: This is a Test
  3.           Matches: Bob said, "Hello World!"   0 2 15
  4.    Does not match: Lizzard Lips
  5.    Does not match: Zebra tails                2
  6.    Does not match: Luke warm milk
  7. Testing -- RZ
  8.    Does not match: This is a Test
  9.    Does not match: Bob said, "Hello World!"   19
  10.    Does not match: Lizzard Lips               5
  11.    Does not match: Zebra tails                3
  12.    Does not match: Luke warm milk             7
  13. Testing -- ZR
  14.    Does not match: This is a Test
  15.    Does not match: Bob said, "Hello World!"
  16.           Matches: Lizzard Lips               2 5
  17.           Matches: Zebra tails                0 3
  18.    Does not match: Luke warm milk
  19. Testing -- KML
  20.    Does not match: This is a Test
  21.    Does not match: Bob said, "Hello World!"
  22.    Does not match: Lizzard Lips
  23.    Does not match: Zebra tails
  24.           Matches: Luke warm milk             2 8 12

MatchCharInString
  1. // Does a lowercase match each character in sMatchChars to a character in the string sSource
  2. // (also lower case).
  3. // Each match is done in sequence. When the first character is found from sMatchChars the
  4. // next character from sMatchChars is searched for the current position of sSource to
  5. // the end of sSource string.
  6. // The position of each match is stored in the vector index that is passed by reference.
  7. // Returns true if all sMatchChars are found before reaching the end of sSource, false otherwise.
  8. bool MatchCharsInString(const wchar_t * pcszSource, const wchar_t * pcszMatchChars, std::vector & index)
  9. {
  10.     std::wstring sSource(pcszSource);
  11.     std::wstring sMatchChars(pcszMatchChars);
  12.     // change input strings to lower case
  13.     std::transform(sSource.begin(), sSource.end(), sSource.begin(), std::tolower);
  14.     std::transform(sMatchChars.begin(), sMatchChars.end(), sMatchChars.begin(), std::tolower);
  15.     bool bFound = true;
  16.     size_t pos = 0;
  17.     std::wstring::iterator itChar = sMatchChars.begin();
  18.     for(itChar; itChar != sMatchChars.end(); itChar++) {
  19.         pos = sSource.find_first_of(*itChar, pos);
  20.         if(pos == std::wstring::npos) {
  21.             // if the position of sSource is the end of the string then
  22.             // there was not a complete match of each character in sMatchChars
  23.             bFound = false;
  24.             break;
  25.         }
  26.         index.push_back(pos);  //push valid position to index
  27.         pos++;
  28.     }
  29.     return bFound;
  30. }

本帖以下内容被隐藏保护;需要你回复后,才能看到!

游客,如果您要查看本帖隐藏内容请回复
回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-26 07:53:53 | 显示全部楼层
小心。
这个版本非常快和错误。 为什么?因为它不考虑本地 Unicode 设置,并且会轰炸任何多字节 Unicode 值。
  1. ////////////////////////////////////////////////////////////////////////
  2. // Will not work for some unicode locales.
  3. ////////////////////////////////////////////////////////////////////////
  4. bool MatchString(const wchar_t * pcszSource, const wchar_t * pcszMatchChars)
  5. {
  6.         while(*pcszMatchChars) {
  7.                 wchar_t c = std::tolower(*pcszMatchChars);
  8.                 while(*pcszSource) {
  9.                         if(c == std::tolower(*pcszSource)) {
  10.                                 break;
  11.                         }
  12.                         pcszSource++;
  13.                 }
  14.                 if(!*pcszSource)
  15.                         break;
  16.                 pcszMatchChars++;
  17.         }
  18.         return (*pcszSource && !*pcszMatchChars);
  19. }

回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-26 22:13:39 | 显示全部楼层
我不知道
  1. #include "stdafx.h"
  2. #include
  3. #include
  4. #include
  5. void MatchString(const wchar_t *pcszSource, const wchar_t *pcszMatchChars,
  6.                  std::vector & index)
  7. {
  8.   std::locale loc;
  9.   bool bMatchIsHigh;
  10.   bool bSrcIsHigh;
  11.   for(size_t idx = 0; *pcszSource != '\0'; idx++)
  12.   {
  13.     if(*pcszMatchChars != '\0')
  14.     {
  15.       bMatchIsHigh = IS_HIGH_SURROGATE(*pcszMatchChars);
  16.       bSrcIsHigh = IS_HIGH_SURROGATE(*pcszSource);
  17.       if(!bMatchIsHigh && !bSrcIsHigh)
  18.       {
  19.         if(std::tolower(*pcszSource,loc) == std::tolower(*pcszMatchChars,loc))
  20.         {
  21.           index.push_back(idx);
  22.           pcszMatchChars++;
  23.         }
  24.         pcszSource++;
  25.       }
  26.       else if(bMatchIsHigh && bSrcIsHigh)
  27.       {
  28.         if( *pcszSource+1 != '\0' && *pcszMatchChars+1 != '\0')
  29.         {
  30.           UINT32 a = ((*pcszSource - 0xD800) * 0x400) +
  31.              (*pcszSource+1 - 0xDC00) + 0x10000;
  32.           UINT32 b = ((*pcszMatchChars - 0xD800) * 0x400) +
  33.             (*pcszMatchChars+1 - 0xDC00) + 0x10000;
  34.           if(std::tolower(a,loc) == std::tolower(b,loc))
  35.           {
  36.             index.push_back(idx);
  37.             pcszMatchChars++;
  38.             pcszMatchChars++;
  39.           }
  40.           pcszSource++;
  41.           pcszSource++;
  42.         }
  43.         else
  44.         {
  45.           return;// bad format
  46.         }
  47.       }
  48.       else if(bMatchIsHigh  && !bSrcIsHigh)
  49.       {
  50.         pcszSource++;
  51.       }
  52.       else if(!bMatchIsHigh && bSrcIsHigh)
  53.       {
  54.         pcszSource++;
  55.         pcszSource++;
  56.       }
  57.     }
  58.     else
  59.     {
  60.       break;
  61.     }
  62.   }
  63. }
  64. int _tmain(int argc, _TCHAR* argv[])
  65. {
  66.   std::vector index;
  67.   wchar_t a[] = {'d', 'a', 0xD834, 0xDD1E,'\0'};
  68.   wchar_t b[] = {'a', 0xD834, 0xDD1E,'\0'};
  69.   //wchar_t a[] = {'L','u','k','e',' ',0xD834,0xDD1E,'w','a','r','m',' ','m','i','l','k','\0'};
  70.   //wchar_t b[] = {'K',0xD834,0xDD1E,'L','\0'}; // 2 5 13
  71.   //wchar_t a[] = {'L','u','k','e',' ','w','a','r','m',' ','m','i','l','k','\0'};
  72.   //wchar_t b[] = {'K','M','L','\0'};
  73.   MatchString(a,b,index);
  74.   for(size_t i = 0; i < index.size(); i++)
  75.   {
  76.     wprintf(_T("%ld "),index[i]);
  77.   }
  78.   system("pause");
  79.   return 0;
  80. }

回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 05:47:53 | 显示全部楼层
这是一个很好的解决方案,丹。我没有看到代理宏,它们可能会工作。
http://msdn.microsoft.com/en-us/library/dd374069(第85节)。aspx
我认为
  1.           UINT32 a = ((*pcszSource - 0xD800) * 0x400) +
  2.              (*pcszSource+1 - 0xDC00) + 0x10000;
  3.           UINT32 b = ((*pcszMatchChars - 0xD800) * 0x400) +
  4.             (*pcszMatchChars+1 - 0xDC00) + 0x10000;
  5.           if(std::tolower(a,loc) == std::tolower(b,loc))
如果(std::tolower(pcszSource,loc)=std::ToLowers(pcsz Mathchars,loc))
可以简化为
,因为它是区域设置感知的(未测试)。如果是这种情况,那么最初的问题就变成了在将指针发送到tolower之前对指针进行简单的记录
唯一要做的另一件事是在应用程序的早期初始化std::locale,并有一个返回其引用的函数,然后这件事就会很快完成
在我的原始版本中,我使用了<cctype>中的std::tolower,因为我没有理解“独立于语言环境”的含义,这是一个很好的理解<再次感谢。
回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 06:43:56 | 显示全部楼层
BTW,能不能澄清一下
uint 32 a =((* pcsz source-0xd 800)* 0x 400)+
(* pcsz source+1-0x DC 00)+0x 10000的意图;
回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 06:49:03 | 显示全部楼层

我认为它是UTF-32的转换,虽然我可能用错了。
回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 06:50:09 | 显示全部楼层
我不知道0xd800以上的字符是否有小写字母,最初我只知道它像<br>或<pre>一样
  1. if((*pcszSource + *pcszSource+1) ==
  2.              (*pcszMatchChars + *pcszMatchChars+1))

回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 06:58:18 | 显示全部楼层
哦,我明白了
我认为,使用代理宏,您只需将指针移动到正确的位置,然后让std::tolower(ptr,loc)处理其余部分。我不确定,因为我的脑袋埋在STL和Boost库中,试图找出它,但所有泛型都妨碍了理解。
回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 07:13:58 | 显示全部楼层

你可能是对的
回复

使用道具 举报

27

主题

193

帖子

5

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
300
发表于 2010-2-27 21:42:53 | 显示全部楼层
不同字符串的内存位置在OS X中是这样的。注意szStr和sStr是用UTF-8编码处理的,而wchar_t和wstring是UTF-32(在Windows上它们是UTF-16)。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-2-5 22:00 , Processed in 0.358754 second(s), 77 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表