quadratische Gleichung in einer Zeile einlesen
-
Vielen Dank für deine Mühe. Leider hilft mir das nicht wikrlich weiter, da ist viel Zeugs drinn was ich noch nie gesehen habe. Auch ist die Syntax ganz anders als das was ich bis jetzt gesehen habe. Ich benutze hier die Visual Studio 2005 Express Edition...falls das irgendwie wichtig sein sollte.
Ich poste einfach mal, was ich bis jetzt fabriziert habe. Vielleicht lässt sich daran auch mein Wissensstand etwas ablesen.
#include <stdio.h> #include <math.h> int main(void) { float fa=4, fb=5, fc=100, fd=0, fDiskriminante=0, fErg1=0, fErg2=0; fc = (fc-fd); if (fa==0) { fErg1 = (-fc/fb); printf("Es handelt sich um keine quadratische Gleichung.\n" "Die vorliegende Gleichung hat die L%csung x = %f\n\n\n", 148, fErg1); } else { fb = (fb/fa); fc = (fc/fa); fa = 1; fDiskriminante = (pow((fb/2),2) - fc); if (fDiskriminante>0) { fErg1 = ((-fb)/2) + sqrt(fDiskriminante); fErg2 = ((-fb)/2) - sqrt(fDiskriminante); printf("x_1 = %f\n\n", fErg1); printf("x_2 = %f\n\n\n", fErg2); } else { if (fDiskriminante==0) { fErg1 = ((-fb)/2) + sqrt(fDiskriminante); printf("x_1 = x_2 = %f\n\n\n",fErg1); } else { fErg1 = sqrt(-fDiskriminante); fErg2 = sqrt(-fDiskriminante); printf("x_1 = %f + i*%f\n\n", (-fb/2), fErg1); printf("x_2 = %f - i*%f\n\n\n", (-fb/2), fErg2); } } ; } return 0; }Das Programm funktionier soweit und gibt auch komplexe Nullstellen aus. Was fehlt ist nur noch die Eingabe.
Um noch mal mein Problem zu schildern: Wenn ich die Eingabe als String eingebe habe ich ja eine Zeichenkette. In der Zeichenkette stehen Dinge die ich brauche (a,b,c,und d), und Dinge die ich nicht brauche(das x^2 z.b.). a,b,c und d muss ich ja jetzt aus dem String ähhhh rausschnipseln und in floats umwandeln. Was noch hinzukommt ist die Tatsache das die Koeffizienten ja nicht nur einstellig sein können, das ganze muss als dynamisch sein. Vielleicht gibts irgendwo eine generelle Erklärung wie ich auf die einzelnen Teile eines Strings Zugriff bekomme? Damit wäre mir, glaube ich, schon sehr geholfen.
-
Knotze schrieb:
da ist viel Zeugs drinn was ich noch nie gesehen habe. Auch ist die Syntax ganz anders als das was ich bis jetzt gesehen habe.
Das liegt dann wohl daran, daß das C++ ist; im Gegensatz zu deinem Code, der in C geschrieben ist.
In welcher Sprache möchtest du das Programm denn schreiben, bzw. welche lernt ihr an der Uni? Sowohl in C als auch in C++ läßt sich die Aufgabe gut lösen, aber der Code würde größtenteils sehr unterschiedlich aussehen. C++ ist eben nicht nur "ein bißchen mehr als C", sondern eine komplett eigene Sprache.
-
Allerdings, das ist vollständig in C. Ich arbeite gerade bei Ein- und Ausgabe nicht gerne mit reinem C, habe ich auch nicht viel Erfahrung drin. Das muss Dich aber nicht entmutigen.
Suche dir hier die passenden Funktionen zusammen: http://www.cplusplus.com/reference/clibrary/cstdio/.
Die einzelnen Zeichen kannst Du dann mit isspace(), isdigit(), atoi() usw. behandeln. Dafür kannst Du pointer auf den String benutzen. Die nötigen Funktionen sind in der genannten Referenz alle gut erklärt. Sogar mit Beispiel.Viel Spaß dabei. Ist ne schöne Aufgabe.
-
So, ich habs hinbekommen.
while ( !(fEingabe==4)) { printf ("\nGeben sie die Gleichung bitte in der Form a*x^2+b*x+c=d ein\n\n"); gets(szEingabe); fEingabe = sscanf (szEingabe,"%f*x^2+%f*x+%f=%f", &fa, &fb, &fc, &fd); }So funktionierts ganz gut. Ich habe noch keinen Fall gefunden in dem Schwachsinn produziert wird.
Vielen Dank an euch Beide!
-
Wenn Dein Prof. Euch gesagt hat, dass Ihr mit sscanf arbeiten sollt, dann passt das schon. Besonders gutes C++ ist das nicht und sscanf ist nicht typsicher. Wenn das in der Vorlesung vorkam, dann gib es so ab, aber behalte bitte im Hinterkopf, dass Du es anders machen wirst, wenn Du irgendwann mal richtiges C++ programmierst.
-
Walli schrieb:
Besonders gutes C++ ist das nicht und sscanf ist nicht typsicher.
Das gilt natürlich ebenso für die anderen C-Funktionen wie
printf()undgets().
-
Das liegt dann wohl daran, daß das C++ ist; im Gegensatz zu deinem Code, der in C geschrieben ist.
Ich hab das bis jetzt gedanklich immer in einen Pott geworfen und den Unterschied ignoriert. Ich hab noch mal nachgeschaut, wir werden wohl ausschließlich C behandeln.
-
Die Aufgabe an sich - mit dem Einlesen der quadratischen Gleichung - finde ich ziemlich schwierig für einen Anfänger. Wenn man das Problem verallgemeinert, und fordert, ein beliebiges Polynom einzulesen, bei dem die einzelnen Summanden in beliebiger Reihenfolge und auch mehrfach mit der gleichen Potenz in x auftreten dürfen, dann ist dies jenseits von allem, was man einem Anfänger zumuten kann.
Andererseits ist es erstaunlich, was man mit boost.spirit relativ schnell und mit wenig Code zum Laufen bringt. Vorausgesetzt man kann auf dem Klavier spielen ...
#include <boost/spirit/include/classic_core.hpp> #include <boost/bind.hpp> #include <boost/scoped_ptr.hpp> #include <iostream> #include <vector> #include <string> namespace spirit = boost::spirit::classic; template< typename InIter > struct polynom_grammer : public spirit::grammar< polynom_grammer< InIter > > { struct Koeff { Koeff() : m_value(1.0), m_sign(1), m_power_of_x(0) {} double m_value; int m_sign; int m_power_of_x; }; template< typename ScannerT > struct definition { spirit::rule< ScannerT > power_of_x, plus_minus, expr, r; int const eins, minus_eins; definition( polynom_grammer const& self ) : eins( 1 ) // Bem.: notwendig, da assign_a(i,j) auch bei j eine Referenz speichert , minus_eins( -1 ) { using boost::bind; using namespace spirit; power_of_x = ch_p('x')[assign_a( self.m_cur->m_power_of_x, eins )] // x[^Exponent] >> !( '^' >> uint_p[assign_a( self.m_cur->m_power_of_x )] ); plus_minus = '+' | ch_p('-')[assign_a( self.m_cur->m_sign, minus_eins )]; // + oder - expr = ( ( real_p[assign_a( self.m_cur->m_value )] >> !( !ch_p('*') >> power_of_x ) ) // Koeffizient [[*]power_of_x] | ( !plus_minus >> power_of_x ) // oder [plus_minus] power_of_x )[bind( &polynom_grammer::store, &self, _1, _2 )]; r = expr >> *( plus_minus >> expr ); // Ausdrücke mit +- verketten } spirit::rule< ScannerT > const& start() const { return r; } }; explicit polynom_grammer( std::vector< double >& poly ) : m_polynom( poly ) , m_cur( new Koeff ) {} void store( InIter, InIter ) const { assert( m_cur->m_power_of_x >= 0 ); // -- aktuellen Koeffizienten *m_cur im Polynom abspeichern const std::size_t n = m_cur->m_power_of_x; if( m_polynom.size() <= n ) m_polynom.resize( n + 1, 0.0 ); m_polynom[ n ] += m_cur->m_sign * m_cur->m_value; *m_cur = Koeff(); // reset } std::vector< double >& m_polynom; boost::scoped_ptr< Koeff > m_cur; }; int main() { using namespace std; cout << " --- ein Polynomparser " << endl; cout << " Geben Sie z.B. '-x^2 + 3x -12' ein;" << endl; cout << " anschliessend werden die Koeffizienten ausgegeben " << endl; cout << " [q or Q] to quit\n" << endl; for( string str; getline( cin, str ); ) { using namespace spirit; if (str.empty() || str[0] == 'q' || str[0] == 'Q') break; cout << "-------------------------\n"; vector< double > polynom; polynom_grammer< string::iterator > g( polynom ); if( parse( str.begin(), str.end(), g.use_parser<0>(), space_p ).full ) { cout << "[" << str << "] parses OK: " << endl; copy( polynom.rbegin(), polynom.rend(), ostream_iterator< double >( cout << "Koeff: ", " " ) ); cout << endl; } else { cout << "Parsing failed\n"; } cout << "-------------------------\n" << endl; } return 0; }man erhält z.B. folgende Ausgabe:
--- ein Polynomparser Geben Sie z.B. '-x^2 + 3x -12' ein; anschliessend werden die Koeffizienten ausgegeben [q or Q] to quit x-5 ------------------------- [x-5] parses OK: Koeff: 1 -5 ------------------------- 8x^2+5*x ------------------------- [8x^2+5*x] parses OK: Koeff: 8 5 0 ------------------------- -x + 34x^3 + 7 ------------------------- [-x + 34x^3 + 7] parses OK: Koeff: 34 0 -1 7 ------------------------- -x + 34*x^3 + 7 + 5x ------------------------- [-x + 34*x^3 + 7 + 5x] parses OK: Koeff: 34 0 4 7 -------------------------:xmas2: Werner
-
Werner Salomon schrieb:
Andererseits ist es erstaunlich, was man mit boost.spirit relativ schnell und mit wenig Code zum Laufen bringt.
Sieht jetzt weder nach relativ schnell noch nach wenig Code aus... Aber ich glaube es dir schon.

Ich lese mich gerade ein wenig in Boost.Regex ein, das ist ja sozusagen die Vorstufe von Boost.Spirit... Mal sehen

-
Werner Salomon schrieb:
Die Aufgabe an sich - mit dem Einlesen der quadratischen Gleichung - finde ich ziemlich schwierig für einen Anfänger. Wenn man das Problem verallgemeinert, und fordert, ein beliebiges Polynom einzulesen, bei dem die einzelnen Summanden in beliebiger Reihenfolge und auch mehrfach mit der gleichen Potenz in x auftreten dürfen, dann ist dies jenseits von allem, was man einem Anfänger zumuten kann.
Andererseits ist es erstaunlich, was man mit boost.spirit relativ schnell und mit wenig Code zum Laufen bringt. Vorausgesetzt man kann auf dem Klavier spielen ...
Von dir hätte ich erwartet, dass du das nur mit stringstreams und << >> Operatorüberladung machst.
-
ich hätte die eingabe übrigens sehr viel einfacher gemacht:
const size_t maxExponent = 2; //quadratische fkt halt ^^ for (size_t i(maxExponent); i != 0; ++i) { std::cout << "Geben sie x^" << i << " ein:"; std::cin >> ;//speichern halt } std::cout << "Geben sie das absolut-Glied ein";//ich hoffe, man nennt den faktor vor x^0 so ;D std::cin >> ;//speichern halt - könnte man auch mit in die schleife machen, aber würd ich nicht - weil x^0 hässlich aussieht und es dann mit der schleife ein wenig umständlicher werden würde ^^bb
-
unskilled schrieb:
ich hätte die eingabe übrigens sehr viel einfacher gemacht:
"Sehr viel einfacher" heißt in diesem Fall: nicht der Aufgabenstellung entsprechend. Die Eingabe sollte in EINER Zeile erfolgen.
-
otze schrieb:
unskilled schrieb:
ich hätte die eingabe übrigens sehr viel einfacher gemacht:
"Sehr viel einfacher" heißt in diesem Fall: nicht der Aufgabenstellung entsprechend. Die Eingabe sollte in EINER Zeile erfolgen.
oh verzeihung - das hatte ich überlesen ^^
bb
-
Huhu,
Ich habe ebenfalls eine ähnliche Aufgabe aufbekommen. Jedoch muss ich hierbei keine Quadratische Gleichung in einer Zeile einlesen, sondern die Pythagoras-Gleichung. Aber das Prinzip ist ja ähnlich ...
Mit dem Systemrumpf, quasi die Fallunterscheidungen sowie die allgemeine Berechnung, habe ich keinerlei Probleme, aber ich wüsste nicht, wie ich die While-Schleife von Knotze am Anfang des Programmes integrieren sollte. Könntet ihr mir vielleicht dabei helfen?
Ich habe zumindestens die Variablen angepasst, fEingabe durch int iEingabe = 0 am Anfang des Programms ersetzt, sowie char szEingabe[81] deklariert. Jedoch wüsste ich jetzt nicht, wie nur die While-Schleife zu dem Erfolg führen soll, dass die Gleichung von der Konsole in einer Zeile eingelesen wird, weil mir im Allgemeinen das Prinzip nicht ganz so klar ist, wieso man eine While-Schleife benutzt. Entweder führt mein Programm nun zum Absturz oder zu einer 1000-fachen Ausgabe der printf-Zeile.
Ich würde mich über Ratschläge und Hilfen sehr freuen. Danke im Voraus.
von Knotze while ( !(fEingabe==4)) { printf ("\nGeben sie die Gleichung bitte in der Form a*x^2+b*x+c=d ein\n\n"); gets(szEingabe); fEingabe = sscanf (szEingabe,"%f*x^2+%f*x+%f=%f", &fa, &fb, &fc, &fd); }