Newbie-Frage - Programm stürzt immer ab
-
Hi erstmal!
Ich lerne seit ein paar Tagen C++. Bisher hat alles ganz gut geklappt, aber jetzt habe ich ein Problem: Ich möchte ein Programm mit folgender Aufgabenstellung schreiben:Entwickeln Sie eine C++-Anwendung, die den Anwender zur Eingabe von drei Zahlen auffordert. Das Programm soll den Wert 10 zur ersten eingegebenen Zahl hinzuaddieren, das Ergebnis mit der zweiten eingegebenen Zahl multiplizieren und dann durch die dritte eingegebene Zahl dividieren. Die Berechnung soll hierbei innerhalb einer einzigen Code-Zeile erfolgen. Das Ergebnis soll auf den Bildschirm ausgegeben werden. Hinweis: Zum Umwandeln einer Zahl innerhalb eines Arrays vom Typ char benötigen Sie die Funktion atoi(). Dieser Funktion übergeben Sie das Array zwischen den runden Klammern und erhalten als Rückgabewert eine Zahl vom Typ int.
Das hat bisher auch ganz gut geklappt und der Compiler (Borlands BCC55 sowie Bloodshed dev-c++) beschweren sich auch nicht über irgendwelche fehler beim kompilieren. allerdings stürzt das programm IMMER nach der eingabe der ersten zahl ab. ich wäre froh, wenn ihr es auch einmal kompilieren könntet und mir sagen könntet, ob es an meinem pc liegt oder an irgendeinem fehler im programm. bitte beschwert euch nicht über den schlechten stil, aber ich lerne noch ;). und schreibt gaaanz viele verbesserungvorschläge
.
bis bald
yhamm#include <iostream> int main() { char Buffer1[20]; char Buffer2[20]; char Buffer3[20]; int a, b, c, Ergebnis; std::cout << "Sie muessen nun drei Zahlen eingeben. Mit Ihnen wird gerechnet. Legen wir los.\nZahl 1:" << std::flush; std::cin.get (Buffer1, sizeof(Buffer1)); a = std::atoi(Buffer1); std::cout << "\nZahl 2:" << std::flush; std::cin.get (Buffer2, sizeof(Buffer2)); b = std::atoi(Buffer2); std::cout << "\nZahl 3:" << std::flush; std::cin.get (Buffer3, sizeof(Buffer3)); c = std::atoi(Buffer3); Ergebnis=(10 + a) * b / c; std::cout << "\nDie Loesung der Aufgabe (10+a)*b/c lautet " << Ergebnis << "." << std::endl; }
-
Versuch mal folgendes:
#include <iostream.h> #include <conio.h> int main() { int zahl_a, zahl_b, zahl_c, ergebnis; std::cout << "Sie muessen nun drei Zahlen eingeben. Mit Ihnen wird gerechnet. Legen wir los.\nZahl 1: \n"; std::cin >> zahl_a; std::cout << "\nZahl 2:\n"; std::cin >> zahl_b; std::cout << "\nZahl 3:\n"; std::cin >> zahl_c; ergebnis=(10 + zahl_a) * zahl_b / zahl_c; std::cout << "\nDie Loesung der Aufgabe (10+a)*b/c lautet " << ergebnis << "."; getch(); return 0; // Programm wird beendet }Ich weiß nicht, warum du zusätzlich noch Buffer benutzt, OK, wenn die Zahlen zu groß werden muss man mit ExceptionHandling arbeiten, aber die Aufgabenstellung erfordert das ja nicht!
Das mit atoi kannst du weglassen, du hast die Werte ja mit cin bereits in die Variable eingelesen, also warum jeden Wert kopieren, der eh schon da ist!
Das #include <conio.h> und getch(); am Ende sorgt dafür, dass dein Programm nicht mit erreichen des Programmendes geschlossen wird (so dass der Benutzer auch noch das Ergebnis der Berechnung zu gesicht bekommt).
Ach ja, Zeilenumbrücke kannst du auch einfach im Text mit \n machen (am Ende hast du das ja hin und wieder weggelassen)... oder durch << endl;
Du könntest das ganze noch in eine Schleife stecken und dann immer wieder ovn vorne laufen lassen, so dass sich das Programm nicht sofort beendet, wenn eine Rechnung vorbei ist (schau dir mal while() oder for() an...).
Schau dir den Code mal an

Edit:
Hinweis: Zum Umwandeln einer Zahl innerhalb eines Arrays vom Typ char benötigen Sie die Funktion atoi(). Dieser Funktion übergeben Sie das Array zwischen den runden Klammern und erhalten als Rückgabewert eine Zahl vom Typ int.
Was soll das? Zahlen liest man mit int ein, nicht mit char!?
... aber gut, es wird ja nicht gefordert, auch wirklich char einzulesen, ist ja nur ein Hinweis...
-
Du kannst mit iostreams auch direkt Integer einlesen, wie im Code unten zu sehen ist.
Dein Code hat nicht funktioniert, weil deas Zeilenvorschubzeichen, das du durch Bestätigung mit Enter erzeugst noch im Buffer bleibt und nicht von get aus diesem entfernt wird. Verwendet stattdessenstd::cin.getline(Buffer1,sizeof(Buffer1),'\n');int main() { int a, b, c, Ergebnis; std::cout << "Sie muessen nun drei Zahlen eingeben. Mit Ihnen wird gerechnet. Legen wir los.\nZahl 1:" << std::flush; std::cin >> a; std::cout << "\nZahl 2:" << std::flush; std::cin >> b; std::cout << "\nZahl 3:" << std::flush; std::cin >> c; Ergebnis=(10 + a) * b / c; std::cout << "\nDie Loesung der Aufgabe (10+a)*b/c lautet " << Ergebnis << "." << std::endl; return 0; }EDIT: Du solltest vielleicht noch eine Überprüfung für c einbauen, denn ein Programm, dass ein Benutzer durch gezielte Fehleingaben zum Absturz bringen kann, ist nicht sehr schick

-
EDIT: Du solltest vielleicht noch eine Überprüfung für c einbauen, denn ein Programm, dass ein Benutzer durch gezielte Fehleingaben zum Absturz bringen kann, ist nicht sehr schick.
Stimmt, eine Division durch Null ist nichts gutes... aber dazu brauchst du keine ExceptionHandlung, ein einfaches "if(c == 0) return 1;" reicht da schon aus!
-
Vielen Dank für die sehr nette, schnelle und ausführliche Hilfe und vor allen Dingen die Tipps, wie ich es verbessern könnte. An die Division durch 0 habe ich auch nicht gedacht.
Danke nochmals und bis bald mal wieder
yhamm
-
eine Frage hätte ich noch: Kann man irgendwie ß, ü, ä oder ö in einem C++-Programm verwenden? Bei mir kommen dann immer komische Zeichen...
-
Das liegt daran, dass der Compiler und/oder IDE nur den ASCII-Zeichensatz verstehen und die deutschen Umlaute dort nicht definiert sind. Du kannst entweder mit Escapesequenzen die Zeichen in Stringliteralen darstellen oder du gibst es in der IDE mit Alt+xxxx ein.
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39326.html
-
ok... ich habe mittlerweile gelernt. aber eine sache ist mir noch unklar. ich möchte mithilfe eines arrays eine vierstellige eingegebene zahl in einer variable (bzw. in einem array) speichern und anschließend dessen quersumme berechnen. ich glaube mein ansatz ist eher schlecht als recht. das speichern im array funktioniert bisher einigermaßen, aber die quersummenberechnung verstehe ich noch nicht ganz. die werte die als ergebnis geliefert werden haben überhaupt nichts mit der quersumme zu tun. ach ja übrigens: die zeile, in der die einzelnen eingegebenen werte des arrays ausgegeben werden ist nur zu entwicklungszwecken von mir geschrieben worden, damit ich weiß ob wenigstens die werte richtig eingelesen werden konnten. bitte helft mir
yhamm#include <iostream.h> #include <conio.h> int main () { char Zahl[5]; int Quersumme; std::cout << "Geben Sie nun eine Zahl ein, deren Quersumme berechnet werden soll: \n"; std::cin.get (Zahl, sizeof(Zahl)); Quersumme=Zahl[0]+Zahl[1]+Zahl[2]+Zahl[3]; std::cout << "1: " << Zahl[0] << " 2: " << Zahl [1] << " 3: " << Zahl[2] << " 4: " << Zahl[3] << " "; std::cout << "Die Quersumme lautet: " << Quersumme; getch(); return 0; }
-
Den genauen Fehler finde ich jetzt so nicht heraus, aber du könntest einfach nacheinander solange jede gedrückte Taste analysieren bis 4 Zahlen eingeben wurden und diese dann jeweils addieren. Dann hast du auch mehr Konstrolle darüber, was der Benutzer eingibt!
Also: Du versuchst, mit Zeichenketten zu rechnen, dass siehst du z.B. daran, wenn du Quersumme = Zahl[0] schriebst, bereits da addierst du fehlerhafte Werte miteinander!
Kann es sein, du den LineBreak (wenn du auf die Enter-Taste drückst) nicht entfernst?
-
Wenn du zahl[0] in einen Zahlwert umwandelst, was du ja durch die Addition dieser machst, arbeitest du mit dem ASCII-Code des jeweiligen Zeichens. Das Zeichen '0' entspräche dabei dem ASCII-Code 48, von daher kann dein Ergebnis nicht stimmen. Du könntest die Quersumme zum Beispiel auf folgende Weise berechnen, es ist jedoch nicht standardkonform, weil man sich bei dieser Lösung darauf verlässt, dass die 48 wirklich die '0' ist.
#include <iostream> #include <conio.h> int main () { char Zahl[5]; int Quersumme = 0; std::cout << "Geben Sie nun eine Zahl ein, deren Quersumme berechnet werden soll: \n"; std::cin.getline(Zahl,sizeof(Zahl),'\n'); char *ptr = Zahl; while( *ptr ) { Quersumme += (*ptr)-48; ptr++; } std::cout << "1: " << Zahl[0] << " 2: " << Zahl [1] << " 3: " << Zahl[2] << " 4: " << Zahl[3] << " "; std::cout << "Die Quersumme lautet: " << Quersumme; getch(); return 0; }Besser wäre es, die Zahl als Integer einzulesen und dann folgendermaßen die Quersumme zu berechnen:
int quersumme(int zahl) { int quersumme = 0; while(zahl > 0) { quersumme += (zahl%10); zahl /= 10; } return quersumme; }
-
masterofx32 schrieb:
Wenn du zahl[0] in einen Zahlwert umwandelst, was du ja durch die Addition dieser machst, arbeitest du mit dem ASCII-Code des jeweiligen Zeichens. Das Zeichen '0' entspräche dabei dem ASCII-Code 48, von daher kann dein Ergebnis nicht stimmen. Du könntest die Quersumme zum Beispiel auf folgende Weise berechnen, es ist jedoch nicht standardkonform, weil man sich bei dieser Lösung darauf verlässt, dass die 48 wirklich die '0' ist.
... Quersumme += (*ptr)-48; ...Hier müsste ein: Quersumme += (*ptr)-'0';
helfen
-
Ja, das ist mir bewusst, aber das Problem bleibt doch noch bestehen. Ist denn laut Standard genau definiert, dass C++-Implementierungen den ASCII in der Form implementieren müssen? Ansonsten könnten die Zahlen ja auch in umgekehrter Reihenfolge auftauchen oder sonstige Abstrusitäten
Also meiner Meinung nach sind ASCII-Rechnereien aus diesem Grunde nicht zu verwenden.
-
Ansonsten, auf die Gefahr hin, dass ich etwas vorgreife, ich würd mit std::string arbeiten. Das sieht dann so aus:
#include <cstdlib> // Da steht atoi eigentlich drin. #include <iostream> #include <string> int main() { std::string zeile; int x; std::getline(std::cin, zeile); // Eine Zeile aus std::cin in zeile einlesen x = std::atoi(zeile.c_str()); std::cout << "2 * " << x " = " << 2 * x << std::endl; }cstdlib ist dabei ein C-Kompatibilitätsheader. Wenn dus ganz dolle C++ig machen willst, sieht das so aus:
#include <iostream> #include <sstream> #include <string> int main() { std::string zeile; std::stringstream sstr; int x; std::getline(std::cin, zeile); sstr.str(zeile); sstr >> x; if(!sstr) std::cerr << "Fehler beim Einlesen!" << std::endl; else std::cout << "2 * " << x << " = " << 2 * x << std::endl; }...woraus sich wunderbar so ein Konstrukt bauen lässt:
#include <iostream> #include <sstream> #include <string> int main() { std::string zeile; std::stringstream sstr; int x; do { std::cout << "Zahl eingeben: "; std::getline(std::cin, zeile); sstr.clear(); sstr.str(zeile); sstr >> x; } while(!sstr); std::cout << "2 * " << x << " = " << 2 * x << std::endl; }stringstream verhält sich dabei im Grunde so wie cin und cout auch, liest/schreibt die Eingabe allerdings nicht von der Tastatur bzw. auf den Monitor, sondern aus bzw. in einen String - in diesem Fall aus dem Buffer, den wir vorher von der Konsole gelesen haben.
Was die Quersumme angeht, wenn du ganz paranoid bist, kannst du natürlich jeden Buchstaben einzeln parsen, aber ich würd mich wahrscheinlich auf ASCII verlassen und c - '0' schreiben. Bei std::string sieht das dann so aus:
std::string zahl_str = "1234"; int quersumme = 0; for(int i = 0; i < zahl_str.size(); ++i) quersumme += zahl_str[i] - '0';Ach ja - ich würd dir raten, von conio.h die Finger zu lassen, sonst gibts ein böses Erwachen, wenn du mal auf einer Nicht-Windows-Plattform coden willst - die haben die nämlich nicht. Wenn du einen getch()-Ersatz brauchst, schreib halt
std::cin.get();Das wartet zwar auf ein ENTER anstatt auf die ANY-KEY, aber das sollte für den Zweck ja reichen.
-
vielen dank für den ganzen quellcode, ich werde versuchen ihn irgendwann mal zu verstehen, genauso wie die diskussion die ich irgendwie ausgelöst habe. aber eine verbesserung hätte ich noch zu machen

std::string zahl_str = "1234"; int quersumme = 0; for(int i = 0; i < zahl_str.size(); ++i) quersumme += zahl_str[i] - '0';dieser quelltext ist nicht ganz korrekt (kp, wieso; compiler meckert irgendwie von wegen unsigned und signed werden verglichen.) richtig wäre:
std::string zahl_str = "1234"; int quersumme = 0; for(unsigned int i = 0; i < zahl_str.size(); ++i) quersumme += zahl_str[i] - '0';
(danke an compiler-fehler^^). dass ich so schnell schon quellcode berichtigen kann...edit: ach ja, wen es interessiert: ich lerne zur zeit mit dem anfänger tut auf www.highscore.de
noch ein edit: ich hab mal noch ne frage: macht es nen unterschied, ob ich
zahl_str.size()oder
sizeof(zahl_str)schreibe?
vorerst letztes edit: ich bin gerade dabei ein programm zur primzahlberechnung zu schreiben. ich bin auch ziemlich nah dran, ich dachte sogar fast ich könnte es ohne eure hilfe schaffen ;). aber jetzt habe ich doch noch eine frage: gibt es ein kommando (denk ich eigenlich mal), dass einen double ohne nachkommastellen anzeigt? ich möchte nämlich zwei zahlen dividieren und prüfen, ob dabei ein "rest" rauskommen würde.
-
Naja, wenn schon pingelig, dann bitte richtig:
for(std::string::size_type i = 0; i < zahl_str.size(); ++i) quersumme += zahl_str[i] - '0';...da dacht ich mir, ich komm mal nicht gleich mit std::string::const_iterator, und dann krieg ich solche Pingeligkeiten. Ts!

Ansonsten, zahl_str.size() und sizeof(zahl_str) sind zwei völlig verschiedene Dinge. sizeof ist ja auch keine Funktion, sondern ein Operator, der zur Compilezeit aufgelöst wird und dir mitteilt, wie viel Speicher das Argument einnimmt. Und zwar nur, wieviel das Objekt direkt einnimmt, nicht etwa eventuell enthaltene Verweise. Das heißt, auf einer gängigen 32bit-Plattform wird zum Beispiel
char const *const p = "Hello, World! Das ist ein relativ langer String." std::cout << sizeof(p) << std::endl;die Ausgabe
4hervorbringen. Das deswegen, weil nur die Größe des Zeigers von sizeof aufgelöst wird, und die ist in dem Fall 4 Byte. zahl_str.size() dagegen ruft eine Methode von std::string auf, die dir dann zurückgibt, wie lang der String ist, den das Objekt kapselt, und das ist im Zweifel das, was du willst.
-
ich hab eine Frage und zwar! wie können wir das Programm schreiben wenn wir viersteligen Zahl eingeben müssen und die Quersumme davon mit einer Schleife berechnen?
Danke