使用C++(无需WinAPI),将UTF-8字符转换为最接近的等效ASCII字符

4

有没有代码片段可以将欧洲语言中最常见的字符转换成其他形式?例如:

testáén

作为UTF-8编码的字符串(即十六进制字节:74 65 73 74 c3 a1 c3 a9 6e 0)

转换为

testaen

(我想使用C/C++和标准库,或者小型跨平台库)


1
我知道Ã映射到a,但为什么©映射到e?第二个Ã怎么了?你有尝试编写这样的代码吗? - Cody Gray
嘿!我使用了这个工具:http://www.cafewebmaster.com/online_tools/utf_decode - Graphyt
1
Á 转换为á,我需要一个。 - Graphyt
1
é 转换为 é,我想要 e。 - Graphyt
2
你是不是想写"testáén"应该映射到"testaen"而不是"testáén"?我认为你可能粘贴了一些失去正确编码的内容。 - CB Bailey
显示剩余8条评论
3个回答

5

这里是处理将字符从ISO-8859-1范围转换为ASCII的代码。对于ASCII范围之外的所有内容,使用替换字符。

#include <codecvt>
#include <array>
#include <string>

#include <iostream>

constexpr char const *rc = "?"; // replacement_char

// table mapping ISO-8859-1 characters to similar ASCII characters
std::array<char const *,96> conversions = {{
   " ",  "!","c","L", rc,"Y", "|","S", rc,"C","a","<<",   rc,  "-",  "R", "-",
    rc,"+/-","2","3","'","u", "P",".",",","1","o",">>","1/4","1/2","3/4", "?", 
   "A",  "A","A","A","A","A","AE","C","E","E","E", "E",  "I",  "I",  "I", "I",
   "D",  "N","O","O","O","O", "O","*","0","U","U", "U",  "U",  "Y",  "P","ss",
   "a",  "a","a","a","a","a","ae","c","e","e","e", "e",  "i",  "i",  "i", "i",
   "d",  "n","o","o","o","o", "o","/","0","u","u", "u",  "u",  "y",  "p", "y"    
}};

template <class Facet>
class usable_facet : public Facet {
public:
    using Facet::Facet;
    ~usable_facet() {}
};

std::string to_ascii(std::string const &utf8) {
    std::wstring_convert<usable_facet<std::codecvt<char32_t,char,std::mbstate_t>>,
                         char32_t> convert;
    std::u32string utf32 = convert.from_bytes(utf8);

    std::string ascii;
    for (char32_t c : utf32) {
        if (c<=U'\u007F')
            ascii.push_back(static_cast<char>(c));
        else if (U'\u00A0'<=c && c<=U'\u00FF')
            ascii.append(conversions[c - U'\u00A0']);
        else
            ascii.append(rc);
    }
    return ascii;
}

int main() {
    std::cout << to_ascii(u8"testáén\n");
}

请注意,C++17中已弃用std::wstring_convert。 - Viktor Sehr
请注意,在Visual Studio中,您需要使用uint32_t而不是char32_t。https://social.msdn.microsoft.com/Forums/vstudio/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral - Viktor Sehr

4

有一个巨大的Unicode字符集需要处理,所以“小”的标准是不可能的标准。ICU库包含您需要的内容,但出于这个原因,您不会发现它很小。例如,您需要处理组合和非组合修饰符。

如果您只关心可能的Unicode字符的一小部分,则可以创建自己的简单映射表。


3

我想使用C/C++和标准库,或者小型跨平台库。

不幸的是,我不确定是否存在符合您所有要求的库。

您可能会找到的最小的东西是iconv,它的UTF-8转ASCII转换器可能无法完全满足您的需求。

我非常确定ICU可以满足您的要求,虽然ICU是跨平台的,但从来没有人称其为小型


你可以编译ICU的小版本,仅包括你想要的最小数据集。不过这很麻烦。 - CB Bailey
1
你可以使用ICU来生成utf-8 => ascii转换序列的静态trie。它应该非常小,极其快速,并且肯定是跨平台的。 - edA-qa mort-ora-y

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接