im buch 'C von A bis Z' steht folgendes geschrieben:
---------------------------------------------
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<string.h>
4
#define MAX 255
5
char*eingabe(char*str){
6
charinput[MAX];
7
printf("Bitte \"%s\" eingeben: ",str);
8
fgets(input,MAX,stdin);
9
returnstrtok(input,"\n");
10
}
11
intmain(void){
12
char*ptr;
13
ptr=eingabe("Vorname");
14
printf("Hallo %s\n",ptr);
15
ptr=eingabe("Nachname");
16
printf("%s, interssanter Nachname\n",ptr);
17
returnEXIT_SUCCESS;
18
}
Der Funktion eingabe() wird hierbei als Argument die Adresse eines
Strings übergeben. In der Funktion werden Sie aufgefordert, einen Namen
einzugeben. Die Anfangsadresse des Strings geben Sie mit folgender Zeile
zurück:
1
returnstrtok(input,"\n");
Die Funktion strtok() liefert ja selbst als Rückgabewert einen
char-Zeiger zurück. Da die Funktion fgets() beim Einlesen von der
Standardeingabe das Newline-Zeichen mit einliest, haben Sie hierbei
gleich zwei Fliegen mit einer Klappe geschlagen. Das Newline-Zeichen
wird mit strtok() entfernt, und die Funktion liefert auch gleich die
Anfangsadresse des Strings input als Rückgabewert zurück, welchen Sie
gleich mit return weiterverwenden. Doch Vorsicht, Folgendes funktioniert
nicht:
1
char*eingabe(char*str){
2
charinput[MAX];
3
printf("Bitte \"%s\" eingeben: ",str);
4
fgets(input,MAX,stdin);
5
returninput;
6
}
Normalerweise sollte hier der Compiler schon meckern, dass etwas nicht
stimmt. Spätestens aber, wenn Sie das Beispiel ausführen, werden Sie
feststellen, dass anstatt des Strings, den Sie in der Funktion eingabe()
eingegeben haben, nur Datenmüll ausgegeben wird.
---------------------------------------------
die strtok funktion liefert ja auch nur einen pointer auf den
übergebenen string , dh. der test mittels return strtok(input, "\n");
sollte auch nur datenmüll liefern ?
>> Normalerweise sollte hier der Compiler schon meckern, dass etwas nicht> stimmt. Spätestens aber, wenn Sie das Beispiel ausführen, werden Sie> feststellen, dass anstatt des Strings, den Sie in der Funktion eingabe()> eingegeben haben, nur Datenmüll ausgegeben wird.
Das Problem an dieser Stelle ist, dass hier ein Pointer auf eine lokale
Variable (nämlich input) zurückgegeben wird. Lokale Variablen werden
aber beim Verlassen einer Funktion zerstört. Damit liefert die Funktion
einen Pointer auf eine Variable die nicht mehr existiert.
> die strtok funktion liefert ja auch nur einen pointer auf den> übergebenen string , dh. der test mittels return strtok(input, "\n");> sollte auch nur datenmüll liefern ?
Genau. Der retournierte Pointer ist im Prinzip immer noch ein Pointer
auf input. strtok ändert daran nichts. Wenn die angegebene Lösung als
Musterlösung präsentiert wird, dann ist diese Musterlösung fehlerhaft.
ok danke - ja im buch wird dies tatsächlich als lösung vorgeschlagen,
und da ja strtok zb keinen neuen speicher vom heap anfordert (als return
value ), kann dies nicht gehen ...
Die übliche Quick-n-Dirty Lösung wäre, einfach das input-array als
static zu deklarieren, dann bleibt der Pointer gültig.
Ist aber keine schöne Lösung, spätestens wenn jemand das ganze mit
Threads verwenden will fliegt er auf die Schnauze…
Ja ja, Zeichenketten in C, immer wieder leidiges Thema.
Am besten, man verabschiedet sich von dem Dogma, dass das Ergebnis als
Returnwert zurückgegeben werden muss, und baut etwas in dieser Art:
Das Ergebnis wird über einen Aufrufparameter herausgereicht, den
Speicher dafür stellt der Aufrufer zur Verfügung und weiß daher auch,
ob der Speicher ggfs. wieder weggeräumt werden muss.
Das Beispiel ist natürlich nur als Demonstration gedacht. Es prüft nicht
auf Buffer Overrun (muss unbedingt gemacht werden!).
Außerdem ists vom Design her etwas merkwürdig, dass eine Routine, die
"eingabe" heißt, als allererstes eine Ausgabe macht. Aber ich wollte
nicht zu sehr von der Vorlage abweichen.
--------------------------------------------------
Ein anderer Ansatz wäre, eine Art "String-Objekt" zu definieren, dass
return-fähig ist und das ganze Speichermanagement intern kapselt. Aber
das geht über Anfängerstoff eindeutig hinaus.