在 C 和 NCURSES 中处理 Unicode 字符
Handling Unicode characters in C and NCURSES
我正在尝试在 C 程序中显示一些 unicode 字符。可以在下面看到一个工作的 MWE:
#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <locale.h>
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
initscr(); // Initialize stdscr
for(int x = 0; x < 20; x++)
{
switch (x%5)
{
case 0:
mvaddstr(1, x, "\u2588");
break;
case 1:
mvaddstr(1, x, "\u2593");
break;
case 2:
mvaddstr(1, x, "\u2592");
break;
case 3:
mvaddstr(1, x, "\u2591");
break;
case 4:
mvaddstr(1, x, " ");
break;
}
}
mvprintw(3, 0, "Press ANY KEY to finish");
refresh();
int ch = getch();
endwin();
return 0;
}
编译使用gcc -o shades shades.c -lncursesw
。它编译良好并正确显示阴影,如下图所示。
但是我想使用 case/switch
语句而不是将我的字符放入一个 数组 的十六进制代码中并对其进行迭代。作为下面的可耻尝试。
#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
initscr(); // Initialize stdscr
uint shades[5] = { 0x2588,
0x2593,
0x2592,
0x2591,
' '};
char utfchar[7];
for(int x = 0; x < 20; x++)
{
sprintf(utfchar, "\u%04x", shades[x%5]);
mvaddstr(1, x, utfchar);
}
mvprintw(3, 0, "Press ANY KEY to finish");
refresh();
int ch = getch();
endwin();
return 0;
}
我在这里使用 sprintf
将十六进制值转换为格式为 \u0000
的字符串,其中 0000
是正确的十六进制值。然后我像在前面的代码中那样使用 mvaddstr
,因为 mvaddstr
在第三个参数中期望 const char *
。
这是许多失败的尝试之一。我无法以 unicode 格式正确复制字符串,当我尝试添加 unicode 内容时,也无法将变量用作 mvaddstr
的参数。
我想知道如何从 uint
有效的 unicode 十六进制值格式化支持 unicode 的 const char *
以将其插入 mvaddstr
?
PS:我在 Linux 中没有使用 C++,只是普通的 C。 C++解决方案不是解决方案
您可以简单地将字符串放入数组中:
const char *shades[] = { "\u2588",
"\u2593",
"\u2592",
"\u2591",
" "};
for(int x = 0; x < 20; x++)
{
mvaddstr(1, x, shades[x%4]);
}
如果您想使用代码点,则需要将其编码为 UTF8(或 NCurse 期望的任何内容):
void sprintutf8(char *buffer, uint32_t code)
{
if (code < 0x80)
sprintf(buffer, "%c", code);
else if (code < 0x800)
sprintf(buffer, "%c%c",
0xC0 | (code >> 6),
0x80 | (code & 0x3F));
else
sprintf(buffer, "%c%c%c",
0xE0 | (code >> 12),
0x80 | (code >> 6 & 0x3F),
0x80 | (code & 0x3F));
}
[...]
for(int x = 0; x < 20; x++)
{
sprintutf8(utfchar, shades[x%4]);
mvaddstr(1, x, utfchar);
}
您可以简单地使用 wctomb
转换和 wchar_t
从十六进制转换为 unicode:
uint shades[5] = { 0x2588,
0x2593,
0x2592,
0x2591,
' '};
char utfchar[MB_CUR_MAX];
for(int x = 0; x < 20; x++)
{
memset(utfchar, 0, sizeof utfchar);
wctomb(utfchar, (wchar_t)shades[x % 5]);
mvaddstr(1, x, utfchar);
}
我正在尝试在 C 程序中显示一些 unicode 字符。可以在下面看到一个工作的 MWE:
#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <locale.h>
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
initscr(); // Initialize stdscr
for(int x = 0; x < 20; x++)
{
switch (x%5)
{
case 0:
mvaddstr(1, x, "\u2588");
break;
case 1:
mvaddstr(1, x, "\u2593");
break;
case 2:
mvaddstr(1, x, "\u2592");
break;
case 3:
mvaddstr(1, x, "\u2591");
break;
case 4:
mvaddstr(1, x, " ");
break;
}
}
mvprintw(3, 0, "Press ANY KEY to finish");
refresh();
int ch = getch();
endwin();
return 0;
}
编译使用gcc -o shades shades.c -lncursesw
。它编译良好并正确显示阴影,如下图所示。
但是我想使用 case/switch
语句而不是将我的字符放入一个 数组 的十六进制代码中并对其进行迭代。作为下面的可耻尝试。
#include <ncurses.h>
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
initscr(); // Initialize stdscr
uint shades[5] = { 0x2588,
0x2593,
0x2592,
0x2591,
' '};
char utfchar[7];
for(int x = 0; x < 20; x++)
{
sprintf(utfchar, "\u%04x", shades[x%5]);
mvaddstr(1, x, utfchar);
}
mvprintw(3, 0, "Press ANY KEY to finish");
refresh();
int ch = getch();
endwin();
return 0;
}
我在这里使用 sprintf
将十六进制值转换为格式为 \u0000
的字符串,其中 0000
是正确的十六进制值。然后我像在前面的代码中那样使用 mvaddstr
,因为 mvaddstr
在第三个参数中期望 const char *
。
这是许多失败的尝试之一。我无法以 unicode 格式正确复制字符串,当我尝试添加 unicode 内容时,也无法将变量用作 mvaddstr
的参数。
我想知道如何从 uint
有效的 unicode 十六进制值格式化支持 unicode 的 const char *
以将其插入 mvaddstr
?
PS:我在 Linux 中没有使用 C++,只是普通的 C。 C++解决方案不是解决方案
您可以简单地将字符串放入数组中:
const char *shades[] = { "\u2588",
"\u2593",
"\u2592",
"\u2591",
" "};
for(int x = 0; x < 20; x++)
{
mvaddstr(1, x, shades[x%4]);
}
如果您想使用代码点,则需要将其编码为 UTF8(或 NCurse 期望的任何内容):
void sprintutf8(char *buffer, uint32_t code)
{
if (code < 0x80)
sprintf(buffer, "%c", code);
else if (code < 0x800)
sprintf(buffer, "%c%c",
0xC0 | (code >> 6),
0x80 | (code & 0x3F));
else
sprintf(buffer, "%c%c%c",
0xE0 | (code >> 12),
0x80 | (code >> 6 & 0x3F),
0x80 | (code & 0x3F));
}
[...]
for(int x = 0; x < 20; x++)
{
sprintutf8(utfchar, shades[x%4]);
mvaddstr(1, x, utfchar);
}
您可以简单地使用 wctomb
转换和 wchar_t
从十六进制转换为 unicode:
uint shades[5] = { 0x2588,
0x2593,
0x2592,
0x2591,
' '};
char utfchar[MB_CUR_MAX];
for(int x = 0; x < 20; x++)
{
memset(utfchar, 0, sizeof utfchar);
wctomb(utfchar, (wchar_t)shades[x % 5]);
mvaddstr(1, x, utfchar);
}