2

在一个项目中,所有内部字符串都保存在 utf-8 编码中。该项目已移植到 Linux 和 Windows。现在需要一个 to_lower 功能。

在 POSIX 操作系统上,我可以使用 std::ctype_byname("ru_RU.UTF-8")。但是对于 g++(Debian 4.3.4-1), ctype::tolower() 不能识别俄语 UTF-8 字符(拉丁文本小写很好)。

在 Windows 上,当我尝试使用“ru_RU.UTF-8”参数构造 std::ctype_byname 时,mingw 的标准库抛出异常“std::runtime_error: locale::facet::_S_create_c_locale name not valid”。

如何在 Windows 上为 utf-8 实现/查找 std::ctype?该项目已经依赖于 libiconv(codecvt facet 基于它),但我没有看到用它实现 to_lower 的明显方法。

4

3 回答 3

3

尝试使用STLport

  以下是如何使用 STLport 读取/写入 utf8 文件的说明。
utf8 是一种编码宽字符的方式。因此,编码管理
C++ 标准库由 codecvt locale facet 处理,它是一部分
属于 ctype 类别。然而 utf8 只描述编码必须如何
执行,它不能用于对字符进行分类,因此信息不足
了解如何生成语言环境的整个 ctype 类别方面
实例。

在 C++ 中,这意味着以下代码将引发异常
创建失败的信号:

#包括
// 将抛出 std::runtime_error 异常。
std::locale loc(".utf8");

出于同样的原因,使用基于的 ctype 构面构建语言环境
UTF8 也是错误的:

// 将抛出 std::runtime_error 异常:
std::locale loc(locale::classic(), ".utf8", std::locale::ctype);

获取将处理 utf8 编码的语言环境实例的唯一解决方案
是专门表示codecvt方面应该基于utf8
编码:

// 如果有必要的平台支持将成功。
locale loc(locale::classic(), new codecvt_byname(".utf8"));

  一旦你获得了一个语言环境实例,你可以将它注入到一个文件流中
读/写 utf8 文件:

std::fstream fstr("file.utf8");
fstr.imbue(loc);

您还可以直接访问 facet 以执行 utf8 编码/解码操作:

typedef std::codecvt codecvt_t;
常量 codecvt_t& 编码 = use_facet(loc);

笔记:

1. 点('.')在utf8前面是必须的。这是一个 POSIX 约定,语言环境
名称具有以下格式:
语言[_country[.encoding]]

例如:'fr_FR'
    '法语'
    'ru_RU.koi8r'

2. utf8编码暂时只支持Windows下。不太常见的
还支持 utf7 编码。
于 2009-09-01T04:55:31.337 回答
2

如果您需要的只是西里尔字符的 to_lower,您可以自己编写一个函数。

АБВГДЕЖ UTF8 D0 90 D0 91 D0 92 D0 93 D0 94 D0 95 D0 96 0A
UTF8 中的 абвгдеж D0 B0 D0 B1 D0 B2 D0 B3 D0 B4 D0 B5 D0 B6 0A

但不要忘记 UTF8 是多字节编码。

您也可以尝试将字符串从 UTF8 转换为 wchar_t(使用 libiconv)并使用 Windows 特定函数来实现 to_lower。

于 2009-09-02T23:04:53.000 回答
0

有一些 STL(例如来自 Apache 的 STDCXX)带有多个语言环境。但在其他情况下,语言环境仅取决于系统。

如果您可以在一个操作系统上使用名称“ru_RU.UTF-8”,这并不意味着其他系统在此语言环境中具有相同的名称。Debian 和 windows 可能有其他名称,这就是您出现运行时异常的原因。

您应该先在系统上安装所需的语言环境。或者使用已经具有此语言环境的 STL。

我的分...

于 2009-08-31T11:41:26.273 回答