stringstream operator input failing - c++

What is wrong with this overloaded operator?
I am trying to parse a stringstream to an object which has the members a, b and c as integers.
istream& operator>> (istream& in, Feedback& object) {
cout << __PRETTY_FUNCTION__ << endl;
in >> object.a;
in >> object.b;
in >> object.c;
cout << object.a << " " << object.b << " " << object.c << endl;
return in;
}
The last cout is printing 0 for all members.
I can see that the stringstream is properly filled before the input operator in this code...
cout << __PRETTY_FUNCTION__ << ": " << ss.str().c_str() << endl;
ss >> feedback;
this cout prints:
Feedback parseFeedbackData(unsigned char*, int): 10 2 4
The output overloaded operator is working fine. You can find the code below:
ostream& operator<< (ostream& out, Feedback& object) {
cout << __PRETTY_FUNCTION__ << endl;
out << object.a << " " << object.b << " " << object.c;
return out;
}

The output of ss.str().c_str() does not necessarily give a clue as to what the other states of the istringstream object are.
You should add tests to make sure that the reads are successful.
istream& operator>> (istream& in, Feedback& object) {
cout << __PRETTY_FUNCTION__ << endl;
if ( !(in >> object.a) )
{
cout << "Problem reading a\n";
return in;
}
if ( !(in >> object.b) )
{
cout << "Problem reading b\n";
return in;
}
if ( !(in >> object.c) )
{
cout << "Problem reading c\n";
return in;
}
cout << object.a << " " << object.b << " " << object.c << endl;
return in;
}
This will help you figure out where the problem lies.

Related

Comma separate in overloading ostream and istream in struct

I want my struct PersonData to get the output (firstname,lastname,personage,countrycode,income) with the comma seperator.
I have written this code but it only works with whitespace.
So output will be (firstname lastname personage countrycode income)
How can i change this to ,(comma) instead?
std::ostream& operator<<(std::ostream& output, const PersonData &pd)
{
output << pd.firstName << " " << pd.lastName << " " << pd.age << " " << pd.countryCode <<
" " << pd.income;
return output;
}
std::istream& operator>>(std::istream& indata, PersonData &pd)
{
indata >> pd.firstName >> pd.lastName >> pd.age >> pd.countryCode >> pd.income;
}
You can just change symbols (string literals) you've been outputting between PersonData's fields.
std::ostream& operator<<(std::ostream& output, const PersonData &pd)
{
output << pd.firstName << ", " << pd.lastName << ", " << pd.age << ", " << pd.countryCode <<
", " << pd.income;
return output;
}

Reading and writing from a file

I need to make card catalog entries for a library system and will need a menu and save the card and read the card from a file. I'm just looking for help and not saving for anyone to do it just tips if you have any because I want ro learn and not just copy and paste.
I already finished the information they need to add but having a problem making them save and read from a file and choosing from the menu to add new entry, review entry.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct libary
{
string title;
string author;
string ISBN_code;
int page_count;
int publish_year;
} s[10];
bool processMenu()
{
int choice, spot;
cout << "Main Menu" << endl;
cout << "Select your options" << endl;
cout << "1. Add a new entry to the system" << endl;
cout << "2. Review an entry" << endl;
cout << "3. Save entries to a file" << endl;
cout << "4. Read entries from a file" << endl;
cin >> choice;
switch (choice)
{
case 1:
cout << "which spot do you want to add a entry to the system " << endl;
cin >> spot;
break;
case 2:
cout << "which spot do you want to review to a file " << endl;
cin >> spot;
break;
case 3:
cout << "Save entries to a file" << endl;
ofstream myfile;
myfile.open("file.txt");
myfile << "this will show in the file";
break;
case 4:
cout << "read entries from a file :" << endl;
break;
case 7:
return 0;
}
}
int main()
{
while (!processMenu())
{
cout << "Sorry, that is not a valid choice." << endl;
cout << "Please try again." << endl << endl << endl;
}
cout << " Enter information of each card catalog" << endl;
for (int i = 0; i < 10; i++)
{
cout << endl;
cout << " Enter title " << endl;
cin >> s[i].title;
cout << endl;
cout << " Enter author " << endl;
cin >> s[i].author;
cout << endl;
cout << " Enter Page count " << endl;
cin >> s[i].page_count;
cout << endl;
cout << " Enter publish year " << endl;
cin >> s[i].publish_year;
cout << endl;
cout << " Enter ISBN code, it should be 13 digits" << endl;
cin >> s[i].ISBN_code;
while (s[i].ISBN_code.length() != 13)
{
cout << " Please enter a ISBN code thats 13 digits" << endl;
cin >> s[i].ISBN_code;
cout << endl;
cout << endl;
}
}
cout << " Displaying Information" << endl;
for (int i = 0; i < 10; i++)
{
cout << " title: " << s[i].title << endl;
cout << " author: " << s[i].author << endl;
cout << " page count: " << s[i].page_count << endl;
cout << " publish year: " << s[i].publish_year << endl;
cout << " ISBN code: " << s[i].ISBN_code << endl;
}
return 0;
}
It lets me pick a spot but won't add new entry nor review or save/read.
You can make your own type writable to a stream (cout or ofstream) and/or readable from a stream (cin or ifstream) just by overriding its output (operator<<) and/or input operator (operator>>).
#include <fstream> // ifstream, ofstream
#include <iostream> // cin, cout
#include <string> // getline, string
using namespace std;
struct Card
{
// Writing to the standard output ('cout').
friend ostream& operator<<(ostream& os, const Card& card);
// Reading from the standard input ('cin').
friend istream& operator>>(istream& is, Card& card);
// Writing to a file ('ofstream').
friend ofstream& operator<<(ofstream& os, const Card& card);
// Reading from a file ('ifstream).
friend ifstream& operator>>(ifstream& is, Card& card);
string title = "";
string author = "";
string isbn = "";
int page_count = -1;
int publish_year = -1;
};
ostream& operator<<(ostream& os, const Card& card)
{
os << "Title: " << card.title << '\n'
<< "Author: " << card.author << '\n'
<< "ISBN: " << card.isbn << '\n'
<< "Page count: " << card.page_count << '\n'
<< "Publish year: " << card.publish_year << '\n';
return os;
}
istream& operator>>(istream& is, Card& card)
{
// 'getline' needs for the reading of strings because the title of a book or
// its author's name may contain Space (' ') characters. 'cin' and
// 'ifstream' separate input by every whitespace. So, if we want to allow
// spaces in our fields we have to separate them by a special delimiter
// character. We use the Newline ('\n') character here to separate fields.
// `page_count` and `publish_year` are numbers, they don't contain
// whitespaces, so they simply can be read with 'operator>>'.
cout << "Title: ";
std::getline(is, card.title);
cout << "Author: ";
std::getline(is, card.author);
cout << "ISBN code: ";
std::getline(is, card.isbn);
cout << "Page count: ";
is >> card.page_count;
cout << "Publish year: ";
is >> card.publish_year;
return is;
}
// The next two functions is for files.
ofstream& operator<<(ofstream& os, const Card& card)
{
os << card.title << '\n'
<< card.author << '\n'
<< card.isbn << '\n'
<< card.page_count << '\n'
<< card.publish_year << '\n';
return os;
}
ifstream& operator>>(ifstream& is, Card& card)
{
std::getline(is, card.title);
std::getline(is, card.author);
std::getline(is, card.isbn);
is >> card.page_count;
is >> card.publish_year;
return is;
}
int main()
{
Card card;
// Read the informations of a card from the standard input.
cin >> card;
// Write the informations of a card to the standard output.
cout << card;
// Write the informations of a card to "file.txt".
ofstream ofs("file.txt");
ofs << card;
ofs.close();
// Read the informations of a card from "file.txt".
ifstream ifs("file.txt");
ifs >> card;
ifs.close();
return 0;
}
Important: For the sake of simplicity, I omitted error checking at the opening of a file and at the writing/reading of a stream. In your code you should do these.

Implementing a non-member IO operator

In my assignment I was asked to create the Product class, and I have finished all the implementations except the "non-member IO operator". The question I found it very vague, it asks me to overload the << and >> operators to work with ostream and istream to read a Product from and print a Product to the console in order to make this main function work.
Here I see the main function has cout or cin to Product's derived class SItem, I wonder how I should implement the << >> operators to make the main work.
My main:
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include "Product.h"
#include <fstream>
#ifdef TAB
# undef TAB
#endif
#define TAB '\t'
using namespace std;
namespace sict {
class SItem :public Product {
public:
SItem(const char* theSku, const char * theName) :Product(theSku, theName) {}
SItem() {}
virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const {
if (!isEmpty()) {
file.open("ms4.txt", ios::out | ios::app);
file << sku() << TAB << name() << TAB << quantity() << TAB << qtyNeeded() << TAB
<< int(taxed()) << TAB << price() << endl;
file.clear();
file.close();
}
return file;
}
virtual std::fstream& load(std::fstream& file) {
file.open("ms4.txt", ios::in);
char buf[2000];
double dbuf;
int ibuf;
file >> buf;
sku(buf);
file >> buf;
name(buf);
file >> ibuf;
quantity(ibuf);
file >> ibuf;
qtyNeeded(ibuf);
file >> ibuf;
taxed(ibuf != 0);
file >> dbuf;
price(dbuf);
file.clear();
file.close();
return file;
}
virtual std::ostream& write(std::ostream& os, bool linear)const {
return isEmpty() ? os : (os << sku() << ": " << name() << ", qty: "
<< quantity() << ", qtyNeeded:" << qtyNeeded()
<< ", Cost: " << fixed << setprecision(2) << cost());
}
virtual std::istream& read(std::istream& is) {
char buf[2000];
double dbuf;
int ibuf;
cout << "Sku: ";
is >> buf;
sku(buf);
cout << "Name (no spaces): ";
is >> buf;
name(buf);
cout << "Qty: ";
is >> ibuf;
quantity(ibuf);
cout << "Qty Needed: ";
is >> ibuf;
qtyNeeded(ibuf);
cout << "Is taxed? (1/0): ";
is >> ibuf;
taxed(ibuf != 0);
cout << "Price: ";
is >> dbuf;
price(dbuf);
return is;
}
};
}
void dumpFile(fstream& f) {
f.open("ms4.txt", ios::in);
char ch;
while (!f.get(ch).fail()) {
cout.put(ch);
}
f.clear();
f.close();
}
using namespace sict;
void test() {
double res, val = 0.0;
fstream F("ms4.txt", ios::out);
F.close();
SItem S;
SItem T;
SItem U;
cout << "Enter Product info: " << endl;
cin >> S;
SItem V = S;
S.store(F);
T.load(F);
cout << "T: (store, load)" << endl;
cout << T << endl;
cout << "S: " << endl;
cout << S << endl;
cout << "V(S): " << endl;
cout << V << endl;
cout << "U=T & op= :" << endl;
U = T;
cout << U << endl;
cout << "Operator == :" << endl;
cout << "op== is " << (T == "1234" ? "OK" : "NOT OK") << endl;
cout << "op+=: " << endl;
U += 10;
cout << U << endl;
cout << "op+=double : " << endl;
res = val += U;
cout << res << "=" << val << endl;
}
int main() {
fstream F("ms4.txt", ios::out);
F.close();
SItem S;
SItem U("4321", "Rice");
cout << "Empty Prouduct:" << endl << S << endl;
cout << "U(\"4321\", \"Rice\"):" << endl << U << endl;
cout << "Please enter the following information:" << endl;
cout << "Sku: 1234" << endl;
cout << "Name(no spaces) : Blanket" << endl;
cout << "Qty : 12" << endl;
cout << "Qty Needed : 23" << endl;
cout << "Is taxed ? (1 / 0) : 1" << endl;
cout << "Price : 12.34" << endl;
test();
cout << "Please enter the following information:" << endl;
cout << "Sku: 1234" << endl;
cout << "Name(no spaces) : Jacket" << endl;
cout << "Qty : 12" << endl;
cout << "Qty Needed : 23" << endl;
cout << "Is taxed ? (1 / 0) : 0" << endl;
cout << "Price : 12.34" << endl;
test();
dumpFile(F);
cout << "----The End" << endl;
return 0;
}
This is my Product.h:
namespace sict {
class Product : public Streamable {
char sku_[MAX_SKU_LEN + 1];
char * name_;
double price_;
bool taxed_;
int quantity_;
int qtyNeeded_;
public:
Product();
Product(const char*, const char*, bool = true, double = 0, int = 0);
Product(const Product&);
virtual ~Product();
Product& operator=(const Product&);
//setters
void sku(const char*);
void price(double);
void name(const char*);
void taxed(bool);
void quantity(int);
void qtyNeeded(int);
//getters
const char* sku()const;
double price()const;
const char* name()const ;
bool taxed()const;
int quantity()const;
int qtyNeeded()const;
double cost()const;
bool isEmpty()const;
//member operators
bool operator==(const char*);
int operator+=(int);
int operator-=(int);
};
double operator+=(double, const Product&);
std::ostream& operator<<(std::ostream& ostr, const Product& p);
std::istream& operator >> (std::istream& istr, Product& p);
}
All the functions have been implemented except the last two, which are the IO operators.
Streamable class is an abstract class that has no implementations.
You did this wrong in many ways.
Best approach in your case is do it like that.
First define interfaces for stream operations, for your products:
class IStreamPrintable
{
public:
virtual std::ostream& PrintToStream(std::ostream& outStream) const = 0;
};
class IStreamReadable
{
public:
virtual std::istream& ReadFromStream(std::istream& inputStream) = 0;
};
Secondly define stream operators which will use this interfaces.
std::ostream& operator<<(std::ostream& out, const IStreamPrintable& printObject)
{
return printObject.PrintToStream(out);
}
std::istream& operator>>(std::istream& input, IStreamReadable& readObject)
{
return printObject.ReadFromStream(input);
}
Now you Product can inherit this interfaces:
class Product
: public IStreamPrintable
, public IStreamReadable
{
…
};
You do not have to implement it immediately. You can implement those methods in specific product classes SItem and it will work out of the box.
Your method virtual std::fstream& store(std::fstream& file, bool addNewLine = true) is total mess. You are passing fstream object and opening some specific file on it. This is wrong since you are unable to write multiple objects to single file. Keep there ostream object and do not change is state (do only writing), so you could cascade calls and so you could avoid hard-coding a file name.

OOP: Method for cout output

I have to create a method, which prints all collected data's on screen, here is my try:
bool UnPackedFood::printer() {
cout << " -- Unpacked Products --" << endl;
cout << "barcode: " << getBarcode() << endl;
cout << "product name: " << getBezeichnung() << endl << endl;
cout << "weight: " << getGewicht() << endl;
cout << "price" << getKilopreis() << endl;
return true;
}
In my main:
UnPackedFood upf;
cout << upf.printer();
This shows me the correct output, but it still delivers me a bool value back, which I actually dont need. I tried to declare the method as void, but thats not working.
You should overload << operator for output stream. Then when you type cout << upf it will print your product.
Take a look at this example and try to do something similar to following snippet:
class UnPackedFood {
...
public:
...
friend ostream & operator<< (ostream &out, const UnPackedFood &p);
};
ostream & operator<< (ostream &out, const UnPackedFood &p) {
out << " -- Unpacked Products --" << endl;
out << "barcode: " << p.getBarcode() << endl;
out << "product name: " << p.getBezeichnung() << endl << endl;
out << "weight: " << p.getGewicht() << endl;
out << "price" << p.getKilopreis() << endl;
return out;
}
Three possible solutions:
Don't do cout << upf.printer();, the output is not needed since the function itself does the output.
Instead of writing to the output in the printer function, append to a string and return the string.
Make an overloaded operator<< for UnPackedFood, so you can just do std::cout << upf;

How to overload istream to accept input giving like this: (5, 6, 7)

I have very little code other than code I use to test. I think this is the way to begin:
istream& operator>>(istream& os, Vect3D& in)
{
is >> in.x >> in.y >> in.z;
return is;
}
Testing code:
cout << "Testing overload of >> operator" << endl;
stringstream stringin("(1.5, 2.5, 3.5)");
stringin >> v;
cout << v << endl;
cout << "Should be:" << endl;
Vect3D vCorrect(1.5, 2.5, 3.5);
cout << vCorrect << endl << endl;
cout << "Testing chaining of overload of >> operator" << endl;
stringstream sin("(2, 3, 4) 5.9");
double x;
sin >> v >> x;
cout << v << " and " << x << endl;
cout << "Should be:" << endl;
cout << "(2, 3, 4) and 5.9" << endl << endl;
There are a few things that look problematic here. The overloaded operator function takes in a istream reference named 'os' but in the block you use 'is'. Also, to pipe from input streams to ints and doubles variables they are separated by spaces so your extra '(' and ',' are likely causing a problem as well.