Использование естественной сортировки по порядку в Windows в пользовательской программе - PullRequest
0 голосов
/ 30 сентября 2018

Как программист, вам, вероятно, приходилось использовать или создавать какую-то функцию сравнения строк.Обычно это довольно просто:

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

Это прекрасно работает в подавляющем большинстве случаев.Однако Windows (XP и более поздние версии) сортирует файлы по-разному - и лучше!- чем плохая реализация ASCII.

Как я могу создать минимальный, полный и проверяемый пример естественной сортировки естественного порядка Windows в пользовательской программе?

ВсеЯ прочитал, указывает на использование функции StrCmpLogicalW в shlwapi.dll.Замечательно!Но как эту функцию можно использовать внутри пользовательской программы на C / C ++?

Я не заинтересован в повторной реализации функции сравнения.Я уже видел это , это , это , это и это .Это, без сомнения, очень близкие приближения, но я просто хочу связать или вызвать функцию Windows API в моей программе.

Вот некоторые другие вещи, которые я исследовал и уже пробовал:

  • чтение документации по shlwapi.dll и StrCmpLogicalW от Microsoft
  • поиск (предположительно) полной программы, опубликованной из более ранних вопросов и ответов здесь, в StackOverflow
  • компиляция нескольких небольших примеров кода для Visual Studio 2010 Express, версии C ++ и C # (fatal error C1190: managed targeted code requires a '/clr' option ... действительно? )
  • компиляция нескольких небольших примеров кода для Visual Studio 2012Express, потому что в какой-то статье говорилось, что это избавит от более ранней ошибки компиляции, связанной с опцией /clr, но вместо этого получит кучу разных ошибок компиляции.
  • попытался скомпилировать несколько небольших примеров кода для Eclipse C ++ с MinGW *.1053 *

Когда я впервые начал изучать это, я подумал: «Это просто Windows API, это будет легко!»Мне еще предстоит создать рабочую программу на любом языке.

Я давно занимаюсь написанием сценариев на C / C ++ и Unix / DOS / Windows, и использование API никогда не было таким утомительным.Позор вам, Microsoft.


Кроме того, я уже читал рассказы о сортировке ASCII, но спасибо.Они содержали плодородную почву для хорошего мышления.

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

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

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

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, похоже, не знают о StrCmpLogicalW().

Хотя он должен работать с Mingw-w64.

0 голосов
/ 30 сентября 2018

Оказывается, библиотеки DLL можно легко вызывать с помощью AutoIt или AutoHotKey.

Я перевел этот пост с форумов AutoIt в минимальный рабочий пример:

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

А вот минимальный пример, извлеченный из этого архивного сообщения на форумах AutoHotkey :

_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)
}

Вот и все!Функция принимает два строки и возвращает -1/0/+1, как и любая другая функция сравнения в мире.

Объедините это с алгоритмом сортировки (например, _ArrayMultiColSort(), _ArrayCustomSort() для AutoIt) и теперь вы можете Быстрая сортировка полных списков.

(Пожалуйста, не используйте Bubble Sort . Подумайте о детях.)

...