putwchar()无法显示wchar_t变量

时间:2016-03-19 23:00:36

标签: c c99 wchar widechar

为什么printf()可以显示é\u00E9 int UTF-16)而putwchar()不能?

使putwchar正确显示é的正确语法是什么?

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

int main() {
  wint_t wc = L'\u00E9';

  setlocale(LC_CTYPE, "fr_FR.utf8");

  printf("%C\n", wc);
  putwchar((wchar_t)wc);
  putchar('\n');

  return 0;
}

环境公司

  • 操作系统:openSUSE Leap 42.1
  • 编译器:gcc版本4.8.5(SUSE Linux)
  • 终端:终结者
  • 终端编码:UTF-8
  • Shell:zsh
  • CPU:x86_64

Shell env:

env | grep LC && env | grep LANG
LC_CTYPE=fr_FR.utf8
LANG=fr_FR.UTF-8
GDM_LANG=fr_FR.utf8

修改

in:

wint_t  wc = L'\u00E9'
setlocale(LC_CTYPE, "");

出:

C3 A9 0A E9 0A

在:

wint_t wc = L'\xc3a9';               
setlocale(LC_CTYPE, "");

出:

EC 8E A9 0A A9 0A

2 个答案:

答案 0 :(得分:2)

在同一个流上,不能混用宽字符和字节输入/输出函数(printf是字节输出函数,无论它是否包含宽字符的格式)。流的方向只能用freopen重置,必须在调用面向字节的putchar函数之前再次完成。

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

int main() {
    wint_t wc = L'\u00E9';

    setlocale(LC_CTYPE, "");

    printf("%lc\n", wc);
    freopen(NULL, "w", stdout);
    putwchar((wchar_t)wc);
    freopen(NULL, "w", stdout);
    putchar('\n');

    return 0;
}

只能通过重新打开流来设置方向这一事实表明这不是简单的,并且大多数程序应该只使用一种输出。 (即wprintf / putwchar或printf / putchar,如果需要打印宽字符,请使用printf或wctomb)

答案 1 :(得分:0)

问题是您的setlocale()来电失败了。如果你检查结果,你会看到。

  if( !setlocale(LC_CTYPE, "fr_FR.utf8") ) {
      printf("Failed to set locale\n");
      return 1;
  }

问题是fr_FR.utf8不是区域设置的正确名称。相反,请使用LANG格式:fr_FR.UTF-8

  if( !setlocale(LC_CTYPE, "fr_FR.UTF-8") ) {
      printf("Failed to set locale\n");
      return 1;
  }

语言环境名称是系统上安装的任何名称,可能在/usr/share/locale/中。或者,您可以获得包含locale -a的列表。

您很少想要对区域设置进行硬编码。通常,您希望使用环境指定的任何内容。要执行此操作,请将""作为区域设置传递,程序将找到它。

  if( !setlocale(LC_CTYPE, "") ) {
      printf("Failed to set locale\n");
      return 1;
  }