Appearance
C 标准库 - <locale.h>
概述
<locale.h> 头文件提供了本地化(localization)支持,允许程序适应不同的文化、语言和地区设置。本地化包括日期格式、时间格式、货币符号、数字格式等。
本地化类别
LC_ALL
所有本地化类别。
c
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "");
printf("当前本地化设置: %s\n", setlocale(LC_ALL, NULL));
return 0;
}LC_COLLATE
字符串比较和排序规则。
c
#include <stdio.h>
#include <locale.h>
#include <string.h>
int main() {
setlocale(LC_COLLATE, "en_US.UTF-8");
printf("排序本地化: %s\n", setlocale(LC_COLLATE, NULL));
char str1[] = "apple";
char str2[] = "banana";
int result = strcoll(str1, str2);
printf("比较结果: %d\n", result);
return 0;
}LC_CTYPE
字符分类和转换。
c
#include <stdio.h>
#include <locale.h>
#include <ctype.h>
int main() {
setlocale(LC_CTYPE, "en_US.UTF-8");
printf("字符本地化: %s\n", setlocale(LC_CTYPE, NULL));
char c = 'A';
printf("'%c' 是字母: %d\n", c, isalpha(c));
return 0;
}LC_MONETARY
货币格式。
c
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_MONETARY, "en_US.UTF-8");
printf("货币本地化: %s\n", setlocale(LC_MONETARY, NULL));
return 0;
}LC_NUMERIC
数字格式(小数点、千位分隔符等)。
c
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_NUMERIC, "en_US.UTF-8");
printf("数字本地化: %s\n", setlocale(LC_NUMERIC, NULL));
double value = 1234567.89;
printf("数字格式: %'.2f\n", value);
return 0;
}LC_TIME
时间和日期格式。
c
#include <stdio.h>
#include <locale.h>
#include <time.h>
int main() {
setlocale(LC_TIME, "en_US.UTF-8");
printf("时间本地化: %s\n", setlocale(LC_TIME, NULL));
time_t now = time(NULL);
struct tm *tm = localtime(&now);
char buffer[100];
strftime(buffer, sizeof(buffer), "%A, %B %d, %Y", tm);
printf("当前日期: %s\n", buffer);
return 0;
}本地化函数
setlocale()
c
char *setlocale(int category, const char *locale);设置或查询程序的本地化设置。
c
#include <stdio.h>
#include <locale.h>
int main() {
char *old_locale;
old_locale = setlocale(LC_ALL, "en_US.UTF-8");
printf("设置后的本地化: %s\n", setlocale(LC_ALL, NULL));
old_locale = setlocale(LC_ALL, "zh_CN.UTF-8");
printf("设置后的本地化: %s\n", setlocale(LC_ALL, NULL));
return 0;
}localeconv()
c
struct lconv *localeconv(void);返回当前本地化的数字和货币格式信息。
c
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "en_US.UTF-8");
struct lconv *lc = localeconv();
printf("小数点: %s\n", lc->decimal_point);
printf("千位分隔符: %s\n", lc->thousands_sep);
printf("分组: %s\n", lc->grouping);
printf("货币符号: %s\n", lc->currency_symbol);
printf("国际货币符号: %s\n", lc->int_curr_symbol);
return 0;
}lconv 结构体
c
struct lconv {
char *decimal_point;
char *thousands_sep;
char *grouping;
char *int_curr_symbol;
char *currency_symbol;
char *mon_decimal_point;
char *mon_thousands_sep;
char *mon_grouping;
char *positive_sign;
char *negative_sign;
char int_frac_digits;
char frac_digits;
char p_cs_precedes;
char p_sep_by_space;
char n_cs_precedes;
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
};实际应用示例
1. 显示所有本地化信息
c
#include <stdio.h>
#include <locale.h>
void print_locale_info() {
struct lconv *lc = localeconv();
printf("=== 数字格式 ===\n");
printf("小数点: '%s'\n", lc->decimal_point);
printf("千位分隔符: '%s'\n", lc->thousands_sep);
printf("分组: '%s'\n", lc->grouping);
printf("\n");
printf("=== 货币格式 ===\n");
printf("货币符号: '%s'\n", lc->currency_symbol);
printf("国际货币符号: '%s'\n", lc->int_curr_symbol);
printf("货币小数点: '%s'\n", lc->mon_decimal_point);
printf("货币千位分隔符: '%s'\n", lc->mon_thousands_sep);
printf("货币分组: '%s'\n", lc->mon_grouping);
printf("正号: '%s'\n", lc->positive_sign);
printf("负号: '%s'\n", lc->negative_sign);
printf("\n");
printf("=== 货币位置 ===\n");
printf("正数货币符号在前: %d\n", lc->p_cs_precedes);
printf("正数货币符号用空格分隔: %d\n", lc->p_sep_by_space);
printf("负数货币符号在前: %d\n", lc->n_cs_precedes);
printf("负数货币符号用空格分隔: %d\n", lc->n_sep_by_space);
printf("正数符号位置: %d\n", lc->p_sign_posn);
printf("负数符号位置: %d\n", lc->n_sign_posn);
}
int main() {
setlocale(LC_ALL, "en_US.UTF-8");
printf("=== 美国本地化 ===\n");
print_locale_info();
setlocale(LC_ALL, "zh_CN.UTF-8");
printf("\n=== 中国本地化 ===\n");
print_locale_info();
return 0;
}2. 格式化货币
c
#include <stdio.h>
#include <locale.h>
#include <string.h>
void format_currency(double amount) {
struct lconv *lc = localeconv();
char buffer[100];
if (amount >= 0) {
if (lc->p_cs_precedes) {
if (lc->p_sep_by_space) {
snprintf(buffer, sizeof(buffer), "%s %.2f",
lc->currency_symbol, amount);
} else {
snprintf(buffer, sizeof(buffer), "%s%.2f",
lc->currency_symbol, amount);
}
} else {
if (lc->p_sep_by_space) {
snprintf(buffer, sizeof(buffer), "%.2f %s",
amount, lc->currency_symbol);
} else {
snprintf(buffer, sizeof(buffer), "%.2f%s",
amount, lc->currency_symbol);
}
}
} else {
amount = -amount;
if (lc->n_cs_precedes) {
if (lc->n_sep_by_space) {
snprintf(buffer, sizeof(buffer), "%s%s %.2f",
lc->negative_sign, lc->currency_symbol, amount);
} else {
snprintf(buffer, sizeof(buffer), "%s%s%.2f",
lc->negative_sign, lc->currency_symbol, amount);
}
} else {
if (lc->n_sep_by_space) {
snprintf(buffer, sizeof(buffer), "%s%.2f %s",
lc->negative_sign, amount, lc->currency_symbol);
} else {
snprintf(buffer, sizeof(buffer), "%s%.2f%s",
lc->negative_sign, amount, lc->currency_symbol);
}
}
}
printf("%s\n", buffer);
}
int main() {
setlocale(LC_ALL, "en_US.UTF-8");
printf("美国货币格式:\n");
format_currency(1234.56);
format_currency(-1234.56);
setlocale(LC_ALL, "zh_CN.UTF-8");
printf("\n中国货币格式:\n");
format_currency(1234.56);
format_currency(-1234.56);
return 0;
}3. 本地化字符串比较
c
#include <stdio.h>
#include <locale.h>
#include <string.h>
void compare_strings(const char *str1, const char *str2) {
int result = strcoll(str1, str2);
if (result < 0) {
printf("'%s' < '%s'\n", str1, str2);
} else if (result > 0) {
printf("'%s' > '%s'\n", str1, str2);
} else {
printf("'%s' == '%s'\n", str1, str2);
}
}
int main() {
setlocale(LC_COLLATE, "en_US.UTF-8");
printf("英语排序:\n");
compare_strings("apple", "banana");
compare_strings("zebra", "apple");
setlocale(LC_COLLATE, "zh_CN.UTF-8");
printf("\n中文排序:\n");
compare_strings("苹果", "香蕉");
compare_strings("香蕉", "苹果");
return 0;
}4. 本地化日期时间
c
#include <stdio.h>
#include <locale.h>
#include <time.h>
void print_localized_time() {
time_t now = time(NULL);
struct tm *tm = localtime(&now);
char buffer[100];
strftime(buffer, sizeof(buffer), "%A, %B %d, %Y", tm);
printf("日期: %s\n", buffer);
strftime(buffer, sizeof(buffer), "%H:%M:%S", tm);
printf("时间: %s\n", buffer);
strftime(buffer, sizeof(buffer), "%x", tm);
printf("短日期: %s\n", buffer);
strftime(buffer, sizeof(buffer), "%X", tm);
printf("短时间: %s\n", buffer);
}
int main() {
setlocale(LC_TIME, "en_US.UTF-8");
printf("英语时间格式:\n");
print_localized_time();
setlocale(LC_TIME, "zh_CN.UTF-8");
printf("\n中文时间格式:\n");
print_localized_time();
return 0;
}5. 本地化数字格式
c
#include <stdio.h>
#include <locale.h>
void print_localized_number(double value) {
printf("数字: %'.2f\n", value);
}
int main() {
double value = 1234567.89;
setlocale(LC_NUMERIC, "en_US.UTF-8");
printf("美国数字格式:\n");
print_localized_number(value);
setlocale(LC_NUMERIC, "de_DE.UTF-8");
printf("\n德国数字格式:\n");
print_localized_number(value);
setlocale(LC_NUMERIC, "zh_CN.UTF-8");
printf("\n中国数字格式:\n");
print_localized_number(value);
return 0;
}6. 检查可用本地化
c
#include <stdio.h>
#include <locale.h>
void test_locale(const char *locale) {
char *result = setlocale(LC_ALL, locale);
if (result != NULL) {
printf("本地化 '%s' 可用: %s\n", locale, result);
} else {
printf("本地化 '%s' 不可用\n", locale);
}
}
int main() {
const char *locales[] = {
"en_US.UTF-8",
"en_US",
"zh_CN.UTF-8",
"zh_CN",
"de_DE.UTF-8",
"fr_FR.UTF-8",
"ja_JP.UTF-8",
NULL
};
for (int i = 0; locales[i] != NULL; i++) {
test_locale(locales[i]);
}
return 0;
}7. 切换本地化
c
#include <stdio.h>
#include <locale.h>
#include <time.h>
void switch_locale(int category, const char *locale) {
char *old_locale = setlocale(category, locale);
if (old_locale != NULL) {
printf("切换到 '%s': 成功\n", locale);
} else {
printf("切换到 '%s': 失败\n", locale);
}
}
int main() {
printf("=== 切换本地化 ===\n");
switch_locale(LC_ALL, "en_US.UTF-8");
switch_locale(LC_ALL, "zh_CN.UTF-8");
switch_locale(LC_ALL, "de_DE.UTF-8");
printf("\n=== 恢复默认本地化 ===\n");
setlocale(LC_ALL, "C");
printf("当前本地化: %s\n", setlocale(LC_ALL, NULL));
return 0;
}本地化注意事项
1. 线程安全
setlocale() 函数会影响整个程序,不是线程安全的。在多线程程序中使用时需要小心。
c
#include <stdio.h>
#include <locale.h>
#include <pthread.h>
void* thread_func(void* arg) {
int thread_id = *(int*)arg;
setlocale(LC_ALL, "en_US.UTF-8");
printf("线程 %d: %s\n", thread_id, setlocale(LC_ALL, NULL));
return NULL;
}
int main() {
pthread_t threads[3];
int ids[3] = {1, 2, 3};
for (int i = 0; i < 3; i++) {
pthread_create(&threads[i], NULL, thread_func, &ids[i]);
}
for (int i = 0; i < 3; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}2. 本地化名称
本地化名称的格式通常为 language_territory.encoding,例如:
en_US.UTF-8- 美国英语,UTF-8 编码zh_CN.UTF-8- 中国中文,UTF-8 编码de_DE.UTF-8- 德国德语,UTF-8 编码
3. 默认本地化
使用空字符串 "" 作为 locale 参数会使用系统的默认本地化设置。
c
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "");
printf("系统默认本地化: %s\n", setlocale(LC_ALL, NULL));
return 0;
}总结
<locale.h> 提供的本地化功能对于开发国际化的应用程序非常重要。通过使用本地化功能,开发者可以:
- 适应不同地区 - 根据用户的地区设置调整程序的显示格式
- 提高用户体验 - 使用用户熟悉的日期、时间、货币和数字格式
- 支持多语言 - 支持不同语言的字符串排序和比较
- 增强程序可用性 - 使程序更容易被不同文化背景的用户接受
记住:
- 本地化设置会影响整个程序
- 在多线程环境中要小心使用
- 使用系统默认本地化时使用空字符串
- 不同的系统可能支持不同的本地化设置