【问题标题】:C++ std:string comparation codification problemsC++ std:string 比较编码问题
【发布时间】:2018-04-20 01:53:56
【问题描述】:

我认为 std::string 与编码比较有问题。问题是我讨厌比较接收到的字符串,而且我不知道它与带有不常用字符的西班牙字符串的编码方式如何。我无法更改 s_area.m_s_area_text 所以我需要设置具有相同值的 s2 字符串,我不知道如何以通用方式进行其他追逐。

std::string s2= "Versión de sistema";  
std::cout << s_area.m_s_area_text << std::endl;

for (const char* p = s2.c_str(); *p; ++p)
{
   printf("%02x", *p);
}
printf("\n");


for (const char* p = s_area.m_s_area_text.c_str(); *p; ++p)
{
   printf("%02x", *p);
}
printf("\n");

而执行的结果是:

Versi├│n de sistema
5665727369fffffff36e2064652073697374656d61
5665727369ffffffc3ffffffb36e2064652073697374656d61

显然,由于 2 个字符串的字节值不同,所有比较方法都会失败:strncmp、std::string ==、std:sstring.comapre 等。

知道如何在不接触 s_area.m_s_area_text 字符串的情况下做到这一点吗?

【问题讨论】:

  • 你不会比较代码中的字符串吧?
  • 看起来你需要一个不比较字节的比较函数,而是别的东西。您可以编写这样的函数,也可以将两个字符串都转换为规范表示,这样字节比较函数就足够了。这取决于您希望忽略哪些字节。
  • 我已经跳过了比较功能……它们都返回假。我需要比较整个字符串而不跳过任何字符。
  • 我认为当您说“编码”时,您的意思是“编码”,问题是“当字符串具有不同的编码时,我如何比较它们是否相等”。答案可能是将两个字符串都转换为相同的编码,并可能对其进行规范化,然后按字节值进行比较。
  • 如果您能提供更多信息,可能会有解决方案。例如,您是否使用已知编码获取用户输入并将其与数据库中的数据或已知编码的数据文件中的数据进行比较,问题实际上是两者是不同的编码但都是已知的(或者至少可以事先弄清楚) .

标签: c++ string encoding std utf


【解决方案1】:

一般来说,通过检查字符串的原始字节来猜测字符串的编码是不可能的。此规则的例外情况是字节顺序标记 (BOM) 出现在字节流的开头。 BOM 会告诉您字节是哪种 unicode 编码以及字节序。

顺便说一句,如果在将来的某个时候您决定需要一个规范的字符串编码(正如一些人在 cmets 中指出的那样,这将是一个好主意)。有强烈的论据支持 UTF-8 作为 C++ 的最佳选择。有关这方面的更多信息,请参阅UTF-8 everywhere

【讨论】:

    【解决方案2】:

    首先,两个正确比较两个字符串你至少需要知道它们的编码。在您的示例中,s_area.m_s_area_text 恰好使用 UTF-8 编码,而 s2 使用 ISO/IEC 8859-1 (Latin-1)。

    如果您确定s_area.m_s_area_text 将始终以UTF-8 编码,您可以尝试使s2 使用相同的编码,然后进行比较。定义 UTF-8 编码字符串的一种方法是将不在基本字符集中的每个字符转义为 \u

    std::string s2 = u8"Versi\u00F3n de sistema";
    ...
    if (s_area.m_s_area_text == s2)
    ...
    

    通过为源文件设置适当的编码并向编译器指定编码,也应该可以在不转义字符的情况下做到这一点。

    正如@nwp 提到的,您可能还希望在比较之前对字符串进行规范化。否则,看起来相同的两个字符串可能具有不同的 Unicode 表示,这将导致您的比较产生假阴性结果。 例如,“Versión de sistema”将不等于“Versión de sistema”。

    【讨论】:

      猜你喜欢
      • 2013-03-28
      • 1970-01-01
      • 2011-04-26
      • 2017-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多