locale.h 定義了程序運行時的本地化環境:數字格式、貨幣符號、日期時間、字符分類/轉換規則。核心是 struct lconv 貨幣/數字格式詳情、setlocale() 設置/查詢類別、localeconv() 獲取格式詳情。本文系統整理所有類別宏、結構體字段、函數語義、實戰代碼。
LC_ALL:所有類別。LC_COLLATE:字符串排序 (strcoll, strxfrm)。LC_CTYPE:字符分類/轉換 (ctype.h 函數)。LC_MONETARY:貨幣格式 (localeconv 相關字段)。LC_NUMERIC:數字格式 (小數點、分組、localeconv)。LC_TIME:日期時間格式 (strftime)。struct lconv 完整字段表| 字段 | 類型 | 含義 |
|---|---|---|
| decimal_point | char* | 非貨幣小數點 (如 ".") |
| thousands_sep | char* | 非貨幣千分位分隔符 (如 ",") |
| grouping | char* | 非貨幣分組大小串 (每字符一組大小,0=重複) |
| int_curr_symbol | char* | 國際貨幣符號 (ISO 4217 三字母+分隔符,如 "USD ") |
| 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 | 正值貨幣符號前置? (1=前, 0=後) |
| p_sep_by_space | char | 正值符號與值空格分隔? (1=是) |
| n_cs_precedes | char | 負值貨幣符號前置? |
| n_sep_by_space | char | 負值符號與值空格分隔? |
| p_sign_posn | char | 正值符號位置 (0=括號, 1=前, 2=後, 3=緊貼符號前, 4=緊貼符號後) |
| n_sign_posn | char | 負值符號位置 (編碼同 p_sign_posn) |
字符指針可能為空串 "" (不可用),字符字段為 CHAR_MAX 表示不可用。
setlocalechar *setlocale(int category, const char *locale);
locale = "C":標準 C 環境 (默認,點號小數、ASCII 排序)。locale = "":環境變量決定 (如 LANG=zh_CN.UTF-8)。locale = NULL:**僅查詢**,不修改,返回當前類別設置字符串。NULL。localeconvstruct lconv *localeconv(void);
lconv 的指針,反映**當前**本地化設置。uselocale (POSIX)。#include <locale.h>
#include <stdio.h>
int main() {
char *old = setlocale(LC_ALL, "C");
printf("Previous locale: %s\n", old);
setlocale(LC_ALL, ""); // 使用環境變量
struct lconv *lc = localeconv();
printf("Decimal point: %s\n", lc->decimal_point);
printf("Thousands sep: %s\n", lc->thousands_sep);
printf("Currency symbol: %s\n", lc->currency_symbol);
return 0;
}
struct lconv *lc = localeconv();
printf("Decimal point: %s\n", lc->decimal_point);
printf("Thousands Separator: %s\n", lc->thousands_sep);
printf("Grouping: %s\n", lc->grouping);
printf("Intl Currency Symbol: %s\n", lc->int_curr_symbol);
printf("Currency Symbol: %s\n", lc->currency_symbol);
printf("Mon Decimal Point: %s\n", lc->mon_decimal_point);
printf("Mon Thousands Sep: %s\n", lc->mon_thousands_sep);
printf("Mon Grouping: %s\n", lc->mon_grouping);
printf("Positive Sign: %s\n", lc->positive_sign);
printf("Negative Sign: %s\n", lc->negative_sign);
printf("Intl Frac Digits: %d\n", lc->int_frac_digits);
printf("Frac Digits: %d\n", lc->frac_digits);
printf("+ Precedes: %d\n", lc->p_cs_precedes);
printf("+ Space: %d\n", lc->p_sep_by_space);
printf("- Precedes: %d\n", lc->n_cs_precedes);
printf("- Space: %d\n", lc->n_sep_by_space);
printf("+ Sign Posn: %d\n", lc->p_sign_posn);
printf("- Sign Posn: %d\n", lc->n_sign_posn);
setlocale 影響**整個進程** (包括庫函數 printf/scanf/strtod 解析數字格式)。庫開發**慎用**,或用 uselocale (線程級)。localeconv 返回靜態指針,並發調用需互斥鎖。LC_ALL > LC_xxx > LANG。setlocale(LC_ALL, "") 遵循此規則。lconv 字段指針指向靜態存儲,**下次 setlocale/localeconv 可能失效**,需立即複製內容。setlocale(LC_NUMERIC, "C") 或用 strtod_l 指定語言環境。locale.h 讓程序說用戶的語言:小數點逗號、貨幣符號位置、日期順序。掌握 lconv 字段語義、setlocale 類別範圍、全局副作用與線程安全限制,能正確處理國際化數據輸入輸出。現代高併發服務建議**避免修改全局 locale**,改用線程級 uselocale 或顯式格式化函數 (snprintf 指定格式)。