Clanintern Clanintern Clanintern

Forum

Öffentliche Foren
FORUM: Spiele & Computer THEMA: Dynamische Allokation in C
AUTOR BEITRAG
Earth

RANG Deckschrubber

#1 - 24.01 21:37

Hi Leute,

ich kenn mich mit pointer und malloc in C leider noch zu wenig aus! Kann mir jemand sagen wie ich folgendes Programm dynamisch mache. Also sozusagen die char Variablen und die struct dynamisch mache:

code:
#include <stdio.h>

struct daten{

char vorname[100];
char nachname[100];
int alter;

};

void main(void){

int i;
struct daten leute[100];

//Eingabe der Personendaten

for(i=1;i<=5;i++){

printf("Vorname der %d. Person eingeben:",i);
scanf("%s",leute[i-1].vorname);
printf("Nachname der %d. Person eingeben:",i);
scanf("%s",leute[i-1].nachname);
printf("Alter der %d. Person eingeben:",i);
scanf("%d",&leute[i-1].alter);

}

//Ausgabe der Personendaten

printf("\n\n");

for(i=0;i<5;i++)
printf("%d. Vorname: %s;  Nachname: %s;  Alter: %d\n",i+1,leute[i].vorname,leute[i].nachname,leute[i].alter)
}


Wenn jemand den Lösungsvorschlag noch etwas beschreiben könnte wär ich sehr dankbar
Crush (korrumpiert die Jugend)

RANG Master of Clanintern

#2 - 24.01 23:31

Eine komplette Lösung bekommst du von mir nicht, denn schlieslich sind das deine Hausaufgaben und nicht meine. Aber ich kann dir gerne erklären wie das mit dynamisch alloziierten Arrays funktioniert.


Um ein Array mit variabler Größe zu machen (char strings sind ebenfalls arrays) deklarierst du erstmal einen normalen Pointer.
code:
int* variableIntegerArray;


Diesen Pointer lässt du dann auf einen durch malloc alloziierten Speicherbereich zeigen.
code:
variableIntegerArray = malloc (sizeof(int) * 100);

Dies heist "Finde und reserviere einen Speicherbereich, der groß genug ist um 100 Integer aufzunehmen und speicher in "variableIntegerArray" wo dieser zu finden ist.

Um dann auf diesen Speicherbereich zuzugreifen, kannst du dann einfach den Pointer wie ein Array verwenden.
code:
variableIntegerArray[42] = 1337;


Vergiss nicht am Ende der Funktion den Speicherbereich wieder freizugeben:
code:
free(variableIntegerArray);
Ansonsten baust du Speicherlecks, denn im Gegensatz zu normalen lokalen Variablen wird der von dynamischen Arrays alloziierte Speicher nicht wieder freigegeben, wenn die Funktion beendet wird.


Wenn dir irgendetwas unklar ist, du Fragen hast oder auf Bugs triffst die du alleine nicht beheben kannst, dann sag ruhig bescheid.
Earth

RANG Deckschrubber

#3 - 25.01 09:06

Brauch ich nicht um auf den Speicher zuzugreifen diesen * Inhaltsoperator. Müsste es nicht
code:
*(variableIntegerArray)[42] = 1337;




Wenn ich beispielsweiße den Speicherplatz für einen 1-Dimensionalses char Feld(Strings) allokiere müsste dann der Code folgendermaßen aussehn?

code:
variablecharArray = malloc (sizeof(char) * strlen(eingabestring))
;

Wobei der eingabestring vorher mit
code:
gets(eingabestring);
eingelesen wurde. Aber wie muss ich dann die Varialbe Eingabestring deklariern. Als Pointer??? nee das kann irgendwie nicht sein...
Crush (korrumpiert die Jugend)

RANG Master of Clanintern

#4 - 25.01 21:30

Den *operator brauchst du bei Arrays nicht, weil Arrays im Prinzip Pointer sind und die [] den *operator ersetzen.

array[0] == *array
array[n] == *(array + n)
array[n] == n[array]

Arrays sind Pointer und genauso lassen sich Pointer als Arrays verwenden. Im Prinzip sind sie exakt dasselbe. Aber vergiss diese Denkweise besser, da sie in der Praxis 1. gefährlich und 2. relativ unnütz ist.


Du brauchst aber den *operator, wenn du einzelne Variablen dynamisch alloziierst.
code:
int* dynamicInt;
dynamicInt = malloc(sizeof(int));
*dynamicInt = 42;
Wobei du aber in diesem Beispiel wie oben beschrieben anstelle der letzten Zeile auch
code:
dynamicInt[0] = 42;
machen könntest (beachte dass die eckigen Klammern hier den * ersetzen). Aber das sind die unnützen Spielereien wodurch die C Sprachfamilie ihren schlechten Ruf bekommen hat.


Was deine Frage bezüglich gets() angeht: gets() kannst du sowohl ein char array als auch einen char* welcher auf einen vorher mit malloc() alloziierten Speicherbereich zeigt als Eingabebuffer übergeben - ist deine Entscheidung. Wie gesagt - Pointer und Arrays sind gegeneinander austauschbar.

In beiden Fällen musst du die Größe des Eingabebuffers aber vorher festlegen. Entweder durch die Dimension des Arrays oder durch die angegebene Größe bei malloc(). Gibt der User mehr ein als dein Eingabebuffer groß ist, kommt es zu einem Buffer Overflow, welcher normalerweise einen Absturz verursacht aber auch erlaubt beliebigen Code ins Programm einzuschleusen. Darum sollte man auch gets() nicht verwenden und statdessen besser fgets() benutzen, welches die maximale Anzahl Zeichen die der User eingeben darf festlegt.


Übrigens will dein Professor bestimmt nicht, dass du JEDE EINZELNE Variable in deinem Programm dynamisch alloziierst, sondern nur die bei denen es zweckmäßig ist. Dies sind hauptsächlich die beiden Zeichenketten in der struct daten und natürlich das Array aus struct daten selber. Das bedeutet als Eingabebuffer einen String verwenden der länger ist als alles was ein User eingeben könnte und wenn du diesen dann mit strcpy in die Struct kopierst das Feld in der Struct nur so groß alloziieren wie es nötig ist um die tatsächliche Eingabe zu halten.