【问题标题】:how to use strxfrm in C language?如何在 C 语言中使用 strxfrm?
【发布时间】:2019-01-27 07:32:41
【问题描述】:

我问一个问题来了解“strxfrm”在C中的用法。

我知道这个功能是根据当前的语言环境配置转换一个字符串。

但我不知道什么是“变换”,以及这个函数是如何变换的。

例如,我在 macOS 中尝试了如下代码:

#include <stdio.h>
#include <string.h>
#include <locale.h>

int main(int argc, char * argv[])
{
    char str1[512] = { 0x68, 0x6c, 0x61, 0x76, 0x61, 0x00 }; //"hlava";
    char str2[512] = { 0xc4, 0x8d, 0xc3, 0xad, 0xc5, 0xa1, 0x6e, 0xc3, 0xad, 0x6b, 0x00 }; //"číšník";
    char xfm1[512] = { '\0', };
    char xfm2[512] = { '\0', };
    char * result = NULL;
    size_t lxfm1 = 0;
    size_t lxfm2 = 0;

    result = setlocale(LC_ALL, "en_US.UTF-8");
    lxfm1 = strxfrm(xfm1, str1, sizeof xfm1);
    lxfm2 = strxfrm(xfm2, str2, sizeof xfm2);
    printf("<en-US>\n");
    printf("setlocale = \"%s\"\n", (result == NULL) ? "NULL" : result);
    printf("str1: \"%s\" --> \"%s\"\n", str1, xfm1);
    printf("str2: \"%s\" --> \"%s\"\n", str2, xfm2);
    printf("strcmp(str1, str2) = %d\n", strcmp(str1, str2));
    printf("strcmp(xfm1, xfm2) = %d\n", strcmp(xfm1, xfm2));
    printf("strcoll(xfm1, xfm2) = %d\n", strcoll(str1, str2));
    printf("returns of strxfrm: %zu / %zu\n", lxfm1, lxfm2);

    result = setlocale(LC_ALL, "cs_CZ.UTF-8");
    lxfm1 = strxfrm(xfm1, str1, sizeof xfm1);
    lxfm2 = strxfrm(xfm2, str2, sizeof xfm2);
    printf("<cs-CZ>\n");
    printf("setlocale = \"%s\"\n", result);
    printf("str1: \"%s\" --> \"%s\"\n", str1, xfm1);
    printf("str2: \"%s\" --> \"%s\"\n", str2, xfm2);
    printf("strcmp(str1, str2) = %d\n", strcmp(str1, str2));
    printf("strcmp(xfm1, xfm2) = %d\n", strcmp(xfm1, xfm2));
    printf("strcoll(xfm1, xfm2) = %d\n", strcoll(str1, str2));
    printf("returns of strxfrm: %zu / %zu\n", lxfm1, lxfm2);

    return 0;
}

我预计“strcmp(xfm1, xfm2)”的结果将是正整数,因为在捷克语中字符“č”在“h”之前。

但是,结果是……

<en-US>
setlocale = "en_US.UTF-8"
str1: "hlava" --> "001Z001^001S001h001S0000001Z001^001S001h001S"
str2: "číšník" --> "0042003_0042001`003_001]0000008?003_009S001`003_001]"
strcmp(str1, str2) = -92
strcmp(xfm1, xfm2) = -3
strcoll(xfm1, xfm2) = -152
returns of strxfrm: 44 / 52
<cs-CZ>
setlocale = "cs_CZ.UTF-8"
str1: "hlava" --> "001Z001^001S001h001S0000001Z001^001S001h001S"
str2: "číšník" --> "0042003_0042001`003_001]0000008?003_009S001`003_001]"
strcmp(str1, str2) = -92
strcmp(xfm1, xfm2) = -3
strcoll(xfm1, xfm2) = -152
returns of strxfrm: 44 / 52

我对这个函数“strxfrm”有误解吗? 其实我现在也不太清楚“变形”是什么意思。

请告诉我该函数的正确用法和用途。

【问题讨论】:

  • "číšník" 是如何工作的?我了解这些字符在您的源文件中以某种方式以 ASCII 编码。你能发布"číšník"字符串的十六进制编码吗?
  • 在 Ubuntu 上,转换后的字符串的 strcmp() 给了我一个正数,顺便说一句。您的环境中可能有些问题。您是否进行了明显的检查,例如确保您的源文件实际上是使用 UTF-8 编码的?
  • 但是,无论如何,如果您将LC_COLLATEen_US.UTF-8 更改为cs_CZ.UTF-8,它仍然是UTF-8。 UTF-8(无论是 cs_CZ 还是 en_US 或任何)都可以表示所有捷克字符,因此不会发生任何变化。字符串číšník 在UTF-8 中是{ 0xc4,0x8d,0xc3,0xad,0xc5,0xa1,0x6e,0xc3,0xad,0x6b,0x00 },在any.UTF-8 中应该*cmp 相同。
  • 谢谢。那么,我可以使用标准 ASCII 文本来准确地举例说明 strxfrm 的用法吗?我想根据语言环境配置查看 strcmp 的区别。
  • 看起来 Mac OS X 语言环境实现中确实存在错误。 Google “mac os x”排序错误。你的代码是正确的,你的操作系统坏了。

标签: c macos string.h


【解决方案1】:

您对strxfrm 的用法是正确的。问题在于 Mac OS X(和 FreeBSD)的语言环境实现。它根本无法与 UTF-8 一起正常工作。在这些操作系统使用的libc 版本中,这显然是一个长期存在的错误/缺陷/不一致/怪癖/任何东西。

【讨论】:

    猜你喜欢
    • 2011-07-04
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    相关资源
    最近更新 更多