ZetCode

C strcoll 函数

最后修改:2025 年 4 月 8 日

字符串比较在 C 编程中是基础的,而 strcoll 提供了带区域设置感知的比较功能。本教程将深入介绍 strcoll,包括其语法、用法和区域设置依赖性。我们将探讨实际示例,并讨论何时使用它而不是 strcmp。理解 strcoll 有助于创建在不同语言设置下都能正确工作的程序。

什么是 strcoll?

strcoll 函数根据当前区域设置比较两个字符串。它声明在 string.h 中,并接受两个字符串指针。与 strcmp 不同,它尊重特定于区域设置的排序规则。strcoll 返回一个整数,指示字符串之间的关系。为了安全起见,当区域设置很重要时,优先使用 strcoll 而不是 strcmp

基本的 strcoll 用法

此示例演示了使用 strcoll 进行基本的字符串比较。

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

int main() {
    setlocale(LC_ALL, "");
    const char *str1 = "apple";
    const char *str2 = "banana";

    int result = strcoll(str1, str2);

    if (result < 0) {
        printf("'%s' comes before '%s'\n", str1, str2);
    } else if (result > 0) {
        printf("'%s' comes after '%s'\n", str1, str2);
    } else {
        printf("Strings are equal\n");
    }

    return 0;
}

在这里,strcoll 按字母顺序比较两个字符串。setlocale 调用初始化程序的区域设置。如果 str1 在 str2 之前,则该函数返回一个负值;如果相等,则返回零;如果 str1 在 str2 之后,则返回一个正值。这个基本示例显示了标准的字母顺序比较行为。

特定于区域设置的比较

此示例显示了 strcoll 在不同区域设置下的行为差异。

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

int main() {
    const char *str1 = "äbc";
    const char *str2 = "abc";

    // Compare with C locale
    setlocale(LC_ALL, "C");
    printf("C locale: %d\n", strcoll(str1, str2));

    // Compare with German locale
    setlocale(LC_ALL, "de_DE.utf8");
    printf("German locale: %d\n", strcoll(str1, str2));

    return 0;
}

此代码演示了区域设置如何影响字符串比较。在 C 区域设置中,带音标的字母(例如 umlauts)的排序可能与德语不同。德语区域设置能够正确处理 'ä',将其视为一个单独的字母,排在 'a' 之后。在使用 strcoll 处理国际文本之前,务必设置适当的区域设置。

使用 strcoll 对字符串进行排序

此示例演示了使用 strcoll 对字符串数组进行排序。

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

#define COUNT 5

int compare(const void *a, const void *b) {
    return strcoll(*(const char **)a, *(const char **)b);
}

int main() {
    setlocale(LC_ALL, "");
    const char *words[COUNT] = {"čaj", "auto", "bůh", "dům", "cedr"};

    qsort(words, COUNT, sizeof(char *), compare);

    printf("Sorted words:\n");
    for (int i = 0; i < COUNT; i++) {
        printf("%s\n", words[i]);
    }

    return 0;
}

此代码在使用 qsort 的比较函数中,通过 strcoll 正确地对捷克语单词进行了排序。区域设置已设置为系统默认值,这应该可以正确处理捷克语字符。比较函数在传递 strcoll 之前,将 void 指针转换为字符串指针。这种方法适用于任何特定于区域设置的排序。

不区分大小写的比较

此示例显示了如何使用 strcoll 进行不区分大小写的比较。

case_compare.c
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>

int strcasecoll(const char *a, const char *b) {
    char a_lower[256], b_lower[256];
    size_t i;

    for (i = 0; a[i] && i < sizeof(a_lower) - 1; i++) {
        a_lower[i] = tolower(a[i]);
    }
    a_lower[i] = '\0';

    for (i = 0; b[i] && i < sizeof(b_lower) - 1; i++) {
        b_lower[i] = tolower(b[i]);
    }
    b_lower[i] = '\0';

    return strcoll(a_lower, b_lower);
}

int main() {
    setlocale(LC_ALL, "");
    const char *str1 = "Zebra";
    const char *str2 = "apple";

    int result = strcasecoll(str1, str2);

    if (result < 0) {
        printf("'%s' comes before '%s'\n", str1, str2);
    } else if (result > 0) {
        printf("'%s' comes after '%s'\n", str1, str2);
    } else {
        printf("Strings are equal\n");
    }

    return 0;
}

此实现创建了 strcoll 的不区分大小写的版本。它首先将字符串转换为小写,然后进行比较。会检查缓冲区大小以防止溢出。请注意,此方法可能无法完美处理所有特定于区域设置的大小写转换。对于生产代码,请考虑更健壮的解决方案。

比较带数值的字符串

此示例演示了 strcoll 如何处理包含数字的字符串。

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

int main() {
    setlocale(LC_ALL, "");
    const char *versions[] = {"file1.txt", "file10.txt", "file2.txt"};
    
    printf("Standard comparison:\n");
    for (int i = 0; i < 2; i++) {
        int res = strcoll(versions[i], versions[i+1]);
        printf("%s vs %s: %d\n", versions[i], versions[i+1], res);
    }

    setlocale(LC_COLLATE, "en_US.utf8");
    printf("\nNumeric-aware comparison:\n");
    for (int i = 0; i < 2; i++) {
        int res = strcoll(versions[i], versions[i+1]);
        printf("%s vs %s: %d\n", versions[i], versions[i+1], res);
    }

    return 0;
}

此代码比较了包含数字的文件名字符串。某些区域设置支持数字感知的排序,其中 "file10.txt" 排在 "file2.txt" 之后。该示例同时显示了标准和数字感知比较结果。请注意,数字排序行为取决于区域设置的支持。为了可靠地进行数字排序,请考虑专门的比较函数。

使用 strcoll 的最佳实践

来源

C strcoll 文档

本教程探讨了 strcoll 函数,从基本用法到特定于区域设置的行为。对于国际化应用程序,strcoll 根据文化惯例提供正确的字符串比较。在选择比较函数时,请始终考虑应用程序的具体需求。

作者

我的名字是 Jan Bodnar,我是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享我的专业知识。凭借十多年的教学经验,我致力于让编程变得易于理解且引人入胜。

列表 C 标准库