std::wstring大小写不敏感比较方案

399 views
Skip to first unread message

meta

unread,
Feb 28, 2010, 9:47:52 PM2/28/10
to pon...@googlegroups.com

std::wstring commandName = getXXX();

std::transform(commandName.begin(), commandName.end(), commandName.begin(), tolower);

if (commandName == “_xyz”)

    do_something

 

有更好的做法吗?

jinhu wang

unread,
Feb 28, 2010, 10:03:28 PM2/28/10
to pon...@googlegroups.com
我一直不很清楚w指的是什么?是utf16吗?
要是图效率的话的,可以通过查表法比较。查表法的逻辑相对也简单的多。上周五看sqlite的代码看到的,呵呵
2010/3/1 meta <carma...@gmail.com>

meta

unread,
Feb 28, 2010, 10:08:48 PM2/28/10
to pon...@googlegroups.com
if (commandName == “_xyz”) should be:
if (commandName == “_xyz”)

2010/3/1 meta <carma...@gmail.com>

meta

unread,
Feb 28, 2010, 10:09:56 PM2/28/10
to pon...@googlegroups.com
if (commandName == “_xyz”) should be:
if (commandName == L“_xyz”)

meta

unread,
Feb 28, 2010, 10:12:00 PM2/28/10
to pon...@googlegroups.com
std::wstring是UTF16 base的.

每次比较的字符串可能都不一样, 这个怎么个查表法?

2010/3/1 jinhu wang <wangji...@gmail.com>

Milo Yip

unread,
Feb 28, 2010, 10:18:06 PM2/28/10
to pon...@googlegroups.com
http://stackoverflow.com/questions/1068134/comparing-wstring-with-ignoring-the-case

wstring 在 C++ standard 裡 *不是* UTF-16 的。
w = wide, 只是相對於 narrow。
但一般用法是用來放 UTF-16,其實也可以放其他 encoding 的。

--
Milo Yip

Twitter @miloyip
http://www.cnblogs.com/miloyip/
http://miloyip.seezone.net/

meta

unread,
Feb 28, 2010, 10:23:44 PM2/28/10
to pon...@googlegroups.com
那个查表法难道是类似:

table[256] = { 0 };
table['A'] = table['a'] = 1;
...
table['A'] = table['a'] = 26;


2010/3/1 Milo Yip <mil...@gmail.com>

Milo Yip

unread,
Feb 28, 2010, 10:27:08 PM2/28/10
to pon...@googlegroups.com
這方面最好不要 reinvent the wheel. 用庫或操作系統提供的方式。他們也會查表的。
最麻煩是考慮到 locale 的問題。不同 locale 的大小寫定義是不同的。

jinhu wang

unread,
Feb 28, 2010, 10:29:07 PM2/28/10
to pon...@googlegroups.com
没怎么用过,不过sqlite的源码中是这么解释的。
 
/*
** Some systems have stricmp().  Others have strcasecmp().  Because
** there is no consistency, we will define our own.
*/


Milo Yip

unread,
Feb 28, 2010, 10:33:19 PM2/28/10
to pon...@googlegroups.com
題外話: case-insensitive 是譯做 "大小寫不敏感" 麼? 這是內地標準譯法?
我覺得"不分大小寫"比較好。

XiongJia Le

unread,
Feb 28, 2010, 10:44:55 PM2/28/10
to pon...@googlegroups.com
不知道是不是 针对,文件系统的 名字比较?我觉得文件系统文件名之类比较还是用系统自己的吧?

比如: NTFS 文件系统文件名是 不分大小写的。但是真没测过针对不同的 Local 会不会不分大小写?

jinhu wang

unread,
Feb 28, 2010, 10:53:30 PM2/28/10
to pon...@googlegroups.com
我觉得不区分大小写比较达意

sagasw

unread,
Feb 28, 2010, 11:53:02 PM2/28/10
to pon...@googlegroups.com
c++必备神书《c++标准程序库》里面介绍了一种大小无关的字符串比较,我想wstring也是一样的。

另外,如果你使用Visual studio 2008 或者更高版本的VS,可以参考MFC中CString的实现。
(当然,实际上也就是调用了_mbsicmp这个微软特定CRT函数)。

说句题外话,我如果有类似的问题,一定要先拜读神书,然后在想自己的解决方案,不造轮子。

------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


On Mon, Mar 1, 2010 at 10:47 AM, meta <carma...@gmail.com> wrote:

jinhu wang

unread,
Feb 28, 2010, 11:58:21 PM2/28/10
to pon...@googlegroups.com
哈哈,这里列出了两个重造轮子的场景:
  • 在不知道有这样一个轮子存在的情况下,发明轮子
  • 自己不喜欢已有的轮子的时候,发明轮子

Ian Yang

unread,
Mar 1, 2010, 12:16:05 AM3/1/10
to TopLanguage
STL里有std::locale, 大部分实现里的std::toupper是可以接受第二个参数类型为std::locate

template<typename _CharT>
_CharT
toupper(_CharT, const locale&);

需要第二个参数可以通过包装类绑定一个

On Mar 1, 12:58 pm, jinhu wang <wangjinhu...@gmail.com> wrote:
> 哈哈,这里列出了两个重造轮子的场景:
>
> - 在不知道有这样一个轮子存在的情况下,发明轮子
> - 自己不喜欢已有的轮子的时候,发明轮子


>
> 在 2010年3月1日 下午12:53,sagasw <sag...@gmail.com>写道:
>
> > c++必备神书《c++标准程序库》里面介绍了一种大小无关的字符串比较,我想wstring也是一样的。
>
> > 另外,如果你使用Visual studio 2008 或者更高版本的VS,可以参考MFC中CString的实现。
> > (当然,实际上也就是调用了_mbsicmp这个微软特定CRT函数)。
>
> > 说句题外话,我如果有类似的问题,一定要先拜读神书,然后在想自己的解决方案,不造轮子。
>
> > ------------------------------------
> > C++, Lua, living in Dalian
> >http://sunxiunan.com/
> >http://twitter.com/sagasw
> > ------------------------------------
>

meta

unread,
Mar 1, 2010, 12:53:44 AM3/1/10
to pon...@googlegroups.com

/* An array to map all upper-case characters into their corresponding

** lower-case character.

*/

const unsigned char sqlite3UpperToLower[] = {

      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,

     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,

     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,

     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,

    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,

    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,

    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,

    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,

    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,

    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,

    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,

    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,

    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,

    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,

    252,253,254,255

};

#define UpperToLower sqlite3UpperToLower

 

 

/*

** Some systems have stricmp().  Others have strcasecmp().  Because

** there is no consistency, we will define our own.

*/

int sqlite3StrICmp(const char *zLeft, const char *zRight){

  register unsigned char *a, *b;

  a = (unsigned char *)zLeft;

  b = (unsigned char *)zRight;

  while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }

  return UpperToLower[*a] - UpperToLower[*b];

}

int sqlite3StrNICmp(const char *zLeft, const char *zRight, int N){

  register unsigned char *a, *b;

  a = (unsigned char *)zLeft;

  b = (unsigned char *)zRight;

  while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }

  return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];

}

 


找到了这坨代码, 就是一般的查表嘛, 而且只能处理char类型的.


2010/3/1 jinhu wang <wangji...@gmail.com>

meta

unread,
Mar 1, 2010, 12:56:04 AM3/1/10
to pon...@googlegroups.com
还有就是应用场景的特殊性, 弄个简单的轮子也花不了多久.

2010/3/1 jinhu wang <wangji...@gmail.com>

XIN, Wang

unread,
Mar 1, 2010, 1:23:48 AM3/1/10
to pon...@googlegroups.com
首先确定你的wstring存储的是否是 UTF-16, 如果记得没错 GCC 的 wchar_t 是 32 位的,存储的是 UTF-32。总之先要确定 ToUpper/ToLower 的实现是正确的。

如果使用的不是 Unicode 编码,可能就要重新发明轮子了,当然也可以试试 ICU。

2010/3/1 meta <carma...@gmail.com>

sagasw

unread,
Mar 1, 2010, 1:54:57 AM3/1/10
to pon...@googlegroups.com
对于:”如果使用的不是 Unicode 编码,可能就要重新发明轮子了“

能否具体说一下问题原因以及什么操作系统可能要重新发明?


------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/3/1 XIN, Wang <xer...@gmail.com>

XIN, Wang

unread,
Mar 1, 2010, 3:00:19 AM3/1/10
to pon...@googlegroups.com
比如说某种自定义的编码,另外 Unicode 中也有一部分码位是留给程序员扩充的,排版类的软件常用。当然这个轮子不一定要自己发明,也许公司里已经有人发明了。

2010/3/1 sagasw <sag...@gmail.com>

archerzz

unread,
Mar 1, 2010, 4:08:02 AM3/1/10
to TopLanguage
std::string和wstring, 只是一个char和wchar的容器。理论上讲,它和encoding无关的,这一点和Java之类的语言
不同。说再通俗一点,是一块连续内存,里面的具体data怎么解释看你程序怎么写。当然,一般情况下,wstring多是UTF-8编码的
unicode字符,否则处理起来要发疯的......

字符处理,涉及了char set和encoding两个重要部分。具体定义请看wikipedia,我就不班门弄斧了。通俗讲,char set定义
了我可以处理的字符的集合,每一个字符有一个code point,可以理解成一个唯一的整型id。然后我怎么serialize和
deserialize字符呢,就靠encoding,它定义了物理存储形式。我们通常所说的UTF-8,其实是指我们的char set是
unicode,encoding是UTF-8。随便弄个示意图:
char set encoding
char 《======》 code point 《=======》 memory value

理论上讲,你可以使用任意char set和encoding的组合。当然实际没特殊情况,还是老老实实用unicode+UTF-8之类流行组合
的。

在有些情况下,可能是需要你自己发明的轮子的。比如unicode里面不一定包含了所有中文字符(所以给小孩子起名字别太怪)。那天朝GOV怎么办,就
有一系列GB规范出来。GB系列规范,我粗看一下,好像是char set和encoding的合体。所以如果你做的应用有这种特殊的字符集要求,要特
别小心。

尽管如此,还是不建议自己写,一不小心,就容易出bug,而且还不容易fix。所以现在做globalization的话,一定要弄清楚char
set和encoding,大家都统一。如果真要处理怪字符集,可以看看ICU。我记得ICU有自己实现的string,应该对于不同char set
和encoding的处理比较友好吧。

以上内容仅凭记忆,以前听过专家关于globalization的讲座,应该有一些错误。还请达人出来指正。

On Mar 1, 2:54 pm, sagasw <sag...@gmail.com> wrote:
> 对于:"如果使用的不是 Unicode 编码,可能就要重新发明轮子了"
>
> 能否具体说一下问题原因以及什么操作系统可能要重新发明?
>
> ------------------------------------

> C++, Lua, living in Dalianhttp://sunxiunan.com/http://twitter.com/sagasw
> ------------------------------------
>
> 2010/3/1 XIN, Wang <xera...@gmail.com>


>
> > 首先确定你的wstring存储的是否是 UTF-16, 如果记得没错 GCC 的 wchar_t 是 32 位的,存储的是 UTF-32。总之先要确定
> > ToUpper/ToLower 的实现是正确的。
>
> > 如果使用的不是 Unicode 编码,可能就要重新发明轮子了,当然也可以试试 ICU。
>

> > 2010/3/1 meta <carmack....@gmail.com>
>
> > 还有就是应用场景的特殊性, 弄个简单的轮子也花不了多久.
>
> >> 2010/3/1 jinhu wang <wangjinhu...@gmail.com>


>
> >>> 哈哈,这里列出了两个重造轮子的场景:
>
> >>> - 在不知道有这样一个轮子存在的情况下,发明轮子

> >>> - 自己不喜欢已有的轮子的时候,发明轮子


>
> >>> 在 2010年3月1日 下午12:53,sagasw <sag...@gmail.com>写道:
>
> >>> c++必备神书《c++标准程序库》里面介绍了一种大小无关的字符串比较,我想wstring也是一样的。
>
> >>>> 另外,如果你使用Visual studio 2008 或者更高版本的VS,可以参考MFC中CString的实现。
> >>>> (当然,实际上也就是调用了_mbsicmp这个微软特定CRT函数)。
>
> >>>> 说句题外话,我如果有类似的问题,一定要先拜读神书,然后在想自己的解决方案,不造轮子。
>
> >>>> ------------------------------------
> >>>> C++, Lua, living in Dalian
> >>>>http://sunxiunan.com/
> >>>>http://twitter.com/sagasw
> >>>> ------------------------------------
>

XIN, Wang

unread,
Mar 1, 2010, 4:23:37 AM3/1/10
to pon...@googlegroups.com
确认了一下,wstring / wchar_t 确实是编译器相关的。在 Wiki 上有这么一段话:

"The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compiler should not use wchar_t for storing Unicode text. The wchar_t type is intended for storing compiler-defined wide characters, which may be Unicode characters in some compilers."

一般来说在 Windows 上 wchar_t 是 16 位的 UTF-16 编码,在 Unix 上是 32 位的 UTF-32 编码。

2010/3/1 archerzz <arch...@gmail.com>

meta

unread,
Mar 1, 2010, 5:04:42 AM3/1/10
to pon...@googlegroups.com
恩, 刚才去扫了一眼Chrome的代码, 发现Unix的确有16和32bits两种:

// Type detection for wchar_t.

#if defined(OS_WIN)

#define WCHAR_T_IS_UTF16

#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \

    defined(__WCHAR_MAX__) && \

    (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)

#define WCHAR_T_IS_UTF32

#elif defined(OS_POSIX) && defined(COMPILER_GCC) && \

    defined(__WCHAR_MAX__) && \

    (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)

// On Posix, we'll detect short wchar_t, but projects aren't guaranteed to

// compile in this mode (in particular, Chrome doesn't). This is intended for

// other projects using base who manage their own dependencies and make sure

// short wchar works for them.

#define WCHAR_T_IS_UTF16

#else

#error Please add support for your compiler in build/build_config.h

#endif



2010/3/1 XIN, Wang <xer...@gmail.com>

Yongwei Wu

unread,
Mar 1, 2010, 7:16:06 AM3/1/10
to pon...@googlegroups.com
如果Windows的话,直接调

if (_wcsicmp(commandName, L"_xyz") == 0)

就行了。其它平台可能提供类似的wcsncasecmp函数。

无论什么平台,使用"=="都是错的(那是指针比较)!!!

--
Wu Yongwei
URL: http://wyw.dcweb.cn/

meta

unread,
Mar 1, 2010, 8:38:42 AM3/1/10
to pon...@googlegroups.com
直接比较指针? 你以为是Java啊~ 去看看basic_string的实现......

2010/3/1 Yongwei Wu <wuyo...@gmail.com>

Yongwei Wu

unread,
Mar 1, 2010, 8:41:55 AM3/1/10
to pon...@googlegroups.com
Sorry,看迷糊了。右边是指针,以为左边也是了......

2010/3/1 meta <carma...@gmail.com>:

Yongwei Wu

unread,
Mar 1, 2010, 8:44:49 AM3/1/10
to pon...@googlegroups.com
2010/3/1 Yongwei Wu <wuyo...@gmail.com>:

> 如果Windows的话,直接调
>
> if (_wcsicmp(commandName, L"_xyz") == 0)

应当是commandName.c_str()。

> 就行了。其它平台可能提供类似的wcsncasecmp函数。

应当是wcscasecmp,没有n。有n的对应于strncmp/_strnicmp。

jiyong wu

unread,
Mar 1, 2010, 9:18:19 AM3/1/10
to pon...@googlegroups.com
用用boost也不错。

http://www.boost.org/doc/libs/1_42_0/doc/html/boost/algorithm/iequals.html

if (iequal(commandName, L"_xyz"))
  ;

XIN, Wang

unread,
Mar 1, 2010, 8:57:00 PM3/1/10
to pon...@googlegroups.com
即使在 Java 中,“==” 比较也是错误的。

2010/3/1 meta <carma...@gmail.com>

meta

unread,
Mar 1, 2010, 8:58:56 PM3/1/10
to pon...@googlegroups.com
我说的是反话~

2010/3/2 XIN, Wang <xer...@gmail.com>

Megahertz

unread,
Mar 4, 2010, 8:43:55 PM3/4/10
to TopLanguage
我喜欢用 wcsicmp
不过 "使用"=="都是错的(那是指针比较)",不会是c用多了吧

On Mar 1, 8:16 pm, Yongwei Wu <wuyong...@gmail.com> wrote:
> 如果Windows的话,直接调
>
> if (_wcsicmp(commandName, L"_xyz") == 0)
>
> 就行了。其它平台可能提供类似的wcsncasecmp函数。
>
> 无论什么平台,使用"=="都是错的(那是指针比较)!!!
>

> On 1 March 2010 11:09, meta <carmack....@gmail.com> wrote:
>
>
>
> > if (commandName == "_xyz") should be:
> > if (commandName == L"_xyz")

> > 2010/3/1 meta <carmack....@gmail.com>


>
> >> if (commandName == "_xyz") should be:
> >> if (commandName == "_xyz")
>

> >> 2010/3/1 meta <carmack....@gmail.com>

CoolJie

unread,
Mar 6, 2010, 8:35:40 AM3/6/10
to pon...@googlegroups.com
这个表格里面的字体色彩是什么配置,我在VS 2008中配置不出来这么清晰的效果,我用的Consoles设置为12号后完全模糊了,操作系统是Windows7 开启了ClearType 

Serenade

unread,
Mar 13, 2010, 4:35:43 AM3/13/10
to pon...@googlegroups.com
Consolas 13号字体
Reply all
Reply to author
Forward
0 new messages