Whileschleife mit vector.push_back macht probleme!



  • Hallo leute,

    Ich bin neu hier im Forum und möchte erstmal alle herlich grüßen.

    Ich mache seid ein paar monaten eine Ausbildung zum IT-Assistenten und wir haben natürlich auch Programmieren in der Schule.

    Mir macht das ganze so viel spass das ich einfach selber angenfangen habe c++ zu lernen und bisher läuft es auch ganz gut.

    In der Schule sollten wir ein prgramm schreiben um wiederstände zu berechnen was auch kein problem war. Das nächste sollte eins sein um wiederständen bestimte farbringe zu zu ordnen.
    Ich habe mir gedacht es wäre gut wenn die beiden sachen in einem Programm zusammen sind und hab deshalb angefangen mein programm zu erweitern.

    Alles funktionierte einwandfrei bis ich ich eine bestimmte whileschleife verwendete. Der Compiler gibt mir keine fehlermeldung aber wenn ich im laufenden programm eie ungültige taste (ich glaube sogar teilweise bei gütligen) drücke schmiert ds programm ab. Für mich sieht aber alles richtig aus bis jetzt und ich kann nicht nachvoll ziehen was da los ist.

    #include <iostream>
    #include <conio.h>
    #include <vector>
    
        using namespace std;
    
    int main(void)
    {
        float ohm=1, ohm2=1, ohmErs=0, ohmGes = 0;
        int i=1,j=1, zahl,index=0,z,a;
        char frage;
        vector<int> storeRev;
        vector<int> store;
    
        while (1){
    
    /**  Benutzermenu zur Auswahl. */
    
        cout << "\nAuswahl: \n\nReihenschaltung    [1] \nParalleschaltung   [2]"
    
                "\nErgebnis           [3]\nWiederstandsringe  [4]"
                "\nReset              [5]\nVerlassen          [0]" << endl << endl;
    
    /**  Antwort abfangen und verarbeiten. */
    
       frage = getch();
        switch (frage){
    
    case '0': //exit
    
        return(0);
    
    case '1': //Reihenschaltung
    
    /** Gesamtwiederstand der Rheinschaltung
        ermitteln und in ohmGes für später speichern */
    
        do
        {
    
        cout << "\nReihenwiederstand " << i++ << ": ";
        cin >> ohm;
        if (ohm !=0) ohmGes += ohm;
        }
        while (ohm !=0) ;
    
        cout << "\nZwischensumme: " << ohmGes << " ohm." << endl;
        i--;
        break;
    
    case '2': //Paralellschaltung
    
    /** Ersatzwiederstand für Parallelschaltung ermitteln
        und in ohmErs für Später speichern. Variable j ist zähler.
        Ohm und ohm2 sind hilfwiederstände. */
    
       do
        {
        cout << "\nParallelwiederstand " << j++ << ": ";
        if (j == 2){
            cin >> ohm;}
        else if (j == 3){
            cin >> ohm2;
            if (ohm !=0 && ohm2 !=0) ohmErs = (ohm*ohm2)/(ohm+ohm2);
        }
        else {
            cin >> ohm;
            if(ohm !=0) ohmErs = (ohmErs*ohm)/(ohmErs+ohm);
             }
        }while (ohm !=0 && ohm2 !=0);
    
        cout << "\nzwischensumme: " << ohmErs << " ohm." << endl << endl;
        j--;
        break;
    
    case '3': //Ergebnis
    
    /** Wiederstände addieren und Gesamtwiederstand ausgeben. */
    
        ohmGes += ohmErs;
        cout << "\nGesamtwiederstand betraegt " << ohmGes << " ohm!" << endl << endl;
        break;
    
    case '4': // Wiederstandsringe
    
        ohmGes += ohmErs;
        zahl = ohmGes;
    
        cout << "Wiederstandsringe!" << endl << endl;
    
    /** Untermenü für Wiederstandsringe erzeugen  */
    
        while (frage !='0')
        {
            cout << "Gesamtwiederstand der Schaltung verwenden [1]\nEigenen Wiederstand verwenden             [2]"
            "\nZurueck zum Menu                          [0]" <<endl;
            frage =getch();
    
            switch (frage)
            {
            case '0': //exit
                cout << "zurueck zum menu!" <<endl;
                break;
    
            case '1': //Schaltungswiederstand
                zahl=ohmGes;
                if (zahl==0){
                    cout << "\nEs befindet sich kein Gesamtwiederstand im Speicher!" << endl << endl;
                }
                break;
    
            case '2': //Eigener Wiederstand
                cout << "Wiederstand angeben: ";
                cin >> ohm;
                zahl = ohm;
                break;
    
            default:
                cout << "Ungueltige Eingabe!" << endl << endl;
                break;
            }
    
        while(zahl){
            ohm = zahl%10;
            store.push_back(ohm);
            zahl/=10;
            index++;
            a = index-2;
            }
            cout << "stellen fuer multiplikation:" << a <<endl;
    
            for (index>=0;index--;){
            cout << "inhalt der box: " << store[index] << endl;
            if (store[index]==z)
                {
    
                    cout << "z ist: " << z << endl;
                    switch (z){
                    case 0: cout << "Schwarz";  break;
                    case 1: cout << "Braun";    break;
                    case 2: cout << "Rot";      break;
                    case 3: cout << "Orange";   break;
                    case 4: cout << "Gelb";     break;
                    case 5: cout << "Grün";     break;
                    case 6: cout << "Blau";     break;
                    case 7: cout << "Violett";  break;
                    case 8: cout << "Grau";     break;
                    case 9: cout << "Weiß";     break;
                    }
                }
            z++;
    
            }
        }
        break;
    
    case '5': //reset
    
    /** Werte Reset */
    
        ohmGes = 0;
        ohmErs = 0;
        i = 1;
        j = 1;
        cout << "Werte wurde zurueckgesetzt!" << endl << endl;
        break;
    
    default:
    
        cout << "\nUngueltige Eingabe!" << endl << endl;      /**Fehlermeldung bei ungültiger auswahl im Menu. */
        break;
        }
    }
    
        return(0);
    }
    

    (alt+c)

    Das Problem ist irgendwo ab zeile 127 denn wenn ich ab da auskommentiere läuft wieder normal.

    Ha ich glaube mir ist gerade eingefallen was es ist. Daa beisst sich nämlich speziell mit dem default etwas.

    Kann es sein das ich die whileschleife in jeden case extra packen muss? da er sonst auch nach dem default in diese schleife geht und dan irgendwas probeleme macht? z.b. das zahl in dem moment irgendeinen komischen wert hat.

    Naja ich poste trotzdem erstmal und probier dann damit etwas rum.

    Was ich noch gerne wissen würde ist. Wenn man so einen code hat. Bei welchen stellen macht es sinn diese als function aus zu lagern und sollte man eventuell sogar klassen oder so schreiben? (davon habe ich noch garkeine ahung).

    Und kennt jemand ne bessere lösung für meinen vector den ich später übringens immer wieder per swap oder so auf new vector setzen will/muss was nich so gut ist wie ich gelesen habe.
    Ein normales array geht nicht weil die zahl der fächer sich dynamisch an die benutzer eingaben anpassen soll.
    Es würde auch vieleicht schon reichen den ganzen inhalt und alle fächers des vectors zu löschen. (was auch nicht so gut sein soll wie ich las).

    So oder so besten Grüße
    aus Berlin



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C (C89, C99 und C11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89, C99 und C11) in das Forum C++ (auch C++0x und C++11) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Photon schrieb:

    Was ich noch gerne wissen würde ist. Wenn man so einen code hat. Bei welchen stellen macht es sinn diese als function aus zu lagern und sollte man eventuell sogar klassen oder so schreiben? (davon habe ich noch garkeine ahung).

    Moin moin!
    Hast Du noch den Überblick? Ist der Code gut wartbar?
    Die Antwort wird wohl "nein" lauten müssen. 🙂

    Die Aufteilung in Funktionen würde ich Dir dringend empfehlen. Z.B. koennte ein Grundgeruest so aussehen:

    float reihenschaltung();
    float parallelschaltung();
    void widerstandsringe(float widerstand);
    
    int main(){
      // ....
      float ohmGes = 0.0f
      int frage;
      // ....
      switch(frage){
      case '0':
        return 0;
      case '1':  // Reihenschaltung
        ohmGes += reihenschaltung();
        break;
      case '2':  // Parallelschaltung
        ohmGes += parallelschaltung();
        break;
      case '3':  // Ergebnis
        std::cout << "\nGesamtwiderstand betraegt " << ohmGes << " ohm!\n\n";
        break;
      case '4':  // Widerstandsringe
        widerstandsringe(ohmGes);
        break;
      case '5':
        ohmGes=0.0f;
        std::cout << "Werte wurden zurueckgesetzt!\n\n";
        break;
      default:
        std::cout << "Ungueltige Eingabe!\n\n";
        break;
      }
      //....
    }
    

    Wie Du jetzt schon siehst fallen die meisten Variablen aus main heraus. Der Code wird strukturierter.
    Evtl. entdeckst Du so sogar schon den Fehler.

    Auf geht's! Wiederstand [sic] ist zwecklos! 🙂



  • Die for-Schleife in Zeile 136 macht sicher nicht das, was du denkst.



  • manni66 schrieb:

    Die for-Schleife in Zeile 136 macht sicher nicht das, was du denkst.

    Aber erstaunlich nah dran.



  • Danke schonmal für die antworten.

    @ Furble ja so in etwa habe ich mir das auch vorgestellt ich bin aber noch nicht so sicher im umgang mit functionen wird daher ne gute übung.
    Warum is der typ der function wiederstandsringe void und etwas steht drin und bei den andern nich? (werde gleich ma irgendwie n tutorial zu functionen gucken).

    Edit: ne den fehler hab ich nich direkt gefunden aber ich glaube es ist weil die schleife ausserhalb der cases liegt und so oder so nach dem switch ausgeführt wird was sie nicht soll.

    zu der forschleife ja stimmt fällt mir auch auf gerade die habe ich gestern abend sehr spät noch geschrieben. Und dan auch mittendrin aufgehört wegen er fehler und weil das bett gerufen hat 😃

    Da müsste noch eine zweite schleife rein damit index stehen bleibt währed z weiterläuft bis sie übereinstimmmen. Dann erst darf der index weiter.

    Aber mal so am rande könnte ich z da nicht auch ganz weg lassen und den switch auf store[index] setzen?



  • Photon schrieb:

    Warum is der typ der function wiederstandsringe void und etwas steht drin und bei den andern nich?

    widerstandsringe() liefert kein Ergebnis zurück. Was also nicht drinsteht - aber bei den anderen - ist ein return (siehe schließende '}' in Zeile 62).
    Wenn Du Dich noch gar nicht mit Funktionen auskennst hilft Dir vielleicht auch dieses etwas mit Leben gefülltes Beispiel:

    #include <iostream>
    
    float reihenschaltung();
    float parallelschaltung();
    void widerstandsringe(float widerstand);
    
    int main(){
      float ohmGes = 0.0f;
      for(;;){
        std::cout << "1. reihenwiderstand\n2. parallelwiderstand\n"
                     "3. anzeigen\n4. widerstandsringe\n";
        int frage;
        std::cin>>frage;
        switch(frage){
        case 1:
          ohmGes += reihenschaltung();
          break;
        case 2:
          ohmGes += parallelschaltung();
          break;
        case 3:
          std::cout << "\nGesamtwiderstand betraegt " << ohmGes << " ohm!\n\n";
          break;
        case 4:
          widerstandsringe(ohmGes);
          break;
        default:
          return 0;
        }
      }
    }
    
    float reihenschaltung(){
      using namespace std;
      int i=1;
      float result = 0.0f, ohm;
      do
        {     
          cout << "\nReihenwiederstand " << i++ << ": ";
          cin >> ohm;
          if (ohm !=0) result += ohm;
        }
      while (ohm !=0) ;
    
      cout << "\nZwischensumme: " << result << " ohm." << endl;
      return result;
    }
    
    float parallelschaltung(){
      float result = 0.0f;
      // dadadi-dadadum
      return result;
    }
    
    void widerstandsringe(float widerstand){
      const char* farbe[] = { "schwarz", "rot", "gold" };
      int i = widerstand; // ganzzahlig machen...
      while(i){
        std::cout << farbe[i%3] << '\n';
        i /= 10;
      }
    }
    


  • ok danke ich denk mit dem beispiel werde ich es hinbekommen die sache als function auszulagern.

    Ich nehme an mit for(;; ) bekommt man auch soetwas wie eine endlosschleife?!

    ist es sicherer oder sauberer float zahlen mit 0.0f zu deklarieren und steht das f für float?

    Diese stelle kann ich noch nicht ganz nachvollziehen.

    void widerstandsringe(float widerstand){
      const char* farbe[] = { "schwarz", "rot", "gold" };
      int i = widerstand; // ganzzahlig machen...
      while(i){
        std::cout << farbe[i%3] << '\n';
        i /= 10;
      }
    

    warum const char* farbe[] und nicht einfach char farbe[]?
    soweit ich weiss hat der stern etwas mit pointern zu tun(mit pointern habe ich noch nicht wirklich gearbeitet.

    Den cout verstehe ich auch nicht so ganz aber ich denke das ist nur ein bespielbefehl?!
    Ich muss nämlich den wiederstand in einzelne ziffern zerlegen bzw die ersten beiden ziffern als wert auslesen und die restlichen stellen zählen damit ich sie für die auswahl des richtigen multiplikators werdenden kann also z.b. 3 stellen wäre *1000 und ein ring der entsprechenden farbe. Hab jetzt mal das hier geschrieben:

    #include <iostream>
    #include <vector>
    
        using namespace std;
    
    int main(void)
    {
        float ohm=0.0f;
        int zahl,index=0,mult;
        vector<int> store;
        const char* arr[] = {"schwarz","braun","rot","orange","gelb","gruen","blau","violett","grau","weiss"};
    
        cin >> ohm;
        zahl = ohm;
    
        while(zahl){
            store.push_back(zahl%10); 
            zahl/=10;
            index++;
            }
        mult=index-2;
        cout << index << endl;
        cout << mult << endl;
    
        for (index>=mult;index--;){
            cout << "inhalt der box: " << store[index] << endl;
            cout << "Farbring: "<< arr[store[index]] << endl;
            }
        cout << arr[mult];
        return(0)
    }
    

    seltsamerweise macht die forschleife nicht was ich will. Sie sollte nach 2 durchläufen stoppen was sie aber nicht tut. Ich könne es schnell mit

    for(int i=0; i < 2; i++){...

    lösen aber das ist nicht so gut finde ich und index muss ich dann eh noch per index-- irgendwo runter setzen deshalb gefällt mir meine variante besser.
    Hat jemand ne ahnung warum das nich geht?

    So ähnlich will ich das später als function einbinden wobei ich noch mehr ringe verteilen muss und auch gleich 2 verscheidene tabellen habe einmal für 4 ringe und einmal für 6 aber das werde ich schon hinbekommen irgendwie.

    Entschuldigung für meine vielen fragen ich möchte alles genau verstehen und verwende ungern codes die ich nicht komplett verstehe.

    edit: 5 mal 😃



  • Photon schrieb:

    Ich nehme an mit for(;; ) bekommt man auch soetwas wie eine endlosschleife?!

    ja.

    Photon schrieb:

    ist es sicherer oder sauberer float zahlen mit 0.0f zu deklarieren und steht das f für float?

    Sicherer nicht, aber vielleicht eindeutiger. 0.0 ist erstmal ein double , der dann vom compiler in ein float umgewandelt werden muss, deswegen kann ich auch gleich einen float hinschreiben. Ja: das f steht für float .

    Photon schrieb:

    warum const char* farbe[] und nicht einfach char farbe[]?
    soweit ich weiss hat der stern etwas mit pointern zu tun(mit pointern habe ich noch nicht wirklich gearbeitet.

    farbe ist ein Array von 3 Zeigern auf const char. Vereinfacht: wenn Du ein string-literal - also einen Text in doppelten Anführungszeichen - im Quellcode hast, kannst Du dem einen "Zeiger auf const char" zuweisen. Damit kannst Du den Text an einer Stelle definieren und an anderer Stelle benutzen. Um nicht für jede Farbe einen Variable haben zu muessen, habe ich die drei const char* in ein Array "gelegt" und kann so bequem über den index darauf zugreifen.z.B.

    int main(){
      // 3 string-literale in einem array
      const char* s[] = { "Hallo", "Welt", "!\n" };
      const char  c  = ' '; // ein char
      std::cout << s[0] << c << s[1] << s[2];
    
      // ein einzelnes string-literal:
      const char* str = "'Widerstand' schreibt sich ohne 'e' nach dem 'i'.\n";
      std::cout << str;
    }
    

    Photon schrieb:

    Den cout verstehe ich auch nicht so ganz aber ich denke das ist nur ein bespielbefehl?!

    Jupp. Nur ein Beispiel.

    Photon schrieb:

    seltsamerweise macht die forschleife nicht was ich will. Sie sollte nach 2 durchläufen stoppen was sie aber nicht tut.

    Schau Dir in Deinen Unterlagen nochmal den Schleifenkopf der for -Schleife an. manni66 und nwp3 haben Dich schon darauf hingewiesen.

    Photon schrieb:

    Entschuldigung für meine vielen fragen ich möchte alles genau verstehen und verwende ungern codes die ich nicht komplett verstehe.

    Das ist gut und okay, solange Du zwischen Deinen Fragen Fortschritte machst und der Wille zur Mitarbeit erkennbar ist.
    Ist beides gegeben. 🙂



  • ok hab mich jetzt nochmal rangesetzt um bin auch schon ein ganzes stück weiter

    Allerdigs stürzt das programm ab wenn ich mit dem gesamtwiederstand der schlatungen in das ringmenü gehe. Ich habe keine ahnung warum.
    Mit eigenem wiederstand funktioniert es.

    Es besteht auch die möglichkeit das die widerstände dezimalzahlen sind. Kann mir jemand einen tip geben wie ich nicht nur die zehnerstellen einer zahl herausfinden kann sondern auch die nachkommastellen bzw wie ich festellen kann ob die zahl eine dezimalzahl ist.

    Keine ahnung wie ich es erklären soll^^ ich es gibt nämlich auch solche wiederstände z.b. 0.15 ohm dafür wird dann der multipliaktor 0.01 verwendet.
    Ich schätze ich werde für diese fall eine eigene funktion schreiben. habe aber keine ahnung wie ich da ran gehen soll.

    Danke schonmal! ohne die hilfe wär ich nicht so weit gekommen.



  • 170 Zeilen Code? Das liest sich niemand durch. Beachte die Informationen in diesem Link:
    Den richtigen Code posten: reduziertes compilierbares Beispiel Besonders, was unter "Den Code reduzieren" steht.

    Warum stürzt es ab? Vielleicht, weil index in widerstandsringe() nicht initialisiert ist, oder der Algorithmus nich stimmt.
    Solche Fehler sollten schon durch einfache Testausgaben feststellbar sein.

    void widerstandsringe(float widerstand,int a){ //Farbringe werden wiederständen zugeordnet
      // yadi yadi yada...
      for (index; index >= mult; index--){
        // zu testzwecken eingefuegt:
        std::cout << "index: " << index << "store.size()" << store.size() << '\n';
        cout << arr[store[index]] << ", ";  //vectorindex rückwärts laufen lassen um
      }                                   //ringe von vorne nach hinten aus array auszugeben
      cout << arr[mult] << endl;
    }
    

    Desweiteren:
    Herstellerspezifische Erweiterungen ( <conio.h> , getch() ) schränken den Kreis Deiner Leserschaft noch weiter ein und sind auch nicht gerne gesehen.
    Benutz standard C++ in von Dir geposteten Code.

    Noch zu Deiner Frage mit den Widerständen mit Nachkommastellen:
    Du könntest doch mit Milliohm oder so rechnen, dann hättest Du wieder Ganzzahlen.



  • ok entschuldigung das hätte ich mir denken könne ich werde mich an die arbeit machen und den code reduzieren. Das mit dem index initialisieren ist eine gute idee.

    zu der milliohm sache habe ich mir jetzt gedacht das man die eingegebenen float zahl solange mal 10 nimmt bis diese eine ganze zahl ist wenn man dabei mitzählt weis man wie viel stellen nach dem komma es sind. Irgendwie sowas da muss ich mal ein bischen tüftlen.

    Warum is conio.h nicht sehr beliebt? Ich hab jetzt schon öfters mal gelesen das diese function oder jenes stück code nicht beliebt sind . Woher weiss ich was ich verwenden solllte und was nicht?

    Ich lösche den quelltext aus meinem post von vorher wegen der übersichtlchkeit. Heute oder morgen folgt die kürzung.



  • Photon schrieb:

    Warum is conio.h nicht sehr beliebt? Ich hab jetzt schon öfters mal gelesen das diese function oder jenes stück code nicht beliebt sind . Woher weiss ich was ich verwenden solllte und was nicht?

    <conio.h> ist ein Header der nur auf Windows Systemen zu finden ist.
    Wenn Menschen, die kein Windows benutzen Deinen Quellcode ausprobieren wollen muessen sie diesen erst portieren - klar, dass da schon die ersten aussteigen.

    Hier im C++ Forum solltest Du nur Dinge verwenden, die in C++ beschrieben werden - gute Bücher/Unterlagen scheuen plattformspezifische Konstrukte.
    Es ist aber auch kein Beinbruch am Anfang nicht zu wissen, was Standard C++ ist, und was nicht.

    Photon schrieb:

    Ich lösche den quelltext aus meinem post von vorher wegen der übersichtlchkeit. Heute oder morgen folgt die kürzung.

    Das mit dem Löschen ist natürlich Deine Sache, aber es hülfe der Übersicht mehr, wenn Dein Posting so bliebe und Du nur ein neues erstelltest.

    Das würde bestenfalls nur noch eine kleine main() haben, die die Funktion widerstandsringe() mit einem festen Parameter aufruft, und Du sagst, was Du erwartest und was das Ergebnis ist:

    int main(){
      int a = 42; // a gibt dieses und jenes an
      float ohm = 320.0f;
      widerstandsringe(ohm, a);
      // wenn ich jetzt 4 Ringe auswähle erwarte ich a,b,c,d
      // bei sechs Ringen eigentlich u,v,w,x,y,z.
      // Stattdessen bekomme ich eine Zugriffsverletzung. Was ist da los?
    }
    


  • ok ich bin ein bischen krank und lag im bett die letzen 2 tage. Ich habe heute nochmal ein wenig rumprobiert und der index war wirklich das problem.
    Jetzt ist das progamm fast fertig nurnoch der kommastellenpart fehlt aber das bekomme ich schon hin.

    Danke lieber Furble Wurble!!!

    Wenn ich das nächste mal ein thread öffne weiss ich auch wie ich mein problem anschaulich machen kann und so weiter.

    👍 👍 👍

    Hier nochmal die funktion falls jemand probleme damit hat und nachschauen will oder so

    void widerstandsringe(float widerstand,int a){ //Farbringe werden wiederständen zugeordnet. 
    
    using namespace std;
    
    int index = 0, mult;
    vector<int> store;
    const char* arr[] = {"schwarz","braun","rot","orange","gelb","gruen","blau","violett","grau","weiss"};
    int i = widerstand;
    
        cout << "Farbringe: ";
        while(i){
            store.push_back(i%10); //Einzelne Ziffer von hinten nach vorne in vector speichern
            i /= 10;  //i auflösen
            index++;
             }
        mult = index - a; //stellen für multiplikator. a bestimmt wiel viele stellen abgeschnitten werden.
        index = index - 1;
    
        for (index; index >= mult; index--){
            cout << arr[store[index]] << ", ";  //vectorindex rückwärts laufen lassen um
            }                                   //ringe von vorne nach hinten aus array auszugeben
        cout << arr[mult] << endl;
        }
    

Log in to reply