string Wert auf char* Array



  • Vielen Dank hat mir sehr geholfen! 👍

    Das einzige was ich nicht ganz verstehe ist hier:

    char **pStringField = malloc(sizeof *pStringField * n);
    

    was genau sagt mir der doppelte Pointer? also char ** ?

    sry soweit sind wir in der Schule noch nicht.. wär sehr nett wenn mir das noch jemand schnell einer erklären könnte.

    aber danke schonmal! 🙂



  • char **strings bedeutet soviel wie ein Zeiger auf einen Zeiger auf ein char. Wenn du char * als String betrachtest hast einen Zeiger auf einen String, bzw mehrere wenn du es entsprechend belegst.

    Es gibt auch eine starke Ähnlichkeit zwischen char **strings, char *strings[] und char strings[][]. Ist nicht ganz dasselbe, aber hilft manchmal sich die Entsprechung vorzustellen.



  • KnufflPuffl schrieb:

    was genau sagt mir der doppelte Pointer? also char ** ?

    Liest sich als Zeiger auf einen Zeiger vom Typ char. Hast du ein char** Array, kannst du darin also char* Zeiger Speichern.
    Guckst du Beispiel:

    int main() { 
    	char* a = "aaa", *b = "bbb", *c = "ccc", *nix = NULL;
    	char** abc = malloc (4 * sizeof(char**));
    	int i=0;
    	abc[0] = a, abc[1] = b, abc[2] = c, abc[3] = nix;
    	while ( abc[i] != nix )
    		puts(abc[i]), i++;
    	free(abc);
    	return 0;     
    }
    


  • Hey nochmals danke, dass hab ich glaub ich sogar verstanden..

    Das heißt ich habe einen Pointer der auf einen anderen Pointer zeigt (in meinem Fall eben der String) und durch malloc kann ich eben mehr Speicher reservieren, sodass ich im Prinzip ein Array initialisiert habe.
    Demnach wäre char ***strings, sowas in der Art wie ein 2-Dimensionales Array, lieg ich da richtig, oder ist das komplett daneben?



  • Man kann es als 2-dimensionales Array von Strings betrachten. Oder als 3-dimensionales Array von chars. Oder als Liste von Stringarrays. Gibt sicher noch einen Haufen anderer Interpretationen.



  • KnufflPuffl schrieb:

    Demnach wäre char ***strings, sowas in der Art wie ein 2-Dimensionales Array, lieg ich da richtig, oder ist das komplett daneben?

    Ein char** s ist ja schon zweidimensional, wenn man so will. Du kannst es wie eine Tabelle von Zeichen betrachten:

    s[zeile][spalte]
    

    , wobei die Spaltenanzahl varieren kannn.
    Mit nem char*** z kannst du mehrere Zeiger solcher Tabellen speichern, kannst dir die Tabellen übereinander denken, eine Art dritte Dimension ( z Koordinate, Höhenkoordinate ).

    char* ebene[] = {"Ebene 1", "Ebene 2", "Ebene 3", "Ebene 4"};
    	char* a = "aaa", *b = "bbb", *c = "ccc", *nix = NULL;
    	char** abc = malloc (4 * sizeof(char**));
    	char*** z = malloc (4 * sizeof(char***));
    	char** p;
    	int i=0, j=0;
    	abc[0] = a, abc[1] = b, abc[2] = c, abc[3] = nix;
    	z[0] = z[1] = z[2] = z[3] = abc; // Hier sind alle 'Ebenen' gleich.
    	while ( j<4 ) {
    		p = z[j];
    		puts(ebene[j]);
    		while ( p[i] != nix ) puts(p[i]), i++;
    		i=0,j++;
    	}
    	free(abc);
    	free(z);
    

    Sicher kann man das auch anders interpretieren. Man kann ein 3D Array auch zwei-oder eindimensional betrachten, etc.



  • 😞

    Also ich hab das ganze jetzt mal so versucht wie ihr mir das geraten habt, es hat schon geholfen, aber leider nicht ganz.

    Das gute ist, das die komische Zeichenkette vom ersten Versuch weg ist (NO..) da nimmt er jetzt den richtigen Wert. Das Problem ist aber das ich nach dem 3en Eingabeversuch noch immer nen Laufzeitfehler kriege.

    Ich hab den Code so verändert:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
        printf("Sorting Strings with Pointers!\n");
    
        int n;
    
        printf("How many Strings do you want to input?\n");
        scanf("%i",&n);
    
       char **pStringField = malloc(sizeof *pStringField * n);
    
        int i = 0;
    
        char *str = malloc(sizeof(100));
    
        for(; i < n; i++)
        {
    
         scanf("%100s",str);
    
         strcpy(pStringField[i],str);
    
         printf("%s\n",pStringField[i]);
    
        }
    
        return EXIT_SUCCESS;
    }
    

    Hmm hab keine Ahnung woran das liegen könnte, könnte mir höchstens vorstellen dass ich irwie nen ungültigen Speicherbereich anspreche, aber ich hab doch genug Speicher reserviert.



  • Dir fehlt noch Speicher. Du benutzt strcpy(pStringField[i],str);, aber in pStringField[i] ist garkein Speicher reserviert. Du musst noch ein pStringField[i] = malloc(100); oder so hinzufügen.



  • nwp2 schrieb:

    Dir fehlt noch Speicher. Du benutzt strcpy(pStringField[i],str);, aber in pStringField[i] ist garkein Speicher reserviert. Du musst noch ein pStringField[i] = malloc(100); oder so hinzufügen.

    👍 super toll, das funktioniert jetzt wunderbar.

    Das heißt jetzt quasi hier:

    char **pStringField = malloc(sizeof *pStringField * n)
    

    wird nur der Speicher für das eigentliche Feld reserviert, nicht aber für die einzelnen Elemente richtig?

    Wenn das so ist frage ich mich nur warum das dann für die ersten 2 Aufrufe überhaupt geklappt hat?! 😮

    Jedenfalls vielen Dank! 😃



  • Yup, so ist es.

    Speicher wird Seitenweise reserviert, eine Seite hat meist 4kb. Das heißt du kannst mit Glück bis zu 4095 Bytes hinter dem Speicherbereich schreiben. Wenn die nächste Seite auch reserviert ist auch noch weiter. Oder du kriegst schon beim ersten nicht reservierten Byte einen Segmentation Fault wenn dieses Byte zufällig auf einer neuen nicht reservierten Seite liegt.



  • KnufflPuffl schrieb:

    Das heißt jetzt quasi hier:

    char **pStringField = malloc(sizeof *pStringField * n)
    

    wird nur der Speicher für das eigentliche Feld reserviert, nicht aber für die einzelnen Elemente richtig?

    Du reservierst:
    n == 1: Speicher für einen Zeiger auf ein Array(Feld),
    n > 1: Speicher für n Zeiger auf n Arrays(Felder).
    Den Speicher für die 'eigentlichen' Felder reservierst du erst innerhalb der for Schleife.

    KnufflPuffl schrieb:

    Wenn das so ist frage ich mich nur warum das dann für die ersten 2 Aufrufe überhaupt geklappt hat?! 😮

    Weil in den ersten 2 Aufrufen keine Speicherschutzverletzung eingetreten ist.



  • nwp2 schrieb:

    Speicher wird Seitenweise reserviert, eine Seite hat meist 4kb.

    Aber doch nicht mit malloc 😕

    char* a, *b;
    	a = malloc (1);
    	b = malloc (1);
    	printf("%d\n", b-a); // Differenz == 4kb?  :confused: 
    	return 0;
    


  • nwp2 schrieb:

    Yup, so ist es.

    Speicher wird Seitenweise reserviert, eine Seite hat meist 4kb. Das heißt du kannst mit Glück bis zu 4095 Bytes hinter dem Speicherbereich schreiben. Wenn die nächste Seite auch reserviert ist auch noch weiter. Oder du kriegst schon beim ersten nicht reservierten Byte einen Segmentation Fault wenn dieses Byte zufällig auf einer neuen nicht reservierten Seite liegt.

    Achso ist das, sprich das war nur Glück ^^

    Jedenfalls vielen Dank an alle die mir geholfen haben, echt super!

    Eine allerletzte Frage hätte ich noch (sry intressiert mich nur sehr) also malloc() zählt ja zur dynamischen Speicherverwaltung richtig? sprich der Speicher wird im heap reserviert. Muss ich in diesem Fall, nicht den Speicher auch manuell wieder freigeben? (sonst bleibt der Speicher ja blockiert oder? -> weiß nur dass es in c++ so mit new und delete ist).

    Tut mir leid falls ich schon nerve ^^



  • KnufflPuffl schrieb:

    nwp2 schrieb:

    Yup, so ist es.

    Speicher wird Seitenweise reserviert, eine Seite hat meist 4kb. Das heißt du kannst mit Glück bis zu 4095 Bytes hinter dem Speicherbereich schreiben. Wenn die nächste Seite auch reserviert ist auch noch weiter. Oder du kriegst schon beim ersten nicht reservierten Byte einen Segmentation Fault wenn dieses Byte zufällig auf einer neuen nicht reservierten Seite liegt.

    Achso ist das, sprich das war nur Glück ^^

    Jedenfalls vielen Dank an alle die mir geholfen haben, echt super!

    Eine allerletzte Frage hätte ich noch (sry intressiert mich nur sehr) also malloc() zählt ja zur dynamischen Speicherverwaltung richtig? sprich der Speicher wird im heap reserviert. Muss ich in diesem Fall, nicht den Speicher auch manuell wieder freigeben? (sonst bleibt der Speicher ja blockiert oder? -> weiß nur dass es in c++ so mit new und delete ist).

    Tut mir leid falls ich schon nerve ^^

    Ok hat sich schon erledigt, hab grad gegoogelt wegen dynamischer speicherverwaltung.. geht ja mit free(..)..

    Dann bleibt mir nur noch übrig euch allen ganz herzlich zu danken! 👍



  • KnufflPuffl schrieb:

    Eine allerletzte Frage hätte ich noch (sry intressiert mich nur sehr) also malloc() zählt ja zur dynamischen Speicherverwaltung richtig? sprich der Speicher wird im heap reserviert. Muss ich in diesem Fall, nicht den Speicher auch manuell wieder freigeben? (sonst bleibt der Speicher ja blockiert oder? -> weiß nur dass es in c++ so mit new und delete ist).

    Genau so ist es. Für jedes malloc muss ein free aufgerufen werden:

    for(i=0; i < n; i++) {
        free(pStringField[i]); // Zeilen löschen
    }
    free (pStringField); // Zeiger auf Zeilen löschen.
    


  • jap habe ich jetzt genauso implementiert.

    Nochmals danke!

    Btw: muss ich den Thread hier irwie als beantwortet markieren oder so?



  • KnufflPuffl schrieb:

    Btw: muss ich den Thread hier irwie als beantwortet markieren oder so?

    Nööö.
    🙂


Anmelden zum Antworten