setlocale_wsetlocale

设置或检索运行时区域设置。

语法

char *setlocale(
   int category,
   const char *locale
);

wchar_t *_wsetlocale(
   int category,
   const wchar_t *locale
);

参数

category
受区域设置影响的分类。

locale
区域设置说明符。

返回值

如果提供了有效的localecategory,函数会返回指向与指定的localecategory关联的字符串的指针。 如果locale参数为NULL,函数会返回当前区域设置。

如果将无效参数传递给任一函数,则返回值为NULL。 无效参数的行为如下所示:

函数 参数无效 调用无效的参数处理程序,如Parameter validation中所述 设置 errno
setlocale category
setlocale locale
_wsetlocale category
_wsetlocale locale

调用:

setlocale( LC_ALL, "en-US" );

设置所有类别,只返回该字符串

en-US

你可以复制由 setlocale 返回的字符串以还原程序的区域设置信息的该部分。 全局或线程本地存储用于由 setlocale 返回的字符串。 稍后调用 setlocale 将覆盖字符串,这将使之前调用返回的字符串指针无效。

注解

使用 setlocale 函数设置、更改或查询 localecategory 指定的部分或全部当前程序区域设置信息。 locale 是指可为其自定义程序的某些方面的局部性(国家/地区和语言)。 一些与区域设置相关的类别包括日期的格式设置和货币值的显示格式。 如果将 locale 设置为一种语言的默认字符串(此字符串在你的计算机上具有多个受支持的形式),则应选定 setlocale 返回值以查看哪种语言有效。 例如,如果将 locale 设置为 "chinese",返回值会是 "chinese-simplified""chinese-traditional"

_wsetlocalesetlocale的宽字符版本; locale 参数和 _wsetlocale 的返回值都是宽字符字符串。 除此以外,_wsetlocalesetlocale 的行为完全相同。

默认情况下,此函数的全局状态范围限定为应用程序。 若要更改此行为,请参阅 CRT 中的全局状态

一般文本例程映射

TCHAR.H 例程 _UNICODE_MBCS 未定义 _MBCS 已定义 _UNICODE 已定义
_tsetlocale setlocale setlocale _wsetlocale

category 参数指定程序的受影响的部分区域设置信息。 用于 category 的宏及其影响的程序的部分如下:

category 标志 影响
LC_ALL 以下列出了所有类别。
LC_COLLATE strcoll_stricollwcscoll_wcsicollstrxfrm_strncoll_strnicoll_wcsncoll_wcsnicollwcsxfrm 函数。
LC_CTYPE 字符处理函数(不受影响的 isdigitisxdigitmbstowcsmbtowc 除外)。
LC_MONETARY localeconv 函数返回的货币格式信息。
LC_NUMERIC 格式化输出例程(例如printf)、数据转换例程和localeconv返回的非货币格式设置信息的十进制点字符。 除小数点字符之外,LC_NUMERIC 还设置 localeconv 返回的千位分隔符和分组控制字符串。
LC_TIME strftimewcsftime 函数。

此函数验证类别参数。 如果类别参数不是上表中提供的值之一,则调用无效参数处理程序,如参数验证中所述。 如果允许执行继续,则该函数将 errno 设置为 EINVAL 并返回 NULL

locale 参数是指向指定区域设置的字符串的指针。 有关 locale 参数的格式信息,请参阅区域设置名称、语言和国家/地区字符串。 如果 locale 指向一个空字符串,则区域设置是实现定义的本机环境。 C 的值为 C 转换指定最小的符合 ANSI 标准的环境。 C 区域设置假设所有 char 数据类型为 1 字节,并且其值始终小于 256。

在程序启动时,将执行以下语句的等效项:

setlocale( LC_ALL, "C" );

locale 参数可以采用区域设置名称、语言字符串、语言字符串和国家/地区代码、代码页或语言字符串、国家/地区代码和代码页。 可用的区域设置名称、语言、国家/地区代码和代码页包括 Windows NLS API 支持的所有内容。 区域设置名称、语言和国家/地区字符串中介绍了setlocale支持的区域设置名称集合。 语言字符串国家/地区字符串中列出了 setlocale 所支持的语言和国家/地区字符串集合。 建议对嵌入到代码中或序列化到存储中的区域设置字符串的性能和可维护性使用区域设置名称格式。 与语言和国家/地区名称格式相比,操作系统的更新更改区域设置名称字符串的可能性会小一些。

作为 locale 参数传递的 null 指针告知 setlocale 查询而不是设置国际环境。 如果 locale 自变量为 null 指针,则不更改程序的当前区域设置。 相反,setlocale 返回指向字符串的指针,该字符串与线程的当前区域设置的 category 关联。 如果 category 参数为 LC_ALL,则该函数返回一个指示每个类别的当前设置(由分号分隔)的字符串。 例如,调用的顺序

// Set all categories and return "en-US"
setlocale(LC_ALL, "en-US");
// Set only the LC_MONETARY category and return "fr-FR"
setlocale(LC_MONETARY, "fr-FR");
printf("%s\n", setlocale(LC_ALL, NULL));

returns

LC_COLLATE=en-US;LC_CTYPE=en-US;LC_MONETARY=fr-FR;LC_NUMERIC=en-US;LC_TIME=en-US

它是与 LC_ALL 类别关联的字符串。

以下示例与 LC_ALL 类别相关。 可使用字符串“.OCP”或“.ACP”(而非代码页号)来分别指定该区域设置名称的用户默认 OEM 代码页和用户默认 ANSI 代码页的用法。

  • setlocale( LC_ALL, "" );

    将区域设置设定为默认值,该值是从操作系统获得的用户默认的 ANSI 代码页。 区域设置名称设置为由 GetUserDefaultLocaleName 返回的值。 代码页设置为由 GetACP 返回的值。

  • setlocale( LC_ALL, ".OCP" );

    将设置区域设置为从操作系统获得的当前 OEM 代码页。 区域设置名称设置为由 GetUserDefaultLocaleName 返回的值。 代码页设置为由 GetLocaleInfoEx 返回的用户默认区域设置名称的 LOCALE_IDEFAULTCODEPAGE 值。

  • setlocale( LC_ALL, ".ACP" );

    将区域设置设定为从操作系统获得的 ANSI 代码页。 区域设置名称设置为由 GetUserDefaultLocaleName 返回的值。 代码页设置为由 GetLocaleInfoEx 返回的用户默认区域设置名称的 LOCALE_IDEFAULTANSICODEPAGE 值。

  • setlocale( LC_ALL, "<localename>" );

    将区域设置设定为由 <localename> 指示的区域设置名称。 代码页设置为由 GetLocaleInfoEx 返回的指定区域设置名称的 LOCALE_IDEFAULTANSICODEPAGE 值。

  • setlocale( LC_ALL, "<language>_<country>" );

    将区域设置设定为由 <language><country> 指示的语言和国家/地区,以及从主机操作系统获得的默认代码页。 代码页设置为由 GetLocaleInfoEx 返回的指定区域设置名称的 LOCALE_IDEFAULTANSICODEPAGE 值。

  • setlocale( LC_ALL, "<language>_<country>.<code_page>" );

    将区域设置设定为由 <language><country><code_page> 字符串指示的语言、国家/地区和代码页。 你可以使用语言、国家/地区和代码页的各种组合。 例如,此调用会将区域设置设定为“法语(加拿大)”并使用代码页 1252:

    setlocale( LC_ALL, "French_Canada.1252" );

    此调用会将区域设置设定为“法语(加拿大)”并使用默认 ANSI 代码页:

    setlocale( LC_ALL, "French_Canada.ACP" );

    此调用会将区域设置设定为“法语(加拿大)”并使用默认 OEM 代码页:

    setlocale( LC_ALL, "French_Canada.OCP" );

  • setlocale( LC_ALL, "<language>" );

    将区域设置设定为由 <language> 指示的语言,为指定的语言使用默认国家/地区,为从主机操作系统获取的国家/地区使用用户默认的 ANSI 代码页。 例如,以下对 setlocale 的调用在功能上是等效的:

    setlocale( LC_ALL, "en-US" );

    setlocale( LC_ALL, "English" );

    setlocale( LC_ALL, "English_United States.1252" );

    建议使用第一种形式以实现较高的性能和可维护性。

  • setlocale( LC_ALL, ".<code_page>" );

    将代码页设置为由 <code_page> 指示的值,以及指定代码页的默认国家/地区和语言(由主机操作系统定义)。

类别必须是 LC_ALLLC_CTYPE 才能影响代码页的更改。 例如,如果主机操作系统的默认国家/地区和语言为“United States”和“English”,则以下两个对 setlocale 的调用在功能上是等效的:

setlocale( LC_ALL, ".1252" );

setlocale( LC_ALL, "English_United States.1252");

有关详细信息,请参阅 C/C++ 预处理器参考中的 setlocale pragma 指令。

函数 _configthreadlocale 用于控制 setlocale 是否影响程序中所有线程的区域设置或仅影响调用线程的区域设置。

UTF-8 支持

从 Windows 10 版本 1803 (10.0.17134.0) 开始,通用 C 运行时支持使用 UTF-8 代码页。 更改意味着传递给 C 运行时函数的char字符串可能需要采用 UTF-8 编码的字符串。 若要启用 UTF-8 模式,请在使用 setlocale 时将 ".UTF8" 用作代码页。 例如,setlocale(LC_ALL, ".UTF8")会使用当前默认的 Windows ANSI 代码页 (ACP) 作为区域设置,使用 UTF-8 作为代码页。

指定 UTF-8 模式的字符串:

  • 不区分大小写
  • 连字符 (-) 是可选的
  • 它必须位于区域设置名称的代码页部分,因此必须具有前导句点 (.),如以下示例所示:"en_US.UTF8"".utf8"

以下示例演示了如何指定 UTF-8 字符串:

".UTF8"
".UTF-8"
".utf8"
".utf-8"
"en_us.utf8"
"ja_JP.Utf-8"

调用setlocale(LC_ALL, ".UTF8")后,可以将“😊”传递给mbtowcs,并且它将正确翻译为wchar_t字符串。 之前,没有可用于执行此翻译的区域设置。

UTF-8 模式还会针对使用默认 Windows ANSI 代码页 (ACP) 的具有过去转换的 char 字符串的函数启用。 例如,在使用 UTF-8 代码页时调用 _mkdir("😊"),将正确生成一个目录,该表情符号将作为文件夹名称,而无需在运行程序之前将 ACP 更改为 UTF-8。 同样,在该文件夹中调用_getcwd()会返回 UTF-8 编码的字符串。 出于兼容性考虑,如果 C 区域设置代码页未设置为 UTF-8,则仍使用 ACP。

C 运行时的以下方面无法使用 UTF-8,因为它们是在程序启动时设置的,必须使用默认的 Windows ANSI 代码页 (ACP):__argv_acmdln_pgmptr

在此支持推出之前,mbrtoc16mbrtoc32c16rtombc32rtomb 用于在 UTF-8 窄字符串、UTF-16(与 Windows 平台上 的 wchar_t 相同的编码)和 UTF-32 之间进行转换。 出于兼容性原因,这些 API 仍仅转换为 UTF-8,而不是通过 setlocale 设置的代码页。

若要在 Windows 10 之前的 OS 上使用此功能,必须使用 Windows SDK 或更高版本的 1803 (10.0.17134.0) 版本静态地使用应用本地部署或链接。 对于 1803 (10.0.17134.0) 之前的 Windows 10 操作系统,仅支持静态链接。

要求

例程 必需的标头
setlocale <locale.h>
_wsetlocale <locale.h><wchar.h>

有关兼容性的详细信息,请参阅 兼容性

示例

// crt_setlocale.c
//
// This program demonstrates the use of setlocale when
// using two independent threads.
//

#include <locale.h>
#include <process.h>
#include <windows.h>
#include <stdio.h>
#include <time.h>

#define BUFF_SIZE 100

// Retrieve the date in the current
// locale's format.
int get_date(unsigned char* str)
{
    __time64_t ltime;
    struct tm  thetime;

    // Retrieve the current time
    _time64(&ltime);
    _gmtime64_s(&thetime, &ltime);

    // Format the current time structure into a string
    // "%#x" is the long date representation in the
    // current locale
    if (!strftime((char *)str, BUFF_SIZE, "%#x",
                  (const struct tm *)&thetime))
    {
        printf("strftime failed!\n");
        return -1;
    }
    return 0;
}

// This thread sets its locale to the argument and prints the date.
unsigned __stdcall SecondThreadFunc(void* pArguments)
{
    unsigned char str[BUFF_SIZE];
    char * locale = (char *)pArguments;

    // Set the thread locale
    printf("The thread locale is now set to %s.\n",
           setlocale(LC_ALL, locale));

    // Retrieve the date string from the helper function
    if (get_date(str) == 0)
    {
        printf("The date in %s locale is: '%s'\n", locale, str);
    }

    _endthreadex( 0 );
    return 0;
}

// The main thread sets the locale to English
// and then spawns a second thread (above) and prints the date.
int main()
{
    HANDLE          hThread;
    unsigned        threadID;
    unsigned char   str[BUFF_SIZE];

    // Enable per-thread locale causes all subsequent locale
    // setting changes in this thread to only affect this thread.
    _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);

    // Set the locale of the main thread to US English.
    printf("The thread locale is now set to %s.\n",
           setlocale(LC_ALL, "en-US"));

    // Create the second thread with a German locale.
    // Our thread function takes an argument of the locale to use.
    hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc,
                                      (void*)"de-DE", 0, &threadID );

    if (get_date(str) == 0)
    {
        // Retrieve the date string from the helper function
        printf("The date in en-US locale is: '%s'\n\n", str);
    }

    // Wait for the created thread to finish.
    WaitForSingleObject( hThread, INFINITE );

    // Destroy the thread object.
    CloseHandle( hThread );
}
The thread locale is now set to en-US.
The date in en-US locale is: 'Thursday, January 4, 2024'

The thread locale is now set to de-DE.
The date in de-DE locale is: 'Donnerstag, 4. Januar 2024'

另请参阅

区域设置名称、语言和国家/地区字符串
_configthreadlocale
_create_locale, _wcreate_locale
区域设置
localeconv
_mbclen, mblen, _mblen_l
strlen, wcslen, _mbslen, _mbslen_l, _mbstrlen, _mbstrlen_l
mbstowcs, _mbstowcs_l
mbtowc_mbtowc_l
_setmbcp
strcoll 函数
strftimewcsftime_strftime_l_wcsftime_l
strxfrmwcsxfrm_strxfrm_l_wcsxfrm_l
wcstombs_wcstombs_l
wctomb_wctomb_l