在自定义程序中使用本机 Windows 自然顺序排序
Using native Windows natural order sorting in a custom program
作为程序员,您可能不得不使用或创建某种字符串比较函数。通常,这些都非常简单:
function compare(s1, s1) { return s1.toLowerCase() - s2.toLowerCase(); }
这适用于绝大多数情况。但是,Windows (XP 及更高版本) 对文件进行排序的方式不同——而且更好! -- 比糟糕的 ASCII 实现。
如何在自定义程序中创建本机 Windows 自然顺序排序的最小、完整且可验证的示例?
我阅读的所有内容都指向在 shlwapi.dll
中使用 StrCmpLogicalW
函数。那太棒了!但是如何在自定义 C/C++ 程序中使用此函数?
我不有兴趣重新实现比较功能。我已经看过了this, this, this, this, and this。这些无疑是非常接近的近似值,但我只想 link 或在我的程序中调用 Windows API 函数。
以下是我已经研究并尝试过的其他一些东西:
- 阅读 documentation on
shlwapi.dll
and StrCmpLogicalW
from Microsoft
- 找到从 an earlier Q&A here on Whosebug
发布的(假定的)完整程序
- 为 Visual Studio 2010 Express 编译几个小代码示例,包括 C++ 和 C# 版本(
fatal error C1190: managed targeted code requires a '/clr' option
...真的吗?)
- 为 Visual Studio 2012 Express 编译几个小代码示例,因为一些文章说这将消除早期关于
/clr
选项的编译错误,但只是得到了一堆不同的编译错误相反
- 尝试使用 MinGW 为 Eclipse C++ 编译几个小代码示例
当我第一次开始研究这个时,我想,"It's just the Windows API, this will be easy!"我还没有想出任何语言的工作程序。
我已经编写 C/C++ 和 Unix/DOS/Windows shell 脚本很长时间了,使用 API 从未如此令人厌烦。微软,你真可耻。
此外,我已经阅读了关于 ASCII 排序的咆哮,但谢谢。这些包含了一些好的思考的沃土。
https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
http://weblog.masukomi.org/2007/12/10/alphabetical-asciibetical/
事实证明,可以使用 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)
}
就是这样!该函数需要两个字符串和 returns -1/0/+1
就像世界上其他比较函数一样。
将其与排序算法(例如 , for AutoIt) and now you can Quicksort 整个列表。
(请不要使用Bubble Sort。想想children。)
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 编译代码失败,因为包 w32api
附带的 <shlwapi.h>
版本没有提供 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 附带的库似乎没有意识到 StrCmpLogicalW()
。
不过它应该可以与 Mingw-w64 一起使用。
作为程序员,您可能不得不使用或创建某种字符串比较函数。通常,这些都非常简单:
function compare(s1, s1) { return s1.toLowerCase() - s2.toLowerCase(); }
这适用于绝大多数情况。但是,Windows (XP 及更高版本) 对文件进行排序的方式不同——而且更好! -- 比糟糕的 ASCII 实现。
如何在自定义程序中创建本机 Windows 自然顺序排序的最小、完整且可验证的示例?
我阅读的所有内容都指向在 shlwapi.dll
中使用 StrCmpLogicalW
函数。那太棒了!但是如何在自定义 C/C++ 程序中使用此函数?
我不有兴趣重新实现比较功能。我已经看过了this, this, this, this, and this。这些无疑是非常接近的近似值,但我只想 link 或在我的程序中调用 Windows API 函数。
以下是我已经研究并尝试过的其他一些东西:
- 阅读 documentation on
shlwapi.dll
andStrCmpLogicalW
from Microsoft - 找到从 an earlier Q&A here on Whosebug 发布的(假定的)完整程序
- 为 Visual Studio 2010 Express 编译几个小代码示例,包括 C++ 和 C# 版本(
fatal error C1190: managed targeted code requires a '/clr' option
...真的吗?) - 为 Visual Studio 2012 Express 编译几个小代码示例,因为一些文章说这将消除早期关于
/clr
选项的编译错误,但只是得到了一堆不同的编译错误相反 - 尝试使用 MinGW 为 Eclipse C++ 编译几个小代码示例
当我第一次开始研究这个时,我想,"It's just the Windows API, this will be easy!"我还没有想出任何语言的工作程序。
我已经编写 C/C++ 和 Unix/DOS/Windows shell 脚本很长时间了,使用 API 从未如此令人厌烦。微软,你真可耻。
此外,我已经阅读了关于 ASCII 排序的咆哮,但谢谢。这些包含了一些好的思考的沃土。
https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
http://weblog.masukomi.org/2007/12/10/alphabetical-asciibetical/
事实证明,可以使用 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)
}
就是这样!该函数需要两个字符串和 returns -1/0/+1
就像世界上其他比较函数一样。
将其与排序算法(例如
(请不要使用Bubble Sort。想想children。)
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 编译代码失败,因为包 w32api
附带的 <shlwapi.h>
版本没有提供 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 附带的库似乎没有意识到 StrCmpLogicalW()
。
不过它应该可以与 Mingw-w64 一起使用。