4

我有个问题。我正在为 Linux 编写一个波兰语应用程序(当然还有波兰语字符),编译时收到 80 条警告。这些只是“警告:多字符字符常量”和“警告:案例标签值超过类型的最大值”。我正在使用 std::string。

如何替换 std::string 类?

请帮忙。提前致谢。问候。

4

3 回答 3

4

std::string没有定义特定的编码。因此,您可以在其中存储任何字节序列。有一些微妙之处需要注意:

  1. .c_str()将返回一个以 null 结尾的缓冲区。如果您的字符集允许空字节,请不要将此字符串传递给采用const char*没有长度的参数的函数,否则您的数据将被截断。
  2. Achar不代表一个字符,而是一个 **byte。恕我直言,这是计算历史上最成问题的命名法。请注意,这wchar_t也必然包含一个完整的字符,具体取决于 UTF-16 规范化。
  3. .size()并将.length()返回字节数,而不是字符数。

[编辑]关于标签的警告case与问题 (2) 有关。您正在使用switch包含多字节字符的语句,该语句使用的类型char不能超过一个字节。[/编辑]

因此,您可以在您的应用程序中使用std::string,前提是您遵守这三个规则。STL 存在一些微妙之处,包括std::find()由此产生的后果。由于规范化形式,您需要使用一些更聪明的字符串匹配算法来正确支持 Unicode。

但是,在使用任何使用非 ASCII 字符的语言编写应用程序时(如果您是偏执狂,请考虑这一切[0, 128)),您需要了解不同文本数据源中的编码。

  1. 源文件编码可能未指定,并且可能会使用编译器选项进行更改。任何字符串文字都将受此规则的约束。我想这就是你收到警告的原因。
  2. 您将从外部来源(文件、用户输入等)获得各种字符编码。当该来源指定编码或者您可以从某个外部来源获取它(即询问导入数据的用户)时,这会更容易。除非另有说明,否则许多(较新的)互联网协议都采用 ASCII 或 UTF-8。

任何特定的字符串类都没有解决这两个问题。您只需要将所有外部源转换为您的内部编码。我一直建议使用 UTF-8,但在 Linux 上尤其如此,因为它具有原生支持。我强烈建议将您的字符串文字放在消息文件中,以忘记问题 (1) 并只处理问题 (2)。

我不建议std::wstring在 Linux 上使用,因为 100% 的原生 API 使用函数签名const char*直接支持 UTF-8。如果您使用任何基于 的字符串类wchar_t,您将需要不停地转换为/从不std::wstring停止并最终出错,除了让一切变慢(呃)。

如果您正在为 Windows 编写应用程序,我会建议完全相反,因为所有本机 API 都使用const wchar_t*签名。此类函数的 ANSI 版本执行与const wchar_t*.

一些“便携式”库/语言使用基于平台的不同表示。char他们在 Linux 上使用 UTF-8,wchar_t在 Windows 上使用 UTF-16。我记得在 Python 参考实现中阅读过那个技巧,但这篇文章已经很老了。我不确定这是否是真的。

于 2010-11-22T20:34:38.327 回答
1

在 linux 上,您应该使用您使用的框架提供的多字节字符串类。

我推荐来自 glibmm 框架的 Glib::ustring,它以 UTF-8 编码存储字符串。如果您的源文件是 UTF-8 格式,那么在代码中使用多字节字符串文字就像:

ustring alphabet("aąbcćdeęfghijklłmnńoóprsśtuwyzźż");

但是您不能使用char. 我建议使用一系列ifs. 您可以使用 Glibmm ,但它的可读性不是很好(您可以使用Wikipedia 中波兰字母表中gunichar的表格获取字符的正确 unicode 值):

#include <glibmm.h>
#include <iostream>

using namespace std;

int main()
{
        Glib::ustring alphabet("aąbcćdeęfghijklłmnńoóprsśtuwyzźż");
        int small_polish_vovels_with_diacritics_count = 0;
        for ( int i=0; i<alphabet.size(); i++ ) {
                switch (alphabet[i]) {
                        case 0x0105: // ą
                        case 0x0119: // ę
                        case 0x00f3: // ó
                                small_polish_vovels_with_diacritics_count++;
                                break;
                        default:
                                break;
                }
        }
        cout << "There are " << small_polish_vovels_with_diacritics_count
                << " small polish vovels with diacritics in this string.\n"; 
        return 0;
}

您可以使用以下方法编译它:

g++ `pkg-config --cflags --libs glibmm-2.4` progname.cc -o progname
于 2010-11-22T16:03:28.277 回答
-1

std::string用于 ASCII 字符串。由于您的波兰字符串不适合,您应该使用std::wstring.

于 2010-11-22T14:55:47.447 回答