NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Porovnání řetězců s diakritikou _wcsicmp_l

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Michal Hadraba:31.10.2023 15:50

Zkouším porovnat (seřadit) řetězce s diakritikou a _wcsicmp_l prostě nefunguje. Písmena s háčky jsou stále na konci mapy.

#include <string>
#include <map>
#include <atlstr.h>
#include "windows.h"
#include <locale>

using namespace std;

struct LessStruct
{
        bool operator()(const CString& str1, const CString &str2) const {
                _locale_t loc = _create_locale(LC_ALL, "cs-CZ");
                return _wcsicmp_l(str1.GetString(), str2.GetString(), loc) < 0;
        }
};

int main(int argc, char const *argv[])
{
        std::map<CString, int, LessStruct> mapa;
        mapa.insert(pair<CString, int>(L"ď", 2));
        mapa.insert(pair<CString, int>(L"a", 2));
        mapa.insert(pair<CString, int>(L"á", 2));
        mapa.insert(pair<CString, int>(L"b", 2));
        mapa.insert(pair<CString, int>(L"c", 2));
        mapa.insert(pair<CString, int>(L"č", 2));
        mapa.insert(pair<CString, int>(L"ch", 2));
        mapa.insert(pair<CString, int>(L"d", 2));
        mapa.insert(pair<CString, int>(L"ď", 2));
        mapa.insert(pair<CString, int>(L"e", 2));
        mapa.insert(pair<CString, int>(L"é", 2));
        mapa.insert(pair<CString, int>(L"ě", 2));
        mapa.insert(pair<CString, int>(L"f", 2));
        mapa.insert(pair<CString, int>(L"g", 2));
        mapa.insert(pair<CString, int>(L"h", 2));
        mapa.insert(pair<CString, int>(L"ú", 2));
        mapa.insert(pair<CString, int>(L"ů", 2));
        mapa.insert(pair<CString, int>(L"v", 2));
        mapa.insert(pair<CString, int>(L"w", 2));
        mapa.insert(pair<CString, int>(L"x", 2));
        mapa.insert(pair<CString, int>(L"y", 2));
        mapa.insert(pair<CString, int>(L"ý", 2));
        mapa.insert(pair<CString, int>(L"z", 2));
        mapa.insert(pair<CString, int>(L"ž", 2));
        mapa.insert(pair<CString, int>(L"i", 2));
        mapa.insert(pair<CString, int>(L"í", 2));
        mapa.insert(pair<CString, int>(L"j", 2));
        mapa.insert(pair<CString, int>(L"k", 2));
        mapa.insert(pair<CString, int>(L"l", 2));
        mapa.insert(pair<CString, int>(L"m", 2));
        mapa.insert(pair<CString, int>(L"n", 2));
        mapa.insert(pair<CString, int>(L"ň", 2));
        mapa.insert(pair<CString, int>(L"o", 2));
        mapa.insert(pair<CString, int>(L"ó", 2));
        mapa.insert(pair<CString, int>(L"p", 2));
        mapa.insert(pair<CString, int>(L"q", 2));
        mapa.insert(pair<CString, int>(L"r", 2));
        mapa.insert(pair<CString, int>(L"ř", 2));
        mapa.insert(pair<CString, int>(L"s", 2));
        mapa.insert(pair<CString, int>(L"š", 2));
        mapa.insert(pair<CString, int>(L"t", 2));
        mapa.insert(pair<CString, int>(L"ť", 2));
        mapa.insert(pair<CString, int>(L"u", 2));

        return 0;
}

Zkusil jsem: Prohledal jsme nápovědu na celém internetu. ve StackOverflow se (překvapivě) diakritikou nezabývají.
Zkoušel jsme i řazení přes wstring::compare(wstring string)

s předešlým nastavením:

const char* locale_name = "Czech_Czechia.1250";
std::locale::global(std::locale(locale_name));

a taky nic.

Chci docílit: Seřadit řetězce v mapě nebo v setu. Je to zkomplikováno ještě potřebou naturálního řazení (str 1, str 10, str 2), tskže nelze použít nějaké defaultní algoritmy.

 
Odpovědět
31.10.2023 15:50
Avatar
Odpovídá na Michal Hadraba
Michal Hadraba:31.10.2023 17:42

No tak jsem tu našel starší post, dokonce můj - kde jsme řešil malinko něco jiného. Nicméně takto to funguje. Ale proč nefunguje to předchozí, stále nevím.

struct LessStruct
{
        bool operator()(const CString& str1, const CString &str2) const {
                setlocale(LC_COLLATE, "cs_CZ.utf8");
                return wcscoll(str1.GetString(), str2.GetString())<0;
        }
};
Editováno 31.10.2023 17:43
 
Nahoru Odpovědět
31.10.2023 17:42
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:31.10.2023 18:04

Zkus popsat slovně to čeho chceš dosáhnout, nikoli imolementačně. Ať se neomezuje na jeden způsob řešení.

Co se týká řazení stránkování, má tedy posloupnost od menšího k většímu vypadat takto?

str 1, str 2, str 100, ...
Tedy řazeno alfanumericky

Nebo

str 1, str 100, str 2, ...
Tedy řazeno kombinované str a pak podle číselné hodnoty?

Bude se řetězec skládat jen z kombinace str a čísla nebo jiných subřetězců?

PS: před pár měsíci jsme tu řešili společně řazení diakritickych řetězců. Tuším že tam byla "žirafa" :-)

Editováno 31.10.2023 18:06
Nahoru Odpovědět
31.10.2023 18:04
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Michal Hadraba:31.10.2023 18:18

Jasně, já jsem chtěl původně řadit jenom písmena, ale postupem vývoje jsem pojal potřebu řešit také řazení čísel numericky. Pro numerické řazení čísel jsme našel nějaký vzorový kód, ten jsme použil - šoupnu ho sem zítra - ale ten zas neřešil diakritiku.
Takže problém je - seřadit, přesně jak píšeš:
stoka 1 - levá
stoka 15 - něco
stoka 2 - pravá
stoka 25 .....
řad
větev

V zásadě jsme to už vyřešil, když jsme si vzpomněl a našel předchozí post.
Nicméně stále nechápu, kdy je třeba použít jaké locale - jedno funguje (nebo nefunguje) pro funkce wstring, string, druhé pro obecné c funkce, jednou se tam přidává "_locale_t loc", podruhé ne....

Editováno 31.10.2023 18:18
 
Nahoru Odpovědět
31.10.2023 18:18
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:31.10.2023 18:46

S locale jsou občas problémy, Také jsem se setkal s tím že jeho použití nevykazovalo to co jsme chtěli.

Pokud chceme variantu řazení:

stoka 1 - levá
stoka 15 - něco
stoka 2 - pravá
stoka 25 .....

Pak je to jednoduché. Řetězce jsou řazeny alfanumericky, tedy že 15 bude v abecedě dříve než 2. Pak můžeš použít funkci wcscmp() pro case sensitive řazení nebo _wscicmp() pro non case sensitive.

Pokud chces řadit hodnotově, tedy že 15 bude více než 2, pak nastavis ukazatel na počátek číselné hodnoty a aplikuješ funkci atoi() pro převod na číselnou hodnotu.

Abys pro řazení neprováděl opakovaně tyto konverze, vytvoříš pole celých čísel o délce počtu záznamu, konverzi zápisem do tohoto pole a řazení budeš provádět na tomto temp poli.

Nahoru Odpovědět
31.10.2023 18:46
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Michal Hadraba:31.10.2023 18:53

Já chtěl řadit numerických, napsal jsem to blbě, už nevím co jsem.
Mělo být:
Stoka 1
Stoka 2
Stoka 15

Logicky. No, tak jak píšeš na konci.
Děkuji.
Ještě zkusím to wscipm.

 
Nahoru Odpovědět
31.10.2023 18:53
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:31.10.2023 21:03

A nebo úplně jednoduše. Zjisti počet záznamů a vytvoř 2 pole o počtu záznamů. Jedno pro hodnoty na dane stoce, druhé pro serazene indexy stok. Načti záznam ze souboru, vyextrahuj z něho ID stoky, na index ID stoky ulož hodnotu pro danou stoku. To dělej pro všechny záznamy. Nyní hledej minima z hodnot v prvnim poli a zapisuj index nejnizsihomprvku postupně do indexu druhého pole. Tím získáš ID stok od nejnižší hodnoty. Nakonec projdeš celé druhé pole a vygeneruješ seřazené stoky podle hodnot na indexech. Budeš-li potřebovat hodnotu pro dáno stoky, jednoduše si sáhneš do prvního pole na index odpovídající hodnotě na indexundruheho pole.

Nahoru Odpovědět
31.10.2023 21:03
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Michal Hadraba:31.10.2023 21:10

Sorry. Příklad byl pouze ilustrativní a příliš zjednodušený. Ty názvy si volí uživatel. Může tam mít 11 Stok, 22 přípojek, 15 větví... a bůhví co ještě lze vymyslet..... Už se mi ten algoritmus začíná rýsovat. Zítra nebo pozítří sem kdyztak picnu nějaké nápady, ať ten problém uzavřeme.

 
Nahoru Odpovědět
31.10.2023 21:10
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:31.10.2023 21:50

Hoď sem úplné přesné zadání..

Nahoru Odpovědět
31.10.2023 21:50
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Michal Hadraba:31.10.2023 23:32

Přesné zadání je "natural sorting s respektem k diakritice, no case sensitive".
Ale hlavně mě zajímá, jak funguje "locale".

Zjistil jsem, že funguje _wscicmp_l(), ale do locale se musí zadat czech_cz.utf8 (to utf8 je tam nutný - to se člověk nikde nedoví)

_locale_t locale;
locale = _create_locale(LC_ALL, "cs-CZ.utf8");
return  _wcsicoll_l(&lhs, &rhs, locale) < 0;
_free_locale(locale);

to mi přijde o hodně jednodušší (a také asi méně náročné na prostředky), než:

char* old_locale = setlocale(typ, NULL);
lcSavedLocale = strdup(old_locale);
if (!lcSavedLocale) throw CMAJEX("Out of memory");
setlocale(LS_COLLATE, "Czech_cz.utf8");
bool res = _wcsicoll_l(&lhs, &rhs, locale) < 0;
setlocale(LS_COLLATE, lcSavedLocale);
free(lcSavedLocale);
 
Nahoru Odpovědět
31.10.2023 23:32
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:1.11.2023 8:30

Razeni cisel se da resit podle delky a pak podle cislic
115 = delka 3 znaky
10 = delka 2 znaky

Problem by nastal s desetinnym cislem nebo cisly s jinym delenim, treba cislovane odrazky, tam bys to musel udelat asi spesl pro danou situaci
1.2.3
1.1.15
Pokud nezalezi na rychlosti, pouzival jsem pro takove spesl situace regularni vyrazy.

 
Nahoru Odpovědět
1.11.2023 8:30
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Peter Mlich
DarkCoder:1.11.2023 12:07

To je dosti neefektivní. Důvodem je to, že řadící rozsah je extrémně malý. Např. pro čísla v rozsahu 1-99 je 9 délek jeden znak a 90 délek dva znaky.

Nahoru Odpovědět
1.11.2023 12:07
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Michal Hadraba:2.11.2023 8:09

Takhle to funguje myslím, že efektivně. Jen ale pro celá čísla, žádné desetinné čárky atd. Nebyl by asi problém to tam doplnit.

#include <locale>
#include <string>

using namespace std;

namespace MajCompare {

        struct MajLoc
        {
        private:
                _locale_t m_loc;
        public:
                MajLoc(){ m_loc = _create_locale(LC_COLLATE, "cs-CZ.utf8");     }
                ~MajLoc() {     _free_locale(m_loc);}
                _locale_t& GetLocale() { return m_loc; }
        };
        static MajLoc s_cLoc;

        //Vrací -1, 0 1
        int CompareNatural(const wchar_t* lhsBegin, const wchar_t* lhsEnd
                , const wchar_t* rhsBegin, const wchar_t* rhsEnd)
        {

                wstring wsPom1, wsPom2;
                const wchar_t* itCurLhs = lhsBegin, *itCurRhs = rhsBegin;
                while (!iswdigit(*itCurLhs) && !iswdigit(*itCurRhs) && itCurLhs != lhsEnd && itCurRhs != rhsEnd)
                {
                        wsPom1.push_back(*itCurLhs);
                        wsPom2.push_back(*itCurRhs);
                        if (*itCurLhs != *itCurRhs)
                                return _wcsicoll_l(lhsBegin, rhsBegin, s_cLoc.GetLocale());

                        itCurLhs++, itCurRhs++;
                }
                if (itCurLhs == lhsEnd || itCurRhs == rhsEnd || iswdigit(*itCurLhs) != iswdigit(*itCurRhs)) //jeden je delší nebo kombinace čísla a písmena, porovnáme původní řetězce bez ohledu na čísla porovnáme standardně
                        return _wcsicoll_l(lhsBegin, rhsBegin, s_cLoc.GetLocale());
                else //oba řetězce mají čísla a nejsou na konci
                {
                        wstring wsNum1, wsNum2;
                        while (iswdigit(*itCurLhs))
                                wsNum1.push_back(*itCurLhs++);
                        while (iswdigit(*itCurRhs))
                                wsNum2.push_back(*itCurRhs++);
                        int iNum1 = _wtoi(wsNum1.data());
                        int iNum2 = _wtoi(wsNum2.data());
                        if (iNum1 != iNum2)
                                return iNum1 > iNum2 ? 1 : -1;
                        return CompareNatural(itCurLhs, lhsEnd, itCurRhs, rhsEnd);
                }
        }

        int CompareNatural(const wchar_t* lsFirst, const wchar_t* lsSecond)
        {
                const wchar_t* it1 = lsFirst;
                while (*it1 != '\0')it1++;
                const wchar_t* it2 = lsSecond;
                while (*it2 != '\0')it2++;
                return CompareNatural(lsFirst, it1, lsSecond, it2);
        }
};
 
Nahoru Odpovědět
2.11.2023 8:09
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:3.11.2023 21:32

Michale, kód, který si uvedl, není efektivní.

Tři body:

1.
Zbytečně generuješ nový řetezec pro textovou i numerickou část. Proč? Ten subřetězec už tam máš. Zbytečně to zpomaluje aplikaci.

2. Způsob, jakým generuješ subřetězce je neefektivní. Pokud v cyklu provádíš pus.back na prázdném dynamickém poli, s každým vkládaným znakem provádíš realokaci řetězce, což velmi spomaluje aplikaci. Zejména jsou-li řetězce dlouhé.

3. S každým voláním funkce provádíš činnost kterou už si dříve dělal. Zejména u velkého množství záznamů se toto negativně projeví na zpomalení aplikace.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
3.11.2023 21:32
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Michal Hadraba:4.11.2023 7:06

Ahoj díky. První dva body chápu. Ten první řetězec wsPom nakonec ani nepoužívám. Ovšem wsNum je nutné, jak to generovat efektivněji? Použít wstring::resize nebo wstring::reserve?

A ten třetí bod úplně nechápu, co tím myslíš. Myslíš volání _wscicoll znova pro celý řetězec? Šlo by to od aktuálního znaku, to jo.

 
Nahoru Odpovědět
4.11.2023 7:06
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:4.11.2023 12:52

Když už máš nějaký řetězec o kterém víš že jej nebudeš měnit, můžeš jej používat na více místech. To první místo je celý samotný řetězec a to druhé je jeho podřetězec, ať už jeho alfa část nebo druhá část numerická. Není třeba vytvářet nějaký další prostor pro kopírování subřetězce z řetězce někam jinam. To platí pochopitelně za přepokladu, že subřetězec nebudeš měnit. A to je tento případ.

Funkce dodané s překladačem pracují pro řetězce, tedy data ukončená nulovým znakem. Ty musíš pro alfa část vytvořit vlastní funkci, protože řetězec měnit nechceš a subřetězce nekončí nulovým znakem. Stačí Ti ukazatel a délka alfa subřetězce. Pro numerickou část subřetězce je situace maličko jiná. Pro ten musíš najít adresu kde číselná část začíná, přečíst jej funkcí pro konverzi ze znakové podoby do číselné a tuto hodnotu někam uložit.

Ještě jednou, pro textový subřetězec v řetězci potřebuješ adresu počátku a jeho délku. Pro číselný subřetězec proměnnou pro uložení čísla a adresu na které se první číselný znak nachází a provést konverzi.

Krátká ukázka:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void) {
        const char* input = "zak100 180cm";
        int number = -1;
        unsigned int nonDigitCount = 0;
        const char* ptr = input;

        while (*ptr) {
                if (isdigit(*ptr)) {
                        number = atoi(ptr);
                        break;
                }
                else {
                        nonDigitCount++;
                }
                ptr++;
        }

        printf("Delka textove casti: %u\n", nonDigitCount);
        printf("Extrahovane cislo: %d\n", number);

        return 0;
}

V cyklu while provádím vše co potřebuji. Posouvám ukazatel postupně celým řetězcem dokud nenarazím na číslici, od této číslice zavolám konverzi a ukončím cyklus. Zároveň počítám počet znaků textové části. Kdykoli se mohu dostat k textové části, neboť znám ukazatel a počet znaků subřetězce. Číselnou část mám uloženou v paměti a s tou poté pracuji. Již nemusím v každém volání provádět konverzi.

K třetímu bodu.

Když se třídí nějaká data pole či jiné kolekce, dochází k opakovanému braní prvku. S tím co bys měl bys opakovaně prováděl úkony které si už jednou nad daným prvkem dělal. Aplikaci je třeba zefektivnit tak že ten krok provedeš pouze jednou. To docílíš tak, že před samotným porovnáváním a tříděním provedeš analýzu všech řetězců, zjistíš délku textové části a získáš číselnou hodnotu z řetězce. Tak jak jsme si ukázali výše. Když pak budeš mít řetězce, provedeš na nich jen porovnání. a na základě výsledku prohodíš indexy.

Ještě jednou, když porovnáš dva řetězce, používáš pro ně to co jsi předpočítal, tedy číselnou hodnotu a délku textové části. A na základě porovnání se prohazují indexy nikoli data! Řetězcová data nikdy nebudeš měnit. Na to budeš mít pole ID řetězců, která budeš měnit podle výsledku porovnání.

Třetí bod ve stručnosti znamená to, že provedeš předzpracování dat, které si někam uložíš a ta pak využíváš pro porovnávání a třídění, aniž bys musel opětovně provádět rozsekání řetězce a vytahování dat, protože už si to dříve dělal. Tím celá aplikace poběží mnohem rychleji, než kdybys tomu tak neudělal.

Nahoru Odpovědět
4.11.2023 12:52
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Michal Hadraba:4.11.2023 20:17

Darku :-) díky.
S tím cashováním to nedám, neb používám std::map a ten si třídí sám. Nicméně, zas takových položek nemám.

Třídící algoritmus jsem upravil:

inline int CompareNatural(const wchar_t* lhsBegin, const wchar_t* lhsEnd
        , const wchar_t* rhsBegin, const wchar_t* rhsEnd)
{

        wstring wsPom1, wsPom2;
        const wchar_t* itCurLhs = lhsBegin, *itCurRhs = rhsBegin;
        while (!iswdigit(*itCurLhs) && !iswdigit(*itCurRhs) && itCurLhs != lhsEnd && itCurRhs != rhsEnd)
        {
                if (*itCurLhs != *itCurRhs)
                        return _wcsicoll_l(itCurLhs, itCurRhs, s_cLoc.GetLocale());

                itCurLhs++, itCurRhs++;
        }
        if (itCurLhs == lhsEnd || itCurRhs == rhsEnd || iswdigit(*itCurLhs) != iswdigit(*itCurRhs)) //jeden je delší nebo kombinace čísla a písmena, porovnáme původní řetězce bez ohledu na čísla porovnáme standardně
                return _wcsicoll_l(lhsBegin, rhsBegin, s_cLoc.GetLocale());
        else //oba řetězce mají čísla a nejsou na konci
        {
                int iNum1 = _wtoi(itCurLhs);
                int iNum2 = _wtoi(itCurRhs);
                if (iNum1 != iNum2)
                        return iNum1 > iNum2 ? 1 : -1;
                else
                {
                        while (iswdigit(*itCurLhs)) ++itCurLhs; //přeskočíme čísla na další písmeno
                        while (iswdigit(*itCurRhs)) ++itCurRhs;
                }
                return CompareNatural(itCurLhs, lhsEnd, itCurRhs, rhsEnd);
        }
}
 
Nahoru Odpovědět
4.11.2023 20:17
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Michal Hadraba
DarkCoder:4.11.2023 23:05

Nemáš zač Michale. Abys viděl blíže, co jsem Ti popisoval v předchozích příspěvcích, zpracoval jsem pro tebe jeden krátký ukázkový příklad. Smyslem příkladu je poukázat na způsob efektivního porovnávání řetězců jak abecedně tak číselně. Podívej se zejména, co předchází samotnému porovnání. V programu není zahrnuta diakritika a třídění, pouze porovnání a analýza vstupu. Pokud bude cokoli nejasného, ptej se.. :-)

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define DEBUG 0

void analyze_strings(const char* strings[], unsigned lengths[], unsigned numbers[], size_t count);
int compareText(const char* strings[], unsigned lengths[], unsigned numbers[], size_t index1, size_t index2);

int main(void) {
        const char* strings[] = {
                "kun3",
                "pesec12",
                "strelec4",
                "pesec2",
                "kun10",
                "dama1"
        };

        size_t count = sizeof(strings) / sizeof(strings[0]);

#if DEBUG==1
        printf("%zu\n", count);
#endif

        unsigned* lengths = (unsigned*)malloc(count * sizeof(unsigned));
        if (lengths == NULL) exit(1);

        unsigned* numbers = (unsigned*)malloc(count * sizeof(unsigned));
        if (numbers == NULL) {
                free(lengths);
                lengths = NULL;
                exit(2);
        }

        analyze_strings(strings, lengths, numbers, count);

#if DEBUG==1
        for (size_t i = 0; i < count; i++) {
                printf("%u ", lengths[i]);
        }
        putchar('\n');

        for (size_t i = 0; i < count; i++) {
                printf("%u ", numbers[i]);
        }
        putchar('\n');
#endif

        for (size_t i = 0; i < count; i++) {
                for (size_t j = 0; j < count; j++) {
                        printf("%s vs %s %d\n", strings[i], strings[j], compareText(strings, lengths, numbers, i, j));
                }
        }

        free(lengths);
        lengths = NULL;

        free(numbers);
        numbers = NULL;

        return 0;
}

void analyze_strings(const char* strings[], unsigned lengths[], unsigned numbers[], size_t count) {
        unsigned number;
        unsigned nonDigitCount;
        const char* ptr = NULL;

        for (size_t i = 0; i < count; i++) {
                number = 0;
                nonDigitCount = 0;
                ptr = strings[i];

                while (*ptr) {
                        if (isdigit(*ptr)) {
                                number = atoi(ptr);
                                break;
                        }
                        else {
                                nonDigitCount++;
                        }
                        ptr++;
                }

                numbers[i] = number;
                lengths[i] = nonDigitCount;
        }
}

int compareText(const char* strings[], unsigned lengths[], unsigned numbers[], size_t index1, size_t index2) {
        unsigned i = 0;
        while (i < lengths[index1] && i < lengths[index2]) {
                if (strings[index1][i] < strings[index2][i]) return -1;
                else if (strings[index1][i] > strings[index2][i]) return 1;
                i++;
        }

        if (i < lengths[index1]) return 1;
        else if (i < lengths[index2]) return -1;

        if (numbers[index1] < numbers[index2]) return -1;
        else if (numbers[index1] > numbers[index2]) return 1;

        return 0;
}
Nahoru Odpovědět
4.11.2023 23:05
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 18 zpráv z 18.