vorbesetztes string Array vs Pointerarray auf Strings - Speicherverbrauch



  • Hallo,

    bin etwas durcheinander bei meinen Übungsaufgaben.

    Ich habe ein

    struct kontodaten { /* DATENSTRUCKTUR FUER EIN KONTO */
           char *name;  
           int kNr;
    };
    
    struct kontodaten konto[ANZAHL];
    

    In der ersten Aufgabe heißt es:
    *
    Der Name des Konto-Inhabers soll mit Hilfe eines vor zu besetzenden Arrays hinzugefügt werden*(Plural)

    Das heißt, beim Start des Programs soll dem ersten Konto der erste Name aus dem namen-Array zugewiesen werden, dem zweiten der zweite usw., weitere Daten werden per scanf() eingelesen.

    **(1)**Ein hieraus resultierendes Problem ist doch, dass im namen-Array für jeden String eine konstante Anzahl Speicher gebraucht, wenn auch nicht genutzt wird. so zB

    char namen[5][50] {..};
    Außerdem kann kein Name länger als 50 Zeichen sein.

    **(1.1)**Ist das überhaupt sozusagen ein String-Array?

    In der folgenden Aufgabe sollen wir die Sache dann umschreiben:
    Statt eines Arrays vorbesetzter Stings, ist ein Array von Zeigern zu bilden, die auf Zeichenfolgen verschiedener Länge zeigen. Für jede Zeichenfolge ist genau der für sie erforderliche Platz zu schaffen.

    Mein Array sähe dann so aus

    static char *namen[] = { "Peter ", "Lisa ", "Klaus ", "Karlheinz ", "Ulrike ", };

    Zuweisen würde ich per

    while(i<ANZAHL){
         neuesKonto(i, namen); 
         i++;
    }
    
    void neuesKonto(int i, char *names[]){
         konto[i].name = names[i];                    
         printf("Kontoinhaber: %s\n", names[i]);      
         konto[i].kNr = i;
    }
    

    **(2)**Ist das richtig 😕
    Also im Prinzip will ich ja jedem konto einen pointer auf den Namen zuweisen.. wird das gemacht? Ist der Speicherplatz somit besser genutzt?

    **(3)**Oder muss ich noch mit malloc() Speicherplatz reservieren?!

    Ich blicke langsam nicht mehr durch, Pointer mit Pointern, arrays mit arrays und pointer auf pointer, **char oder *char[],.... 🙄

    Grüße



  • Dein struct beinhaltet ein char *, damit du also dort einen Wert speichern kannst, musst du zwangsläufig Speicher mit malloc reservieren.

    Du hast ja in einem seperatem Array bereits die Namen für die Konten gespeichert. Du müsstest also die Länge des Namen mit strlen ermitteln und die Länge + 1 (+ 1 wegen Terminierungszeichen) mit malloc reservieren.



  • zu 1: Ja.

    zu 1.1: Der Datentyp ist char.



  • Ich hab mal was probiert. Ich kann mir aber kaum vorstellen, dass das so verlangt wird. Für einen Anfänger ist sowas doch nicht zu bewältigen?

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define ANZAHL 10 // Max
    
    struct kontodaten {
           char *name;  
           int kNr;
    };
    
    struct kontodaten konto[ANZAHL]; 
    
    static char *namen[] = { "Peter ", "Lisa ", "Klaus ", "Karlheinz ", "Ulrike ", }; 
    
    int main(void)
    {
    	int i;
    
    	int nNamen = sizeof(namen) / sizeof(namen[0]);
    
    	printf("--- In ---\n\n");
    
    	for (i = 0; i < ANZAHL; ++i)
    	{
    		konto[i].kNr = i;
    
    		if (i < nNamen && konto[i].name)
    		{
    			konto[i].name = malloc(strlen(namen[i]) + 1);
    
    			strcpy(konto[i].name, namen[i]);
    		}
    		else
    		{
    			char buf[25];
    
    			printf("Name: ");
    
    			fgets(buf, 25, stdin);
    
    			buf[strlen(buf) - 1] = '\0';
    
    			konto[i].name = malloc(strlen(buf) + 1);
    
    			strcpy(konto[i].name, buf);
    		}
    
    		konto[i].kNr = i;
    	}
    
    	printf("\n--- Out ---\n\n");
    
    	for (i = 0; i < ANZAHL; ++i)
    	{
    		printf("Nr: %i\nName: %s\n\n", konto[i].kNr, konto[i].name);
    	}
    
    	for (i = 0; i < ANZAHL; ++i)
    	{
    		free(konto[i].name);
    	}
    
    	return 0;
    }
    


  • char namen[5][50] {..};
    Außerdem kann kein Name länger als 50 Zeichen sein.

    49

    static char *namen[] = { "Peter ", "Lisa ", "Klaus ", "Karlheinz ", "Ulrike "};
    

    Hier ist alles schon speichergrößenoptimal.

    **(3)**Oder muss ich noch mit malloc() Speicherplatz reservieren?!

    Wenn du hier nur Werte aus dem vordefinierten, programmglobalen char*[] zuweist, nein, denn der Speicher für die Einzelstrings wurde für dich vom Compiler schon allokiert s.o.

    Ich blicke langsam nicht mehr durch, Pointer mit Pointern, arrays mit arrays und pointer auf pointer, **char oder *char[],....

    Das ist verständlich und geht jedem C-Neuling so.

    Mal ein Vorschlag:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define ANZAHL 10
    
    typedef struct {char *name;int kNr;} kontodaten;
    
    void neuesKonto(kontodaten *konto,int i,char *name){
         konto->name = name;                    
         printf("Kontoinhaber: %s\n", name);      
         konto->kNr = i+1;
    } 
    
    char*mystrdup(const char*s)
    {
    	char *d=malloc(strlen(s)+1);
    	return strcpy(d,s);
    }
    
    int main()
    {
      kontodaten konto[ANZAHL];
      char *namen[] = { "Peter ", "Lisa ", "Klaus ", "Karlheinz ", "Ulrike " };
    	int i,nNamen = sizeof namen/sizeof *namen;
    	char sd[100];
    
    	for(i=0;i<nNamen;++i)
    		neuesKonto(&konto[i],i,namen[i]);
    	for(i=nNamen;i<ANZAHL;++i)
    		neuesKonto(&konto[i],i,(scanf("%99s",sd),mystrdup(sd)));
    
    	for(i=0;i<ANZAHL;++i)
    		printf("%d. %s\n",konto[i].kNr,konto[i].name);
    	for(i=nNamen;i<ANZAHL;++i)
    		free(konto[i].name);
    
    	/* nochmal das Ganze mit (variablen) Strings und eigenem Speicherplatz, welcher anschließend auch zusätzlich wieder freigegeben werden muss */
    	namen[0]=mystrdup("Peter");
    	namen[1]=mystrdup("Lisa");
    	namen[2]=mystrdup("Klaus");
    	namen[3]=mystrdup("Karlheinz");
    	namen[4]=mystrdup("Ulrike");
    	for(i=0;i<nNamen;++i)
    		neuesKonto(&konto[i],i,namen[i]);
    	for(i=nNamen;i<ANZAHL;++i)
    		neuesKonto(&konto[i],i,(scanf("%99s",sd),mystrdup(sd)));
    
    	for(i=0;i<ANZAHL;++i)
    		printf("%d. %s\n",konto[i].kNr,konto[i].name);
    	for(i=0/*!!!*/;i<ANZAHL;++i)
    		free(konto[i].name);
    
    }
    


  • Danke für die Mühe die ihr euch gemacht habt, vor allem Wutz und ..........
    Fragen wurden soweit beantwortet, die Beispiele werd ich mir nochmal genauer angucken aber ich denke das geht genau in die richtige Richtung.

    @.........
    Vorweg sind blöderweise die Frage- und Aufgabenstellungen von meinem Prof für einen Anfänger nicht zu bewältigen, zumindest teilweise. Sogar unser Tutor hat da Verständnisprobleme.

    Danke und Grüße!!


Anmelden zum Antworten