op>> + op<< + stream
-
Hi
ich habe seit langer zeit mal wieder ein wenig programmiert und dabei kam ne bruch klasse raus(iwelche aufgaben irgend ner uni, die ich auf die schneller gefunden habe halt). nun habe ich aber bei op>> (und damit auch op<<) ein problem:
1/1als ausgabe sieht doof aus, also soll er nur1ausgeben. kein problem. aber eine1soll eben auch korrekt eingelesen werden...
also hab ich mir folgendes zusammen gebaut:#include <iostream> template<char X> std::istream& skip_char(std::istream& s) { if( !s ) return s; auto next_char = s.get(); if( next_char == std::istream::traits_type::eof() ) { s.setstate(std::ios::eofbit); return s; } if( static_cast<char>(next_char) != X ) { s.unget(); s.setstate(std::ios::failbit); } return s; } template<typename T> struct fraction { fraction(const T& nominator = T(0), const T& denominator = T(1)) : lhs_(nominator), rhs_(denominator) {} const T& nom() const { return lhs_; } T& nom() { return lhs_; } const T& denom() const { return rhs_; } T& denom() { return rhs_; } private: T lhs_; T rhs_; }; template<typename T> std::istream& operator>>(std::istream& s, fraction<T>& to_set) { s >> to_set.nom(); if( !s ) return s; s >> skip_char<'/'>; if( !s ) { s.clear(s.rdstate() & ~std::ios::failbit); to_set.denom() = 1; } else s >> to_set.denom(); return s; } template<typename T> std::ostream& operator<<(std::ostream& s, const fraction<T>& out) { s << out.nom(); if( out.denom() != T(1) ) s << '/' << out.denom(); return s; } #include <cstdlib> #include <iostream> #include <fstream> #include <sstream> #include <vector> int main() { std::stringstream inss("1 1/13 4/17 4test"); std::ifstream in; in.set_rdbuf(inss.rdbuf()); std::stringstream out; std::vector< my::fraction<int> > vec; for( my::fraction<int> i; in >> i; ) vec.push_back(i); std::string rest; std::getline(in, rest); for( auto &i : vec ) out << i << ' '; std::cout << out.str() << rest << std::endl; std::system("PAUSE"); }der vector (und damit out) sieht schon mal ziemlich gut aus. das problem ist:
- die implementierung erscheint mir äußerst frickelig
- in der implementierung sind sicherlich einige (sonder-)fälle nicht bedacht
- das"test", welches durchgetlineinreststehen sollte, ist nicht da-> hat jemand nen besseren vorschlag als lösung?
-> hab ich bei dem getline nen denkfehler? oder wieso funktioniert das nicht?
danke
-
#include <istream> #include <ostream> template<typename T> struct fraction { fraction(const T& numerator = T(0), const T& denominator = T(1)) : mNum(numerator), mDenom(denominator) {} const T& num() const { return mNum; } T& num() { return mNum; } const T& denom() const { return mDenom; } T& denom() { return mDenom; } private: T mNum; T mDenom; }; template<typename T> std::istream& operator>>(std::istream& s, fraction<T>& to_set) { if (!(s >> to_set.num())) return s; s >> std::ws; if (s.peek() == '/') { s.ignore(); s >> to_set.denom(); } else to_set.denom() = 1; return s; } template<typename T> std::ostream& operator<<(std::ostream& s, const fraction<T>& out) { s << out.num(); if (out.denom() != T(1)) s << '/' << out.denom(); return s; } #include <iostream> #include <sstream> int main() { std::stringstream inss("1 1/13 4/17 4test"); for( fraction<int> i; inss >> i; ) std::cout << i << '\n'; }
-
oh. peek gibts da also - danke : D
bin vorhin dann auch noch auf meinen getline-fail gekommen: da fehlt natürlich nen
in.clear()davorPS: Beim Antworten wird (wie vor ~5 Jahren) noch immer kein html-decode auf den Thread-Titel angewendet...
-
T& num() { return mNum; }(sowie gleiches bei denom()) finde ich doch arg unsauber (dann kann man gleich public Member nehmen). Sollte der operator>> nicht besser friend der Klasse fraction sein (um dann direkt die Member zu setzen)?
-
Sollte der operator>> nicht besser friend der Klasse fraction sein (um dann direkt die Member zu setzen)?
Warum denn das?
-
Was ist denn dann deine Alternative dazu?
Eigentlich sollte m.E. so eine Klasse (bzw. Struktur) immutable sein - dann kann man jedoch den operator<<() nicht benutzen, sondern müsste eine Funktion
fraction read(std::istream &istr)o.ä. erzeugen.
-
Arcoth schrieb:
Sollte der operator>> nicht besser friend der Klasse fraction sein (um dann direkt die Member zu setzen)?
Warum denn das?

Um die Attribute privat zu halten.
-
Das war nicht sarkastisch gemeint. Ich dachte Th69 will total ueberfluessigerweise einen
frienddraus machen.Ich wusste ja nicht dass ihr die Struktur nach aussen hin immutable machen wollt - das halte ich naemlich nicht fuer sinnvoll. Warum?
-
Arcoth schrieb:
Ich wusste ja nicht dass ihr die Struktur nach aussen hin immutable machen wollt - das halte ich naemlich nicht fuer sinnvoll. Warum?
Naja, ein Setter dürfte es schon sein, getrennt vom Getter. Solange kein Bedarf an sowas ist, mache ich nicht auf. Und siehe da, in 4 Wochen gibt's immernoch keinen Setter. Irgendwann kommt man daher und kürzt die Brüche oder erzwingt, daß demom!=0 oder gar positiv. Das halte ich mir einfach offen.
-
@Arcoth: du hast trotzdem noch nicht meine Frage beantwortet - was ist deine Alternative zum friend (ohne Setter)?
-
(sowie gleiches bei denom()) finde ich doch arg unsauber (dann kann man gleich public Member nehmen). Sollte der operator>> nicht besser friend der Klasse fraction sein (um dann direkt die Member zu setzen)?
Wo steht da auch nur ansatzweise irgendwas von Immutability? Du hast nur darauf hingewiesen dass man lieber
publicMember anstelle von derartigen Funktionen nehmen kann. Solange man die Member von außen direkt verändern kann braucht man kein friend.
-
volkard schrieb:
Arcoth schrieb:
Ich wusste ja nicht dass ihr die Struktur nach aussen hin immutable machen wollt - das halte ich naemlich nicht fuer sinnvoll. Warum?
Naja, ein Setter dürfte es schon sein, getrennt vom Getter. Solange kein Bedarf an sowas ist, mache ich nicht auf. Und siehe da, in 4 Wochen gibt's immernoch keinen Setter. Irgendwann kommt man daher und kürzt die Brüche oder erzwingt, daß demom!=0 oder gar positiv. Das halte ich mir einfach offen.
Man sollte aber schon wissen, ob man Brüche oder rationale Zahlen implementieren will...
-
Arcoth schrieb:
(sowie gleiches bei denom()) finde ich doch arg unsauber (dann kann man gleich public Member nehmen). Sollte der operator>> nicht besser friend der Klasse fraction sein (um dann direkt die Member zu setzen)?
Wo steht da auch nur ansatzweise irgendwas von Immutability? Du hast nur darauf hingewiesen dass man lieber
publicMember anstelle von derartigen Funktionen nehmen kann. Solange man die Member von außen direkt verändern kann braucht man kein friend."(dann kann man gleich public Member nehmen)" war wie "(dann kann man sich auch gleich erschießen)". Das war doch keine Handlungsempfehlung! Trink erstmal nen Kaffee, ist noch sehr früh am Tag.

-
camper schrieb:
volki schrieb:
Naja, ein Setter dürfte es schon sein, getrennt vom Getter. Solange kein Bedarf an sowas ist, mache ich nicht auf. Und siehe da, in 4 Wochen gibt's immernoch keinen Setter. Irgendwann kommt man daher und kürzt die Brüche oder erzwingt, daß demom!=0 oder gar positiv. Das halte ich mir einfach offen.
Man sollte aber schon wissen, ob man Brüche oder rationale Zahlen implementieren will...
Ach, das halte ich mir vielleicht am besten auch noch offen.

-
@Volkard: genau so war es gemeint - irgendwie kommt mein Sarkasmus wohl nicht immer an!?