Hash Tabelle mit Doppelt verketteten Listen



  • Vielen Dank erstmal euch beiden für die Antworten.

    Was ich machen möchte:

    Ich möchte mit der Hash Tabelle ein Spielfeld realisieren. Das Problem dabei war das jedes Feld mehrer Informationen speichern muss. Und da kahm mir verkette listen in den Sinn. Ich muss aber von einer Liste in die andere schauen können um überprüfungen zu machen.

    Deshalb dann eine Hash Tabelle. Und weil ich auch vor und zurück gehen muss doppelt verkettet.

    Gerade mit dem zeigern habe ich noch meine Problem. Wenn ich "pointer" das letzte element nenne und "Helfer" das jetzt neue was angehängt werden soll:

    helfer->next=helfer;//Helfer next zeigt zuerst auf seinen eigenen Header
    			helfer->prev=pointer->next;//Helfer prev zeigt jetzt auf den Header der struct davor da pointer->next ja auf seinen header zeigte
    		    pointer->next=helfer;//Pointer next zeigt jetzt auf den Header von Helfer
    			pointer=helfer;//pointer wird zum zeiger auf den Header von helfer
    			pointer->leben=0;//ein paar daten rein
    			pointer->status=0;
    

    Oder hab ich da was falsch gesehen?

    Und zu der anderen Frage. Wenn ich z.b.

    poiner=hashtabelle[0];
    

    Habe. Da weiß ich jetzt nicht genau wo der pointer drauf zeigt. Der müsste dann ja auf die Zeile zeigen. Zeigt er jetzt aber auf die Hash Tabelle oder auf ein Element 0 der Hash Tabelle? Weil eigentlich brauch ich ja den Pointer der von der Hash Tabelle 0 zu der Verketten liste zeigt. 😞



  • poiner=hashtabelle[0];
    

    pointer bekommt den Wert vom 1.Element aus dem Array hashtabelle.
    Somit zeigt pointer auf das Selbe Element im Speicher.

    Da bleibt nur die Frage ob auch hashtabelle[0] auf gültigen Speicher zeigt.

    Was soll helfer->next=helfer; bewirken? Ist das sinnvoll.
    So läufst du im Kreis, wenn du die Liste durchgehst.
    Wenn es das letzte Element (anhängen am Ende) ist, sollte da NULL stehen.
    Wenn es eingefügt wird wäre es helfer->next=pointer->next



  • DirkB schrieb:

    Wenn es das letzte Element (anhängen am Ende) ist, sollte da NULL stehen.
    Wenn es eingefügt wird wäre es helfer->next=pointer->next

    Aber das pointer->next sollte am Ende eh NULL sein. 😉

    Achte darauf das alle ungültigen Zeiger den Wert NULL bekommen.



  • Odatas schrieb:

    poiner=hashtabelle[0];
    

    Weil eigentlich brauch ich ja den Pointer der von der Hash Tabelle 0 zu der Verketten liste zeigt. 😞

    Das tut er, wenn die Speicherreservierung ok war.
    hashtabelle[1] zeigt auf die zweite Liste, etc.

    Odatas schrieb:

    Ich möchte mit der Hash Tabelle ein Spielfeld realisieren. Das Problem dabei war das jedes Feld mehrer Informationen speichern muss. Und da kahm mir verkette listen in den Sinn. Ich muss aber von einer Liste in die andere schauen können um überprüfungen zu machen.

    Deshalb dann eine Hash Tabelle. Und weil ich auch vor und zurück gehen muss doppelt verkettet.

    Das geht auch ohne Zeiger über einen Index, vor und zurück.
    Und du kannst jedes Element direkt adressieren,

    hash_tabelle[y][x]
    

    ohne dich durch die Liste hangeln zu müssen.



  • CJosef schrieb:

    Das geht auch ohne Zeiger über einen Index, vor und zurück.
    Und du kannst jedes Element direkt adressieren,

    hash_tabelle[y][x]
    

    ohne dich durch die Liste hangeln zu müssen.

    Dann brauch ich ja auch garkeine zeiger nutzen wenn ich die einfach so ansprechen kann oder?



  • Wenns keinen triftigen Grund gibt, würde ich das per Index(Koordinaten)-Adressierung machen, also ohne verkettete Liste.
    Und wenn die Feldgrößen schon vorher feststehen, dann brauchst du auch keine Zeiger für malloc/calloc.



  • CJosef schrieb:

    Wenns keinen triftigen Grund gibt, würde ich das per Index(Koordinaten)-Adressierung machen, also ohne verkettete Liste.
    Und wenn die Feldgrößen schon vorher feststehen, dann brauchst du auch keine Zeiger für malloc/calloc.

    Das ist ja noch besser als erwartet.

    Wie addressiere ich dann die einzelnen items. Einfach mit:

    hashtabelle[4][3]->leben=10;
    

    Funktioniert das so?

    EDIT: Das es so nicht geht weiß ich nu. Wie ist aber die Syntax dafür?



  • hashtabelle[4][3].leben=10;
    


  • Also das klappt nun alles sehr gut. Ich hab jetzt noch eine andere Anwendung die ich bräuchte. Und zwar will ich etwas von einer Datei in eine Hash Tabelle einlesen. Ich hab hier mal experimentel was geschrieben aber ich bekomme immer einen Fehler beim öffnen der Datei.

    Jemand ne Anmerkung?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define SCHIFFANZAHL 8
    
    struct stats {
    	int name, spawn, kosten, angriff, leben, schussweite;
    };
    
    int einlesen ()
    {
    	struct stats *ships[1]= {0};
    
    	if ( NULL == ( ships[0] = calloc ( SCHIFFANZAHL, sizeof ( struct stats )))) {
    		printf("Fehler bei Speicherplatzreservierung");
    
    	}
    
    	char bla[30];
    	int i=0;
    	FILE *f= fopen("stats.txt","r");
    
    	if (f==NULL) {
    		printf("Fehler beim öffnen der Datei\n\n");
    		return 0;
    		fclose(f);/*Datei schließen*/
    		free(ships[0]);
    	}
    
    	for (i=0; i<SCHIFFANZAHL; i++) {
    		fscanf(f, "%s %d %d %d %d %d %d",bla[30] ,ships[0][i].name, ships[0][i].spawn ,ships[0][i].kosten ,ships[0][i].angriff ,ships[0][i].leben ,ships[0][i].schussweite);
    		printf("  Name: %s", bla);
    		printf("%d %d %d %d %d %d\n" ,ships[0][i].name, ships[0][i].spawn ,ships[0][i].kosten ,ships[0][i].angriff ,ships[0][i].leben ,ships[0][i].schussweite);
    	}
    	fclose(f);/*Datei schließen*/
    
    	free(ships[0]);
    	return 1;
    }
    
    int main()
    {
    
    	einlesen();
    	getchar();
    }
    


  • Wo liegt denn die Datei? Im Debug/Release-Verzeichnis?

    Hast du schon mal den kompletten Pfad ausprobiert?

    Die Anweisungen ach dem return 0; werden nicht mehr ausgeführt.
    Also auch kein free.



  • Oh man ich mal wieder....Hab das return 0; verschoben.

    Die Datei liegt überall.

    Hab ein Exemplar im Debug und eins im Release Ordner. Beides geht nicht.

    Edit: Sinn in die Sätze gebracht.



  • Geh doch mal mit der Shell/Cmd oder dem Explorer in das Verzeichnis von der exe und starte es dort.



  • Du solltest bei fehlgeschlagenem calloc ebenso aus der Funktion raus.
    Verwende

    perror("stats.txt");
    

    vor dem return, um genauere Fehlerbeschreibungen zu erhalten.



  • Wutz schrieb:

    Du solltest bei fehlgeschlagenem calloc ebenso aus der Funktion raus.
    Verwende

    perror("stats.txt");
    

    vor dem return, um genauere Fehlerbeschreibungen zu erhalten.

    Danke für den Tipp. Er sagt die Datei gibt es nicht... Ich mache hier also irgend ein unendlich banalen Fehler wie es mir scheint ...

    EDIT: Ahja....die Datei hat heißt "stats.txt.txt"....niemals versuchen die Endung mit in den Dateinamen zu schreiben..... So weit so gut. Jetzt hab ich ber das Problem das er die Daten nicht ausliest aus der Datei. Ich hab mal den nhalt der Datei angehängt:
    quote] Jäger
    1
    1
    5
    10
    30
    1
    Fregatte
    2
    1
    100
    50
    300
    1
    Kreuzer
    3
    2
    200
    1000
    1
    Schlachtkreuzer
    4
    5
    1000
    1000
    3000
    1
    laser1
    51
    1
    5
    10
    30
    1
    laser2
    52
    1
    100
    50
    300
    1
    laser3
    53
    2
    200
    1000
    1
    laser4
    54
    5
    1000
    1000
    3000
    1[/quote]

    Das Ziel ist es die Zahlen auszulesen. Den Namen brauch ich garnicht der wird einfach in der Variablen "bla" zwischengespeichert und dann wieder überschrieben.



  • Bei scanf sollte man für nicht-Arrays schon de nQAdressoperator verwenden.
    Das nicht-Array bezieht sich auf den Typ den du einlesen willst. Z.B. mit %d ein int.



  • Warum ist ships ein *ships[1] und nicht einfach ein *ships ?
    Bei nur einem Eintrag macht das doch nur mehr Aufwand beim Zugriff.



  • DirkB schrieb:

    Warum ist ships ein *ships[1] und nicht einfach ein *ships ?
    Bei nur einem Eintrag macht das doch nur mehr Aufwand beim Zugriff.

    Mit dem Index ist es einfacher zu arbeiten fande ich. Ich schätze aber mal man kann den 1. Index auch weglassen und trozdem den Zugriff wie auf eine Hashtabelle nutzen.

    Wie dem auch sei es funktioniert (schon seid längerem). Und hier nochmal zur Vollständigkeit die jetztige Version.

    void einlesen ()//Einlesen der Stats aus der txt Datei.
    {
    
    	int i=0;
    	FILE *f= fopen("stats.txt","r");
    
    	if (f==NULL) {
    		printf("Fehler beim Oeffnen der Datei: stats.txt\n\n");
    		perror("stats.txt");
    		getchar();
    		fclose(f);/*Datei schließen*/
    		terminate();
    		getchar();
    	}
    
    	for (i=0; i<SCHIFFANZAHL; i++) {
    		fscanf(f, "%d %d %d %d %d %d",&ships[0][i].name, &ships[0][i].spawn ,&ships[0][i].kosten ,&ships[0][i].angriff ,&ships[0][i].leben ,&ships[0][i].schussweite);
    		//printf("%d %d %d %d %d %d\n" ,ships[0][i].name, ships[0][i].spawn ,ships[0][i].kosten ,ships[0][i].angriff ,ships[0][i].leben ,ships[0][i].schussweite);
    	}
    	fclose(f);/*Datei schließen*/
    
    }
    

    Danke für eure Hilfe


Anmelden zum Antworten