如何将宽字符串转换为ASCII

时间:2016-05-23 20:33:01

标签: c++ character-encoding ascii

我正在寻找一种将wstring转换为仅包含ASCII字符的普通string的方法。 ASCII(0-127)中不存在的任何字符都应转换为最接近的ASCII字符。如果没有类似的ASCII字符,则应省略该字符。

为了说明,我们假设以下宽字符串:

wstring text(L"A naïve man called 晨 was having piña colada and crème brûlée.");

我正在寻找的转换版本就是这样(注意没有变音符号):

string("A naive man called  was having pina colada and creme brulee.")

修改

关于目的:我正在编写一份分析英文文本的应用程序。输入文件是UTF-8,可能包含特殊字符。我的应用程序的一部分使用用C编写的只能理解ASCII的库。所以我需要一种方式来减少"将文本转换为ASCII而不会丢失太多信息。

关于精确要求:任何作为ASCII字符变音符号的字符都应转换为该ASCII字符;应省略所有其他字符。因此,ıĩî应该成为i,因为它们都是拉丁字母i的所有版本。另一方面,角色ɩ(iota)虽然在视觉上相似,但不是小拉丁字母i的版本,因此应该省略。

2 个答案:

答案 0 :(得分:4)

在GitHub上,unidecode-cxxnode-unidecode的(有些未完成的)C ++端口,它是Perl的Text::Unicode的JavaScript端口。 C ++版本边缘有点粗糙,但src/unidecode.cxx中的示例可以修改为转换示例字符串,

  

A naïve man called 晨 was having piña colada and crème brûlée.

如下:

  

A naive man called Chen was having pina colada and creme brulee.

为了让代码在没有Gyp的情况下编译(我从未使用过的东西,现在还没有时间弄清楚),我不得不稍微修改代码(快速和脏):

  • #include <iostream>添加到src/unidecode.cxx,并添加以下main例程:

    int main() {
      string output_buf;
      string input_buf = "A naïve man called 晨 was having piña colada and crème brûlée.";
      unidecode(&input_buf, &output_buf);
      cout << output_buf.c_str() << endl;
    }
    
  • NULL src/data.cxxnullptr的所有提及替换为g++ -std=c++11 -o unidecode unidecode.cxx

然后我用

编译
/etc/resolv.conf

获得理想的结果。

代码看起来像一个相当原始的端口,可以做一些改进,尤其是更“适当”的C ++。它内部使用静态编译的转换表,如果没有,可以根据您的需要进行调整。

答案 1 :(得分:0)

wstringstring的{​​{1}},这是一个大小为2或4个字节的字符。 同时,UTF8是一种可变长度编码,符号大小为1-4字节。所以你的要求并不完全一致。

假设您已经弄清楚数据存储在字符串中的准确性,我建议您查看ICU库以进行进一步的转换。

您可以规范化字符串,然后删除所有变音符号。但是你仍然会留下希腊语,西里尔语和其他东西。 或者您可以使用更像您正在寻找的transliteration功能。

Mindriot的解决方案更简洁,但您仍然需要将wchar转换为正确的UTF8序列。