Ausnahmebehandlung für eine string Funktion



  • Hi Tyrdal,

    Tyrdal schrieb:

    muemmel schrieb:

    den Test auf NULL

    Wenn dann würde ich eh auf nullptr testen.

    Muss ich mal, wenn ein bisschen Zeit ist probieren.

    Und verwirr bitte die Anfänger nicht mit _TCHAR und ähnlichem.

    Das baut meine Entwicklungs-Umgebung so als Vorgabe zusammen. (c++Builder xe2)

    Gruß Mümmel



  • nullptr ist der aktuelle Standard und _TCHAR nicht, sondern Windows-spezifisch.



  • habe die Umlaute weggemacht. Ausgabe meiner Meinung nicht korrekt:

    #include <iostream>
    #include <stdexcept>
    #include <string>
    
    using namespace std;
    
    // Definition einer Funktion vom Typ std::string namens nick (nickname):
    string nick(string nickname)
    {
        if (nickname.empty()) // wenn leere Zeichenkette
            throw runtime_error("NickName ist leer");
    
        int GueltigVorhanden = 0; // Vorbelegen auf Falsch
        for (size_t i = 0; i < nickname.size(); ++i) // durch alle Zeichen gehen
        {
    
            if (
                ((nickname[i] >= 'a') && (nickname[i] <= 'z')) || 
                ((nickname[i] >= 'A') && (nickname[i] <= 'Z'))
               )
    
            {
                GueltigVorhanden = 1; // nicht nur Leerzeichen
            }
            else // sonst wenn kein erlaubtes
            {
                if (nickname[i] != ' ') // und wenn es kein Leerzeichen ist
                {
                    throw runtime_error(" nick(), verbotenes Zeichen ");
                // muss es ein falsches sein, also Exception werfen
                }
            }
        }
    
        if (GueltigVorhanden == 0) {
            throw runtime_error{ " nick(), Leere Zeichenkette übergeben" };
        }
    }
    
    int main()
    {
    
        string x;
    
        try {
    
            nick(" /ncapitalQ ");
    
            return 0;
        }
    
        catch (const runtime_error& re) {
    
            cerr << " Caught: " << re.what() << endl;
    
            cout << " Eingabe für weiter " << endl; 
            cin >> x; // gibt immer aus =>  nick(), verbotenes Zeichen
                     //  Eingabe für weiter a ergibt weiter nichts
    
            return -1;
        }
    }
    

    Passiert es vielleicht weil nick() schon ein string im Main stehen hat?
    das Compiler denkt ach nickname nicht leer ist also verbotenes Zeichen.
    cout und cin ergeben irgendwie keinen sinn am ende. Kann man die direkt nach catch reinmachen?



  • Hi Helenchen,

    helenchen schrieb:

    Passiert es vielleicht weil nick() schon ein string im Main stehen hat?
    das Compiler denkt ach nickname nicht leer ist also verbotenes Zeichen.
    cout und cin ergeben irgendwie keinen sinn am ende. Kann man die direkt nach catch reinmachen?

    Mal in Ruhe selber überlegen, warum der Computer einen Fehler ausgibt! 😉
    Die Zeichenkette " /ncapitalQ " hat nach dem Leerzeichen am Anfang das Zeichen /n. Das sind keine zwei einzelnen Zeichen in C und c++ sondern es ist eine sogenannte Escape-Sequenz die als Symbol für einen Zeilenvorschub steht. Das gilt aber nur zur Compilierzeit. Der Compiler wandelt das dann um in das eine Zeichen für einen Zeilenvorschub (ich glaube 13). Aber das geht nur zur Compilierzeit.
    Bei einer normalen Eingabe über die Tastatur wären es zwei Zeichen.
    Das /-Zeichen ist in C das sogenannte "Fluchtsymbol" das dem nächsten Zeichen eine Sonderbedeutung zuordnet. Will man aber zur Compilierzeit das Zeichen / selbst darstellen muss man es durch // darstellen. " //ncapitalQ " wäre also im Gegensatz dazu ein zulässiger Nickname, wenn Du nur auf 33-125 getestet hättest. So mit der Eingrenzung auf nur Groß- und Kleinbuchstaben wäre es natürlich auch ein Fehler gewesen. /n ist aber in jedem Fall ein Fehler, schon deshalb, weil es keinen gültigen Nicknamen geben kann, der mit einem Zeilenvorschub am Anfang beginnt, weil Du den an der Konsole beim Anmelden nie eingeben könntest denn es würde immer als Ende der Eingabe interpretiert.

    Vielleicht war ja das /n am Anfang des Nicknamens der Fehler den ihr mit Eurer Testfunktion finden solltet.

    Cout und cin am Ende sollen verhindern, dass das Programm gleich geschlossen wird und das Konsolen-Fenster sofort wieder zu geht. Wenn Du es aus Command startest müsste es auch ohne gehen.
    Klar, in dem speziellen Fall könntest Du es theoretisch auch gleich nach catch "reinmachen" (reinmachen kannst Du höchsten in Deine Hosen wenns Essen verdorben war 😃 ).
    Dadurch dass nach dem Aufruf von Nick nichts mehr passiert, würde das nichts ändern. Aber schon wenn Du am Schluss noch mal den Nicknamen ausgeben würdest wäre er nicht zu sehen, weil dann die Wartestelle mit cout und cin entweder nicht angesprungen würde und das Programm daher gleich zumacht oder wenn nicht fehlerhaft die Ausgabe durch den direkten Sprung in die Ausnahmebehandlung übersprungen würde.

    Gruß Mümmel



  • hier ist der code :

    #include <iostream>
    #include <stdexcept>
    #include <string>
    
    using namespace std;
    
    // Definition einer Funktion vom Typ std::string namens nick (nickname):
    string nick(string nickname)
    {
    
        if (nickname.empty()) // wenn leere Zeichenkette
            throw runtime_error("NickName ist leer");
    
        int GueltigVorhanden = 0; // Vorbelegen auf Falsch
        for (size_t i = 0; i < nickname.size(); ++i) // durch alle Zeichen gehen
        {
    
            if (
                ((nickname[i] >= 'a') && (nickname[i] <= 'z')) || 
                ((nickname[i] >= 'A') && (nickname[i] <= 'Z'))
               )
            // mit Zeiger statt Indexzugriff wäre es performanter
            // geht aber auch so
            {
                GueltigVorhanden = 1; // nicht nur Leerzeichen
            }
            else // sonst wenn kein erlaubtes
            {
                if (nickname[i] != ' ') // und wenn es kein Leerzeichen ist
                {
                    throw runtime_error(" nick(), verbotenes Zeichen "); // muss es ein falsches sein, also Exception werfen
                }
            }
        }
    
        if (GueltigVorhanden == 0)
    
            throw runtime_error{ " nick(), Leere Zeichenkette übergeben" };
    
        return nickname;
    }
    
    int main()
    {
    
        string x;
        string Nick_Name;
        try {
    
            Nick_Name = nick("\ncapitalQ");
            cout << "Bitte richtigen Nick_Name eingeben:" << endl;
            // Eingabe damit Ergebnis sthen bleibt
            cout << "Eingabe für weiter" << endl;
            cin >> x;
    
            return 0;
        }
    
        catch (const runtime_error& re) {
            cout << " Eingabe für weiter " << endl;
            cin >> x;
            cerr << " Caught: " << re.what() << endl;
    
            return -1;
        }
    }
    

    alles was ich herausbekommen habe :

    Funktion ist tatsächlich leer, über cin werden die Zeichen eingegeben aber werden irgendwie nicht weiter verarbeitet.

    Nach paar Veränderungen gibt es nur verbotene Zeichen Meldung.
    zwischen for und if anweisung mit nick[i] fehlt noch was. Also nach zeichen durchgehen muss eine if mit prüfbereich für nick[i] geben. Damit es nicht nur leerzeichen sind.

    das mit dem if( *it <= zahl etc ) funktioniert bei mir nicht

    😃 Mümmel kannst du paar Tipps dem C++ Anfängerdössel geben? ich sitze hier und weiß nicht weiter 😕



  • muemmel schrieb:

    Die Zeichenkette " /ncapitalQ " hat nach dem Leerzeichen am Anfang das Zeichen /n. Das sind keine zwei einzelnen Zeichen in C und c++ sondern es ist eine sogenannte Escape-Sequenz
    die als Symbol für einen Zeilenvorschub steht. Das gilt aber nur zur Compilierzeit. Der Compiler wandelt das dann um in das eine Zeichen für einen Zeilenvorschub (ich glaube 13).

    Das tut der compiler garantiert nicht. Waere es eine escape-sequence, dann vielleicht aber SLASH+n ist definitiv keine... \n fyi



  • Hi Cardiac,

    Cardiac schrieb:

    muemmel schrieb:

    Die Zeichenkette " /ncapitalQ " hat nach dem Leerzeichen am Anfang das Zeichen /n. Das sind keine zwei einzelnen Zeichen in C und c++ sondern es ist eine sogenannte Escape-Sequenz
    die als Symbol für einen Zeilenvorschub steht. Das gilt aber nur zur Compilierzeit. Der Compiler wandelt das dann um in das eine Zeichen für einen Zeilenvorschub (ich glaube 13).

    Das tut der compiler garantiert nicht. Waere es eine escape-sequence, dann vielleicht aber SLASH+n ist definitiv keine... \n fyi

    Ja, Danke! Das hatte ich vertauscht. Die Funktion sollte den Fehler in der Zeichenkette finden und da haben sich die Augen automatisch an "/n" festgebissen und das gelesen was sie lesen wollten.
    Wenn ich mir das selber noch mal laut vorgelesen hätte, wäre mit sicher auchaufgegangen, das '/' kein Backslash ist. Man soll halt lesen was da steht und nicht was man lesen will. 😉

    Gruß Mümmel



  • Hi Helenchen,

    So müsste es gehen.

    #include <iostream>
    #include <string>
    #include <stdexcept>
    
    using namespace std;
    
    string nick(string nickname)
    {
        int GueltigVorhanden = 0;
    
        for (size_t i = 0; i < nickname.size(); ++i)
        {
            if (
                 ( ( nickname[ i ] >= 'a' ) && ( nickname[ i ] <= 'z' ) ) ||
                 ( ( nickname[ i ] >= 'A' ) && ( nickname[ i ] <= 'Z' ) )
               )
            {
                GueltigVorhanden = 1;
            }
            else
            {
              if ( nickname[ i ] != ' ' )
              {
                throw runtime_error( " Fehler, verbotenes Zeichen" );
              }
            }
        }
        if ( GueltigVorhanden == 0 )
        {
            throw runtime_error( " Fehler, Leere Zeichenkette übergeben" );
        }
        return nickname;
    }
    
    int main()
    {
        string x;
        string Nick_Name;
        try
        {
            while ( 1 )
            {
                cout << "Bitte richtigen Nick_Name eingeben:" << endl;
                cin >> x;
                // auswerten und anzeigen
                cout << "Nick_Name ist " <<  nick( x ) << endl;
            }
            return 0;
        }
        catch (const runtime_error& re)
        {
            cerr << " Caught: " << re.what() << endl;
            cout << " Eingabe für weiter " << endl;
            cin >> x;
            return -1;
        }
    }
    

    Viel Glück beim Ausprobieren.
    Gruß Mümmel



  • Hi Helenchen,

    so müsste es besser laufen:

    #include <iostream>
    #include <string>
    #include <stdexcept>
    
    using namespace std;
    
    string nick(string nickname)
    {
    
        int GueltigVorhanden = 0;
    
        for (size_t i = 0; i < nickname.size(); ++i)
        {
            if (
                 ( ( nickname[ i ] >= 'a' ) && ( nickname[ i ] <= 'z' ) ) ||
                 ( ( nickname[ i ] >= 'A' ) && ( nickname[ i ] <= 'Z' ) )
               )
            {
                GueltigVorhanden = 1;
            }
            else
            {
              if ( nickname[ i ] != ' ' )
              {
                throw runtime_error( "verbotenes Zeichen" );
              }
            }
        }
        if (GueltigVorhanden == 0)
        {
            throw runtime_error( "leere Zeichenkette uebergeben" );
        }
        return nickname;
    }
    
    int main()
    {
        string x;
        try
        {
            while ( 1 )
            {
                cout << "Bitte  gewuenschten Nick-Name eingeben:" << endl;
                getline( cin, x );
                // auswerten und anzeigen
                cout << "Nick-Name ist " <<  nick( x ) << endl;
            }
            return 0;
        }
        catch (const runtime_error& re)
        {
            cerr << "Fehler: " << re.what() << endl;
    
            cout << " Eingabe fuer weiter " << endl;
            getline( cin, x );
            return -1;
        }
    }
    

    Gruß Mümmel


Anmelden zum Antworten