代码之家  ›  专栏  ›  技术社区  ›  JonathanDavidArndt

在自定义程序中使用本机Windows自然顺序排序

  •  -4
  • JonathanDavidArndt  · 技术社区  · 6 年前

    作为程序员,您可能不得不使用或创建某种字符串比较函数。通常,这些都很简单:

    function compare(s1, s1) { return s1.toLowerCase() - s2.toLowerCase(); }
    

    这在绝大多数情况下都非常有效。但是,Windows (XP及更高版本) 对文件进行不同的排序--而且更好!--而不是糟糕的ASCII实现。

    如何在自定义程序中创建本机Windows自然顺序排序的最小、完整且可验证的示例?

    我读到的所有东西都指向使用 StrCmpLogicalW shlwapi.dll

    我是 this , this , this this ,和 this . 这些无疑是非常接近的近似值,但我只想在我的程序中链接或调用windowsapi函数。

    当我第一次开始研究这个问题时,我想,“这只是windowsapi,这将很容易!”我还没有用任何语言提出一个工作程序。

    长期以来,我一直在做C/C++和UNIX/DOS/Windows shell脚本,而使用API从来都不那么令人讨厌。你真丢脸,微软。


    https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/

    http://weblog.masukomi.org/2007/12/10/alphabetical-asciibetical/

    2 回复  |  直到 6 年前
        1
  •  3
  •   Swordfish    6 年前

    C++:

    #include <windows.h>
    #include <shlwapi.h>
    #pragma comment(lib, "shlwapi.lib")
    
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <iostream>
    
    bool str_cmp_logical(std::wstring const &lhs, std::wstring const &rhs)
    {
        return StrCmpLogicalW(lhs.c_str(), rhs.c_str()) < 1;
    }
    
    int main()
    {
        std::vector<std::wstring> foo{
            L"20string", L"2string", L"3string", L"st20ring", L"st2ring",
            L"st3ring", L"string2", L"string20", L"string3"
        };
    
        for (auto const &f : foo)
            std::wcout << f << L' ';
        std::wcout.put(L'\n');
    
        std::sort(foo.begin(), foo.end(), str_cmp_logical);
    
        for (auto const &f : foo)
            std::wcout << f << L' ';
        std::wcout.put(L'\n');
    }
    

    20string 2string 3string st20ring st2ring st3ring string2 string20 string3
    2string 3string 20string st2ring st3ring st20ring string2 string3 string20
    

    尝试用MinGW编译代码失败,因为 <shlwapi.h> 这是它的包装 w32api 不提供原型 StrCmpLogicalW() . 当我自己宣布的时候

    C:\MinGW\bin>"g++.exe" -lshlwapi C:\Users\sword\source\repos\Codefun\main.cpp
    C:\Users\sword\AppData\Local\Temp\ccMrmLbD.o:main.cpp:(.text+0x23): undefined reference to `StrCmpLogicalW(wchar_t const*, wchar_t const*)'
    collect2.exe: error: ld returned 1 exit status
    

    所以MinGW附带的库似乎不知道 结构() .

    不过,它应该与Mingw-w64配合使用。

        2
  •  -1
  •   JonathanDavidArndt    6 年前

    事实证明,使用AutoIt或AutoHotKey可以很容易地调用dll。

    我已经蒸馏了 this post from the AutoIt forums

    Func _StrCmpLogicalW($s1, $s2)
       Return DllCall('shlwapi.dll', 'int', 'StrCmpLogicalW', 'wstr', $s1, 'wstr', $s2)[0]
    EndFunc
    

    下面是一个从 this archive post on the AutoHotkey forums

    _StrCmpLogicalW(s1, s2)
    {
       VarSetCapacity(ws1, StrLen(s1)*2+1,0), DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&s1, "Int",-1, "UInt",&ws1, "Int",StrLen(s1)+1)
       VarSetCapacity(ws2, StrLen(s2)*2+1,0), DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&s2, "Int",-1, "UInt",&ws2, "Int",StrLen(s2)+1)
       return DllCall("Shlwapi.dll\StrCmpLogicalW","UInt",&ws1,"UInt",&ws2)
    }
    

    就这样!函数接受两次Sting并返回 -1/0/+1 就像世界上其他的比较函数一样。

    _ArrayMultiColSort() , _ArrayCustomSort() 现在你可以 Quicksort 整个列表。

    Bubble Sort . 想想孩子们。)