使用`strstr`在字符串中搜索多字节UTF-8字符是否安全?

时间:2014-08-29 15:38:16

标签: c string utf-8 multibyte-functions

按照我之前的问题:Why `strchr` seems to work with multibyte characters, despite man page disclaimer?,我发现strchr是一个糟糕的选择。

相反,我正在考虑使用strstr来查找单个字符(多字节而不是char):

const char str[] = "This string contains é which is a multi-byte character";
char * pos = strstr(str, "é"); // 'é' = 0xC3A9: 2 bytes 
printf("%s\n", pos);

输出继电器:

  

é是一个多字节字符

我期望的是:我的多字节字符的第一个字节的位置。

先验,这不是strstr的规范用法,但它似乎运作良好 这种解决方法安全吗?您能想到会导致错误的任何副作用或特殊情况吗?

[编辑]:我应该确切地说我不想使用wchar_t类型,并且我处理的字符串是UTF-8编码的(我知道这个choice可以讨论,但这是一个无关紧要的辩论)

3 个答案:

答案 0 :(得分:7)

修改
基于来自OP的更新问题,"在UTF-8环境中存在这样的误报" 所以答案是UTF-8的设计方式使它不受如上所示的部分不匹配的影响,并导致任何误报。 因此,使用带有UTF-8编码多字节字符的strstr是完全安全的。

原始答案
No strstr不适用于包含多字节字符的字符串。

如果要搜索的字符串在包含多字节字符的字符串中不包含多字节字符,则可能会出现误报。 (在日语语言环境中使用shift-jis encoding时,strstr("引出某些内容"," @ some")可能会出现误报)

+---------+----+----+----+
|   c1    | c2 | c3 | c4 |  <--- string
+---------+----+----+----+

     +----+----+----+
     | c5 | c2 | c3 |  <--- string to search
     +----+----+----+

如果c1的尾随部分(意外)与c5匹配,则可能会得到错误的结果。我建议使用带unicode子串检查功能的unicode或多字节子串检查功能。 (例如_mbsstr

答案 1 :(得分:1)

现代系统使用UTF-8(或ASCII)作为多字节编码,使用此功能是安全的。

要严格遵守并使您的代码在旧/异国平台上运行,您需要考虑其他问题。

首先,好消息:在每个多字节编码中,0字节表示字符串的结尾,而不管状态如何。这意味着,您的strstr不会导致崩溃或其他事情,但结果可能是错误的。

作为一个例子,考虑UTF-7,一种7位清晰的Unicode编码方式。 UTF-7是具有移位状态的多字节编码,这意味着如何解释字节可能取决于它出现的上下文。例如。 (参见Wikipedia)“£1AKM”在UTF-7中被编码为+AKM-AKM,其中+符号会更改状态以及A等字母的解释。执行strstr(str, "AKM")会匹配第一个AKM部分(+之后),尽管这是£编码的一部分,实际上应该匹配AKM之后的-部分1}}(将班次状态设置回初始状态)。

答案 2 :(得分:-2)

这种解决方法安全吗?你能想到会导致错误的任何副作用或特殊情况吗?

一个副作用是,如果strtr()找不到任何匹配项,那么您将打印一个空指针值,这将导致Segmentation fault

在打印字符串之前,您应该检查指针是否具有NULL值。 检查如下:

if(pos == NULL)
   printf("letter not found");
else 
   printf("%s\n", pos);