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

How to search a non-ASCII character in a c++ string?

本文关键字:搜索 ascii 字符 字符串 c++      更新时间:2023-10-16
string s="x1→(y1⊕y2)∧z3";
for(auto i=s.begin(); i!=s.end();i++){
    if(*i=='→'){
       ...
    }
} 

char比较绝对是错误的,正确的方法是什么?我使用的是vs2013。

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

你实际上有两个问题:

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

您的第一个问题是在您的string s中获得实际字符串。根据源代码文件的编码,MSVC可能会损坏该字符串中的任何非ascii字符。

  • 将c++文件保存为UTF-16 (Windows混淆地称为Unicode),并使用whcar_twstring(有效地将表达式编码为UTF-16)。保存为UTF-8和BOM也可以。任何其他编码和您的L"..."字符字面量将包含错误的字符。

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

  • 在所有其他情况下,您不能只在源文件中写入这些字符。最可移植的方法是将字符串字面值编码为UTF-8,对所有非ascii字符使用x转义码。像这样:"x1xe2x86x92axe2x8ax95" "b)"而不是"x1→(a⊕b)"

    是的,这是不可读的和麻烦的。根本问题是MSVC并不真正支持使用UTF-8。在Visual c++ 2008中如何创建一个UTF-8字符串字面值

    但是,也要考虑这些字符串在源代码中实际出现的频率

问题#2:查找字符

(如果使用UTF-16,则只能找到L'→'字符,因为该字符可表示为一个whcar_t。对于U+FFFF以上的字符,您必须使用下面的宽版本的解决方案。

不可能定义一个表示箭头字符的char。但是,您可以使用字符串:"xe2x86x92"。(这是一个包含3个字符的箭头和结束符的字符串。

你现在可以在你的表达式中搜索这个字符串:

s.find("xe2x86x92");

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

我的评论太大了,所以我把它作为一个答案提交。

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

还有一个问题是复合字符,它会把你正在进行的任何搜索弄得一团糟。

假设你正在寻找一个字符' ',你在Unicode中找到它为U+00E9并进行搜索,但不能保证这是表示该字符的唯一方法。也可能是U+0065 U+0301的组合。这实际上是完全相同的字符

是的,不仅仅是"看起来一样的字符",而且它是完全一样的,所以任何软件,甚至一些编程库都可以自由地从一个转换到另一个,甚至不需要告诉你。

因此,如果您希望进行搜索,这是健壮的,您将需要一些东西,不仅表示Unicode的不同编码,而且Unicode字符本身具有复合字符和现成字符之间的平等。