I am trying to override toString method like it is possible in Java. I am really new to C++, so even though test program using this header file will compile, it could have a lot of mistakes. My goal is to get the point back as string in the form of "(x1, x2, x3....x4)". The amount of coordinates will be changeing from 0 to n. How can I change toString() so that it would not return "test" but would return the coordinates of the point as String?
#ifndef POINT_H
#define POINT_H
#include <iostream>
#include <list>
#include <cmath>
using std::ostream;
using std::list;
using ::std::sqrt;
using namespace std;
template<unsigned short n>
class Point {
public:
list <float> coords;
Point <n>() = default;
Point <n>(list<float> coords){
if (coords.size()!=n) {
throw string ("Vale kordinaatide arv");
}
this-> coords=coords;
}
string toString() const {
return "Test toString";
}
float distanceFrom (Point <n> v){
float s=0;
list<float> coords;
auto it1= coords.begin();
auto it2= v.coords.begin();
while ((it1) != coords.end()){
s+=(*it1 -*it2)*(*it1-*it2);
it1++;
it2++;
}
return sqrt(s);
}
friend std::ostream& operator <<(std::ostream& out, const Point<n>& v)
{
out << "("<<"Test"<<")";
return out;
}
};
#endif
Related
I have to read patient data from a .csv file and using a decision tree determine, based on the data being read in for each patient, whether the tumor is Benign or Malignant.
I am really struggling with how to even start this. So far I have written code that reads from the .csv file and stores the data into a vector as shown below spreading over a few header and cpp files.
From what I gather, I can create a parent decision class and then each attribute I am to process are the children classes. Not sure if that makes sense. Please let me know.
Below you will find the attributes I am to process along with a graphical tree that shows how it is determined whether the tumor is Benign or Malignant that I need to base my code off of. I will also include a small sample of the .csv file.
Please could I get some guidance as how I am to do this. I am having the greatest difficulty with pointer notation. Any guidance will greatly be appreciated.
CSVLine.h
#ifndef CSVLINE_H
#define CSVLINE_H
#include <string>
#include <sstream>
#include <vector>
using namespace std;
class CSVLine
{
private:
vector<string> data;
public:
CSVLine() {}
CSVLine(const CSVLine& other)
{
data = other.data;
}
CSVLine operator = (const CSVLine& other)
{
data = other.data;
}
~CSVLine() {}
void parse(string line, char delimiter = ',');
string getString(int columnNumber);
int getInt(int columnNumber);
};
#endif
CSVLine.cpp
#include "CSVLine.h"
void CSVLine::parse(string line, char delimiter)
{
stringstream inLine(line);
string tempColumn = "";
while (getline(inLine, tempColumn, delimiter))
{
data.push_back(tempColumn);
}
}
string CSVLine::getString(int columnNumber)
{
return data[columnNumber];
}
int CSVLine::getInt(int columnNumber)
{
return atoi(data[columnNumber].c_str());
}
CSVReader.h
#ifndef CSVREADER_H
#define CSVREADER_H
#include <vector>
#include <fstream>
#include <iostream>
#include "CSVLine.h"
using namespace std;
class CSVReader
{
public:
CSVReader() {}
vector<CSVLine> read(string fileName);
};
#endif
CSVReader.cpp
#include "CSVReader.h"
vector<CSVLine> CSVReader::read(string fileName)
{
ifstream inputFile;
vector<CSVLine> lines;
inputFile.open(fileName.c_str());
string line = "";
while (getline(inputFile, line))
{
CSVLine csvLine;
csvLine.parse(line);
lines.push_back(csvLine);
}
return lines;
}
Here is what I would do.
First, I would translate the table of features to a higher-order macro:
#define FOREACH_FEATURE(OP) \
OP(1, SampleCodeNumber, int, -1) \
OP(2, ClumpThickness, int, -1) \
OP(3, UniformityOfCellSize, int, -1)
// Fill in the rest of the table of features here yourself
Then I would use this macro to generate a struct with all the features of a patient like this:
struct PatientData {
#define DECL_FEATURE(index, name, type, init) type name = init;
FOREACH_FEATURE(DECL_FEATURE)
#undef DECL_FEATURE
PatientData() {}
PatientData(CSVLine& src) {
#define READ_FEATURE(index, name, type, init) name = src.getInt(index-1);
FOREACH_FEATURE(READ_FEATURE)
#undef READ_FEATURE
}
};
Then I would construct a PatientData object from a CSVLine:
CSVLine line = ...;
PatientData patientData(line);
Then I would implement the decision tree as nested if-statements on the patientData object:
if (patientData.UniformityOfCellSize <= 2) {
// ...
} else {
// ...
}
This would get you started but you need to complete and possible extend the FOREACH_FEATURE macro and implement the decision tree...
Nodes and pointers approach
If you don't want to implement your tree like above, ditch the above code and instead do the following. Start by including a few files that we need and implement a Feature class:
#include <memory>
#include <functional>
struct Feature {
int index1;
int apply(CSVLine& line) const {return line.getInt(index1-1);}
};
and translate the table of features to Feature like this:
Feature SampleCodeNumber{1};
Feature ClumpThickness{2};
Feature UniformityOfCellSize{3};
// Fill in the rest yourself
We are going to use an std::function<bool(CSVLine)> to decide for the branch in the tree:
typedef std::function<bool(CSVLine&)> BranchCondition;
Overloading the comparison operator for a Feature and double to return a BranchCondition lets us neatly express BranchConditions:
#define DEF_FEATURE_OP(op) BranchCondition operator op (Feature f, double x) {return [f, x](CSVLine& line) {return f.apply(line) op x;};}
DEF_FEATURE_OP(<)
DEF_FEATURE_OP(<=)
DEF_FEATURE_OP(>)
DEF_FEATURE_OP(>=)
#undef DEF_FEATURE_OP
We also need to declare the return value of the classification:
enum class Severity {
Benign, Malign
};
As a base class for the decision tree we declare
class PatientClassifier {
public:
virtual Severity classify(CSVLine& p) const = 0;
virtual ~PatientClassifier() {}
};
and implement it for the trivial case of a constant value along with a function severity to construct it:
class ConstantClassifier : public PatientClassifier {
public:
ConstantClassifier(Severity v) : _value(v) {}
Severity classify(CSVLine&) const override {return _value;}
private:
Severity _value;
};
std::shared_ptr<PatientClassifier> severity(Severity v) {
return std::make_shared<ConstantClassifier>(v);
}
and for the branching case along with a function branch:
class BranchingClassifier : public PatientClassifier {
public:
BranchingClassifier(
BranchCondition f,
const std::shared_ptr<PatientClassifier>& onTrue,
const std::shared_ptr<PatientClassifier>& onFalse)
: _f(f), _onTrue(onTrue), _onFalse(onFalse) {}
Severity classify(CSVLine& p) const override {
return (_f(p)? _onTrue : _onFalse)->classify(p);
}
private:
BranchCondition _f;
std::shared_ptr<PatientClassifier> _onTrue;
std::shared_ptr<PatientClassifier> _onFalse;
};
std::shared_ptr<PatientClassifier> branch(
BranchCondition f,
const std::shared_ptr<PatientClassifier>& onTrue,
const std::shared_ptr<PatientClassifier>& onFalse) {
return std::make_shared<BranchingClassifier>(f, onTrue, onFalse);
}
and then we just build the tree like
auto decisionTree = branch(
UniformityOfCellSize <= 2.0,
severity(Severity::Benign),
severity(Severity::Malign));
CSVLine line;
auto result = decisionTree->classify(line);
Note: You don't need custom copy constructor and assignment operator for CSVLine. And the getInt method could be marked as const.
I am fairly new to classes. I created a class called Counter which basically creates a counter object and has certain data members and function members associated with it.
The header file for the class is:
#ifndef c
#define c
#include <iostream>
#include <string>
#include <vector>
using std::vector; using std::string; using std::ostream;
class Counter{
int v_;
public:
vector<string> log_;
int initialized_;
Counter(int);
int value();
int get_v() const { return v_; } //getter
void set_v(int val) { v_ = val; } //setter
friend ostream & operator<<(ostream &, Counter &);
friend Counter operator+(const Counter &, const Counter &);
};
ostream & operator<<(ostream &, Counter &);
Counter operator+(const Counter &, const Counter &);
#endif
and the cpp implementation file looks like this:
#include "counter.h"
#include <iostream>
#include <vector>
#include <string>
using std::string; using std::vector; using std::ostream;
Counter::Counter(int a){
v_ = a;
initialized_ = a;
log_.push_back("Constructor called with a " + std::to_string(a));
}
int Counter::value(){
log_.push_back("value called. returned a " + std::to_string(v_));
return (v_--);
}
ostream & operator<<(ostream & out, Counter & c){
c.log_.push_back("<< called."); //line 1
out << "Counter("<< c.initialized_ << ")#" << c.v_; //line 2
return out;
}
Counter operator+(const Counter & c_one, const Counter & c_two){
Counter c_three(c_one.initialized_ + c_two.initialized_);
c_three.set_v(c_one.get_v()+c_two.get_v());
return c_three;
}
When I compile the file I get bombarded with expected primary-expression before ‘.’ token in line 1 and line 2 of the "<<" operator overloaded function. I really have no idea as to why this is happening. Any help?
What is c? You've defined it as nothing and then you use
c.log_.push_back(...)
Which the preprocessor changes to
.log_.push_back(...)
I'm not sure what you're trying to do but the error clearly states it's looking for an expression before the period, where it appears you have none.
Vector2D hpp files
#ifndef Vector2D_hpp
#define Vector2D_hpp
#include <iostream>
#include "Point2D.hpp"
namespace GeoBox{
class Vector2D{
Point2D m_point1{};
Point2D m_point2{};
public:
Vector2D() = default;
Vector2D(Point2D &point1, Point2D &point2)
{
m_point1 = point1;
m_point2 = point2;
}
void setVector(Point2D &point1, Point2D &point2);
};
Vector2D.cpp files
#include "Vector2D.hpp"
#include "Point2D.hpp"
void GeoBox::Vector2D::setVector(GeoBox::Point2D &point1, GeoBox::Point2D &point2) {
Vector2D(point1, point2);
}
main.cpp
int main(int argc, const char * argv[]) {
GeoBox::Point2D point1{3.0, 1.0};
GeoBox::Point2D point2{2.0, 3.0};
GeoBox::Vector2D vect1{point1, point2};
}
I am trying to create a vector consisting of 2 points. how can i create their getters and settlers? I think I created the setter function, but I'm not sure.
note:GeoBox my file name
To create a vector, you should initialize it as a template type.
For the setter function you must implement the erase () function that can receive two iterators, one that points to the value you want to delete or two iterators if you want to delete an element range pointing to the initial and last value.
The erase () function is already a function implemented in c ++ 11 but it can be developed.
Its seems like this might work. I changed your class to store pointers and not objects for efficiency. Granted, I can't test that this because I don't have the rest of your code and can't guarantee your setup.
#ifndef Vector2D_hpp
#define Vector2D_hpp
#include <iostream>
#include "Point2D.hpp"
namespace GeoBox {
class Vector2D {
Point2D* points[2];
public:
Vector2D() = default;
Vector2D(Point2D* point1, Point2D* point2)
{
setVector(point1, point2);
}
void setVector(Point2D* point1, Point2D* point2) {
points[0] = point1;
points[1] = point2;
}
Point2D* getVector() {
return points;
}
};
}
#endif
To do this with a struct (and without pointers in this case) you would set it up like this:
#ifndef Vector2D_hpp
#define Vector2D_hpp
#include <iostream>
#include "Point2D.hpp"
namespace GeoBox {
class Vector2D {
struct Vector { //Define the struct
Point2D point1;
Point2D point2;
} points; //Create instance of struct
public:
Vector2D() = default;
Vector2D(Point2D point1, Point2D point2)
{
setVector(point1, point2);
}
void setVector(Point2D i_point1, Point2D i_point2) {
points.point1 = i_point1; //Access struct components
points.point2 = i_point2;
}
Vector getVector() {
return points; //return struct
}
};
}
#endif
Pointers can (and should) still be used in this case however as they allow for increased speed in your program overall.
I have two classes:
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
#include <algorithm>
#include <cmath>
#include <list>
using namespace std;
enum class Programm{Koch, Normal, Bunt, Fein};
class KleidSt {
private:
string bezeichnung;
int gewicht;
Programm Pflegehinweis;
public:
KleidSt(string bezeichnung, int gewicht);
KleidSt(string bezeichnung, int gewicht, Programm Pflegehinweis);
int get_gewicht() const;
bool vertraeglich(Programm)const;
int get_Pflegehinweis() const;
friend ostream& operator<<(ostream& os, const KleidSt& kleid);
};
class WaschM{
private:
int ladungsgewicht;
vector<KleidSt> wasch;
public:
WaschM(int ladungsgewicht);
void zuladen(const vector<KleidSt>& z);
void waschen(Programm);
friend ostream& operator<<(ostream& os, const WaschM& kleid);
int programme() const;
vector<KleidSt> aussortieren(Programm pr);
};
I want to create the function vector<KleidSt> aussortieren(Programm), that will delete all elements from wasch vector, if these elements will have Pflegehinweis attribute higher(by using static_cast<int>(elem) function) then is defined by aussortieren function and will return a vector of deleted elements.
My first try was to use Erase–remove idiom:
vector<KleidSt> WaschM::aussortieren(Programm pr){
wasch.erase(remove_if(begin(wasch), end(wasch), vertraeglich(pr)), end(wasch));
return wasch;
}
And here vertraeglich(pr) does the job, that I described above.
But it's clearly returns error, because vertraeglich function was defined out of the scope of class WaschM. The question is: how can I use Erase–remove idiom(or maybe some other variants), such that code will work?
Looks like a job for a lambda function
vector<KleidSt> WaschM::aussortieren(Programm pr){
wasch.erase(
remove_if(
begin(wasch),
end(wasch),
[&](const KleidSt& k){ return k.vertraeglich(pr); }),
end(wasch));
return wasch;
}
Untested code.
You can use a lambda function.
vector<KleidSt> WaschM::aussortieren(Programm pr){
wasch.erase(remove_if(begin(wasch),
end(wasch),
[pr](KleidSt const& item) {return item.vertraeglich(pr);},
end(wasch));
return wasch;
}
I got these 2 files for now and anytime I want to compile I get the error
string does not name a type
in Bestellung.h on the line with std::string name;.
Why?
main.cpp
#include "Bestellung.h"
#include <iostream>
using namespace std;
int main()
{
Bestellung();
cout << Bestellung{"maki"} << endl;// [maki,10€]
}
Bestellung.cpp
#include "Bestellung.h"
Bestellung(string bestellV, double preisV = 10){
name = "bestell V";
preis = "preis V";
};
string get_name const(Bestellung v) {
return Bestellung.name;
};
double get_preis const(Bestellung v){
return Bestellung.preis;
};
ostream& print(ostream&) const {
};
Bestellung.h
#ifndef BESTELLUNG_H
#define BESTELLUNG_H
#include <string>
#include <iostream>
class Bestellung{
std::string name;
std::double preis;
public:
Bestellung(string, double = 10);
string get_name const {
};
double get_preis const {
};
ostream& print(ostream&) const {
};
};
#endif
You have to use a namespace qualifier. You have:
Bestellung(string,double=10);
You should have:
Bestellung(std::string,double=10);
You also have:
string get_name const {
You should have:
std::string get_name const {
If you don't want to specify the std namespace every time you use a string, you can do this near the beginning:
using std::string;
Doing that in header files is bad practice though, so I would just use the full qualifications like I said to first.
After correcting this error, you need to do the same thing to that ostream you have too.
Read more about namespaces here.