Toon posts:

[c] qsort op een pointer naar een array

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ik moet voor de avondschool een opdracht maken die gebruik maakt van het qsort commando.
het eerste deel heb ik al gedaan. nl het inlezen van een aantal namen, gebruik makende van pointers en geheugenallocatie. Maar het laatste deel lukt me niet: qsort gebruiken in combinatie met pointers.
In het programma mogen we nog geen gebruik maken van type def.
Ik zit precies vast met de pointers. Wat doe ik verkeerd?
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <cstdlib>
#define MAX_NAAM_LENGTE 40

char** readStudents(char **studentList, int *aantal);

int compare_strings (const void* a, const void* b ) {
    char*string1=(char*)a;
    char*string2=(char*)b;
    printf("\n  %d %x",string1,string1);
    return (strcmp ( string1, string2));
    }

int _tmain(int argc, _TCHAR* argv[]){
    
char **snt=(char**)(malloc(1*sizeof(char*)));
int aantalStudentenSnt=0;
    snt=readStudents(snt,&aantalStudentenSnt);
printf("\nvoor het sorteren\n----------------------\n");
for(int i=0;i<aantalStudentenSnt;i++){
    printf("%d: %s %x , %d\n",(i),snt[i]);
    }
printf("\nsnt pointer %x , %d\n",snt,snt);
//sorteren
qsort( snt[0], aantalStudentenSnt , sizeof(char[8]), compare_strings );
printf("\nNa het sorteren\n----------------------\n");
for(int i=0;i<aantalStudentenSnt;i++){
    printf("%d: %s\n",(i+1),snt[i]);
    }
return 0;
}


    char** readStudents(char **studentList, int *aantal){
        int NumberOfStudents=*aantal;
        printf("geef een naam in, CTRL+z om te stopppen :");
        char buffer[MAX_NAAM_LENGTE];
        while (gets(buffer)){
            int naamLengte=strlen(buffer);
            if(NumberOfStudents>0){
                studentList=(char**)(realloc(studentList, ((NumberOfStudents+1)*sizeof(char*))));
            }
            studentList[NumberOfStudents]=(char*)malloc(sizeof (naamLengte+1));
            strcpy(studentList[NumberOfStudents], buffer);
            NumberOfStudents++;
            printf("Geef de volgende naam in (ctrl+z om te stoppen):");
            }
        *aantal=NumberOfStudents;
        return studentList;
        }

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-09 20:04
De aanroep naar qsort is niet goed, qsort verwacht een array van elementen die gesorteerd moeten worden, snt[0] is de inhoud van het eerste element.

Daarna is dus het type die je voor a en b krijgt dus ook niet char*, maar char**

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
farlane schreef op vrijdag 02 januari 2009 @ 23:06:
De aanroep naar qsort is niet goed, qsort verwacht een array van elementen die gesorteerd moeten worden, snt\[0] is de inhoud van het eerste element.
maar dit kan toch niet kloppen:
code:
1
 qsort( snt, aantalStudentenSnt , sizeof(char*), compare_strings );
Daarna is dus het type die je voor a en b krijgt dus ook niet char*, maar char**
maar de compare functie moet toch een void* zijn en niet een **, hoe kan ik hieromheen?

[ Voor 15% gewijzigd door Verwijderd op 03-01-2009 00:44 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

qsort verwacht een array van "items", dus een pointer-naar-item. Jouw items zijn pointers-naar-characters, ofwel char*, dus de input naar qsort is een pointer-naar-pointer-naar-char, char**. Maar omdat qsort met alle typen moet kunnen werken is de input void* en de grootte van elk stukje item geheugen. De implementatie geeft dan aan de compare functie een pointer naar elk stukje item geheugen, en die cast jij zelf naar wat je weet dat het betekent: char* (char* string1=(char*)a;)

Dus, ja, je moet "snt" meegeven als eerste argument, of wat ik ook vaak doe &snt[0] wat hetzelfde is. Maar dat is een char**, dus die moet je casten naar void*: (void*)(snt), of (void*)(&snt[0]). Je verliest dan informatie, namelijk dat die pointer wijst naar char*'s, maar die informatie haal je terug in de compare functie met een cast.

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-09 20:04
Verwijderd schreef op zaterdag 03 januari 2009 @ 00:09:
maar dit kan toch niet kloppen:
code:
1
 qsort( snt, aantalStudentenSnt , sizeof(char*), compare_strings );
En toch klopt dat inderdaad :) Lees de help van qsort maar eens goed door en probeer dat te vertalen naar jouw situatie.
maar de compare functie moet toch een void* zijn en niet een **, hoe kan ik hieromheen?
Een void* is een beetje een speciaal geval in C en C++, nl alle datatypen zijn te converteren naar void* en void* is converteerbaar naar alle datatypen ( dus ook een char** zoals bij jou het geval is ) . Het wordt gebruikt om 'onbekende' typen te kunnen meegeven aan functies bv, maar je moet in alle gevallen het terug casten naar een bekend type om er wat mee te kunnen. ( Dat is ook de reden dat qsort de grootte van de elementen nodig heeft, hij weet anders niet waar het volgende element zit omdat je een void* meegeeft )

Je moet dus eigenlijk void* niet letterlijk als een pointer lezen maar meer als 'onbekend datatype'.

Lees dit http://www.cplusplus.com/doc/tutorial/pointers.html maar eens door, er is een apart stukje over void pointers.

[ Voor 13% gewijzigd door farlane op 03-01-2009 09:31 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 23-09 21:37

Creepy

Tactical Espionage Splatterer

Ik zit precies vast met de pointers. Wat doe ik verkeerd?
Als je PRG Beleid enHet algemeen beleid #topicplaatsen eens door wilt lezen dan zou je zien dat we voor een topicstart net iets meer vragen. Alleen aangeven dat iets niet lukt en je code plaatsen is niet de bedoeling. Dus wat gaat er precies mis en wat lukt er precies niet? Krijg je foutmeldingen? Zo ja, welke? etc. Ben je zelf al aan het debuggen geslagen? Dit zou je moeten kunnen aangeven, zeker omdat het een schoolopdracht is en je ook nog een docent hebt die je er mee kan helpen.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ok ik snap nu dat qsort een array nodig heeft, in mijn geval zal dit een array van pointers naar een array van chars (=strings) zijn.
dus de reden waarom je zelf moet je compare functie schrijven is omdat je dan kun werken met verschillende array types.

Maar nu moet ik nog even denken hoe ik de strings uit die pointers kan dereferentieren.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ok gevonden,
code:
1
2
3
4
5
6
7
int compare_strings (const void* a, const void* b ) {
    char**hulp1=(char**)a;
    char**hulp2=(char**)b;
    char*string1=*hulp1;
    char*string2=*hulp2;
    return (strcmp ( string1, string2));
    }


ik zal mijn code nog wat opschonen en hier ook posten, dan heeft iemand anders er ook nog wat aan.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ziehier de volledige code, enkel van het Free memory stuk ben ik niet zeker.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "stdafx.h"
#include <malloc.h>
#include <string.h>
#include <cstdlib>
#define MAX_NAAM_LENGTE 40

char** readStudents(char **studentList, int *aantal);

int compare_strings (const void* a, const void* b );

int _tmain(int argc, _TCHAR* argv[]){
    
char **snt=(char**)(malloc(1*sizeof(char*)));
int aantalStudentenSnt=0;
    snt=readStudents(snt,&aantalStudentenSnt);

//uitprinten van een lijst voor het sorteren
printf("\nvoor het sorteren\n----------------------\n");
for(int i=0;i<aantalStudentenSnt;i++){
    printf("%d: %s\n",(i),snt[i]);
    }

//sorteren
qsort( snt, aantalStudentenSnt , sizeof(char*), compare_strings );

//uitprinten van een lijst na het sorteren
printf("\nNa het sorteren\n----------------------\n");
for(int i=0;i<aantalStudentenSnt;i++){
    printf("%d: %s\n",(i+1),snt[i]);
    }

//geheugen terug vrij maken
free (snt);
return 0;
}

        
char** readStudents(char **studentList, int *aantal){
    int NumberOfStudents=*aantal;
    printf("geef een naam in, CTRL+z om te stopppen :");
    char buffer[MAX_NAAM_LENGTE];
    while (gets(buffer)){
        int naamLengte=strlen(buffer);
        if(NumberOfStudents>0){
            studentList=(char**)(realloc(studentList, ((NumberOfStudents+1)*sizeof(char*))));
        }
        studentList[NumberOfStudents]=(char*)malloc(sizeof (naamLengte+1));
        strcpy(studentList[NumberOfStudents], buffer);
        NumberOfStudents++;
        printf("Geef de volgende naam in (ctrl+z om te stoppen):");
        }
    *aantal=NumberOfStudents;
    return studentList;
    }

int compare_strings (const void* a, const void* b ) {
    char**hulp1=(char**)a;
    char**hulp2=(char**)b;
    char*string1=*hulp1;
    char*string2=*hulp2;
    return (strcmp ( string1, string2));
    }

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-09 20:04
code:
1
2
3
4
int compare_strings (const void* a, const void* b )
{
    return strcmp ( *(char**)a, *(char**)b );
}


Normaal ben ik niet echt van het korter schrijven van code als het niet hoeft maar bij namen als hulpje1 begint het een beetje te jeuken. :P

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Je mist natuurlijk wel een partij free's.

Elke pointer die je uit malloc haalt, moet je ook free-en. Op regel 47 zie ik een malloc in een loop, die geen free heeft. De malloc op regel 13 is wel goed, die ruim je op op 33.

Als je begint met pointers etc is het soms handig om even een overzichtje te maken van wat je nou eigenlijk doet. Bijvoorbeeld in een geval met 3 namen, er horen hier 4 free's (naar de dingen waar de pijlen naar wijzen)
code:
1
2
3
4
5
6
7
char ** (snt)
||
\/
char *, char *, char * ...
||          ||           ||
\/          \/           \/
char[]     char[]       char[]


Na een tijdje gaat het vanzelf :)

-niks-

Pagina: 1