Scanf mit character pointer
-
Hi Leute,
Ich hätte mal ne Frage bezüglich der Funktion scanf mit Pointern.
Und zwar, kann man ja ein Array deklarieren und mit scanf einen String in dieses deklarierte Array reinkopieren, indem man bei scanf für %s einfach die Array Variable angibt.
Nun sind ja Arrays fast das gleiche wie Pointer. Man kann ja durch Pointer Schreibweise genauso auf die Array Elemente zugreifen, wie mit Array Schreibweise.Nun wollte ich aber kein Array deklarieren, sondern einen char pointer und mit scanf einen String an diesen Pointer übergeben. Dies klappt nur leider gar nicht, es führt immer zum Programmabsturz.
Merkwürdigerweise funktioniert das ganze aber, wenn ich bei scanf und anschließend bei printf die pointervariable noch mit dem & Adressoperator bestücke.
Das ergibt für mich nicht wirklich Sinn, weil ich dachte, dass man bei der scanf und printf Funktion dem %s nur die Adresse des String/Array Anfangs übergeben soll, und der Pointer hat doch die Adresse in sich gespeichert.Könnt ihr mir da vielleicht einen Rat geben, wie das ganze mit scanf und printf bei pointern funktioniert? Wenn ich ein Array am Anfang habe und danach mit Pointer Schreibweise weiterarbeite ist mir alles klar denke ich, aber wenn ich es von vornherein mit Pointern mache verstehe ich das nicht wirklich =/.
Hier noch der Code mit dem ich rumprobiert habe.
Da sieht man auch, dass der am Anfang zugewiesene String mit printf ausgegeben werden kann, ohne & zu benutzen, aber danach ab scanf muss ich immer & benutzen.#include<stdlib.h> #include <stdio.h> int main(void){ char *a = "Hello!"; printf("%s",a); scanf("%s",&a); printf("%s",&a); system("pause"); return 0; }
-
Du hast hier ein Stringliteral definiert. Da sollst du nicht reinschreiben. Probier es doch lieber mal so:
char a[] = "Hello!"; printf("%s",a); scanf("%s",a); printf("%s",a);
Was passiert eigentlich, wenn du bei der scanf-Eingabe mehr als 6 Zeichen eingibst?
Du hast übrigens in die Zeigervariable selbst geschrieben, da du ihre Adresse (nicht die Adresse des char-Arrays) übergeben hast. Damit hast du den Zeiger ungültig gemacht.
-
Das
char *a = "Hello!";
ist kein Array sondern ein Zeiger auf ein Stringliteral. Da diese irgendwo im Speicher stehen können, sind sie meist nicht beschreibbar.Das mit dem & ist großer Mist. Das fuunktioniert nur scheinbar. Damit übergibst du die Adresse des Pointers und ab dort wird dann der Text geschrieben.
#include<stdlib.h> #include <stdio.h> int main(void){ int vor = 0; char *a = "Hello!"; int nach = 0; printf("%s",a); scanf("%s",&a); printf("%d|%s|%d",vor ,&a, nach); // hier sollt zweimal 0 ausgegeben werden. system("pause"); return 0; }
Nimm ein Array und es funktioniert:
char a[] = "Hello!";
Das Array hat nur Platz für 6 Zeichen. Du darfst da nicht mehr eingeben. Darum ist es besser, du sorgst für mehr Platz.
char a[200] = "Hello!";
-
Der Code von mir ist keine Lösung, sondern soll das Problem verdeutlichen.
-
Vielen Dank für eure schnellen Antworten.
Ich dachte auch immer, dass ich doch die Adresse, des zu betrachtenden/auf was der Pointer zeigt, übergeben muss. Nur das hatte mich sehr verwirrt, weil ich immer dachte wenn ich das ganze am Anfang mit Pointern mache sollte es doch genauso wie mit Arrays funktioniere, da diese fast identisch seien, so sagte man mir.Aber, nur um scanf und printf genauer zu verstehen, heißt das, dass scanf einen String erstellt im Speicher irgendwo ablegt?
Wenn ja, dann übergibt scanf doch anschließend die Adresse dieses erstellten Strings an den Pointer oder nicht? Oder funktioniert dieser Abschnitt anders?Ich hab nochmal alle möglichen Varianten mit Array ausprobiert und das ganze noch kurz kommentiert.
Den 1. Abschnitt verstehe ich eigentlich, aber das mit dem Pointer ist mir leider noch incht ganz klar.Sry für den langen Post...aber ich stehe da irgendwie bisschen auf dem Schlauch^^.
Vielen Dank für eure Geduld.
#include<stdlib.h> #include <stdio.h> int main(void){ char b[10] = "Array"; printf("%s\n",b); printf("%s\n",(b+3)); printf("%c\n",b[2]); printf("%c\n",*(b+3)); scanf("%s",b); printf("%s\n",b); scanf("%s",(b+3)); printf("%s\n",(b+4)); scanf("%s",&b[2]); printf("%s\n",b); /*den oberen Abschnitt verstehe ich denke ich. Scanf übergibt doch die Adresse des erstellten Strings an die Variable die hinter dem Komma steht. Also muss das b ein Pointer sein, der dann diese Adresse bekommt oder?*/ char *a = "Hello!"; printf("%s",a); scanf("%s",&a); printf("%s",&a); system("pause"); return 0; }
-
scanf braucht auch die Adresse der Speichervariable. Allerdings muss diese genügend (beschreibbaren) Platz für die Eingabe bieten.
Wenn es Dich verwirrt, bei Arrays als Zielvariable keinen Adressoperator angeben zu müssen, kannst Du natürlich auch &array[0] verwenden und damit ebenso wie durch array die Startadresse ansprechen.char cArray[11]; char cFeld[11] = "0123456789"; char *cPointer; char *cLiteral = "9876543210"; // Jetzt hast Du 2 gleichartige Arrays von Chars, // in deren Feldern 0-9 jeweils ein char drinsteht. // Bei cArray steht das drin, was zufällig an der // Speicherstelle liegt, wenn das Programm grade läuft. // Bei cFeld steht "0123456789" drin. // Du kannst nun sowohl cArray, als auch cFeld verwenden, // um mit scanf() dort etwas abzulegen. // Allerdings solltest Du das Formatkennzeichen in der // Länge begrenzen (Arraygröße). scanf ("%10s", cArray); // Hier steht cArray für die Startadresse des Arrays cArray[] und braucht deshalb keinen Adressoperator. // Wenn Du in cPointer etwas abspeichern willst, musst Du erst festlegen, wieviel reinpassen soll und den entsprechenden Speicherplatz reservieren - später natürlich wieder freigeben. // Dafür gibt's malloc() und free(). // Auf Stringliterale solltest Du tunlichst nicht schreiben, darfst Du eigentlich auch nicht. Und wenn Du keinen Speicher allokiert hast für cPointer, wirds da auch beim scanf knallen.
-
RiceBall schrieb:
Aber, nur um scanf und printf genauer zu verstehen, heißt das, dass scanf einen String erstellt im Speicher irgendwo ablegt?
Wenn ja, dann übergibt scanf doch anschließend die Adresse dieses erstellten Strings an den Pointer oder nicht? Oder funktioniert dieser Abschnitt anders?Nein, scanf schreibt den String einfach nur in den Speicher auf den der übergebene Pointer zeigt. Wie strcpy etc. das auch machen.
-
ah ok. Ich denke ich hab es jetzt kappiert.
Vielen vielen Dank für eure schnellen Antworten^^. Hat mir super geholfen.mfG
RiceBall
-
Warum setzt du das nicht um was Matze dir zeigte
@ Dirk
Hier noch mal etwas für die, die ans Limit gehen:
http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by-theDer gcc soll das korrekt umsetzen. Ist C99. Wie weit das die Compiler der Konkurrenten umsetzen
MfG f.-th.
-
Was soll dieser Link zum Thema?
Eine Adresse auf einen Zeiger auf Daten und was anderes als ein Zeiger auf Daten, da hat DirkB völlig recht.
Da braucht man auch nicht ans "Limit" gehen und rumraten, was Compiler dabei wohl machen, sondern bloß in den Standard schauen zum Thema Adressoperator.