Problem mit void-Pointer!
-
Hi,
Ich muss einen Merge-Sort schreiben der halt mit allen möglichen DAtentypen umgehen kann. Man muss der Funktion dazu aber eine Funktion mitgeben die den jeweiligen Datentyp vergleichen kann. Mein Merge-Funktions-Prototyp sieht so ausvoid msort(void* base, long number, long size, int (*cmp) (void*, void*));
Für ints habe ich als cmp-Funktion, folgende geschrieben:
int int_compare(void *vp1, void *vp2) { int* ip1=(int*)vp1; int* ip2=(int*)vp2; printf("%d - %d\n",ip1[0],ip2[0]); // Manchmal falsche Werte!!! return(*ip1-*ip2); }
Diese Funktion wird in meiner Merge-Funktion folgendermaßen aufgerufen:
printf("Übergabe: %d, %d\n",*(feld1+(i1*size)),*(feld2+(i2*size))); // Alles noch richtig!!! if ( (i2>=g2) || (i1<g1 && cmp((feld1+(i1*size)),(feld2+(i2*size)))<0)) { // nehme aus Feld1 charbase[i*size] = feld1[i1*size]; i1++; }
In (feld1+(i1*size)) und (feld2+(i2*size)) stehen die Zahlen noch normal drin, ahbe ich mit einem printf vorher getestet, aber in der Funktion cmp-Funktion, kommt es teilweise zu veränderungen der Zahlen.
Nicht imemr aber manchmal ist eine der Zahlen oder sogar beide total verfälscht.
Also zB aus 2 wird 5304 oder so.
Woran liegt das denn?
-
Debugger verwenden.
-
Joa dann müsst cih mir mal ne Entwicklungsumgebung besorgen.
Programmiere momentan unter Linux mit nem normalen Editor und gcc.
Hät ja sein können das ein offensichtlicher Fehler drin ist.
-
gdb, printf(...), assert() sind deine Freunde zum Debuggen.
-
Naja aber was soll ich denn beim Debugen noch feststellen?
Ich hab ja vorm Funktionsaufruf ein printf und in der Funktion und da seh ich ja dass in der Funktion die Werte auf einmal falsch sind.
Mehr werd ich beim Debugen doch auch nicht feststellen oder?
-
du raeumst jetzt mal diesen sauhaufen auf. das sieht ja aus wie kraut und rueben!
wenn du im chaos leben willst, musst du nicht nur deinen debugger beherrschen, du musst selbst zum debugger und compiler werden. text rumschubsen und beten dass es klappt, das ist nicht.
edit: oder WENIGSTENS poste einen kuerzestmoeglichen code, der dein problem darstellt. liest du keine faqs? da haette dringestanden, was ich dir jetzt sage.
-
Wo isn das ein Sauhaufen ^^
Ich mein, du kannst ja gern ma versuchen die Logik irgendwie kürzer darzustellen, aber ich bezweifle dass das geht.
Und die Funktion is ja schon ziemlich klein....
Also weiß net was du mir jetzt damit sagen wolltest?!
-
ich pflueck dir das jetzt nicht auseinander (kannst du selbst machen), aber so viel kannst du wissen:
mir sind da zu viele sterne und zu wenig [] drin.
und nimm bitte die klammern weg, die eindeutig sind, z.b. in deinen additionen und multiplikationen.
mach auch mal ein paar leerzeichen.
-
Wenn ich aber in der cmp-Funktion das mit [] übergebe dann dereferenziert der mir das doch und die Funktion erwartet nen Pointer.
Wie könnt ich das dem denn anders übergeben sodass der trotzdem ein Pointer ist?
-
Muss das ganze denn unbedingt in C sein?
Also bei dem Stichwort "alle möglichen Datentypen" springen einen doch Templates förmlich ins Gesicht.
-
Ja, muss C sein...
Und der Prototyp void msort(void* base, long number, long size, int (*cmp) (void*, void*)) ist auch vorgegeben!Also hab mal versucht den Code was übersichtlicher zu machen:
Funktionsaufruf:
printf("Uebergabe: %d, %d\n", feld1[i1*size], feld2[i2*size]); if ( (i2 >= g2) || (i1 < g1 && cmp(&feld1[i1*size], &feld2[i2*size]) < 0)) { // nehme aus Feld1 charbase[i*size] = feld1[i1*size]; i1++; }
Funktion:
// Integers vergleichen int int_compare(void *vp1, void *vp2) { int* ip1 = vp1; int* ip2 = vp2; printf("%d - %d\n", ip1[0], ip2[0]); return(*ip1 - *ip2); }
-
Also ich habs jetzt hinbekommen dass es mit ints läuft, aber mit floats läuft es leider nicht.
Da man mit void* selbst ja nicht arbeiten kann hab ich dann immer an nen char* übergeben. Keine Ahnung ob das so richtig war. Und in den Vergleichsfunktionen hab ich dann auch char* als Übergabewerte. So funktionierte es dann mit ints richtig aber halt nicht mit floats.Hier mal mein kompletter Code. Hoffe mir kann da jemand helfen....
#include <stdio.h> int int_compare(void *vp1, void *vp2); float flt(void *vp1, void *vp2); void msort(void* base, long number, long size, int (*cmp) (void*, void*)); int main(void) { float zahlen[] = {1.5,7.7,1.2,2.2,3.2,5.1,1.0,9.1,7.9}; int i; msort(zahlen,9,sizeof(float),flt); for(i=0;i<9;i++) { printf("%d => %f\n",i,zahlen[i]); } return 0; } // Integers vergleichen int int_compare(char* vp1, char* vp2) { int temp1 = vp1[0]; int temp2 = vp2[0]; //printf("%d - %d\n",vp1[0],vp2[0]); return(*vp1 - *vp2); } // Floats vergleichen float flt(char* vp1, char* vp2) { float temp1 = (float) vp1[0]; float temp2 = (float) vp2[0]; return(*vp1 - *vp2); } void msort(void* base, long number, long size, int (*cmp) (void*, void*)) { if(number>1) { long g1 = number/2; long g2 = number-g1; char* feld1=NULL; char* feld2=NULL; int i; int i1=0; int i2=0; char* charbase = (char*)base; // Speicherallokation feld1 = malloc(g1*size); feld2 = malloc(g2*size); // Feld in 2 Felder teilen for(i=0;i<g1;i++) { feld1[i*size] = charbase[i*size]; } for(i=0;i<g2;i++) { feld2[i*size] = charbase[(i + g1)*size]; } // rekursiver Aufruf von msort mit den geteilten Feldern msort(feld1,g1,size,cmp); msort(feld2,g2,size,cmp); // Zusammensetzen der geteilten Felder for(i = 0; i < (g1 + g2); i++) { if ( (i2 >= g2) || (i1 < g1 && ( cmp(&feld1[i1*size], &feld2[i2*size]) <= 0 ))) { // nehme aus Feld1 charbase[i*size] = feld1[i1*size]; i1++; } else { // nehme aus Feld2 charbase[i*size] = feld2[i2*size]; i2++; } } // Speicherfreigabe free(feld1); free(feld2); } else { return; } }
-
Ich bezweifle, dass das mit Integern richtig funktionert (auch wenn ein kurzer Test diesen Anschein erweckt). Du machst hier nämlich denselben Fehler wie bei den floats auch. Du musst den void* in type* casten und dann erst dereferenzieren.
Und dass der Code mit den Prototypen für die Vergleichsfunktionen überhaupt übersetzt wird bezweifle ich auch stark.
-
Also in Visual Studio hat das so echt kompiliert und lief mit ints auch.
Hab mal mehrere Zahlenreihen durchgetestet.
Also soll ich mal wirklich als void* an die Funktionen übergeben und dort in type* casten und dann dereferenzieren und an einen int bzw. float übergeben?