Istream input checking - c++

I have function, which recieves coeffecents of polynomial via istream input. Im struggling with implementing this piece of code into it (can't fully understand how istream& works), so i can shield it from incorrect input. :
while (!std::cin.good())
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "error";
std::cin >> A;
}
Into the function itself:
std::istream& operator>>(std::istream& s, Polynom& c)
{
for (int i = 0; i <= c.degree; i++)
s >> c.coefficents[i];
return s;
}
Needless to say, that's how it is implemented in main()
std::cin >> A;
Polynom class:
class Polynom
{
private:
int degree;
double* coefficents;
public:
Polynom();
Polynom(int size);
Polynom(const Polynom&);
~Polynom();
int get_degree();
double get_coefficents(int);
Polynom operator+(const Polynom&);
Polynom operator-(const Polynom&);
Polynom operator*(double p);
void operator=(const Polynom&);
friend std::ostream& operator<< (std::ostream& s, const Polynom& c);
friend std::istream& operator>> (std::istream& s, Polynom& c);
double& operator()(int i)
{
return coefficents[i];
}
};
Any hints or optimal solutions are welcomed :)

Expanding my comment to an answer, it's possible to make a function which takes the stream and uses the read-validation loop inside it to get the value.
Then in your operator>> overload you call this function to get each value.
Perhaps something like this:
template<typename T>
bool get_value(std::istream& input, T& value)
{
while (!(input >> value))
{
// If end of file, don't attempt any more validation
if (input.eof())
{
return false;
}
// Clear the error
input.clear();
// Ignore the rest of the line
input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
// When the loop ends, we have successfully read a value from the stream
// Return true to tell that
return true;
}
You could use it as:
std::istream& operator>>(std::istream& s, Polynom& c)
{
double value;
for (int i = 0; i <= c.degree && get_value(s, value); i++)
c.coefficents[i] = value;
return s;
}

Related

How can I read data from file to vector?

So I have this code where an object of class Group has vector with objects from class Student. I am already writing information about the students from the vector into a file but I have problem with reading this information back. How can I do that?
Here is my code so far:
class Group
{
private:
string name;
vector <Student*> studentList;
public:
~Group();
Group(void);
Group(string s);
void addStudent(string name,int age,int stNum);
void removeStudent(int stNum);
friend ostream& operator << (std::ostream& out, const Group& g) {
out << g.name << "\n";
out << g.studentList.size() << "\n";
for (unsigned i=0;i<g.studentList.size();i++) {
out<< g.studentList[i]->getStudentName()<<"\n";
out<< g.studentList[i]->getStudentAge()<<"\n";
out<< g.studentList[i]->getStudentNumber()<<"\n"<<endl;
}
return out;
}
friend istream& operator>>(std::istream& in, Group& g){
in >> g.name;
for (unsigned i=0;i<g.studentList.size();i++) {
//READ DATA FROM FILE
}
return in;
}
};
Gathering up the commentary. Note this pushes the hard part, the reading and writing, into Student and I left that bit blank. Normally I'd do it because I'm evil, but apparently in this case it is already written.
Major changes:
No Student pointers. Lest memory management overhead and better cache friendliness! By Grabthar's hammer. What a savings.
Student does the Student reading and writing.
std::vector handles the element counting so it doesn't need to be stored in and read from the output. Note: This could slow the reading down a little because you can't pre-allocate storage in the vector.
#include <string>
#include <iostream>
#include <vector>
// note the lack of using namespace std;
// it can be problematic, and especially so in a header.
class Student
{
//fill in the blanks
friend std::ostream& operator <<(std::ostream& out, const Student& s)
{
//fill in the blanks
return out;
}
friend std::istream& operator >>(std::istream& in, const Student& s)
{
//fill in the blanks
return in;
}
};
class Group
{
private:
std::string name;
std::vector<Student> studentList; // death to pointers!
public:
//~Group(); // Don't need a destructor without the pointer
Group(void);
Group(std::string s);
void addStudent(std::string name, int age, int stNum);
void removeStudent(int stNum);
friend std::ostream& operator <<(std::ostream& out, const Group& g)
{
out << g.name << "\n";
//out << g.studentList.size() << "\n"; not necessary. vector handles it.
for (std::vector<Student>::const_iterator it = g.studentList.cbegin();
it != g.studentList.cend();
++it)
{
if (!(out << *it))// let Student's << do all the work
{ // write failed. Might as well stop trying to write.
break;
}
}
return out;
}
friend std::istream& operator>>(std::istream& in, Group& g)
{
in >> g.name;
Student temp;
while (in >> temp) // let Student's >> do all the work
{
g.studentList.push_back(temp);
}
return in;
}
};

reverse function doesn't reverse the referenced string of a class instantiation

I'm trying to reverse the string from the FunnyNumber class. The problem is that when I call the method reverse in main on f2, it doesn't reverse the f2 string. But when I print out the reversed string from the reverse method implementation, it works. Also I overloaded the << operator to print out the string value in the class Number which is inherited in FunnyNumber class. Any help would be appreciated.
#ifndef NUMBER_H
#define NUMBER_H
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class Number {
public:
// Make a number with value 0
Number();
// Make a number with value val
Number(string val);
// Get the number's value
virtual string getValue() const;
// Print this number to the stream
virtual void print(ostream& stream) const;
// Read this number from the stream
virtual void read(istream& stream);
// Overload the insertion operator
friend ostream& operator <<(ostream& outs, const Number& n);
// Overload the extraction operator
friend istream& operator >> (istream& ins, Number& n);
protected:
string value;
};
#endif
Number::Number()
{
value = "";
}
Number::Number(string args)
{
value = args;
}
string Number::getValue()const
{
return value;
}
ostream& operator <<(ostream& outs, const Number& n)
{
n.print(outs);
return outs;
}
void Number::print(ostream& stream)const
{
stream << getValue();
}
void Number::read(istream& stream)
{
stream >> value;
}
istream& operator >> (istream& ins, Number& n)
{
n.read(ins);
return ins;
}
#ifndef FUNNYNUMBER_H
#define FUNNYNUMBER_H
#include<iostream>
#include<string>
#include"Number.h"
#include<algorithm>
using namespace std;
class FunnyNumber : public Number
{
public:
FunnyNumber();
FunnyNumber(string val);
virtual string operator+(const FunnyNumber &other)const;
virtual bool operator==(const FunnyNumber &other)const;
void reverse();
int find_first_not_this(char a);
protected:
string value;
};
#endif // !FUNNYNUMBERS_H
FunnyNumber::FunnyNumber()
{
value = "";
}
FunnyNumber::FunnyNumber(string val) : Number(val)
{
value = val;
}
string FunnyNumber::operator+ (const FunnyNumber& other)const
{
return getValue() + other.getValue();
}
int FunnyNumber::find_first_not_this(char a)
{
int pos = 0;
for(int i = 0; i < value.length(); i++)
{
if(value[i] != a)
{
pos = i;
return pos;
}
}
return pos;
}
bool FunnyNumber::operator==(const FunnyNumber& other)const
{
bool isEqual = true;
for (int i = 0; i < other.getValue().length(); i++)
{
bool found = false;
for (int j = 0; j < getValue().length(); j++)
{
if(getValue()[j] == other.getValue()[i])
{
found = true;
break;
}
}
if(!found)
{
isEqual = found;
return isEqual;
}
}
return isEqual;
}
void FunnyNumber::reverse()
{
std::reverse(value.begin(), value.end());
value.erase(0, find_first_not_this('0'));
}
#include <iostream>
#include<string.h>
#include "FunnyNumber.h"
using namespace std;
int main()
{
FunnyNumber f2;
f2 = FunnyNumber("223");
f2.reverse();
cout<<"Reversed value "<<f2<<endl;
system("pause");
return 0;
}
output is 223 instead of 322
Your FunnyNumber stores the value twice, once in a subobject of type Number, and once in string FunnyNumber::value.
Your reverse function modifies the second one, but doesn't have any effect on the Number base subobject. And then the only output function you call is working on the Number base subobject, and knows nothing about string FunnyNumber::value. That's why what is printed is not the result of reversal.
the overloaded operator << is a friend function on the Number class and friend functions are not inherited.
class Number {
public:
// Make a number with value 0
Number();
// Make a number with value val
Number(string &val);
// Get the number's value
virtual string getValue() const;
// Print this number to the stream
virtual void print(ostream& stream) const;
// Read this number from the stream
virtual void read(istream& stream);
// Overload the insertion operator
friend ostream& operator <<(ostream& outs, const Number& n);
// Overload the extraction operator
friend istream& operator >> (istream& ins, Number& n);
protected:
string *value;
};
Number::Number()
{
value = NULL;
}
Number::Number(string &args)
{
value = &args;
}
string Number::getValue()const
{
return *value;
}
ostream& operator <<(ostream& outs, const Number& n)
{
n.print(outs);
return outs;
}
void Number::print(ostream& stream)const
{
stream << getValue();
}
void Number::read(istream& stream)
{
stream >> *value;
}
istream& operator >> (istream& ins, Number& n)
{
n.read(ins);
return ins;
}

Private members of class - within this context

I get weird notification that I'm using private members of class - which is entirely valid, but I though that I'm allowed to do so, since I did say that the method I'm using is a friendly one.
Take a look at this:
#include <iostream>
using namespace std;
class complex {
private:
double Re, Im;
public:
complex(): Re(0.0), Im(0.0){}
complex(double Re, double Im): Re(Re), Im(Im){}
double getRe() const { return Re; }
double getIm() const { return Im; }
friend complex operator+(const complex&, const complex&);
friend ostream& operator<<(ostream&, const complex&);
friend istream& operator>>(istream &, const complex &); // FRIENDLY FUNCTION
};
complex operator+(const complex& a, const complex& b) {
double r, i;
r = a.getRe()+ b.getRe();
i = a.getIm() + b.getIm();
return complex(r, i);
}
ostream& operator<<(ostream& out, const complex &a) {
out << "(" << a.getRe() << ", " << a.getIm() << ")" << endl;
return out;
}
istream &operator>>(istream &in, complex &c)
{
cout<<"enter real part:\n";
in>>c.Re; // ** WITHIN THIS CONTEXT ERROR **
cout<<"enter imag part: \n";
in>>c.Im; // ** WITHIN THIS CONTEXT ERROR **
return in;
}
int main(void) {
complex a, b,c;
cin >> a;
cin >> b;
c = a+b;
cout << c;
}
Should I declare some sort of setFunction within the class in order to get the values which are private ?
istream& operator>>(istream &, const complex &);
is not the same as
istream &operator>>(istream &in, complex &c);
Spot the difference left as exercise to the reader.

How to read enums from a std::istream in a generic fashion [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Input from stream to enum type
I have several classes with different enums as class members and I want to read the classes from a stream.
The following code shows an exemplary class:
enum enSide{
eLeft,
eRight
};
enum enType{
eConUndefined,
eConRoom
};
class MyClass{
public:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> val.mSide >> val.mType >> val.mTargetId;
return in;
}
MyClass(){}
private:
enSide mSide;
enType mType;
int mTargetId;
};
Unfortunately this does not work since direct reading into an enum Value is not possible (no template for >>).
Thus I created a helper class:
template<class ENUM>
class ScanTo{
public:
friend std::istream& operator>>(std::istream& in, ScanTo<ENUM>& eval) {
unsigned int val;
in >> val;
eval.mrEnum = static_cast<ENUM>(val);
return in;
}
ScanTo(ENUM& eRef):mrEnum(eRef){}
private:
ENUM& mrEnum;
};
Now I can write the code for reading MyClass as follows:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
ScanTo<enSide> scanside(val.mSide);
ScanTo<enType> scantype(val.mType);
in >> scanside >> scantype >> val.mTargetId;
return in;
}
This is already not far from what I wanted but still needs two indirections over the helper class, which cannot be written as temporarys:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> ScanTo<enSide>(val.mSide)>> ScanTo<enType>(val.mType) >> val.mTargetId;
return in;
}
does not compile (gcc 4.43), because a non const reference to a temporary is forbidden as pointed out in the comments.
So here comes the question:
Can this be done easier without resorting to some temporaries and templates as done above?
I think you may write a helper function template:
template <class T>
std::istream& operator >>(std::istream& is, T& t)
{
int i;
is >> i;
t = (T)i;
return is;
}
which makes
in >> val.mSide >> val.mType >> val.mTargetId;
possible.
The best option for you is to define your data members as int, and use type safe accessors to set and retrieve them.
class MyClass{
public:
friend std::istream& operator>>(std::istream& in, MyClass& val) {
in >> val.mSide >> val.mType >> val.mTargetId;
return in;
}
MyClass(){}
enSide side () const { return static_cast<enSide>(mSide); }
void side (enSide v) { mSide = v; }
enType type () const { return static_cast<enType>(mType); }
void type (enType v) { mType = v; }
int targetId () const { return mTargetId; }
void targetId (int v) { mTargetId = v; }
private:
int mSide;
int mType;
int mTargetId;
};
This avoids the temporaries as you desired.

Operator overloading with files

Is there a way in which I can use a operator overloader to output to a file. I understand the code behind the actual outputting to a file but I don't understand how I would actually invoke a overloader to carry out the out to the file
Any help in helping me understand this would be appreciated
struct A {
int a;
public:
std::ostream& save(std::ostream& out) const {
return out << a;
}
std::istream& load(std::istream& in) {
return in >> a;
}
};
std::ostream& operator<<(std::ostream& out, const A& obj) {
return obj.save(out);
}
std::istream& operator>>(std::istream& in, A& obj) {
return obj.load(in);
}
int main() {
A a;
std::cin >> a;
std::cout << a;
return 0;
}