打印UTF-8字符串与printf的 - 宽与多字节字符串文字(Printing UTF-8 str

2019-07-22 04:11发布

在这样的陈述,其中两个将被输入到源代码与相同的编码(UTF-8)和语言环境设置不当,有它们之间的任何实际的差?

printf("ο Δικαιοπολις εν αγρω εστιν\n");
printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν\n");

因此没有任何理由,更喜欢一个比其他做输出时? 我想象中的第二个执行公平有点差,但它有超过面值的多字节任何优势(或劣势)?

编辑:有与这些字符串印刷没有问题。 但我不使用宽字符串函数,因为我希望能够使用printf等为好。 所以,问题是打印有什么不同(给定的情况如上文所述)的这些方式,如果是这样,那么第二个有什么优势?

EDIT2:按照下面的评论,我现在知道,这个程序的工作原理 - 我认为是不可能的:

int main()
{
    setlocale(LC_ALL, "");
    wprintf(L"ο Δικαιοπολις εν αγρω εστιν\n");  // wide output
    freopen(NULL, "w", stdout);                 // lets me switch
    printf("ο Δικαιοπολις εν αγρω εστιν\n");    // byte output
}

EDIT3:我已经通过看发生了什么事情有两种类型做了一些进一步的研究。 以一个简单的字符串:

wchar_t *wides = L"£100 π";
char *mbs = "£100 π";

编译器产生不同的代码。 宽字符串:

.string "\243"
.string ""
.string ""
.string "1"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string " "
.string ""
.string ""
.string "\300\003"
.string ""
.string ""
.string ""
.string ""
.string ""

而第二个是:

.string "\302\243100 \317\200"

看着那Unicode编码,二是简单的UTF-8。 宽字符表示是UTF-32。 我知道这将是实现相关的。

因此,也许文字的宽字符表示是更加便携? 我的系统将不直接打印UTF-16 / UTF-32编码,所以它被自动转换为UTF-8进行输出。

Answer 1:

printf("ο Δικαιοπολις εν αγρω εστιν\n");

打印字符串文字( const char* ,特殊字符被表示为多字节字符)。 虽然你可能会看到正确的输出,也有可能会被处理同时用非ASCII字符,像这样的工作的其他问题。 例如:

char str[] = "αγρω";
printf("%d %d\n", sizeof(str), strlen(str));

输出9 8 ,因为每个这些特殊字符是由2表示char秒。

当使用L前缀你有文字组成的宽字符( const wchar_t* )和%ls格式说明导致这些宽字符转换为多字节字符 (UTF-8)。 请注意,在这种情况下,区域设置应适当设置,否则这种转换可能会导致输出为无效:

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

int main(void)
{
    setlocale(LC_ALL, "");
    printf("%ls", L"ο Δικαιοπολις εν αγρω εστιν");
    return 0;
}

但同时用宽字符工作时,有些事情可能会变得更加复杂,其他的事情可能会更简单,更直接。 例如:

wchar_t str[] = L"αγρω";
printf("%d %d", sizeof(str) / sizeof(wchar_t), wcslen(str));

将输出5 4作为一个自然希望。

一旦你决定用字符串广的工作, wprintf可以用来直接打印宽字符 。 这也是值得这里要注意的是,在Windows控制台的情况下,翻译模式, stdout应该明确设置为通过调用Unicode的模式之一_setmode

#include <stdio.h>
#include <wchar.h>

#include <io.h>
#include <fcntl.h>
#ifndef _O_U16TEXT
  #define _O_U16TEXT 0x20000
#endif

int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    wprintf(L"%s\n", L"ο Δικαιοπολις εν αγρω εστιν");
    return 0;
}


文章来源: Printing UTF-8 strings with printf - wide vs. multibyte string literals