8

使用 printf 将双字节字符串格式化为单字节字符串时:

printf("%ls\n", L"s:\\яшертыHello");   // %ls for a wide string (%s varies meaning depending on the project's unicode settings).

显然,有些字符不能表示为 ascii 字符,所以有时我看到双字节字符变成“?”的行为。标记字符。但是,这似乎取决于特定的字符。对于上面的 printf,输出是:

s:\

我希望我可能会得到类似的东西:

s:\??????Hello

恐怕我已经失去了这个例子,但我认为对于一个字符串,当它遇到 unicode 字符时,将第一个字符串替换为“?” 然后放弃了剩下的。

所以,我的问题是,当您将宽字符串格式化为单字节字符串时会发生什么。此处的文档:http: //msdn.microsoft.com/en-us/library/hf4y5e3w.aspx说“字符显示到第一个空字符”。但是,我没有看到。这是 printf 中的错误,还是我在某处看到的行为记录在哪里,如果是,在哪里。

谢谢你的帮助。

更新

感谢人们为我提供使用 printf 的替代方案的回答。我将改用另一种方法,但出于好奇,我真的很感兴趣 printf 为什么没有可靠的记录行为。似乎它的实施者竭尽全力使这不起作用。

4

2 回答 2

12

我希望您的代码能够正常工作——它可以在 Linux 上工作——但它取决于语言环境。这意味着您必须设置语言环境,并且您的语言环境必须支持使用的字符集。这是我的测试程序:

#include <locale.h>
#include <stdio.h>

int main()
{
    int c;
    char* l = setlocale(LC_ALL, "");
    if (l == NULL) {
        printf("Locale not set\n");
    } else {
        printf("Locale set to %s\n", l);
    }
    printf("%ls\n", L"s:\\яшертыHello");
    return 0;
}

这是一个执行跟踪:

$ env LC_ALL=en_US.utf8 ./a.out
Locale set to en_US.utf8
s:\яшертыHello

如果它说没有设置语言环境或设置为“C”,那么您没有得到您期望的结果是正常的。

编辑:请参阅此问题的答案,以获取相当于 Windows 的 en_US.utf8 的信息。

于 2012-04-04T08:31:46.353 回答
5

在 C++ 中,我通常std::stringstream用来创建格式化文本。我还实现了一个自己的运算符来使用 Windows 函数进行编码:

ostream & operator << ( ostream &os, const wchar_t * str )
{
  if ( ( str == 0 ) || ( str[0] == L'\0' ) )
   return os;
  int new_size = WideCharToMultiByte( CP_UTF8, 0, str, -1, NULL, NULL, NULL, NULL );
  if ( new_size <= 0 )
    return os;
  std::vector<char> buffer(new_size);
  if ( WideCharToMultiByte( CP_UTF8, 0, str, -1, &buffer[0], new_size, NULL, NULL ) > 0 )
    os << &buffer[0];
  return os;
}

此代码转换为 UTF-8。对于其他可能性检查:WideCharToMultiByte

于 2012-04-04T08:26:33.287 回答