Operator [ ] rundet Wert
-
Hallo !
Ich möchte im Rahmen einer Übung "[ ]" als Operator definieren.
Es ist eine Klasse für einen Punkt im 3D Raum definiert.
Die Punktkoordinaten sind double Werte.Beim Zugriff mittels Operator wird der Wert auf
die erste Nachkommastelle gerundet, nur warum ist das so?- .hpp File:
class Point3D { private: double x, y, z; unsigned short int precicion; std::string str; public: //.... some Code double operator [] ( int index ); //.... some Code };
- .cpp File:
double Point3D::operator [] ( int index ) { switch (index) { case 0: return x; case 1: return y; case 2: return z; default: std::cerr << "Junge, gib 0 || 1 || 2 ein !" << std::endl; exit(1); } }
- main:
#include "19_6_class_Point_3D.hpp" int main(void) { Point3D p1, p2; //Test Operator [] p1.Set_x(4); p1.Set_y(4.5687); p1.Set_z(5.67); std::cout << "\n\nOperator '[]' Test: \n p1( 4; 4,5687; 5,67 )" << " Jetzt Ausgabe des y-Elementes von p1:" << std::endl; std::cout << " p1[1] = " << p1[1] << std::endl; //Ausgegeben wird 4.6 !!! :-( system("pause"); }
MfG, 0xFF
-
@0xFF am
cout
kann es nicht liegen?was gibt p1[1] * 10000 ?
-
@DirkB ..nein, das glaube ich nicht, weil wenn ich p1 so ausgeben lasse, dann wird p1 wie definiert ausgegeben,
das habe ich schon getestet.
-
@0xFF Am einfachsten ist es für uns, wenn du den Code so zusammen schreibst, dass wir den raus kopieren und compilieren können um das Problem direkt nachzuvollziehen.
-
Ja Schlangenmensch, da hast Du vollkommen recht!
Hier der Code:
- Header:
#pragma once #ifndef _19_6_CLASS_POINT_3D_HPP_ #define _19_6_CLASS_POINT_3D_HPP_ // wie Ueb. 19.5 ergaenzt um Operator // fuer Multiplikation, Skalarprodukt usw. #include "general_definitions.h" #if RUN_Uebung_19_6 == 1 #include<string> #include<iostream> #include<iomanip> #include<sstream> // Klasse die einen Punkt im 3 dimensionalen Raum beschreibt class Point3D { private: double x, y, z; unsigned short int precicion; std::string str; public: // Konstruktor -- Default Point3D() : x(0.00), y(0.00), z(0.00) { Set_precision(4); } // Konstruktor -- Mit Parametern Point3D(double x_, double y_, double z_); Point3D operator - (Point3D *p3d_p); //Substraktion von 2 Punkten; Ueb.: 19.6 Point3D operator - (Point3D& p3d) { this->x -= p3d.x; this->y -= p3d.y; this->z -= p3d.z; return p3d; } Point3D operator -= (Point3D& p3d) { this->x -= p3d.x; this->y -= p3d.y; this->z -= p3d.z; return p3d; } Point3D operator += (Point3D& p3d) { this->x += p3d.x; this->y += p3d.y; this->z += p3d.z; return p3d; } Point3D operator * ( double d ) { //Skalarprodukt this->x *= d; // 1. Ueberladung des * - Operator this->y *= d; //Test i.O. 2.2. 2020 this->z *= d; return *this; } Point3D operator * ( Point3D &p3d ) { //Produkt zweier Punkte this->x *= p3d.x; // 2. Ueberladung des * - Operator this->y *= p3d.y; //Test i.O. 2.2. 2020 this->z *= p3d.z; return *this; } #if 1 double operator [] ( int index ); //fuer nicht Konstante Objekte #endif #if 1 double operator [ ] ( int index ) const { //fuer Konstante Objekte switch (index) { case 0: return x; case 1: return y; case 2: return z; default: std::cerr << "Index must be 0, 1 or 2!" << std::endl; exit(1); } } #endif friend std::ostream& operator << (std::ostream& os, Point3D p3d); // Getter inline const double Get_x(void) { return x; } inline const double Get_y(void) { return y; } inline const double Get_z(void) { return z; } inline const double Get_precision(void) { return precicion; } inline std::string Get_str(void); //string // Setter inline void Set_x(double x_) { this->x = (const double)x_; } inline void Set_y(double y_) { this->y = (const double)y_; } inline void Set_z(double z_) { this->z = (const double)z_; } inline void Set_precision(unsigned short int prec) { if (prec > 15) { prec = 15; } this->precicion = prec; } protected: // --- }; #endif //if RUN_Uebung_19_6==1 #endif //_19_6_CLASS_POINT_3D_HPP_ // EOF
- cpp-File:
#include "general_definitions.h" #if RUN_Uebung_19_6 == 1 #include "19_6_class_Point_3D.hpp" Point3D::Point3D(double x_, double y_, double z_) //Ueb. 19.5 { x = (double)x_; y = (double)y_; z = (double)z_; } #if 1 double Point3D::operator [] ( int index ) //Ueb. 19.6 { switch (index) { case 0: return x; case 1: return y; case 2: return z; default: std::cerr << "Junge, gib 0 || 1 || 2 ein !" << std::endl; exit(1); } } #endif std::ostream& operator << (std::ostream& os, Point3D p3d) { //friend of Point3D #if 1 //Ueb. 19.5 os << "(" + std::to_string(p3d.Get_x()) + ", " + std::to_string(p3d.Get_y()) + ", " + std::to_string(p3d.Get_z()) + ")"; return os; #endif #if 0 return os << p3d.Get_str(); #endif } Point3D Point3D::operator - (Point3D *p3d_p) //2. Punkt als Pointer { //Ueb. 19.6 x -= p3d_p->x; y -= p3d_p->y; z -= p3d_p->z; return *this; //OK getestet: 2.2.2020 } inline std::string Point3D::Get_str(void) //Ueb. 19.5 { this->str = "(" + std::to_string(x) + ", " \ + std::to_string(x) + ", " + std::to_string(x) + ")"; return str; } #endif //if RUN_Uebung_19_6==1 // EOF
- main:
// A_19_6_MAIN.cpp: Definiert den Einstiegspunkt für die Konsolenanwendung. #include "general_definitions.h" #if RUN_Uebung_19_6 == 1 #include <iostream> #include <fstream> #include "19_6_class_Point_3D.hpp" void Test_InneresProdukt_2er_Punkte( void ); void Test_Produkt_doubleZahl_x_Punkt( void); void Test_Punkt_1_minus_Punkt_2( void); int main( void ) { Point3D p1, p2; // Auruf Deufault Konstruktor Point3D p3(20, 40, 60), p4(4, 6, 8); // Auruf Konstruktor mit Para. std::cout << "\n=============== Uebung 19.6 Operatoren ==============" << std::endl //Test Operator [] ... neu hinzu bei 19.6 p1.Set_x(4); p1.Set_y(4.5687); p1.Set_z(5.67); std::cout << "\n\nOperator '[]' Test: \n p1( 4; 4,5687; 5,67 )" << " Jetzt Ausgabe des y-Elementes von p1:" << std::endl; std::cout << " p1[1] = " << p1[1] << std::endl; system("pause"); return 0; } // EOF
-
#include "general_definitions.h"
Der Inhalt dieser Datei fehlt. Unter Annahme, dass die Datei leer ist, ist das Problem nicht reproduzierbar.
VS2019:
=============== Uebung 19.6 Operatoren ============== Operator '[]' Test: p1( 4; 4,5687; 5,67 ) Jetzt Ausgabe des y-Elementes von p1: p1[1] = 4.5687 Drücken Sie eine beliebige Taste . . .
GCC 9.2.0 (libstdc++ und MinGW-w64):
=============== Uebung 19.6 Operatoren ============== Operator '[]' Test: p1( 4; 4,5687; 5,67 ) Jetzt Ausgabe des y-Elementes von p1: p1[1] = 4.5687 Dr▒cken Sie eine beliebige Taste . . .
Das beschriebene Phänomen tritt bei mir mit beiden Compilern nur dann auf, wenn ich die
precision
für Floating-Point-Ausgabe verändere:std::cout.precision(2); ... std::cout << " p1[1] = " << p1[1] << std::endl;
gibt bei mir dann tatsächlich
p1[1] = 4.6
aus. Welchen Compiler verwendest du? Wird eventuell in
general_definitions.h
noch irgendwas komisches gemacht?Und Frage an andere: Wie weit ist eigentlich der initiale Zustand von
cout
vom Standard vorgegeben? Könnte es tatsächlich Compiler geben, bei denencout
standardkonform mit so einerprecision
initialisiert wird?
-
@Finnegan
Hi, danke für Deine Mühe,
Das File fehlt, da schalt ich nur die Files der
betreffenden Übung zu oder ab.Ich muss heute Abend mal checken ob ich evtl.
versehentlich cout.precision irgendwo vorher in meiner main
gesetzt hatte,
habe nicht das ganze main-File gepostet, weil ich da noch
andere Funktionen getestet habe -- und war der (offentsichlich falschen)
Ansicht dass der Code nicht relevant ist --- Asche auf mein HauptIch werde die komplette main heute Abend posten.
Als Compiler verwende ich den Standard C++ Compiler von Visual Studio Code 2019.
Grüsse
-
@0xFF sagte
Beim Zugriff mittels Operator wird der Wert auf
die erste Nachkommastelle gerundetNein, wird er nicht.
@0xFF sagte
wenn ich p1 so ausgeben lasse
Tust du nicht. Du verwendest to_sting.
x = (double)x_;
Was soll der Cast? Ein double wird nicht doubliger.
-
Hallo Manni,
Danke für Deinen Input,
Da hast Du recht in allen Punkten.MfG, Dirk
-
Guten Abend,
also hier ist die vollständige main:// A_19_6_MAIN.cpp: Definiert den Einstiegspunkt für die Konsolenanwendung. // //#include "stdafx.h" #include "general_definitions.h" #if RUN_Uebung_19_6 == 1 #include <iostream> #include <fstream> #include "19_6_class_Point_3D.hpp" void Test_InneresProdukt_2er_Punkte( void ); void Test_Produkt_doubleZahl_x_Punkt( void); void Test_Punkt_1_minus_Punkt_2( void); int main( void ) { Point3D p1, p2; // Auruf Deufault Konstruktor Point3D p3(20, 40, 60), p4(4, 6, 8); // Auruf Konstruktor mit Para. std::cout << "\n=============== Uebung 19.6 Operatoren ==============" << std::endl << "Es wurden 4 Punkte angelegt, ihre Werte lauten:" << std::endl << "p1: " << std::setprecision(2) << p1 << std::endl << "p2: " << std::setprecision(2) << p2 << std::endl << "p3: " << std::setprecision(2) << p3 << std::endl << "p4: " << std::setprecision(2) << p4 << std::endl; //Test Setter std::cout << "\n\nManipulieren mit Setter, p1 auf 4.456, 5.34, 68" << std::endl; p1.Set_x(4.456); p1.Set_y(5.34); p1.Set_z(68); std::cout << "p1: " << p1 << std::endl; //Test operator - std::cout << "\n\nOperator '-=' Test: \n p1( 4.456, 5.34, 68 )" << " -= p2( 1.00, 2.34, 8.00 ) ergibt:" << std::endl; p2.Set_x(1.00); p2.Set_y(2.34); p2.Set_z(8.00); p1 -= p2; // '-=' Operator wirkt hier std::cout << " p1" << p1 << std::endl; //Funktioniert. //Test Operator [] ... neu hinzu bei 19.6 p1.Set_x(4); p1.Set_y(4.5687); p1.Set_z(5.67); std::cout << "\n\nOperator '[]' Test: \n p1( 4; 4,5687; 5,67 )" << " Jetzt Ausgabe des y-Elementes von p1:" << std::endl; std::cout << " p1[1] = " << p1[1] << std::endl; Test_InneresProdukt_2er_Punkte(); //19.6 Test_Produkt_doubleZahl_x_Punkt(); //19.6 Test_Punkt_1_minus_Punkt_2(); //19.6 system("pause"); return 0; } void Test_InneresProdukt_2er_Punkte(void) //Test i.O. 2.2. 2020 { //1. Überladung Operator * ... neu hinzu bei 19.6 Point3D p1(2.2, 3.3, 4.4), p2(1.1, 1.2, 2.0); std::cout << "\n\nTest des inneren Produktes aus 2 Punkten im 3D-Raum" << "\n p1( 2.2, 3.3, 4,4 ) und p2( 1.1, 1.2, 2.0 )" << "\n Das Ergebnis muss 2.42, 3.96, 8.8 lauten:" << "\n p1 * p2 = " << p1 * p2 << std::endl; } void Test_Produkt_doubleZahl_x_Punkt(void) //Test i.O. 2.2. 2020 { //2. Überladung Operator * ... neu hinzu bei 19.6 Point3D p1(2.2, 3.3, 4.4); double z; z = 1.3; std::cout << "\n\nTest Produkt double-Zahl mit Punkt im 3D-Raum" << "\n p1( 2.2, 3.3, 4.4 ) und double-Zahle = 1.30" << "\n Das Ergebnis muss 2.86, 4.29, 5.72 lauten:" << "\n p1 * 1.3 = " << p1 * z << std::endl; } void Test_Punkt_1_minus_Punkt_2(void) //Test i.O. 2.2 2020 { //2. Überladung Operator - ... neu hinzu bei 19.6 Point3D p1(2.2, 3.3, 4.4), p2(1.1, 2.2, 1.39); // p2 muss fuer diese Überladung als Zeiger übergeben werden std::cout << "\n\nTest Subtraktion 2er Punkte im 3D-Raum" << "\n p1( 2.2, 3.3, 4.4 ) und p2( 1.1 , 2.2 , 1.39 )" << "\n Das Ergebnis p1 - p2 muss 1.1, 1.1, 3.01 lauten:" << "\n p1 - p2 = " << p1 - &p2 << std::endl; } //p1 wird dabei nicht verändert, wenn man das Ergebnis //speichern will muss man in neuen Punkt schreiben oder //in p1 schreiben: p1 = p1 - p2; das geht. #endif //if RUN_Uebung_19_6 == 1 // EOF
... Und hier noch der Vollständigkeit halber
das File mit den Define-Schaltern:#pragma once #ifndef general_definitions_H_ #define general_definitions_H_ // Fuer Uebung zu Operatoren // // Uebungsbuch: "C++ Das Übungsbuch" 3. Auflage // // Autoren Peter Prinz, Ulla Kirch-Prinz // #define RUN_Uebung_19_5 0 //Thema: Point 3D #define RUN_Uebung_19_6 0 //Thema: Point 3D #define RUN_Uebung_19_7 1 //Thema: Student Scores #define RUN_Uebung_19_8 0 #define RUN_Uebung_19_9 0 #define RUN_Uebung_19_10 0 #if RUN_Uebung_19_5 + RUN_Uebung_19_6 + RUN_Uebung_19_7 \ + RUN_Uebung_19_8 + RUN_Uebung_19_9 + RUN_Uebung_19_10 != 1 # error " You Have to Choose 1 Option! " #endif #endif //general_definitions_H_ // EOF
Schönen Abend euch ..
-
-
.. Ja den fand ich auch zum schmunzeln, recht hat er !
-
@0xFF Nur ein ganz kleiner Tipp. Nimm für die Übungen in der Konsole statt system("pause") zB
void ready() { std::cerr << "\nready_\n"; std::cin.sync(); std::cin.get(); }
Nur um das rauszuhaben plus auf Tastendruck warten
-
Jo, Danke für den Tip!
-
@0xFF
std::setprecision(2)
da ist doch der Übeltäter
-
-
@Swordfish sagte in :
@0xFF sagte in Operator [] rundet Wert:
exit(1);
lass das!
Wichtiger wäre, die Fehlerausgabe wegzulassen. Es ist nicht der Job von
operator[]
, den Benutzer zu belehren. Die Funktion sollte eine Vorbedingung,0 <= index && index < 3
, haben, dokumentieren, und mitassert
abprüfen. Das genügt. Es liegt dann in der Verantwortung des Aufrufers, einen gültigen Index zu übergeben.
-
@Bashar
Jup, das stimmt, war eben in der Übung so gefordert, sollte aber
bei einem Professionellen Programm anders abgefangen werden,
Danke für den Hinweis.
@Schlangenmensch
Ja, ich war der Meinung std::setprecision wirkt nur bis zum nächsten
Aufruf von cout ...