c - setlocale() 没有按预期工作
c - setlocale() not working as expect
以下程序使用 setlocale()
从环境变量中获取区域设置,并打印时间。
locale_test.c:
// locale test
#include <stdio.h>
#include <locale.h>
#include <time.h>
// locale test
void locale_test() {
// use environment variable to get locale setting,
setlocale(LC_ALL, "");
char buf[26];
time_t now = time(NULL);
ctime_r(&now, buf);
printf("time: %s", buf);
char *time_locale = setlocale(LC_TIME, NULL);
printf("current LC_TIME locale: %s\n", time_locale);
}
int main(int argc, char *argv[]) {
locale_test();
return 0;
}
执行:
LC_ALL=fr_FR LC_TIME=fr_FR ./a.out
,输出为:
time: Wed Oct 14 13:16:35 2015
current LC_TIME locale: C
LC_ALL=en_US LC_TIME=en_US ./a.out
,输出为:
time: Wed Oct 14 13:17:12 2015
current LC_TIME locale: C
问题是:
- 由于语言环境不同,2次执行的结果应该是不同的格式,但它们是一样的,为什么?
- 当尝试获取当前
LC_TIME
时,它只打印 C
,而不是环境变量指定的值。
更新-解决方案:
根据评论和回答,做了以下修改:
- 根据
locale -a
的结果使用正确的语言环境名称
- 使用
strftime()
代替ctime()
生成时间字符串
新节目:
// locale test
#include <stdio.h>
#include <locale.h>
#include <time.h>
// locale test
void locale_test() {
// use environment variable to get locale setting,
if(setlocale(LC_ALL, "") == NULL) {
printf("error while setlocale()\n");
}
// get current LC_TIME
char *time_locale = setlocale(LC_TIME, NULL);
if(time_locale == NULL) {
printf("error while setlocale()\n");
} else {
printf("LC_TIME: %s\n", time_locale);
}
// print time in locale,
size_t buf_size = 50;
char buf[buf_size];
// char *format = "%F %T %z";
char *format = "%A, %d %B %Y, %H:%M:%S %Z";
time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now);
strftime(buf, buf_size, format, &tm_now);
printf("time: %s\n", buf);
}
int main(int argc, char *argv[]) {
locale_test();
return 0;
}
然后执行:
LC_ALL=en_US.utf8 LC_TIME=en_US.utf8 ./a.out
,输出为:
LC_TIME: en_US.utf8
time: Wednesday, 14 October 2015, 16:36:36 CST
LC_ALL=zh_CN.utf8 LC_TIME=zh_CN.utf8 ./a.out
,输出为:
LC_TIME: zh_CN.utf8
time: 星期三, 14 十月 2015, 16:38:10 CST
LC_ALL=en_US.utf8 LC_TIME=en_US.utf8 ./a.out
,输出为:
LC_TIME: ja_JP.utf8
time: 水曜日, 14 10月 2015, 16:40:05 CST
这是预期的工作。
您必须检查 setlocale
的 return 值,因为如果语言环境字符串无效、您想要的语言环境未安装或其他原因,它将失败。
if (setlocale(LC_ALL, "") == NULL) {
puts("Unable to set locale");
}
您可以查看 locale -a
可用的语言环境。也许您确实安装了法语语言环境,但您必须使用 fr_FR.utf8
.
进行设置
然后,ctime
输出不依赖于语言环境; standard 指定其确切格式,并且始终为英文。对于本地化输出,请改用 strftime
。
以下程序使用 setlocale()
从环境变量中获取区域设置,并打印时间。
locale_test.c:
// locale test
#include <stdio.h>
#include <locale.h>
#include <time.h>
// locale test
void locale_test() {
// use environment variable to get locale setting,
setlocale(LC_ALL, "");
char buf[26];
time_t now = time(NULL);
ctime_r(&now, buf);
printf("time: %s", buf);
char *time_locale = setlocale(LC_TIME, NULL);
printf("current LC_TIME locale: %s\n", time_locale);
}
int main(int argc, char *argv[]) {
locale_test();
return 0;
}
执行:
LC_ALL=fr_FR LC_TIME=fr_FR ./a.out
,输出为:time: Wed Oct 14 13:16:35 2015
current LC_TIME locale: CLC_ALL=en_US LC_TIME=en_US ./a.out
,输出为:time: Wed Oct 14 13:17:12 2015
current LC_TIME locale: C
问题是:
- 由于语言环境不同,2次执行的结果应该是不同的格式,但它们是一样的,为什么?
- 当尝试获取当前
LC_TIME
时,它只打印C
,而不是环境变量指定的值。
更新-解决方案:
根据评论和回答,做了以下修改:
- 根据
locale -a
的结果使用正确的语言环境名称
- 使用
strftime()
代替ctime()
生成时间字符串
新节目:
// locale test
#include <stdio.h>
#include <locale.h>
#include <time.h>
// locale test
void locale_test() {
// use environment variable to get locale setting,
if(setlocale(LC_ALL, "") == NULL) {
printf("error while setlocale()\n");
}
// get current LC_TIME
char *time_locale = setlocale(LC_TIME, NULL);
if(time_locale == NULL) {
printf("error while setlocale()\n");
} else {
printf("LC_TIME: %s\n", time_locale);
}
// print time in locale,
size_t buf_size = 50;
char buf[buf_size];
// char *format = "%F %T %z";
char *format = "%A, %d %B %Y, %H:%M:%S %Z";
time_t now = time(NULL);
struct tm tm_now;
localtime_r(&now, &tm_now);
strftime(buf, buf_size, format, &tm_now);
printf("time: %s\n", buf);
}
int main(int argc, char *argv[]) {
locale_test();
return 0;
}
然后执行:
LC_ALL=en_US.utf8 LC_TIME=en_US.utf8 ./a.out
,输出为:LC_TIME: en_US.utf8
time: Wednesday, 14 October 2015, 16:36:36 CSTLC_ALL=zh_CN.utf8 LC_TIME=zh_CN.utf8 ./a.out
,输出为:LC_TIME: zh_CN.utf8
time: 星期三, 14 十月 2015, 16:38:10 CSTLC_ALL=en_US.utf8 LC_TIME=en_US.utf8 ./a.out
,输出为:LC_TIME: ja_JP.utf8
time: 水曜日, 14 10月 2015, 16:40:05 CST
这是预期的工作。
您必须检查 setlocale
的 return 值,因为如果语言环境字符串无效、您想要的语言环境未安装或其他原因,它将失败。
if (setlocale(LC_ALL, "") == NULL) {
puts("Unable to set locale");
}
您可以查看 locale -a
可用的语言环境。也许您确实安装了法语语言环境,但您必须使用 fr_FR.utf8
.
然后,ctime
输出不依赖于语言环境; standard 指定其确切格式,并且始终为英文。对于本地化输出,请改用 strftime
。