Einlesen von Array mit scanf() und dem &-Operator



  • Hmm. Das war immer noch nicht so klar, wie ich rüberbringen wollte. Ich sag sicherheitshalber noch dazu:
    Du kannst allgemein davon ausgehen, daß der Compiler einen Ausdruck wie

    array[n]
    

    behandlet wie

    *(array + n)
    


  • µngbd , du hast hier ja ganz schön viel Versuche gestartet mir auf die Sprünge zu helfen. Da gibt's extra viel Ruhm für :).
    Ich denke, dass ich noch etwas mehr Beispiele brauche. Also lese ich das gleiche Thema nun in "C von A bis Z". Arrays sind wohl nicht so ganz intuitiv zu bedienen :). Deinen Beiträgen konnte ich größtenteils folgen. nach dem Lesen werde ich mich hier nochmal vergewissern b ich alles richtig verstanden habe.
    (Eben war Mittag - deswegen dauerte es bis meine Antwort kam. Danke für deine Bemühungen!)



  • µngbd , du hast hier ja ganz schön viel Versuche gestartet mir auf die Sprünge zu helfen. Da gibt's extra viel Ruhm für :).

    Freut mich, daß ich dir helfen konnte. Da hast du Glück, daß ich gerade am Hardware-Basteln bin, und andauernd darauf warte, daß ein Betriebssytem bootet 😞 .

    Am besten wäre es aber, wenn du es verstehst, und es dann der/dem nächsten erklärst, die/der danach fragt -- solche Fragen kommen nämlich oft. 🙂



  • (Eben war Mittag - deswegen dauerte es bis meine Antwort kam. Danke für deine Bemühungen!)

    Mach dir mal keine Sorgen, nur weil du eine Stunde lang nicht hier warst. Dieses Forum ist eine der großen Ausnahmen von der Regel, daß in Chat-Rooms schnellere Antworten kommen. Das ist aber noch kein Grund, sich zu hetzen.



  • Jetzt habe ich den Grund meiner Verwirrung gefunden. Das Missverständnis ist früh gewachsen: Kapitel 5 Formatierte Eingabe mit scanf(). Besonders interessant war Kapitel "5.1 Der Adressoperator »&«". Das letzte Beispiel verstehe ich nicht. Warum ist

    scanf("Bitte geben Sie eine Zahl ein: %d\n",&zahl);
    

    falsch?

    scanf("%d",&i);
    

    Im Quellcode oben auf der verlinkten Webseite ist doch nach dem selben Prinzip aufgebaut? Die Verwirrt meinerseits trat wohl durch die nicht konsistente Verwendung des &-Operators auf.

    Aber nun nochmal zu dem Ausgangsproblem. Array sind Pointer(-vektoren), die keine Werte aufnehmen können, sondern nur Adressen von Werten speichern? Ich vereinfache mal das den Code aus dem Startbeitrag:

    #include <stdio.h>
    
    int main (void)
    {
       int a[1];
       scanf ("%d", &a[0]);
       printf ("%d", a[0]);
       return 0;
    }
    

    a[0] wäre (das einzige) Arrayelement. Diesem kann ich nur Speicheradressen zuweisen. Deswegen muss der &-Operator vorangestellt werden. Aber hier möchte ich dem Array keine Speicheradresse einer bekannten Variablen übergeben. Der Wert wird per scanf() eingelesen. Kann jemand den Ablauf dieses Programms erklären und warum der &-Operator benötigt wird?



  • Katzenstreu schrieb:

    Jetzt habe ich den Grund meiner Verwirrung gefunden. Das Missverständnis ist früh gewachsen: Kapitel 5 Formatierte Eingabe mit scanf(). Besonders interessant war Kapitel "5.1 Der Adressoperator »&«". Das letzte Beispiel verstehe ich nicht. Warum ist

    scanf("Bitte geben Sie eine Zahl ein: %d\n",&zahl);
    

    falsch?

    scanf("%d",&i);
    

    Im Quellcode oben auf der verlinkten Webseite ist doch nach dem selben Prinzip aufgebaut? Die Verwirrt meinerseits trat wohl durch die nicht konsistente Verwendung des &-Operators auf.

    scanf liest Dinge ein und gibt sie nicht aus. Deshalb wirst du bei obigem Code keine Ausgabe sehen. Das ist einfach so und wird auch so bleiben 🙂

    Katzenstreu schrieb:

    Aber nun nochmal zu dem Ausgangsproblem. Array sind Pointer(-vektoren), die keine Werte aufnehmen können, sondern nur Adressen von Werten speichern? Ich vereinfache mal das den Code aus dem Startbeitrag:

    #include <stdio.h>
    
    int main (void)
    {
       int a[1];
       scanf ("%d", &a[0]);
       printf ("%d", a[0]);
       return 0;
    }
    

    [cpp]a[0] wäre (das einzige) Arrayelement. Diesem kann ich nur Speicheradressen zuweisen.

    Du weist einem Arrayelement einen Wert zu, keine Speicheradresse.

    Katzenstreu schrieb:

    Deswegen muss der &-Operator vorangestellt werden.

    Nur bei scanf . Beim ersten Element kannst du aber auch einfach scanf ("%d", a); schreiben. Dieser Adressoperator gilt aber nicht nur für Arrays.
    EDIT: Nicht nur bei scanf , sondern allen Funktionen die als Argument eine Referenz erwarten.

    Katzenstreu schrieb:

    Kann jemand den Ablauf dieses Programms erklären und warum der &-Operator benötigt wird?

    Du übergibst scanf die Speicheradresse - Stichwort call by reference. Somit kann scanf deine Variable verändern.



  • monstermunchkin schrieb:

    Katzenstreu schrieb:

    Jetzt habe ich den Grund meiner Verwirrung gefunden. Das Missverständnis ist früh gewachsen: Kapitel 5 Formatierte Eingabe mit scanf(). Besonders interessant war Kapitel "5.1 Der Adressoperator »&«". Das letzte Beispiel verstehe ich nicht. Warum ist

    scanf("Bitte geben Sie eine Zahl ein: %d\n",&zahl);
    

    falsch?

    scanf("%d",&i);
    

    Im Quellcode oben auf der verlinkten Webseite ist doch nach dem selben Prinzip aufgebaut? Die Verwirrt meinerseits trat wohl durch die nicht konsistente Verwendung des &-Operators auf.

    scanf liest Dinge ein und gibt sie nicht aus. Deshalb wirst du bei obigem Code keine Ausgabe sehen. Das ist einfach so und wird auch so bleiben 🙂

    Jupp, da stimme ich dir zu. Das war aber auch schwer zu sehen. Es soll eine Ganzzahl eingelesen werden, %d, aber hier macht es keinen Sinn den Operator \n, neue Zeile", einzufügen.

    monstermunchkin schrieb:

    Du übergibst scanf die Speicheradresse - Stichwort call by reference. Somit kann scanf deine Variable verändern.

    Nun habe ich es verstanden, denke ich. So herum gehts. (Ich fragte mich was eine Speicheradresse mit einem Wert soll. Aber andersherum: Ein Wert bekommt eine Speicheradresse zugewiesen und kann in diese Zelle geschrieben werden :).)

    Danke monstermunchkin! Grüße
    Tim



  • Jupp, da stimme ich dir zu. Das war aber auch schwer zu sehen. Es soll eine Ganzzahl eingelesen werden, %d, aber hier macht es keinen Sinn den Operator \n, neue Zeile", einzufügen.

    So oft als möglich den bevorzugten Slang verwenden, das schadet nie. \n ist eine Escape-Sequenz:
    http://de.wikipedia.org/wiki/Escape-Sequenz

    Es könnte übrigens durchaus Sinn machen, ein \n im scanf()-Format-String zu haben, das weist scanf() an, bis zum Zeilenumbruch zu lesen. Also z.B. um einen String bis zum Zeilenumbruch zu lesen:

    char string[SIZE];
    scanf("%s\n", string);  // oder auch &string[0]
    

    (das ist natürlich per se schon überlaufgefährdet)

    Was aber folgendes macht, ist schwieriger vorauszusagen:

    int number;
    scanf("%d\n", &number);
    

    Es kann sein, daß zwischen der Zahl und dem Umbruch noch etwas eingegeben wird. scanf() reagiert dann in irgendeiner (hoffentlich) wohldefinierten Weise, die ich nicht kenne, weil ich es nicht mag.

    Nimm dich auch in acht vor den C++-Leuten die verstehen unter einer Referenz (reference) einen magischen Namen, nicht einen Zeiger (pointer).



  • Hallo µngbd,

    nachdem du in http://www.c-plusplus.net/forum/viewtopic.php?p=1773208#1773208 auf diesen Eintrag verweist, muß ich jetzt doch mal etwas dazu schreiben.

    Der Aufruf 'scanf("%s\n", buffer)' macht nicht das, was du geschrieben hast:
    selbst hier wird nur bis zum nächsten Whitespace (Leerzeichen, Tab, NewLine) gelesen.
    Um wirklich bis zum NewLine zu lesen, mußt du folgendes benutzen:

    scanf("[^\n]", buffer); // <- lese alles bis auf ein Zeilenendezeichen
    

    Die Angabe von Zeichenliteralen innerhalb des ersten Parameters von scanf() bewirkt, daß dieser Text exakt so in der Eingabe vorkommen muß, ansonsten wird nicht weitergeparst, z.B.

    int n = scanf("Text:%s\n%d", buffer, &zahl);
    

    Anhand des Rückgabewertes kannst du überprüfen, wieviele Felder eingelesen wurden.

    Wenn nun nicht exakt "Text:" am Anfang eingegeben wird, dann wird scanf auch nicht weiter abgearbeitet. Ähnlich sieht es mit dem '\n' aus: wenn du also nun "Text:hallo world\n10" eintippst, wird nur bis 'hallo' gelesen und da danach dann kein Zeilenumbruchzeichen folgt, wird der scanf abgebrochen und nur 1 zurückgegeben (da nur in 'buffer' ein Wert eingetragen wurde, nicht aber in 'zahl').

    Ich hoffe, dir wird damit die Funktionsweise von scanf deutlicher.



  • Der Aufruf 'scanf("%s\n", buffer)' macht nicht das, was du geschrieben hast:
    selbst hier wird nur bis zum nächsten Whitespace (Leerzeichen, Tab, NewLine) gelesen.

    O je, schlecht wenn man Blödsinn redet glaubt dass es stimmt. Danke für die Korrektur!

    Ich hoffe, dir wird damit die Funktionsweise von scanf deutlicher.

    In der Tat, das war nett von dir. Trotzdem fürchte ich, dass ich es in halben Jahr vergessen haben werde, weil es irgendwie gar nicht intuitiv ist. Ich hatte mal in meiner Signatur stehen, dass man mich bitte nicht ernstnehmen soll, wenn ich scanf() rede, aber ich bin ja nicht registriert... 🙄

    Ich weiss aber auch nicht, was ich gegen diese seltsam unbewusste Abneigung tun kann, ein Psychologe würde ich wahrscheinlich strinrunzelnd an einen Psychiater verweisen, und der mich, weil ich Angst vor scanf() habe, drei Jahre lang mit Drogen vollpumpen, bis er draufkommt, dass es das wirklich gibt...



  • Die Angst vor scanf() kann dir ja genommen werden: benutze C++ (d.h. den typsicheren Streaming-Operator >>) -)



  • Th69 schrieb:

    Die Angst vor scanf() kann dir ja genommen werden: benutze C++ (d.h. den typsicheren Streaming-Operator >>)

    willst du ihn endgültig ins irrenhaus bringen? 'cin' u.ä. ist voll daneben. das hat noch nicht mal 'nen rückgabewert, an dem man erkennen kann, wieviel eingelesen wurde.
    🙂



  • Th96 schrieb:

    Die Angst vor scanf() kann dir ja genommen werden: benutze C++ (d.h. den typsicheren Streaming-Operator >>) -)

    Aber dann müsste ich doch auch malloc() casten (oder -- brrr -- new verwenden). Und das tue ich hauptsächlich deshalb nicht, um volkard zu ärgern.
    🙂

    µ


Anmelden zum Antworten