输入或输出非 ASCII 文本的 C 程序(符合 ISO C99 或更高版本,或 POSIX.1 或更高版本)应使用宽字符串、宽 I/O 和本地化。
例如:
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
int main(void)
{
/* Tell the C library to use the current locale settings. */
setlocale(LC_ALL, "");
/* Standard output is used with the wide I/O functions. */
fwide(stdout, 1);
/* Print some Greek text. */
wprintf(L"Γειά σου Κόσμε!\n");
return EXIT_SUCCESS;
}
请注意,宽字符串文字使用L"..." 编写,而普通(ASCII 或窄)字符串文字使用"..."。类似地,宽字符常量(wint_t 类型)用L 前缀编写;例如,L'€'。
编译时,您确实需要告诉编译器源代码使用什么字符集。在 Linux 中,GCC 使用区域设置,但还提供了一个选项 -finput-charset=windows-1252 以将其更改为 Windows 西欧,例如。
我建议您编写一个 Bash 辅助脚本,而不是摆弄标志,例如 to-utf8:
#!/bin/bash
if [ $# -lt 2 ] || [ ":$1" = ":-h" ] || [ ":$1" = ":--help" ]; then
printf '\n'
printf 'Usage: %s [ -h | --help ]\n' "$0"
printf ' %s windows-1252 file.c [ ... ]\n' "$0"
printf '\n'
exit 0
fi
charset="$1"
shift 1
Work=$(mktemp) || exit 1
trap "rm -f '$Work'" EXIT
for src in "$@" ; do
iconv -f "$charset//TRANSLIT" -t UTF-8 "$src" > "$Work" || exit $?
sed -e 's|\r$||' "$Work" > "$src" || exit $?
printf '%s: Converted successfully.\n' "$src"
done
exit 0
如果你愿意,你可以在系统范围内使用
sudo install -o 0 -g 0 -m 0755 to-utf8 /usr/bin/
第一个命令行参数是源字符集(使用iconv --list 可以查看全部),然后是要修复的文件列表。
脚本会创建一个自动删除的临时文件。 iconv 行将每个文件的字符集转换为 UTF-8,将结果保存到临时文件中。 sed 文件将任何 CRLF (\r\n) 换行符更改为 LF (\n),覆盖文件的内容。
(而不是使用第二个临时文件来保存内容,让sed 将其输出定向到原始文件,这意味着原始文件保持其所有者和组不变。)