首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C標準庫參考指南(6):locale.h 國際化本地化接口完整解析

     編輯:關於C語言

前言:locale.h——程序適應世界的接口

locale.h 定義了程序運行時的本地化環境:數字格式、貨幣符號、日期時間、字符分類/轉換規則。核心是 struct lconv 貨幣/數字格式詳情、setlocale() 設置/查詢類別、localeconv() 獲取格式詳情。本文系統整理所有類別宏、結構體字段、函數語義、實戰代碼。

一、 類別宏與 lconv 結構體

1. 類別宏 (用於 setlocale 第一參數)

  • LC_ALL:所有類別。
  • LC_COLLATE:字符串排序 (strcoll, strxfrm)。
  • LC_CTYPE:字符分類/轉換 (ctype.h 函數)。
  • LC_MONETARY:貨幣格式 (localeconv 相關字段)。
  • LC_NUMERIC:數字格式 (小數點、分組、localeconv)。
  • LC_TIME:日期時間格式 (strftime)。

2. struct lconv 完整字段表

字段類型含義
decimal_pointchar*非貨幣小數點 (如 ".")
thousands_sepchar*非貨幣千分位分隔符 (如 ",")
groupingchar*非貨幣分組大小串 (每字符一組大小,0=重複)
int_curr_symbolchar*國際貨幣符號 (ISO 4217 三字母+分隔符,如 "USD ")
currency_symbolchar*本地貨幣符號 (如 "$")
mon_decimal_pointchar*貨幣小數點
mon_thousands_sepchar*貨幣千分位分隔符
mon_groupingchar*貨幣分組大小串
positive_signchar*正號 (如 "+" 或 "")
negative_signchar*負號 (如 "-" 或 "()")
int_frac_digitschar國際貨幣小數位數
frac_digitschar本地貨幣小數位數
p_cs_precedeschar正值貨幣符號前置? (1=前, 0=後)
p_sep_by_spacechar正值符號與值空格分隔? (1=是)
n_cs_precedeschar負值貨幣符號前置?
n_sep_by_spacechar負值符號與值空格分隔?
p_sign_posnchar正值符號位置 (0=括號, 1=前, 2=後, 3=緊貼符號前, 4=緊貼符號後)
n_sign_posnchar負值符號位置 (編碼同 p_sign_posn)

字符指針可能為空串 "" (不可用),字符字段為 CHAR_MAX 表示不可用。

二、 核心函數

1. setlocale

char *setlocale(int category, const char *locale);
  • locale = "C":標準 C 環境 (默認,點號小數、ASCII 排序)。
  • locale = "":環境變量決定 (如 LANG=zh_CN.UTF-8)。
  • locale = NULL:**僅查詢**,不修改,返回當前類別設置字符串。
  • 成功返回**之前**的設置字符串指針 (靜態緩衝區),失敗返回 NULL。

2. localeconv

struct lconv *localeconv(void);
  • 返回指向靜態 lconv 的指針,反映**當前**本地化設置。
  • 線程不安全 (返回靜態對象),多線程需加鎖或用 uselocale (POSIX)。

三、 實戰代碼示例

1. 設置並查詢

#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;
}

2. 完整字段打印

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);

四、 避坑指南

  1. 全局副作用:setlocale 影響**整個進程** (包括庫函數 printf/scanf/strtod 解析數字格式)。庫開發**慎用**,或用 uselocale (線程級)。
  2. 線程安全:localeconv 返回靜態指針,並發調用需互斥鎖。
  3. 環境變量優先級:LC_ALL > LC_xxx > LANG。setlocale(LC_ALL, "") 遵循此規則。
  4. 字符串指針有效期:lconv 字段指針指向靜態存儲,**下次 setlocale/localeconv 可能失效**,需立即複製內容。
  5. 「C」語言環境可移植:跨平台解析數字/日期**必須**先 setlocale(LC_NUMERIC, "C") 或用 strtod_l 指定語言環境。

五、 總結

locale.h 讓程序說用戶的語言:小數點逗號、貨幣符號位置、日期順序。掌握 lconv 字段語義、setlocale 類別範圍、全局副作用與線程安全限制,能正確處理國際化數據輸入輸出。現代高併發服務建議**避免修改全局 locale**,改用線程級 uselocale 或顯式格式化函數 (snprintf 指定格式)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved