qsort i sortowanie tablicy wskaźników - czy to możliwe?

0

Witajcie. Od długiego już czasu borykam się z problemem. Szybko i na temat, najprostszy przykład kodu:
**Jak za pomocą funkcji qsort posortować tablicę wskaźników w ten sposób, aby wartości oryginalnej tablicy nie zostały zmienione? **Moja implementacja podejrzewam, że zamienia wartości wskaźników, a nie adresy. Jak to zmienić? Nie chcę implementować żadnego innego algorytmu, to potrafię, ale chcę skorzystać z wbudowanej funkcji, która będzie zamieniać same wskaźniki. Czy jest to w ogóle możliwe? Podejrzewam, że funkcja porównaj powinna wyglądać inaczej, ale nie potrafię sobie tego wyobrazić, ani zaimplementować.

#include <stdio.h>
#include <stdlib.h>
void print(int *t, int rozmiar){
    for(int i=0; i<rozmiar; i++)
        printf("%d ",t[i]);
    printf("\n");
}
int porownaj(const void *w1, const void *w2);
int main() {
    printf("Hello, World!\n");
    int tab[10] = {9,8,7,6,5,4,3,2,1,0};
    int *wskazniki[10];
    for(int i=0; i<10; i++)
        wskazniki[i] = &tab[i];
    printf("Przed sortowaniem[tab]:       ");
    print(tab,10);
    printf("Przed sortowaniem[wskazniki]: ");
    print(*wskazniki,10);
    qsort(*wskazniki,10,sizeof(int),porownaj);
    printf("Po sortowaniu[tab]:           ");
    print(*wskazniki,10);
    printf("Po sortowaniu[wskazniki]:     ");
    print(tab,10);
    return 0;
}
int porownaj(const void *w1, const void *w2){
    int *a1 = (int*) w1;
    int *a2 = (int*) w2;
    if(*a1<*a2)
        return -1;
    if(*a1==*a2)
        return 0;
    else
        return 1;
}

**Wyniki w kompilatorze: **
Przed sortowaniem[tab]: 9 8 7 6 5 4 3 2 1 0
Przed sortowaniem[wskazniki]: 9 8 7 6 5 4 3 2 1 0
Po sortowaniu[tab]: 0 1 2 3 4 5 6 7 8 9
Po sortowaniu[wskazniki]: 0 1 2 3 4 5 6 7 8 9

4

Masz tablicę wskaźników, ale jej nie używasz.

*wskazniki to wyłuskuje pierwszy element tablicy - wskaźnik na tab

    qsort(wskazniki,10,sizeof(int*),porownaj);

poprawę funkcji porownaj zostawię Tobie. Zauważ tylko, że będziesz operował na wskaźnikach na wskaźniki, a nie bezpośrednio na wskaźnikach.

0

Niewyobrażalne podziękowania kieruję do Ciebie. Udało mi się to zrobić. Tyle czasu główkowałem nad tym, już myślałem, że to niemożliwe, a tu taki błąd. Stokrotne dzięki.

Zapytam jeszcze o jedną rzecz, bo nie mam nikogo, kto by mi to wytłumaczył, a postaram się zrozumieć raz na zawsze. Dlaczego, żeby to działało poprawnie potrzebna mi jest druga funkcja, do wypisywania wartości, mam ją zdefiniowaną tak:

void print2(int **t, int rozmiar) {
    for (int i = 0; i < rozmiar; i++)
        printf("%d ", *(*(t + i)) + 0);
    printf("\n");
}

Używam: print(tab,10); efekt: 9 8 7 6 5 4 3 2 1 0 (prawidłowo)
Używam nieprawidłowo print([gwiazdka]wskazniki,10); efekt: 9 8 7 6 5 4 3 2 1 0 (dlaczego tutaj wypisuje prawidłowe wartości)
po sortowaniu qsort, znów używam print(tab,10); efekt: 9 8 7 6 5 4 3 2 1 0 (prawidłowo)
Używam nieprawidłowo print([gwiazdka]wskazniki,10); efekt: 0 16 10 6053760 0 4199367 0 0 0 47 (tutaj wypisuje już nieprawidłowe wartości)
Używam print2(wskazniki,10); efekt: 0 1 2 3 4 5 6 7 8 9 (prawidłowo)
Nie umiem tego do końca wytłumaczyć, chodzi najogólniej o to, że przed sortowaniem używam *wskazniki, więc to jest niedobrze, bo wyłuskuje tylko pierwszy element tablicy - wskaźnik na tab, mimo to wypisuje prawidłowe wartości. Ale już po sortowaniu, kiedy te wskaźniki są zamienione i znów wywołam nieprawidłowo w ten sposób funkcje print wartości będą złe.

1
print(*wskazniki, 10);

jest prawidłowe. *wskazniki to jest to samo co wskazniki[0], czyli pierwszy element tablicy wskazniki.
Przed sortowaniem wskazniki[0] zawiera adres pierwszego elementu tablicy tab, czyli wskazniki[0] == &tab[0] == tab.
Po sortowaniu elementy zostały pomieszane, więc wskazniki[0] już nie wskazuje na początek tablicy tab. Wskazuje na najmniejszy element tablicy tab, czyli na ostatnią komórkę tej tablicy, która zawiera liczbę 0. Stąd wypisujesz 0 oraz 9 innych wartości spoza tablicy.

print2 leci po elementach tablicy wskazniki, więc zawsze będzie działać. Inaczej mówiąc print2 wypisuje

*wskazniki[0], *wskazniki[1], *wskazniki[2], itd.

natomiast print wypisuje

*wskazniki[0], *(wskazniki[0] + 1), *(wskazniki[0] + 2), itd.

1 użytkowników online, w tym zalogowanych: 0, gości: 1