如何在c ++字符串中搜索非ASCII字符?

时间:2015-07-14 01:26:28

标签: c++ string

string s="x1→(y1⊕y2)∧z3";

for(auto i=s.begin(); i!=s.end();i++){
    if(*i=='→'){
       ...
    }
} 

字符比较肯定是错误的,这是正确的方法吗?我正在使用vs2013。

2 个答案:

答案 0 :(得分:3)

首先,您需要对程序如何处理Unicode有一些基本的了解。否则,你应该阅读,我非常喜欢this post on Joel on Software

你实际上有两个问题:

问题#1:将字符串输入程序

您的首要问题是在string s中获取实际字符串。根据源代码文件的编码,MSVC可能会破坏该字符串中的任何非ASCII字符。

  • 将您的C ++文件保存为UTF-16(Windows令人困惑地称之为 Unicode ),并使用whcar_twstring(有效地将表达式编码为UTF -16)。保存为带有BOM 的 UTF-8也可以。任何其他编码和您的L"..."字符文字都将包含错误的字符。

    请注意,其他平台可能将wchar_t定义为4个字节而不是2个。因此,处理U + FFFF以上的字符将是不可移植的。

  • 在所有其他情况下,您不能只在源文件中写入这些字符。最便携的方法是将字符串文字编码为UTF-8,对所有非A​​SCII字符使用\x转义码。像这样:"x1\xe2\x86\x92a\xe2\x8a\x95" "b)"而不是"x1→(a⊕b)"

    是的,这就像它得到的那样难以理解和繁琐。根本问题是MSVC并不真正支持使用UTF-8。您可以在此处查看此问题以获取概述:How to create a UTF-8 string literal in Visual C++ 2008

    但是,还要考虑这些字符串实际显示在源代码中的频率。

问题#2:找到角色

(如果您使用的是UTF-16,则可以找到L'→'字符,因为该字符可以表示为whcar_t。对于U + FFFF以上的字符,您将会必须使用下面的广泛版本的解决方法。)

无法定义代表箭头字符的char。但是,您可以使用字符串:"\xe2\x86\x92"。 (这是一个包含箭头的3个字符的字符串,以及\0终止符。

您现在可以在表达式中搜索此字符串:

s.find("\xe2\x86\x92");

UTF-8编码方案保证始终找到正确的字符,但请记住这是 bytes 中的偏移量。

答案 1 :(得分:1)

我的评论太大了,所以我将其作为答案提交。

问题在于每个人都在关注Unicode可能使用的不同编码问题(UTF-8,UTF-16,UCS2等)。但是你的问题才会开始。

还存在复合字符的问题,这会使你想要进行的任何搜索陷入困境。

假设您正在寻找一个字符'é',您会在Unicode中找到它作为U + 00E9并进行搜索,但不能保证这是表示此字符的唯一方法。该文件还可能包含U + 0065 U + 0301组合。这实际上是完全一样的角色。

是的,不仅仅是“看起来相同的角色”,但它完全相同,所以任何软件甚至一些编程库都可以在不告诉你的情况下自由地从一个转换为另一个。

因此,如果你想进行搜索,那就是强大的,你需要的东西不仅代表Unicode的不同编码,而且还需要Unicode字符本身在Composite和现成字符之间具有相等性。