String-Array: Wie geht's richtig?
-
Hi,
Ich möchte ein Array aus Strings deklarieren, bei dem sowohl die Anzahl der Strings, als auch die Länge der Strings selber dynamisch sein sollen. Gedacht hab ich mir, ich müsse ein Array aus char-pointern machen, die ich dann nach belieben wie ein normales char* füllen kann:char **oldlist; int list_length = 5; oldlist = malloc(list_length*sizeof(char*)); for(i=0;i<list_length;i++) oldlist[i] = funktionDieEinenStringAnhandDesParametersZurückGibt(i);
Pustekuchen. Jedes Element in oldlist hat am Ende selben Wert, und zwar den der letzten Zuweisung.
Nun die Frage: Woran liegt's und wie macht man's richtig?
Luke
-
Gegenfrage: Was gibt die Funktion denn zurück?
Wenn es sich um einen Zeiger auf ein statisches Array (oder bei den meisten Architekturen sogar bei Stack-Arrays) handelt war das Ergebnis vorauszusehen.Lösung: Den Speicherbereich für die eigentlichen Strings (für jeden!) auch mit malloc beschaffen.
-
LordJaxom schrieb:
Gegenfrage: Was gibt die Funktion denn zurück?
Wenn es sich um einen Zeiger auf ein statisches Array (oder bei den meisten Architekturen sogar bei Stack-Arrays) handelt war das Ergebnis vorauszusehen.ist der Fall, die funktion gibt einen char* zurück.
LordJaxom schrieb:
Lösung: Den Speicherbereich für die eigentlichen Strings (für jeden!) auch mit malloc beschaffen.
Hab ich auch schon probiert:
for(i=0;i<list_length;i++) { oldlist[i] = malloc((strlen(funktion(i))+1)*sizeof(char)); oldlist[i] = funktion(i); }
und
for(i=0;i<list_length;i++) { oldlist[i] = (char*)malloc((strlen(funktion(i))+1)*sizeof(char)); oldlist[i] = funktion(i); }
bringt beides das selbe Ergebnis.
-
Luke-2 schrieb:
LordJaxom schrieb:
Gegenfrage: Was gibt die Funktion denn zurück?
Wenn es sich um einen Zeiger auf ein statisches Array (oder bei den meisten Architekturen sogar bei Stack-Arrays) handelt war das Ergebnis vorauszusehen.ist der Fall, die funktion gibt einen char* zurück.
Die Aussage hat den Informationswert von 0. Viel interessanter ist die Frage, woher die Adresse kommt, die return geliefert hat.
LordJaxom schrieb:
Lösung: Den Speicherbereich für die eigentlichen Strings (für jeden!) auch mit malloc beschaffen.
Hab ich auch schon probiert:
for(i=0;i<list_length;i++) { oldlist[i] = malloc((strlen(funktion(i))+1)*sizeof(char)); oldlist[i] = funktion(i); }
und
for(i=0;i<list_length;i++) { oldlist[i] = (char*)malloc((strlen(funktion(i))+1)*sizeof(char)); oldlist[i] = funktion(i); }
bringt beides das selbe Ergebnis.
Das ist nicht verwunderlich. Wenn, dann sollte function() den nötigen Speicher anfordern (oder du übergibst ihr einen char*, in den sie reinschreiben darf).
-
CStoll schrieb:
Die Aussage hat den Informationswert von 0. Viel interessanter ist die Frage, woher die Adresse kommt, die return geliefert hat.
Hm, versteh ich nicht ganz. Sorry. Ich ruf ne Funktion aus der Winamp-API auf die da deklariert ist as
char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE);
Kann daher der Funktion auch keinen char* zum reinschreibnen übergeben...
-
Ok, auch ich versteh mittlerweile das Problem, und ich will jetzt nicht uneigenständig erscheinen, aber weiß das jemand ne Lösung für? Die Funktion die ich benutze gibt mir den Pfad einer Datei in der Playlist an position index zurück, andere wirkliche Playlist-Funktionen (außer um die Länge der Liste zu kriegen) gibt es nicht. Ich will halt die komplette Playlist in ein Array bekommen. Hat jemand ne Idee wie man das noch machen könnte?
-
Ok, so geht's:
int i, list_length; char *tmp; list_length = 5; oldlist = malloc(list_length*sizeof(char*)); for(i=0;i<list_length;i++) { tmp = SendMessage(plugin.hwndParent,WM_WA_IPC,i,IPC_GETPLAYLISTFILE); oldlist[i] = (char*)malloc((strlen(tmp2)+1)*sizeof(char)); strcpy(oldlist[i], tmp); }
-
sizeof(char) ist immer 1 und malloc() sollte nicht gecastet werden.
-
TactX schrieb:
malloc() sollte nicht gecastet werden.
Warum? Das hab ich schon so oft gesehen...
Noch eine Frage: Ich will das ganze nun in eine Funktion get_playlist packen, als Parameter ein Pointer zu einer Variable in die die Liste geschrieben werden soll. Hoffte es sei ganz einfach
char **oldlist; void get_playlist(char **playlist) { int i, list_length; char *tmp; list_length = SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GETLISTLENGTH); playlist = malloc(list_length*sizeof(char*)); for(i=0;i<list_length;i++) { tmp = SendMessage(plugin.hwndParent,WM_WA_IPC,i,IPC_GETPLAYLISTFILE); playlist[i] = (char*)malloc((strlen(tmp)+1)*sizeof(char)); strcpy(playlist[i], tmp); } } [..] get_playlist(oldlist);
Aber wenn ich die Playlist dann verwenden will kackt das Programm ab. Nun die Standardfrage: Woran liegt's? Wie macht man's richtig?
-
Luke-2 schrieb:
TactX schrieb:
malloc() sollte nicht gecastet werden.
Warum? Das hab ich schon so oft gesehen...
Ich habe es schon zuoft gesehen. Gegenfrage (weil ich gerade keinen Bock habe diese Frage zum hundertsten mal zu beantworten und ich mich ankotze, dass ich das noch nicht in der FAQ drin hab): Warum castet du denn?
Luke-2 schrieb:
Noch eine Frage: Ich will das ganze nun in eine Funktion get_playlist packen, als Parameter ein Pointer zu einer Variable in die die Liste geschrieben werden soll. Hoffte es sei ganz einfach
char **oldlist; void get_playlist(char **playlist) { int i, list_length; char *tmp; list_length = SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GETLISTLENGTH); playlist = malloc(list_length*sizeof(char*)); for(i=0;i<list_length;i++) { tmp = SendMessage(plugin.hwndParent,WM_WA_IPC,i,IPC_GETPLAYLISTFILE); playlist = (char*)malloc((strlen(tmp)+1)*sizeof(char)); strcpy(playlist[i], tmp); } } [..] get_playlist(oldlist);
Aber wenn ich die Playlist dann verwenden will kackt das Programm ab. Nun die Standardfrage: Woran liegt's? Wie macht man's richtig?*
Es liegt daran, wie in C Parameter übergeben werden. Die Zuweisung [i]playlist = malloc(list_length*sizeof(char*));* gilt nur innerhalt der Funktion, da playlist nur eine Kopie des übergebenen Parameters oldlist ist. Richtig macht mans, indem man einfach einen entsprechenden Zeiger zurückgibt, anhand dessen du deine Playlist zusammengebaut hast.
char **get_playlist(void){ char **playlist; // Speicher für playlist reservieren etc. return playlist;
-
TactX schrieb:
Warum castet du denn?
Um ganz ehrlich zu sein, nur aus dem Grund dass ich es oft so gesehen und als 'ok, verstehe nicht ganz warum, werde aber eines Tages dahinter kommen' abgestemptelt hab ^^
TactX schrieb:
Es liegt daran, wie in C Parameter übergeben werden. Die Zuweisung playlist = malloc(list_length*sizeof(char*)); gilt nur innerhalt der Funktion, da playlist nur eine Kopie des übergebenen Parameters oldlist ist. Richtig macht mans, indem man einfach einen entsprechenden Zeiger zurückgibt, anhand dessen du deine Playlist zusammengebaut hast.
char **get_playlist(void){ char **playlist; // Speicher für playlist reservieren etc. return playlist;
Achso, dachte ich übergeb nur nen Pointer und kann dementsprechen an der 'original' Variable rumbasteln. Nun ja, so geht es. Danke
-
Luke-2 schrieb:
Achso, dachte ich übergeb nur nen Pointer und kann dementsprechen an der 'original' Variable rumbasteln. Nun ja, so geht es. Danke
Wenn du einen Pointer übergibst, dann kannst du das manipulieren worauf der Pointer zeigt. Den Wert des Pointers selbst (also die Adresse worauf er zeigt) aber nicht.
-
Wollt ja auch den Inhalt bearbeiten...
-
Und den Wert des übergebenen Pointers.
void get_playlist(char **playlist) { // ... playlist = malloc(list_length*sizeof(char*)); // eben hier // ... }