springen - aber OHNE goto



  • Hi Leute!

    Ich hab folgendes Programm entwickelt, dass in ein array der max. Größe von 100 Elemente vom Benutzer der Reihe nach Werte einließt und danach den minimalen sowie den maximalen Wert und den Durchschnittswert der Elemente ausgibt. Außerdem soll bei einer Eingabe einer negativen Zahl das Programm sofort abgebrochen werden. Mein Problem ist nun, dass ich nicht weiß, wie ich ans Ende vom Programm komme, wenn der Benutzer an der Stelle an der er die Arraywerte einließt, eine negative Zahl eingibt.

    Goto wäre eine Möglichkeit, die ich aber (aus gutem Grund) nicht verwenden möchte. Könnt ihr mir helfen?

    Hier der Code:

    #include<iostream>
    using namespace std;
    
    int main()
    {
        int i, a, b, array1[100], wmax, wmin, durch, arraywert1, arraywert2;
    
        cout << "Wie viel Zahlen wollen sie eingeben (nur unter 100)? ";
        cin >> a;
    
    if(a <= 100 && a >=0)
    {
     for(i=0; i<a; i=i+1)
     {
      cin >> b;
      if(b < 0)
      {
       break;
      }
      else
      {
       array1[i] = b;
      }
     }
    
    //Suche nach wmax
    
    arraywert1 = 0;
    wmax = 0;
    for(i=0; i<=(a-1); i=i+1)
    {
     arraywert1 = array1[i];
     if(arraywert1 >= wmax)
     {
      wmax = 0;
      wmax = wmax + arraywert1;
     }
    }
    cout << "maximaler Wert im Array: " << wmax << endl;
    
    //Suche nach wmin
    
    arraywert2 = 0;
    wmin = 0x7FFFFFFF;
    for(i=0; i<=(a-1); i=i+1)
    {
     arraywert2 = array1[i];
     if(arraywert2 <= wmin)
     {
      wmin = 0;
      wmin = wmin + arraywert2;
     }
    }
    cout << "minimaler Wert im Array: " << wmin << endl;
    
    //Durchschnitt
    
    durch = 0;
    for(i=0; i<a; i=i+1)
    {
     durch = durch + array1[i];
    }
    cout << "Durchschnitt: " << ((float)durch) / 2 << endl << endl;
    }
    else
    {
    
    }
    
    system("pause");
    return 0;
    }
    


  • main ist auch nur eine Funktion ... return sollte das schaffen, egal ob in einem if oder anderswo.



  • Besser du schreibst eine Funktion eingabe, packst dort deinen gesamten Code hinein und beendest mit return. In der main kannst du dann dein komisches
    system("pause"); anbringen.


  • Mod

    weglagerer schrieb:

    Besser du schreibst eine Funktion eingabe, packst dort deinen gesamten Code hinein und beendest mit return. In der main kannst du dann dein komisches
    system("pause"); anbringen.

    Wenn wir schon so komische Konstrukte wie system("pause") haben, könnte man hier tatsächlich mal das (zurecht) selten genutzte atexit benutzen.



  • SeppJ schrieb:

    weglagerer schrieb:

    Besser du schreibst eine Funktion eingabe, packst dort deinen gesamten Code hinein und beendest mit return. In der main kannst du dann dein komisches
    system("pause"); anbringen.

    Wenn wir schon so komische Konstrukte wie system("pause") haben, könnte man hier tatsächlich mal das (zurecht) selten genutzte atexit benutzen.

    Wieso (zurecht) selten genutzt?



  • Weil es keinen Sinn macht, nach Programmende noch auf einen Tastendruck zu warten. Der Benutzer will schliesslich weiterarbeiten.


  • Mod

    Weil es in C++ sehr selten Sinn macht. Die Destruktoren sollten ja alles aufräumen. Das atexit ist eher für C Programme, wenn man dort auch bei unerwarteten Abbrüchen noch aufräumen muss.

    Für so etwas wie auf Tastendruck warten (fände ich als Benutzer jedoch ziemlich nervig) ist es ein nettes Werkzeug.



  • Man kann auch ganz verwegen sein, und den Code der vor "system pause" laufen soll in eine eigene Funktion packen.
    Diese kann man dann mittels return verlassen, und in main() wird "system pause" dann trotzdem ausgeführt.
    Voll der kuhle Trick, uh jeah.

    EDIT: lol, hab den Beitrag von wegelagerer übersehen, sorry 😃


  • Mod

    Aber das coole an atexit ist, dass man dann das Programm auch im Fehlerfall mittels exit verlassen kann und trotzdem noch nach der Taste gefragt wird. Wobei man sich dann jedoch wieder die Frage gefallen lassen muss, wieso man das Programm mit exit verlässt, anstatt z.B. eine exception zu schmeißen.

    Aber das ist alles nur Theorie, atexit sollte man aus genannten Gründen nicht nutzen, aber für Leute die sich für system("pause") nicht zu schade sind, ist das ein netter kleiner Trick auf einem stilistisch ähnlichem Niveau.



  • Wie du das Programm vorzeitig beenden kannst, wurde ja schon gesagt.
    Allerdings wundert mich dass bisher noch niemand was zu deinem code ansich gesagt hat.
    Nehmen wir beispielsweise folgenden Ausschnitt:

    bandchef schrieb:

    ...

    //Suche nach wmax
    
    arraywert1 = 0;
    wmax = 0;
    for(i=0; i<=(a-1); i=i+1)
    {
     arraywert1 = array1[i]; 
     if(arraywert1 >= wmax)
     {
      wmax = 0;
      wmax = wmax + arraywert1;
     }
    }
    cout << "maximaler Wert im Array: " << wmax << endl;
    

    ...

    Dann erscheint mir das doch sehr umständlich und einiges überflüssig.
    Wozu wird arraywert1 benötigt? warum wird wmax 0 zugewiesen, nur um in der darauffolgenden Zeile einen anderen Wert zuzuweisen?
    Einfacher wäre es doch beispielsweise folgendermassen:

    //Suche nach wmax
    wmax = 0;
    for(i=0; i!=a; ++i) {
    	if ( array1[i] > wmax )
    		wmax = array1[i];
    }
    cout << "maximaler Wert im Array: " << wmax << endl;
    

    Das gilt natürlich auch für den Rest des Programms.



  • SeppJ schrieb:

    [...] aber für Leute die sich für system("pause") nicht zu schade sind, ist das ein netter kleiner Trick auf einem stilistisch ähnlichem Niveau.

    Was für ein Niveau? Ich benutze system("pause") zwar nur in Testprojekten, aber es ist mir allemals lieber als irgendein Herumgefrickel auf cin , dessen Erfolg davon abhängt, ob bisher im Programm formatierte Eingabe verwendet wurde oder nicht. Schon alleine wegen der Grösse des benötigten Codes.



  • Nexus schrieb:

    SeppJ schrieb:

    [...] aber für Leute die sich für system("pause") nicht zu schade sind, ist das ein netter kleiner Trick auf einem stilistisch ähnlichem Niveau.

    Was für ein Niveau? Ich benutze system("pause") zwar nur in Testprojekten, aber es ist mir allemals lieber als irgendein Herumgefrickel auf cin , dessen Erfolg davon abhängt, ob bisher im Programm formatierte Eingabe verwendet wurde oder nicht. Schon alleine wegen der Grösse des benötigten Codes.

    Ich mache da dann einfach CTRL+F5, aber sonst finde ich das auch einiges angenehmer, als jedesmal dieses Ding kopieren zu gehen.



  • drakon schrieb:

    Ich mache da dann einfach CTRL+F5

    Unter Visual Studio 2010 bleibt das Konsolenfenster bei "Starten ohne Debugging" nicht offen.



  • Nexus schrieb:

    drakon schrieb:

    Ich mache da dann einfach CTRL+F5

    Unter Visual Studio 2010 bleibt das Konsolenfenster bei "Starten ohne Debugging" nicht offen.

    Ich starte für solche Sachen das Programm direkt aus einem Terminal. Hat den netten Nebeneffekt, dass man ein brauchbares Terminal nutzen kann und nicht zeitaufwendig jedes mal das Projekt übersetzen lassen muss.



  • Nick Unbekannt schrieb:

    Hat den netten Nebeneffekt, dass man ein brauchbares Terminal nutzen kann und nicht zeitaufwendig jedes mal das Projekt übersetzen lassen muss.

    😕
    Jedes mal das Projekt übersetzen lassen muss wenn man was machen möchte?

    ----

    Man kann in den Projekteinstellungen einstellen was das Studio beim Debuggen starten soll. Auch jede andere IDE die ich kenne bietet so eine Option. Das muss nicht direkt das Programm sein, das kann genau so gut ein Batchfile sein wo hinten "pause" dran steht. Dann muss man im Programm gar nix anpassen.

    EDIT: OK, ist auch wieder Kacke, dann hängt der Debugger auf der Shell drauf und nicht auf dem Programm. Hmpf. Auch doof 🙂


  • Mod

    Nexus schrieb:

    ]Was für ein Niveau? Ich benutze system("pause") zwar nur in Testprojekten, aber es ist mir allemals lieber als irgendein Herumgefrickel auf cin , dessen Erfolg davon abhängt, ob bisher im Programm formatierte Eingabe verwendet wurde oder nicht. Schon alleine wegen der Grösse des benötigten Codes.

    Und in Testprogrammen finde ich es auch ok, atexit zu benutzen.



  • hustbaer schrieb:

    Jedes mal das Projekt übersetzen lassen muss wenn man was machen möchte?

    Wenn ich zum Testen den Code verändere, dann muss ich neu übersetzen. Man kann zwar das system("pause") auch drin lassen, doch das stört mich dann ehrlich gesagt beim Debuggen.

    hustbaer schrieb:

    EDIT: OK, ist auch wieder Kacke, dann hängt der Debugger auf der Shell drauf und nicht auf dem Programm. Hmpf. Auch doof 🙂

    Es ging ja gerade um das Starten ohne Debugger. 😉
    Mit Debugger macht man einfach einen Haltepunkt auf die letzte Zeile und braucht auch am Code nichts verändern.



  • Etwas vom Thema abgeschweift, wie? 😉

    OK, @bandchef:

    Was andere schon sagten: Schreibe eine eigene Funktion für jede Aufgabe. Dann schrumpft main( ) und Du kannst auch auf Rückgabewerte besser reagieren.
    Etwa so:

    main( )
    {
        Initialisierung...
    
        int eingabeErgebnis = eingabe( );   // liefert 0 wenn erfolgreich, sonst -1
    
        if( 0 == eingabeErgebnis )
        {
            maximumBerechnen( );
            minimumBerechnen( );
            durchschnittBerechnen( );
        }
    
        warteAufTaste( );     // oder eben der Befehl Deiner Wahl...
    }
    


  • Nick Unbekannt schrieb:

    hustbaer schrieb:

    Jedes mal das Projekt übersetzen lassen muss wenn man was machen möchte?

    Wenn ich zum Testen den Code verändere, dann muss ich neu übersetzen. Man kann zwar das system("pause") auch drin lassen, doch das stört mich dann ehrlich gesagt beim Debuggen.

    Ja.
    Musst du auch wenn du ne Shell offen hast.

    Oder meinst du du änderst Code und möchtest dann aber öfter mal den alten Code nochmal testen? In dem Fall ist ne Shell natürlich kein Fehler...
    Wobei das ein Wunsch ist den ich kaum jemals verspürt habe 🙂



  • hustbaer schrieb:

    Oder meinst du du änderst Code und möchtest dann aber öfter mal den alten Code nochmal testen? In dem Fall ist ne Shell natürlich kein Fehler...
    Wobei das ein Wunsch ist den ich kaum jemals verspürt habe 🙂

    Ich auch nicht. Ich sehe auch keinen Sinn darin, ein geändertes Programm ohne Debugger zu testen. Wenn es mir nur um das Laufzeitverhalten geht, sollte der Code eigentlich schon stehen. Deswegen gibt es eigentlich keinen Grund dann das Programm neu übersetzen zu lassen.
    Ich bin eigentlich bisher auch nur in diese Versuchung gekommen, wenn ich eine Client-Server-Anwendung erstellt habe, wo der Client und der Server in der selben Projektmappe liegen. Zwei Projekte lassen sich wohl nicht gleichzeitig Debuggen und ob da der Menüpunkt starten ohne Debugger einen Unterschied macht? Das letzte ist eine Frage, weil ich es ehrlich gesagt nie ausprobiert habe.


Anmelden zum Antworten