c++ - C++ 中目录文件名的自然排序

标签 c++ c linux sorting directory

我有一个目录列表,我想为其检索文件名并将它们放入一个字符串 vector 中,以便它们以“自然”方式排序。例如{ "10.txt" "0.txt" "2.txt" "1.m" "Jan12" "July13.txt" "Nov25.txt" "Jane" "John" }应该是 {"0.txt" "1.m" "2.txt" "10.txt" "Jan12" "July13.txt" "Nov25.txt" "Jane" "John" } .最简单的方法是什么?

详细说明“自然”,我们假设一个字符串由数字 (N) 和文本 (T) 组成,这样 ...(N)(T)... , 然后为 ...(N1)(T1)......(N2)(T2)...将是 (N1<N2) (<) (T1<T2)其中 (<)意味着左项优先于右项。在这种情况下,如果数字在字符串中的位置相同,则数字优先于文本字段,即 1.z (<) 1_t.txt .

是否已经有一个库函数可以对字母数字字符串或目录条目进行这种排序?

DESIRED order 文件应该出现的顺序。文件名将存储在字符串 vector 中。

Abhinav@Abhinav-PC /cygdrive/c/AbhinavSamples/shell
$ ls -lv
total 8
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:51 1.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:55 1_t.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:50 3.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:51 4.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:53 10.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:56 10_t.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:56 13.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:53 20.txt

**Simple Sort**
Abhi@Abhi-PC /cygdrive/c/AbhinavSamples/shell
$ ls -l
total 8
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:51 1.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:53 10.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:56 10_t.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:56 13.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:55 1_t.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:53 20.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:50 3.txt
-rw-r--r--+ 1 Abhinav None 2 Mar 17 00:51 4.txt

最佳答案

您需要一个函数来生成 natural comparison两根弦之间。之后,您可以将 std::sort 与比较函数一起用作第三个参数(正如@chac 已经指出的那样)。在下文中,我尝试以递归的方式实现这样的功能。请注意,它可以处理不需要以数字部分开头和以字符串部分结尾的任意文件名:

bool compareNat(const std::string& a, const std::string& b)
{
    if (a.empty())
        return true;
    if (b.empty())
        return false;
    if (std::isdigit(a[0]) && !std::isdigit(b[0]))
        return true;
    if (!std::isdigit(a[0]) && std::isdigit(b[0]))
        return false;
    if (!std::isdigit(a[0]) && !std::isdigit(b[0]))
    {
        if (std::toupper(a[0]) == std::toupper(b[0]))
            return compareNat(a.substr(1), b.substr(1));
        return (std::toupper(a[0]) < std::toupper(b[0]));
    }

    // Both strings begin with digit --> parse both numbers
    std::istringstream issa(a);
    std::istringstream issb(b);
    int ia, ib;
    issa >> ia;
    issb >> ib;
    if (ia != ib)
        return ia < ib;

    // Numbers are the same --> remove numbers and recurse
    std::string anew, bnew;
    std::getline(issa, anew);
    std::getline(issb, bnew);
    return (compareNat(anew, bnew));
}

这是一个简单的测试用例:

#include <iostream> // std::cout
#include <string>
#include <algorithm> // std::sort, std::copy
#include <iterator> // std::ostream_iterator
#include <sstream> // std::istringstream
#include <vector>
#include <cctype> // std::isdigit

int main()
{
    std::vector<std::string> str;
    str.push_back("20.txt");
    str.push_back("10.txt");
    str.push_back("1.txt");
    str.push_back("z2.txt");
    str.push_back("z10.txt");
    str.push_back("z100.txt");
    str.push_back("1_t.txt");

    std::sort(str.begin(), str.end(), compareNat);
    std::copy(str.begin(), str.end(),
              std::ostream_iterator<std::string>(std::cout, "\n"));
}

结果是:

1.txt
1_t.txt
10.txt
20.txt
z2.txt
z10.txt
z100.txt

关于c++ - C++ 中目录文件名的自然排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9743485/

相关文章:

c++ - 在数组中查找唯一数字

PHP/C++ : shm_open() error when sharing memory

linux - 执行 flock 命令时出现错误

c++ - g++ 链接可能尚未编译的 .so 库

java - 如何从 JNI 代码中检测字节顺序?

c++ - 以编程方式确定是否启用异常

c++ - 错误 : Label used but not defined when using && operator

c - 在 CentOS 6.6 上测试 openGL/libGL 库

改变指针的值

regex - 为什么 ' grep "*.h"' and ' grep -E "*.h"' 在同一文件上的不同输出