Forum: PC-Programmierung C++ Programm tut nicht was es soll


von wulga (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Programm geschrieben, welches Eingaben entgegennehmen und 
diese dann auswerten soll. Die Eingabe soll z.B. so erfolgen: 2,3p; 
daraufhin wird die Permutation aus 2 und 3 errechnet. Ob die Berechnung 
richtig ausgeführt wird, soll erstmal nicht wichtig sein. Mir gehts in 
erster Linie um eine Fehlerbehandlung die scheinbar ignoriert wird. Ich 
prüfe ob die erste Zahl größer als die zweite ist, ist dies der Fall, 
dann soll das Programm eine Fehlermeldung ausgeben und beendet werden.

Hier der Code, ich hoffe ihr könnt mir da helfen:
1
/*
2
Das Programm soll:
3
    den Benutzer auffordern zwei Zahlen einzugeben
4
    abfragen, ob die Anzahl der möglichen Permutationen oder Kombinationen berechnet werden soll
5
    und schließlich das Ergebnis ausgeben.
6
7
Diese Aufgabe besteht aus mehreren Teilen:
8
    Zuerst analysieren Sie die obigen Anforderungen.
9
    Schreiben Sie genau auf, was das Programm tun muss.
10
11
Gehen Sie dann zur Entwurfsphase über:
12
    Schreiben Sie Pseudocode für das Programm und zerlegen Sie ihn in Teilkomponenten.
13
14
Das  Programm  sollte  auch  über  eine  vernünftige  Fehlerbehandlung  verfügen:
15
    Stellen  Sie sicher, dass für fehlerhafte Eingaben nützliche Fehlermeldungen ausgegeben werden
16
*/
17
#include "../../std_lib_facilities.h"
18
19
class PermComb {
20
public:
21
    PermComb();
22
    bool getInput();
23
    int calculate();
24
    void printResult();
25
    int faculty(int num1, int num2);
26
27
    // Konstanten
28
    const char comma;
29
    const char semicolon;
30
    const char permutation;
31
    const char combination;
32
33
    // Variablen
34
    int num1, num2, result;
35
    char ch1, ch2, ch3;
36
};
37
38
PermComb::PermComb():num1(0), num2(0), ch1('_'), ch2('_'), ch3('_'), comma(','), semicolon(';'), permutation('p'), combination('c')
39
{
40
    // entweder über die Memberinitialiererliste initialisieren oder direkt hier drin, beide richtig
41
    /*
42
    num1 = num2 = 0;
43
    ch1 = ch2 = ch3 = '_';
44
    comma = ',';
45
    semicolon = ';';
46
    permutation = 'p';
47
    combination = 'c';
48
    */
49
}
50
51
bool PermComb::getInput()
52
{
53
    cin >> num1 >> ch1 >> num2 >> ch2 >> ch3; // note that >> skips whitespace (space, newline, tab, etc.)
54
    if(!cin) error("Fehler: Zahl erwartet");    // ein char akzeotiert sowohl Zahlen als auch Ziffern, daher greift die Abfrage if(!cin) nur bei num1 und num2
55
    else if(ch1 != comma) error("Fehler: ',' zwischen erster und zweiter Zahl erwartet");
56
    else if(ch2!='p' && ch2 != 'c')  error("Fehler: 'p' oder 'c' als Eingabe erwartet");
57
    else if(ch3 != semicolon) error("Fehler: ';' als Eingabe erwartet");
58
    return 1;
59
}
60
61
int PermComb::calculate()
62
{
63
    // Vorbedingung num1 muss größer als num2 sein
64
    if(num1>num2) error("Fehler: Zahl1 < Zahl2");
65
    cout << num1 << "   " << num2 << '\n';
66
67
    if(ch2=='p') result=faculty(num1, num2);
68
    //else result=combination(num1, num2);
69
70
}
71
72
void PermComb::printResult()
73
{
74
    cout << num1 << ch1 << num2 << ch2 << ch3;
75
    cout << '\n' << result << '\n';
76
}
77
78
int PermComb::faculty(int num1, int num2)
79
{
80
    int sum = num1-num2;
81
    for(int i=sum; i>0; --i) {
82
        sum = sum*(sum-1);
83
    }
84
    return sum;
85
}
86
87
int main()
88
try{
89
    cout << "Bitte zwei ganze Zahlen eingeben (getrennt mit Komma),\n";
90
    cout << "gefolgt von 'p' oder 'm'. Mit ';' Eingabe beenden. (Bsp.: 3,2;): ";
91
    PermComb t;
92
    while(t.getInput())
93
    {
94
        //t.getInput(); // speichert zwei Zahlen in der Klasse
95
        t.calculate(); // Frage ob Permutation oder Kombination berechnen + Berechnung(Funktionsaufruf)
96
        t.printResult(); // Ausgabe d. Ergebnisses
97
    }
98
}
99
catch (runtime_error e) {  // this code is to produce error messages
100
  cout << e.what() << '\n';
101
  //keep_window_open("0");  // For some Windows(tm) setups
102
}
103
catch (...) {
104
    cerr << "Komische Ausnahmeauslösung";
105
}

von Rainer V. (rudi994)


Lesenswert?

Compilieren von o.g. Code liefert hier Warnungen, weil comma, semicolon 
usw. in Klasse PermComb als Konstanten definiert sind und erst später 
initialisiert werden. Ich habe das in private-Variablen geändert, die im 
Konstruktor auf ihre Sollwerte gesetzt werden. Dann funktioniert auch 
die Eingabe-Fehlerabfrage. Zudem: Wertrückgabe in PermComb::calculate() 
fehlt. std_lib_facilities.h habe ich von stroustrup.com kopiert, kann 
ich nicht gebrauchen wg. Fehlern, die ich nicht beseitigen kann. Für 
exception handling includiere ich Header <stdexcept> und habe auch mal 
in der Eingabe-Abfrage anstatt Ausgaben mit error() Ausnahmen mit throw 
(char*)"Fehlermeldung" geworfen und mit catch (char *e){...} abgefangen. 
Funktioniert ebenfalls. LG

von Wilhelm M. (wimalopaan)


Lesenswert?

Ist das eine Übungsaufgabe eines C++-Kurses?

Neben einigen Fragwürdigkeiten ist schlecht, das SRP (Single 
Responsibility Principle) nicht eingehalten wird: was hat die Klasse 
PermComb mit der Benutzereingabe zu tun? Nichts.

Der Kommentar im ctor
1
// entweder über die Memberinitialiererliste initialisieren oder direkt hier drin, beide richtig

ist falsch, denn initialisieren macht man für primitive DT (am besten) 
als in-class-initializer, oder (wie hier) in der 
Elementinitialisierungsliste. Aber zuweisen (wie ctor-Rumpf als 
Kommentar) ist keine Initialisierung und bei const-Membern nicht 
möglich! Bei primitiven DT mag der Unterschied klein erscheinen, bei UDT 
kann er gewaltig sein bis hin zu schlicht unmöglich (wenn der DT nicht 
kopier-/verschiebzuweisbar ist.

Und noch ein Tipp: liefere kleinere und vollständige Beispiele, die auch 
direkt so compiliert werden können, ohne weitere Files zu benötigen.

von wulga (Gast)


Lesenswert?

Hallo Rainer, habe es jetzt auch ohne "const" gemacht und alles im 
Konstruktor initialisiert, jetzt funktioniert die Fehlerbehandlung auch, 
mir ist allerdings immernoch unklar warum das mit dem "const" ein 
Problem war. Wenn ich z.B. folgendes mache (siehe Code), dann 
funktioniert das Programm zwar, aber der Compiler gibt Warnmeldungen 
aus:
1
...
2
    // Konstanten
3
    const char comma = ',';
4
    const char semicolon = ';';
5
    const char permutation = 'p';
6
    const char combination = 'c';
7
...

Wanrmeldung des Compilers:
"non-static data-memebr initializer only available with C++11"



Hallo Wilhelm, so in der Art, es handelt sich um eine Übungsaufgabe aus 
dem Buch "Einführung in die Programmierung mit C++ - Stroustrup".

Dass die Klasse nicht sinnvoll aufgebaut ist, hat damit zu tun, dass ich 
Anfänger bin und wie es aussieht Übung brauche um besser zu werden, an 
dieser Stelle danke für den Hinweis, habe es mir zu Herzen genommen.

Mein Kommentar im Konstruktor ist in der Tat unsinnig, da habe ich die 
Memberinitialisierungsliste mit ganz normaler Initialisierung von 
Variablen gleichgesetzt. Aber ich muss Konstanten doch einen Wert 
zuweisen können, wie wird das dann richtig gemacht? 
Memberinitialisierungsliste scheint ja nicht zu funktionieren und wenn 
ich die Konstanten sofort bei der deklaration definiere - also einen 
Wert übergebe - dann bekomme ich Warnmeldungen vom Compiler...

von wulga (Gast)


Lesenswert?

wulga schrieb:
> Aber ich muss Konstanten doch einen Wert
> zuweisen können, wie wird das dann richtig gemacht?

Ups da habe ich jetzt blödsinn geschrieben, wenn ich die Konstanten nur 
deklariere und dann im Konstruktor initialisiere, dann funzt es 
einwandfrrei, habe es eben getestet.

von Mark B. (markbrandis)


Lesenswert?

Wozu jetzt einen zweiten Thread?

von beric (Gast)


Lesenswert?

wulga schrieb:
> Diese Aufgabe besteht aus mehreren Teilen:
>     Zuerst analysieren Sie die obigen Anforderungen.
>     Schreiben Sie genau auf, was das Programm tun muss.
>
> Gehen Sie dann zur Entwurfsphase über:
>     Schreiben Sie Pseudocode für das Programm und zerlegen Sie ihn in
> Teilkomponenten.

Dein Code sieht nicht danach aus, dass du diesen Teil der Aufgabe schon 
bewältigt hast.

von wulga (Gast)


Lesenswert?

Mark B. schrieb:
> Wozu jetzt einen zweiten Thread?

Ist nur ein wenig dumm gelaufen,  in  diesem Beitrag sollte nur 
behandelt werden warum die Fehlerbehandlung nicht funktioniert, 
letztendlich sind wir dann bei den Konstanten gelandet die ich in einem 
anderen Beitrag erwähnt habe, das Problem wurde dort ja aber behoben. 
Von dem her ist dieser Beitrag also abgeschlossen.

 @beric
 Analyse und Programmablauf mache ich im Kopf. Pseudocode macht man doch 
nur wenn das Problem wirklich komplex und unübersichtlich wird? Aus 
meiner Sicht alles eingehalten.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.