【问题标题】:How to use scandir() in C for case insensitive?如何在 C 中使用 scandir() 来区分大小写?
【发布时间】:2021-12-31 11:05:41
【问题描述】:

我正在学习 C,我有这个实现来对文件和文件夹进行排序,但这不区分大小写:

#include <dirent.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

int main(void) {
    struct dirent **namelist;
    int n;

    n = scandir(".", &namelist, NULL, alphasort);
    if (n < 0)
        perror("scandir");
    else {
        printf("Inside else, n = %d\n", n);
        while (n--) {
            printf("%s\n", namelist[n]->d_name);
            free(namelist[n]);
        }
        free(namelist);
    }
}

如果我有 a.txt、b.txt、C.txt 和 z.txt,它将按以下顺序排序:C.txt、a.txt、b.txt、z.txt。我希望它像这样不区分大小写:a.txt、b.txt、C.txt、z.txt

【问题讨论】:

  • 那么不要使用alphasort。编写自己的比较器函数。
  • elvis, "I want this to be sort in case insensitive" --> 如果文件名包含'_",(大小写字母之间的 ASCCI 章程),那么文件名在字母之前还是在字母之后排序?想要不区分大小写 可以描述平等(例如a 应该等于A),但不足以描述顺序。 (在Aa 之前或之后是_
  • @chux-ReinstateMonica:这确实是一个真正的问题。我想知道strcasecmp 是否被指定为比较大写或小写转换,或者其他一些赋予它非传递行为的替代方法,这是用作qsort 比较函数的问题。
  • @chqrlie strcasecmp() 不在标准库中。由于不在 STL 中,以 str + 小写字母开头违反了保留的名称空间 (7.31.12)。 *nix 在野外的实现我遇到过折叠到下层和折叠到上层揭示了这个问题。是的,我确信缺乏精确的定义风险qsort() 问题和可移植性。更多thoughts 和快速alternative
  • @chux-ReinstateMonica: strcasecmp 是在 POSIX 中定义的,正如您所指出的,manual page 指定 在 POSIX 语言环境中,strcasecmp()strncasecmp() 的行为就像字符串已转换为小写,然后执行字节比较。结果在其他语言环境中未指定。 这似乎与 qsort 兼容(只要所有指针具有相同的表示和调用约定,这是另一个 POSIX 要求。

标签: c sorting scandir sortdirection


【解决方案1】:

scandir 是用这个原型定义的:

int scandir(const char *restrict dirp,
            struct dirent ***restrict namelist,
            int (*filter)(const struct dirent *),
            int (*compar)(const struct dirent **,
                          const struct dirent **));

函数alphasort 按字典顺序对文件名进行排序,因此区分大小写。如果您想要不区分大小写的排序,请使用不同的比较函数:

int alphasort_no_case(const struct dirent **a, const struct dirent **b) {
    return strcasecmp((*a)->d_name, (*b)->d_name);
}

scandirstrcasecmp 都是 POSIX 函数:strcasecmp 很可能在支持 scandir 并在 &lt;strings.h&gt; 中定义的系统上可用。

修改器版本:

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

int alphasort_no_case(const struct dirent **a, const struct dirent **b) {
    return strcasecmp((*a)->d_name, (*b)->d_name);
}

int main(void) {
    struct dirent **namelist;
    int n;

    n = scandir(".", &namelist, NULL, alphasort_no_case);
    if (n < 0) {
        perror("scandir");
    } else {
        printf("Inside else, n = %d\n", n);
        while (n--) {
            printf("%s\n", namelist[n]->d_name);
            free(namelist[n]);
        }
        free(namelist);
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 2011-10-14
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多