keine korrekte Ausgabe bei cin.getline



  • Hallo Zusammen,

    lernen gerade in der Schule erst C++ und habe ein Problem.

    Beim Einlesen über cin.getline ist noch alles in Ordnung, aber die
    Ausgabe stimmt überhauptnicht. Kann mir jemand weiterhelfen?

    Danke, bella

    hier der Quellcode:

    #pragma hdrstop
    #include <iostream.h>
    #include <stdlib.h>
    #include <cstdio.h>
    //------------------------------------------------------------------------
    
    #pragma argsused
    int main(int argc, char* argv[])
    {
    
        cout << "Ausgabevariationen zu Vektoren (Felder) !!! " << endl << endl;
    
        // Deklar. eines Feldes vom Typ "char" fuer 80 Zeichen
        // Es wird Speicherplatz fuer 80 Zeichen freigehalten
        char satz[80];
    
        // Ausgabe der Anfangsadr. des Feldes "Satz"
        cout << "Anfangsadresse des Feldes 'Satz': " << &satz << endl << endl;
    
        // Fuellen des Feldes 'Satz' in einer For-Schleife
        // Es koennen 20 Zeichen eingegeben werden, da bei Null begonnen
        // wird mit zaehlen
        cout << "Geben Sie 5 Zeichen hintereinander ein: " << endl;
        for (int i=0; i<5; i++)
        {
        cin >> satz [i];
        }
        char i='\0';
    
        // Ausgabe der gerade eingegebenen Zeichen
        cout << endl <<"Ausgabe der eingegebenen Zeichen: " << satz << endl << endl;
    
        // Eingabe von Zeichenketten (Textfeldern)
        cout << endl << endl;
    
        // Init der Variablen "Zeichenkette" mit 80 Zeichen
        char zeichenkette [80];
    
        // Eingabeaufforderung für die Zeichenkette
        cout << "Geben Sie einen Satz ein." << endl;
        cin.getline (zeichenkette,80);
    
        // Ausgabe der eingegebenen Zeichenkette
        cout <<"Hier der eben eingegebene Satz: " << zeichenkette << endl << endl;
    
        cout << endl << endl;
        system ("pause");
        return 0;
    }
    

    Bitte Code-Tags verwenden!

    [ Dieser Beitrag wurde am 07.06.2003 um 19:15 Uhr von HumeSikkins editiert. ]



  • for (int i=0; i<5; i++)
    {
    cin >> satz [i];
    }
    char i='\0';
    

    würde ich in

    for (int i=0; i<5; i++)
    {
    cin >> satz [i];
    }
    satz[i]='\0';
    

    ändern.



  • Hallo Deus,

    hier bekomme ich einen Fehler zurück
    "Undefiniertes Symbol 'i'.

    Warum??

    Gruß, Anke



  • weil deus den compiler von M$ verwendet, und das, was er macht, dort erlaubt ist, mit dem c++ standard aber nicht übereinstimmt 😉

    i wird im sichtbarkeitsbereich der schleife deklariert, also gibt es keine variable namens i außerhalb der schleife:

    //kein i
    
    for (int i = 0; i < 10; ++i) { //hier fängt i an zu leben
    } //hier stirbt i wieder
    
    //kein i
    
    /* Ändere das in */
    
    //kein i
    
    {
    int i; //erschaffe i
    
    for (i = 0; i < 10; ++i) { 
    }
    
    //i existiert immer noch
    
    } //hier erst stirbt i
    


  • 🙄
    ups 🙂



  • Hallo C++,

    ich benutzte Borland Prof. und leider funtioniert es auch so nicht.
    Dann bekomme ich einen Fehler von BS und das Programm hängt sich auf.

    Gruß, bella



  • Poste nochmals deinen Code, diesmal aber bitte mit CodeTags!



  • Hallo,
    dann wollen wir mal:

    #include <cstdio.h>
    

    Einen solchen Header gibt es in Standard-C++ nicht. Entweder <cstdio> oder <stdio.h>.

    #include <iostream.h>
    

    Auch das ist kein Standard-Header. Wenn *möglich* solltest du <iostream> verwenden.

    #pragma argsused
    

    Wozu der pragma-Hammer. Warum nicht einfach

    int main()
    

    statt

    int main(int argc, char* argv[])
    

    schreiben?

    // Fuellen des Feldes 'Satz' in einer For-Schleife
    // Es koennen 20 Zeichen eingegeben werden, da bei Null begonnen
    // wird mit zaehlen
    cout << "Geben Sie 5 Zeichen hintereinander ein: " << endl;
    for (int i=0; i<5; i++)
    {
        cin >> satz [i];
    }
    char i='\0';
    

    Das ist Käse. Der Kommentar ist falsch und das char i = '\0' ist sinnlos.
    Besser:

    cout << "Geben Sie 5 Zeichen hintereinander ein: " << endl;
    int i;
    for (i = 0; i < 5 && cin >> satz[i]; ++i);
    satz[i] = '\0';
    // Wir sind an weiteren Zeichen nicht interessiert.
    // Also solche falls vorhanden ignorieren.
    cin.ignore(cin.rdbuf()->in_avail());
    

    Und noch zwei allgemeine Hinweise:
    1. Du verwendest viel zu oft den Manipulator endl. Dieser fügt nicht nur ein Newline ein, er flusht auch den Stream. Und das ist zweimal direkt hintereinander überflüssig.
    Ein simples "\n" tut's auch.
    2. Verzichte auf überflüssige Kommentare und auf Kommentare die beschreiben, *was* der Code macht (à la: Deklaration eines Integers a) oder *wie* er es tut (à la: Liest 5 Zeichen in einer for-Schleife). Das wird bereits durch den Code beschrieben. Wenn du Kommentierst, dann beschreibe das *warum*.

    Hier mal der etwas korrigierte Code:

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    int main()
    {
        cout << "Ausgabevariationen zu Vektoren (Felder) !!!\n\n";
        char satz[80];
        cout << "Anfangsadresse des Feldes 'Satz': " << &satz;
        cout << "\n\nGeben Sie 5 Zeichen hintereinander ein: ";
    
        int i;
        for (i = 0; i < 5 && cin >> satz[i]; ++i);
        satz[i] = '\0';
    
        // Wir sind an weiteren Zeichen nicht interessiert.
        // Also solche falls vorhanden ignorieren.
        cin.ignore(cin.rdbuf()->in_avail());
        cout << "\nAusgabe der eingegebenen Zeichen: " << satz;
    
        char zeichenkette [80];
        cout << "\n\n\nGeben Sie einen Satz ein.\n";
        cin.getline (zeichenkette,80);
        cout <<"Hier der eben eingegebene Satz: " << zeichenkette << "\n\n\n\n";
        system ("pause");
        return 0;
    }
    


  • Ich hoffe, jetzt ist der Code richtig hinterlegt.

    Gruß, Anke

    #pragma hdrstop
    #include <iostream.h>
    #include <stdlib.h>
    #include <cstdio.h>
    //------------------------------------------------------------------------
    
    #pragma argsused
    int main(int argc, char* argv[])
    {
    
    cout << "Ausgabevariationen zu Vektoren (Felder) !!! " << endl << endl;
    
    // Deklar. eines Feldes vom Typ "char" fuer 80 Zeichen
    // Es wird Speicherplatz fuer 80 Zeichen freigehalten
    char satz[80];
    
    // Ausgabe der Anfangsadr. des Feldes "Satz"
    cout << "Anfangsadresse des Feldes 'Satz': " << &satz << endl << endl;
    
    // Fuellen des Feldes 'Satz' in einer For-Schleife
    // Es koennen 20 Zeichen eingegeben werden, da bei Null begonnen
    // wird mit zaehlen
    cout << "Geben Sie 5 Zeichen hintereinander ein: " << endl;
    for (int i=0; i<5; i++)
    {
    cin >> satz [i];
    }
    char i='\0';
    
    // Ausgabe der gerade eingegebenen Zeichen
    cout << endl <<"Ausgabe der eingegebenen Zeichen: " << satz << endl << endl;
    
    // Eingabe von Zeichenketten (Textfeldern)
    cout << endl << endl;
    
    // Init der Variablen "Zeichenkette" mit 80 Zeichen
    char zeichenkette [80];
    
    // Eingabeaufforderung für die Zeichenkette
    cout << "Geben Sie einen Satz ein." << endl;
    cin.getline (zeichenkette,80);
    
    // Ausgabe der eingegebenen Zeichenkette
    cout <<"Hier der eben eingegebene Satz: " << zeichenkette << endl << endl;
    
    cout << endl << endl;
    system ("pause");
    return 0;
    }
    


  • Hallo HumeSikkins,
    
    du hast mich mit deinem Beitrag echt erschlagen.
    Ich muß sagen, daß ich in der Schule seit 1/2 Jahr C++ lerne und das was
    dort steht, wurde mir bis jetzt so beigebracht. Die Kommentare habe ich 
    in diesem Fall so ausführlich gemacht, weil das eine Lernhilfe für die 
    Klausur am donnerstag werden soll und ich habe mir auch den Output dazu
    ausgedruckt. Ich bringe immer die * und & durcheinander und deshalb auch
    "init Zeiger". Dann weiß ich in 2 tagen auch noch, daß der * zum Zeiger gehört.
    
    Du hast viel geschrieben, das mir unbekannt ist und ich nicht verstehe.
    " #pragma argsused
    
    Wozu der pragma-Hammer. Warum nicht einfach "
    
    ich weiß überhaupt nicht, was das hinter int main (...) bedeutet. Unser Lehrer
    hat nur gesagt es tut nichts und soll einfach stehen bleiben. Genauso die endl;.
    \n kenne ich noch nicht.
    
    Was soll der ganze Code hier heißen?
    
    for (i = 0; i < 5 && cin >> satz[i]; ++i);
    satz[i] = '\0';
    // Wir sind an weiteren Zeichen nicht interessiert.
    // Also solche falls vorhanden ignorieren.
    cin.ignore(cin.rdbuf()->in_avail());
    
    Gruß, Anke
    


  • Hallo,
    also #pragma argsused ist nicht Standard. Die Bezeichnung argsused hat mich vermuten lassen, dass es sich hier in irgendeiner Form um die Benutzung (oder Nichtbenutzung) von Funktionsargumenten dreht. Eine google-Suche hat dann schnell ergeben, dass es sich bei dieser Pragma-Anweisung um eine borland-spezifische Anweisung handelt, die Warnungen bezüglich ungenutzer Funktionsparameter unterdrückt.

    Schaut man sich nun dein Programm an, stellt man fest, dass die beiden Parameter der main-Funktion (argc und argv) nirgends benutzt werden.
    Diese beiden Parameter dienen dazu auf an das Programm übergebene Kommandozeilenargumente zuzugreifen.
    In argc steht dabei die Zahl der übegebenen Parameter. Und in argv die einzelnen Parameter als Strings.
    Da du nirgends von dieser Information gebrauch machst, würde dich dein Compiler im Normalfall darauf hinweisen, dass du unbenutzte Parameter in deinem Programm hast. Die pragma-Anweisung unterdrückt nun genau diesen Hinweis.
    Compilerhinweise zu unterdrücken ist aber in der Regel eine sehr schlechte Angewohnheit.
    Anstatt sie brutal auszuschalten, sollte man sie lesen, verstehen und dann ihre *Ursache* bekämpfen.
    In diesem konkreten Fall heißt das:
    Wenn du nicht an den Argumenten interessiert bist, dann benutze sie nicht. Deshalb gibt es ja schließlich extra eine main-Funktion mit der Signatur:

    int main();
    

    Unser Lehrer
    hat nur gesagt es tut nichts und soll einfach stehen bleiben.

    Da es in diesem Beispiel offenkundig nicht um Kommandozeilenargumente geht und da das Hinschreiben des Pragma-Anweisung und der beiden Parameter in dieser Situation *keinen* Vorteil bringt, ist es natürlich großer Käse von deinem Lehrer auf die beiden Sachen zu bestehen ohne sie zu erklären. Es ist einfach nur sinnloses Zeugs das vom eigentlichen Ziel ablenkt. Kannst du ihm ja mal von mir ausrichten 🙂

    Genauso die endl;.
    \n kenne ich noch nicht.

    Interessant. Ich hätte gedacht man lernt "\n" vor endl; oder zumindest gleichzeitig.
    Naja, '\n' ist eine sogenannte Escape-Sequenz. Sie stellt ein Newline-Zeichen dar.
    Andere bekannte Escape-Sequenzen sind z.B.:
    '\t' : Horizontaler Tab
    '\b' : Backspace
    '\' : Backslash
    ...

    endl hingegen ist ein sogenannter Manipulator. Er fügt der Ausgabe ein '\n' hinzu und ruf danach ostream::flush auf.

    Was soll der ganze Code hier heißen?
    for (i = 0; i < 5 && cin >> satz[i]; ++i);
    satz[i] = '\0';
    // Wir sind an weiteren Zeichen nicht interessiert.
    // Also solche falls vorhanden ignorieren.
    cin.ignore(cin.rdbuf()->in_avail());

    Naja, die for-Schleife sollte dir bekannt sein. Neu ist hier vielleicht nur das cin >> satz[i] im Bedingungsteil. Das Objekt cin kann in einem booleschen Ausdruck verwendet werden. In diesem Fall gilt:
    Ist das Objekt gültig (das Einlesen hat funktioniert) so wird cin nach true ausgewertet. Ist das Objekt ungültig (weil das Einlesen z.B. fehlgeschlagen ist), so wird cin nach false ausgewertet.

    Die Schleife läuft also solange i < 5 ist und das Einlesen eines Zeichens erfolgreich war.

    cin.ignore(cin.rdbuf()->in_avail());

    Diese Zeile führt dazu, dass alle Zeichen die noch im Eingabepuffer sind ignoriert werden. ignore ist dabei eine Methode von cin, die n-Zeichen im Eingabepuffer ignoriert. n wird dabei als Argument an ignore übergeben.
    cin.ignore(2);
    würde also 2 Zeichen ignorieren.

    cin.rdbuf()->in_avail()
    ist eine lustige Art und Weise herauszubekommen, wieviele Zeichen noch im Eingabepuffer stehen (eine Erklärung was hier genau funktioniert führt im Moment wohl noch zu weit).
    Der gesamte Aufruf ignoriert also genausoviele Zeichen wie noch im Eingabepuffer zur Verfügung stehen.

    Falls du dich fragst warum das nötig sein sollte:
    Es könnte z.B. sein, dass der Benutzer die Aufforderung:

    cout << "\n\nGeben Sie 5 Zeichen hintereinander ein: ";
    

    mehr oder weniger bewusst ignoriert und satt 5 Zeichen einfach "Elefant" (7 Zeichen) eingibt.
    In diesem Fall würde die for-Schleife die ersten fünf Zeichen lesen (Elefa). Die restlichen drei Zeichen (nt sowie das Newline-Zeichen) würde aber im Eingabepuffer stehen bleiben.

    In diesem Fall würde das nachfolgende getline

    cout << "Geben Sie einen Satz ein." << endl;
    cin.getline (zeichenkette,80);
    

    aber nun genau diese Zeichen lesen. Der Benutzer hätte gar keine Chance einen Satz einzugeben.

    [ Dieser Beitrag wurde am 08.06.2003 um 00:30 Uhr von HumeSikkins editiert. ]


Anmelden zum Antworten