Hilfe bei der Ausgabe in eine .txt datei.



  • Bool ist ein C++-Datentyp, der einen Wahrheitswert speichern kann, also entweder true oder false. Er ist aber nicht nur ein Bit groß, sondern ein Byte (da er sonst nicht adressiert werden könnte.



  • void berechnen_einzelne_kraft()
    {
    					  ergebnis_1 = 0;											
    					  zähler_1 +=  1;												
    			cout << "Wieviel Kräfte haben Sie? : "; cin >> anzahlkraefte;		
    			cout << "\nGeben Sie nun die Kräfte an.\n";							
    
    			 for(i = 0; i < anzahlkraefte; i++)									
    			 {   
    			  cout <<"Geben Sie Kraft Nummer " << i + 1 << " ein : ";cin >> kraefte[i]; 			 
    			  ergebnis_1 += kraefte[i];	
    			  if (i<1)																
    				{																		
    				ofstream outfile;														
    				outfile.open ("Kräfteausgabe.txt", ios::app); 
    				outfile << "Einzelne Kraft\n";
    				outfile << "Die Daten der Berechnung "<<zähler_1<<"  : ";
    				outfile.close();  
    				}
    			 ofstream outfile;															
    			 outfile.open ("Kräfteausgabe.txt", ios::app);								
    			 outfile << " | "<<kraefte[i]<<" ";
    			 outfile.close(); 
    			 }																			 
    			 ergebnis_1 *= -1; 	
    
    			 ofstream outfile;															// Schreiben des Ergebnisses
    			 outfile.open ("Kräfteausgabe.txt", ios::app); 
    			 outfile << "\nDie berechnete fehlende Kraft beträgt : "<< ergebnis_1 <<" N\n\n" ;
    			 outfile.close(); 
    
    			 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),BACKGROUND_INTENSITY|BACKGROUND_RED); 
    			 cout << "\nDie fehlende Kraft betraegt: " << ergebnis_1 << " kN\n\n";							   			
    			 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);	
    			Sleep(3000);					
    }
    
    int main() 
    
    {  
    setlocale(LC_ALL,"GERMAN");	
    
      willkommens_bildschirm();
      bool abbruch = false;
      do
      {
      char menueauswahl = menue();
        switch(menueauswahl) 
        { 
    
        case '1':
          hilfe_bildschirm ();
          break;  
    
        case '2':		
          berechnen_einzelne_kraft();		  
          break;
    
    	case '3':
          berechnung_lagerkraefte();
          break;
    
    	case 'q':
          abbruch=true;
          break;  
    
        default:
          cout << "\n\nFalsche Eingabe!\n";
          cout << "Bitte erneut versuchen";
    	  Sleep(3000);	
    	}
    }while (!abbruch); 
    }
    

    Bevor ich mich nun ranmache das ganze zusammen zu bauen (sind insgesamt 9 einzelne Berechnungen 😉 ), habe ich noch Fragen.

    Ist es möglich, das wenn die Zeilen 56 - 58 (case 2) ausgeführt worden sind, man da eine Auswahl hinmacht wo man auswählen kann ob man zu 56 oder zu 48 springt.

    Wie ich das mit goto machen würde weiß ich ja, aber das ist ja nicht der richtige Weg 😉

    Wenn ich die Berechnung in 56 - 58 gemacht habe, kommt das Ergebnis, das ich mir mit sleep ein paar sekunden anschauen kann. Gibt es ein Befehl, der eine Pause einbaut und erst bei drücken von Enter fortfährt?

    Ich danke Euch schonmal.



  • Ist es möglich, das wenn die Zeilen 56 - 58 (case 2) ausgeführt worden sind, man da eine Auswahl hinmacht wo man auswählen kann ob man zu 56 oder zu 48 springt.

    Was genau meinst Du, eine Auswahl, ob man die gleiche Berechnung nochmal durchführen will?

    Du solltest übrigens die Sleep( ) ebenso weglassen - auf der Console kommt immer gleich die nächste Ausgabe. Und niemand wartet gern.

    Versuche getchar( ) .



  • Getchar() funktioniert nicht. mit getch() klappt es.

    Ja, ich meine das man entweder die selbe Berechnung nochmal macht oder zum Auswahlbiledschirm gelangt und eine Andere berechnet. Das man das über ein kleines Menü macht. Auswahl 1 oder 2.

    Das Menü ist nicht das Problem, nur wie ich es dann umsetze, das weiß ich nicht, da es ja in mehreren "case" vorkommt.



  • Es gibt viele Wege. Ein eleganter wäre folgender: Du trennst die Auswahl des später zu verwendenden Algorithmus' (also Lagerkräfte, einelne Kraft etc.) von der eigentlichen Berechnung. Warum? Weil Du eine Art Steuerkonstrukt dazwischenschalten willst, nämlich die Steuerung, ob der Algorithmus einmal oder mehrmals aufgerufen werden soll.

    Zunächst lese bitte etwas über Funktionspointer.

    Dazu definierst Du einen neuen Typ, nämlich pointer auf eine Funktion, die void nimmt und void zurückgibt:

    typedef void(*berechnung_t)(void);
    

    Dann hast Du Deine Berechnungen wie gehabt. Die Signatur dieser Funktionen passt zum Funktionspointer-Typ:

    void berechnen_einzelne_kraft()     // <-- ist eine void-Funktion, die void zurückgibt
    {
    	cout << "einzeln" << endl;
    }
    
    void berechnung_lagerkraefte()           // <-- ebenso
    {
    	cout << "lager" << endl;
    }
    

    Das Wiederholungssteuerkonstrukt ist wieder eine eigene Funktion, die einen Pointer auf jede beliebige solche Funktion nimmt:

    void mehrfach_berechnen( berechnung_t berechnungPtr )
    {
        for( ; ; )
        {
            // Hier wird die übergebene Berechnung tatsächlich aufgerufen:
            berechnungPtr( );
    
            // Auswahlmenü
            cout << "1: Wiederholen" << endl;
            cout << "2: Ende" << endl;
            char auswahl;
            cin >> auswahl;
    
            if( '2' == auswahl )
                break;
        }
    }
    

    In main ist jetzt nur noch die Auswahl des Algorithmus':

    char auswahl = menue( );
    
    switch( auswahl )
    {
        case '2':
            // Übergibt die auszuführende Berechnung:
            mehrfach_berechnen( berechnen_einzelne_kraft );
    	break;
    
        case '3':
            mehrfach_berechnen( berechnung_lagerkraefte );
            break;
    }
    

    PS: Man kann natürlich den Aufruf von mehrfach_berechnen( ) nochmal aus dem switch-Block rausziehen und statt dessen in den cases einen lokalen Funktionspointer entsprechend füllen. Das sind dann die Feinheiten für später...



  • Hat alles super Funktioniert danke.

    Wie funktioniert das for( ; ; ) ?

    Den Rest suche ich mir so zusammen. Muß alles in einer Präsentation erklären.
    Nur über das for mit leeren Inhalt habe ich nichts gefunden.



  • Genauso wie while(true).
    Goto-Ersatzcode:

    :startlbl
    //Schleifeninhalt
    //break würde so aussehen: goto afterlbl
    goto startlbl  //jedesmal nach der Schleife wird zurückgesprungen, man kann nur mit break; die Schleife abbrechen
    :afterlbl
    


  • wxSkip schrieb:

    Goto-Ersatzcode:

    Bin nicht so ganz überzeut, ob goto jemals ein Ersatzcode für etwas anderes ist...

    for( ; ; ) ist eine übliche Notation, um eine Endlosschleife zu produzieren. Es sticht sofort ins Auge und man weiß, was gemeint ist.

    Im ersten Argument wird definiert, was vor Start der Schleife ausgeführt werden soll, im dritten Argument, was nach jedem Durchlauf geschehen soll. Hier haben wir: nichts.
    Entscheidend ist nur der mittlere Teil: wenn die Bedingung darin falsch ist, bricht die Schleife ab. Ein komplett leerer Test wird als wahr angesehen, daher funktionert eine Endloschleife. Wenn Dir das zu haarig ist, verwende eine der anderen üblichen Schreibweisen statt dem for :
    while( 1 == 1 )

    while( true )

    Übrigens ist es nicht ganz unumstritten, was ich vorgeschlagen habe. Es gibt auch die Ansicht, dass, wenn man eine Abbruchbedingung hat (und das haben wir: die entsprechende Taste), man auch eine Schleife mit Abbruchbedingung nehmen soll - und eine Endlosschleife nur dann, wenn sie wirklich endlos läuft.

    Man hätte z.B. das auch so schreiben können:

    char auswahl = '\0';
    do
    {
        ....
        cin >> auswahl;
    } while( '2' != auswahl );
    

    Das habe ich deshalb nicht gemacht, da die Variable, die über den Abbruch entscheidet ( auswahl ), außerhalb des Schleifenkörpers definiert werden muss. Wenn die Schleife länger wird, wird der Abstand (Anzahl der Zeilen) zwischen Definition und erstmaligem Gebrauch auch größer. Diese vertikale Distanz sollte immer so klein wie möglich bleiben.

    Letztlich ist es Geschmackssache, und ich denke, wenn auf den ersten Blick ersichtlich ist, was das Programm tut und auch unsere Abruchbedingung mit dem break gut zu sehen und eindeutig ist, man den pragmatischen Weg so gehen kann. Nur falls jemand bei Deiner Präsentation fragt...



  • minastaros schrieb:

    Übrigens ist es nicht ganz unumstritten, was ich vorgeschlagen habe. Es gibt auch die Ansicht, dass, wenn man eine Abbruchbedingung hat (und das haben wir: die entsprechende Taste), man auch eine Schleife mit Abbruchbedingung nehmen soll

    Generell ist es sicher vorzuziehen, auf eine der üblichen Schleifen ohne Sprünge aus dem Rumpf zurückzugreifen. Manchmal muss man so aber Code duplizieren oder Hilfsvariablen einführen, und dann spricht nichts gegen ein continue oder break im Rumpf.

    minastaros schrieb:

    und eine Endlosschleife nur dann, wenn sie wirklich endlos läuft.

    Ich kann mir da gerade nichts vorstellen, was kein Fehler oder unschön programmiert ist (wie ein Thread, der von aussen terminiert wird). Hast du ein Beispiel?



  • Nexus schrieb:

    Manchmal muss man so aber Code duplizieren oder Hilfsvariablen einführen, und dann spricht nichts gegen ein continue oder break im Rumpf.

    Genau, deswegen mache ich das ja auch und sehe auch keinen Grund, es nicht zu tun, solange es gleich erkennbar ist (im Gegensatz z.B. zu so "Tricks", die Abbruchbedingung von for-Schleifen zu manipulieren). Ich meine jedoch, in Büchern zum Thema "sauberes Programmieren" sowas gelesen zu haben, ähnlich wie "jede Schleife nur ein Ausstiegspunkt". Wobei die guten Bücher auch sagen, die Empfehlungen zwar zu bedenken, es aber pragmatisch angehen zu lassen.
    Ich wollte rellik nur darauf hinweisen, dass eine solche Frage kommen könnte.

    Nexus schrieb:

    Ich kann mir da gerade nichts vorstellen, was kein Fehler oder unschön programmiert ist (wie ein Thread, der von aussen terminiert wird). Hast du ein Beispiel?

    Ein embedded System, was so lange laufen soll, bis man tatsächlich die Spannung wegnimmt. Also etwas, wo die Schleife nicht durch "normale" Ereignisse wie hier durch eine Benutzereingabe beendet wird, sondern nur im äußersten Extremfall durch einen übergeordneten Fehler.

    Edit: ich würde auch in jenen Threads durch eine Endlosschleife deutlich zu machen, dass die Schleife immer laufen sollte. Spricht ja nichts gegen eine Abbruchbedingung.


Anmelden zum Antworten