I am trying to take out to the console window my vector of pointers but still doesn't work. I can fill the vector but when I try to cout<< my object noting comes out on the console window.
This is header file with declarations of the private class members and functions:
#pragma once
#include"CDealer.h"
#include<vector>
#include<fstream>
#include<iterator>
class CShop
{
public:
CShop();
~CShop();
CShop(const string &fname);
friend ostream &operator << (ostream &toStream, const CShop &S);
friend istream &operator >> (istream &fromStream, CShop &S);
private:
string m_strNameShop;
string m_strCity;
vector<CDealer*> Dealers;
};
This is my constructor with file from where I bring the data
#include "CShop.h"
CShop::CShop(){}
CShop::~CShop(){}
CShop::CShop(const string &fname)
{
fstream File(fname, ios::in);
if (File.is_open())
{
CDealer c;
File >> m_strNameShop;
File >> m_strCity;
while (File.is_open())
{
File >> c;
Dealers.push_back(new CDealer(c));
}
File.close();
}
else
throw "ERROR! ";
}
and this is overloading operator<<:
ostream &operator << (ostream &toStream, const CShop &S)
{
return toStream << "Name Shop: " << S.m_strNameShop << " City: " << S.m_strCity;
vector<CDealer *>::const_iterator it = S.Dealers.begin();
while (it != S.Dealers.end())
{
toStream << "Dealer " << *it++;
}
}
So in the end my main
#include"CShop.h"
#include<iostream>
#include<string>
#include <stdlib.h>
#include<vector>
using namespace std;
int main()
{
CShop SS1("data.txt");
cout << SS1;
system("pause");
return 0;
Please help Me :)
You have a premature return in the function.
return toStream << "Name Shop: " << S.m_strNameShop << " City: " << S.m_strCity;
//^^^
Remove it.
toStream << "Name Shop: " << S.m_strNameShop << " City: " << S.m_strCity;
Add a return before the end of the function.
std::ostream& operator<<(std::ostream& toStream, const CShop &S)
{
toStream << "Name Shop: " << S.m_strNameShop << " City: " << S.m_strCity;
vector<CDealer *>::const_iterator it = S.Dealers.begin();
while (it != S.Dealers.end())
{
toStream << "Dealer " << *it++;
}
return toStream;
}
Suggestions for further improvement.
The line
toStream << "Dealer " << *it++;
will print only the pointer values. If you want to print the details of the object the pointers point to, change it to:
Dealer* dealerPtr = *it++;
toStream << "Dealer " << *dealerPtr;
The following block is not right. File.is_open() will be always true in this block.
while (File.is_open())
{
File >> c;
Dealers.push_back(new CDealer(c));
}
Change it to:
while (File >> c)
{
Dealers.push_back(new CDealer(c));
}
Related
I'm guessing I might have to use pointers, but haven't gone in depth too much on them in class yet to try and implement them in my program. I have this so far, the printing function is towards the middle of the program. I'm not quite sure on how to print out the elements from the vector as my approach didn't work.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class rolodex
{
string name;
string street, town, state;
string zip;
string phone;
vector <rolodex> entries;
public:
rolodex();
void getmenu();
void add_entry();
void set_name();
void set_address();
void set_phone();
void printinfo();
};
rolodex :: rolodex() : name(""), street(""), town(""), state(""), zip(""),
phone(""), entries()
{
}
void rolodex :: getmenu()
{
cout << "\n\n1)Add Entry";
cout << "\n5)Print All Entries";
cout << "\n6)Exit" << endl;
}
void rolodex :: add_entry()
{
rolodex temp;
cout << "\n\nEnter Name: ";
temp.set_name();
temp.set_address();
cout << "\n\nEnter Your Phone Number: ";
temp.set_phone();
entries.push_back(temp);
}
void rolodex :: set_name()
{
cin.ignore();
getline(cin, name);
}
void rolodex :: set_address()
{
cout << "\n\nNow we'll enter address information.";
cout << "\n\nStreet: ";
getline(cin, street);
cout << "\n\nTown: ";
getline(cin, town);
cout << "\n\nState: ";
getline(cin, state);
cout << "\n\nZip: ";
getline(cin, zip);
}
void rolodex :: set_phone()
{
getline(cin, phone);
}
void rolodex :: printinfo()
{
for(unsigned int i = 0; i < entries.size(); i++)
{
cout << entries[i] << endl; //This is where I'm stuck since I've only
//worked with vectors of non-object data
//type
}
}
int main()
{
rolodex person, menu;
short choice;
bool done = false;
do
{
menu.getmenu();
cout << "\n\nEnter a choice: ";
cin >> choice;
switch(choice)
{
case 1:
person.add_entry();
break;
case 5:
person.printinfo();
break;
case 6:
done = true;
break;
default:
cout << "\n\nInvalid Entry." << endl << endl;
}
} while(!done && isdigit(choice));
return 0;
}
πάντα ῥεῖ is right, but to add a little more detail...
You need to specify how you want the stream to handle your object. This is done by by adding a << operator. For example:
std::ostream& operator<<(std::ostream& s, const rolodex& r){
// Or however you want to format it.
s << "Name: " << r.name << " : ";
s << "Street: " << r.street << " : ";
s << "Town: " << r.town << " : ";
s << "State: " << r.state << " : ";
s << "Zip: " << r.zip << "\n";
}
Unfortunately, the function above tries to access the private fields of your class, which it can't because it is not part of the class definition.
An easy way to address that is to declare this function a "friend" inside of the class definition, like such:
friend std::ostream& operator<<(std::ostream&, const rolodex&);
...And since you might appreciate it, one big copy-pasteable chunk that you can use directly that should make your function work:
class rolodex
{
string name;
string street, town, state;
string zip;
string phone;
vector <rolodex> entries;
public:
rolodex();
void getmenu();
void add_entry();
void set_name();
void set_address();
void set_phone();
void printinfo();
friend std::ostream& operator<<(std::ostream&, const rolodex&);
};
std::ostream& operator<<(std::ostream& s, const rolodex& r){
// Or however you want to format it.
s << "Name: " << r.name << " : ";
s << "Street: " << r.street << " : ";
s << "Town: " << r.town << " : ";
s << "State: " << r.state << " : ";
s << "Zip: " << r.zip << "\n";
}
Following up on πάντα ῥεῖ's suggestion, here's one way of doing that, changing your design as little as possible:
1) Create a non-member overloaded operator<< for your rolodex class:
std::ostream& operator<< (std::ostream& os, const rolodex& rol)
{
os << rol.name << ":" << std::endl
<< "\t" << rol.street << std::endl
<< "\t" << rol.town << std::endl
<< "\t" << rol.state << std::endl
<< "\t" << rol.zip << std::endl
<< "\t" << rol.phone << std::endl;
return os;
}
.. but the compiler will chide you for attempting to access private members (by default, members are private) from outside the class, so you would have to relax the rules a bit:
class rolodex
{
...
public:
...
friend std::ostream& operator<< (std::ostream& os, const rolodex& rol);
};
You can't have the operator<< inside the class itself, see does-overloading-operator-works-inside-the-class.
However, it is almost always better design to add getter functions to your public interface anyway. You would have get_name() etc in the public: section of your class def, those functions would initially just return the values of the private member variables, and then your operator<< can use them instead of trying to access the private members. You then no longer require the friend declaration.
I upvoted Some programmer dude's remark about your design
The code for letting the use input the data really shouldn't be inside the rolodex class, because it makes the class hard to reuse. Image wanting to re-use the rolodex from a graphical interface, for example, and it's not such a good idea to have the rolodex contain instances of itself inside the vector.
I would suggest a
1) Person class containing all the person's attributes, with public getters get_name() and setters set_name() that don't use a specific entry method, just take the data as arguments e.g. set_name(std::string& name).
2) an non-member operator<< to output a person to an output stream
3) a Rolodex class with a private std::vector<Person> and methods to add a person, write all the persons to an output stream, etc..
Good luck & enjoy :-)
Edit: the menu structure on the terminal should IMHO be left inside the main() function or encapsulated into another class. But certainly don't leave it in Rolodex or worse, Person.
I have a problem with fill container map with information . I read the information with operator>> but it gives me these errors in my second class CDealer. no operator ">>" matches these operands and binary">>": no operator found which takes a right-hand operand of type 'const CStock'(or these is no acceptable conversion)
I have three classes: CStock, CDealer who have map<CStock, pair<unsigned, double>> Stock; and CShop who have vector<CDealer*> Dealers;
I'll be very thankful if someone can help me.
This is my operators << and >> in CStock
ostream &operator << (ostream &toStream, const CStock &S){
toStream << "Name Stock: " << S.m_strName_stock << " Producer: " << S.m_strProducer <<
"Date: " << S.Date;
return toStream;
}
istream &operator >> (istream &fromStream, CStock &S)
{return fromStream >> S.m_strName_stock >> S.m_strProducer >> S.Date;}
This is my operators << and >> in CDealer
`
ostream &operator << (ostream &toStream, CDealer &D)
{
toStream << "Name Dealer: " << D.m_strName_Dealer << " Agent: " << D.m_strAgent <<
"Address: " << D.m_strAddress;
map<CStock, pair<unsigned, double>>::const_iterator it = D.Stock.begin();
while (it != D.Stock.end())
{
toStream << it->first <<it->second.first << it->second.second;
}
return toStream;
}
istream &operator >> (istream &fromStream, CDealer &D)
{
map<CStock, pair<unsigned, double>>::iterator it = D.Stock.begin();
fromStream >> D.m_strName_Dealer >> D.m_strAgent >> D.m_strAddress;
while (it!= D.Stock.end())
{fromStream >> it->first >> it->second.first >> it->second.second;}
return fromStream
}
And this is the constructor with parameter: file name and these tho operators <<, >>
CShop::CShop(const string &fname)
{
CDealer c;
fstream File(fname, ios::in);
if (File.is_open())
{
File >> m_strNameShop;
File >> m_strCity;
while (File>>c)
{
Dealers.push_back(new CDealer(c));
}
File.close();
}
else
throw "ERROR! ";
}
ostream &operator << (ostream &toStream, const CShop &S)
{
toStream << "Name Shop: " << S.m_strNameShop << " City: " << S.m_strCity;
vector<CDealer* >::const_iterator it = S.Dealers.begin();
while (it != S.Dealers.end())
{
CDealer* dealerPtr = *it++;
toStream << *dealerPtr<< endl;
}
return toStream;
}
istream &operator >> (istream &fromStream, CShop &D)
{
return fromStream >> D.m_strNameShop >> D.m_strCity;
}
And in the end main()
#include"CDealer.h"
#include"CShop.h"
#include<iostream>
#include<string>
#include <stdlib.h>
#include<vector>
using namespace std;
int main()
{
CShop SS1("data.txt");
cout << SS1;
system("pause");
return 0;
}
The implmentation of istream &operator >> (istream &fromStream, CDealer &D)
is poorly thought through.
The objective of the function is to read data from an input stream and flesh out the contents of the CDealer object. Normally the operator<< and operator>> functions work in tandem so that what you write using operator<< can be read back using operator>>.
From that point of view, even the operator<< function needs to revamped.
Here's one implementation that should work as long as there are no spaces in the string objects. If you have space in your string objects, the code needs be changed.
std::ostream& operator<<(std::ostream &toStream, CDealer cosnt& D)
{
// Write the name of the dealer, without any decorative text.
// Add a space character to the output so you can read the name back.
toStream << D.m_strName_Dealer << " ";
// Do the same for name of the agent and address.
toStream << D.m_strAgent << " ";
toStream << D.m_strAddress << " ";
// Write the number of items in Stock first.
// This will be necessary when reading the data.
toStream << D.Stock.size() << " ";
// Now write the Stock items, which spaces between each field you write.
map<CStock, pair<unsigned, double>>::const_iterator it = D.Stock.begin();
while (it != D.Stock.end())
{
toStream << it->first << " " << it->second.first << " " << it->second.second << " ";
}
return toStream;
}
std::istream &operator>>(std::istream &fromStream, CDealer &D)
{
// Read the name of the dealer.
fromStream >> D.m_strName_Dealer;
// Read the name of the agent.
fromStream >> D.m_strAgent;
// Read the address.
fromStream >> D.m_strAddress;
// Read the number of items.
size_t num;
fromStream >> num;
// Now read the Stock items.
for ( size_t i = 0; i < num; ++i )
{
// Obtained the types for key, val1, and val2 from
// the error message posted in a comment by OP.
CStock key;
int val1;
double val2;
fromStream >> key >> val1 >> valu2;
// Add the item to Stock.
D.Stock.insert(std::make_pair(key, std::make_pair(val1, val2)));
}
return fromStream
}
Problem
The problem can be reduced to the following case:
#include <map>
int main(void) {
std::map<int, int> val;
auto it = val.begin();
it->first = 10;
}
The key values in a std::map are const (the pair of key and value is defined as std::pair<const Key, T>), so for
map<CStock, pair<unsigned, double>>
we have a map containing pairs of
std::pair<const CStock, pair<unsigned, double>>
which makes it->first in
fromStream >> it->first >> it->second.first >> it->second.second;
a const CStock and results in the reported error.
This all makes sense because the map is ordered by the key, so if you could change the key whenever you wanted to whatever you wanted the map would soon be incoherent.
Documentation on std::map
Solution
There is no simple solution. You cannot do this. You must either make the items and then place them in the map or use one of the emplace family of functions to construct them directly in the map. Once they are in the map you can change the value, but not the key. You could remove the item, and thus the key, and reinsert with a different key, but why are you doing this in the first place? I recommend a rethink of your logic.
I hope this time my question is better formulated and formatted.
Here's the code that produces two separate outputs when I think it should not since I use everytime (I think) the overloaded operator<< for an enum type.
#include <iostream>
using namespace std;
enum Etat { Intact = 5 };
class Ship {
public:
Etat etat_;
Ship ( Etat t = Intact) : etat_(t) {}
~ Ship() {}
ostream& description ( ) const { return cout << "Etat: " << etat_ << " --- ";}
//---------------------------------------ˆˆˆˆ----
};
ostream& operator<< ( ostream& s, const Etat& etat_ )
{
switch ( etat_ )
{
case Intact: s << "intact"; break;
default: s << "unknown state";
}
return s;
}
ostream& operator<< ( ostream& s, Ship n ) { return s << "Etat: " << n.etat_ ; }
int main()
{
Etat etat_ = Intact;
cout << endl << endl << "Etat: "
<< etat_ << " \"cout << etat_\"" << endl << endl;
cout << Ship(etat_)
<< " \"cout << Ship(etat_)\"" << endl << endl;
cout << Ship(etat_).description()
<< " \"cout << Ship(etat_).description()\"" << endl << endl;
return 0;
}
This is what I get in the terminal:
Etat: intact "cout << etat_"
Etat: intact "cout << Ship(etat_)"
Etat: 5 --- 1 "cout << Ship(etat_).description()"
Can anyone explain to me why, in the last case, not only it takes the integer value of the enum attribut, but also adds a "1" after the test string " --- "???
The only thing I can think of is because I used an unorthodox return method in description(), ie 'return cout << ..", but it seems to work since the test string appears.
Is there a way to force the use of the operator<< overload in description()?
Thanks
In the description() function you are returning a reference to std::cout and use it in the std::cout call in main function. There is a reason why operator<< takes an ostream reference as it's first argument. You should modify your function like this and all should work:
ostream& description(ostream& os) const {
return os << "Etat: " << etat_ << " --- ";
}
The random "1" printed out there is caused likely due to the ostream in your example trying to print out reference to itself.
So far I have defined a simple class...
class person {
public:
string firstname;
string lastname;
string age;
string pstcode;
};
...then added some members and values to an object named "bill"...
int main() {
person bill;
bill.firstname = "Bill";
bill.lastname = "Smith";
bill.age = "24";
bill.pstcode = "OX29 8DJ";
}
But how would you simply output all those values? Would you use a for loop to iterate over each member?
I typically override operator <<, so that my objects are as easy to print as any built-in object.
Here is one way to override operator <<:
std::ostream& operator<<(std::ostream& os, const person& p)
{
return os << "("
<< p.lastname << ", "
<< p.firstname << ": "
<< p.age << ", "
<< p.pstcode
<< ")";
}
And then to use it:
std::cout << "Meet my friend, " << bill << "\n";
Here is a complete program using this technique:
#include <iostream>
#include <string>
class person {
public:
std::string firstname;
std::string lastname;
std::string age;
std::string pstcode;
friend std::ostream& operator<<(std::ostream& os, const person& p)
{
return os << "("
<< p.lastname << ", "
<< p.firstname << ": "
<< p.age << ", "
<< p.pstcode
<< ")";
}
};
int main() {
person bill;
bill.firstname = "Bill";
bill.lastname = "Smith";
bill.age = "24";
bill.pstcode = "OX29 8DJ";
std::cout << "Meet my friend, " << bill << "\n";
}
Simplistically, you output each element using an ostream:
class Person
{
public:
void Print_As_CSV(std::ostream& output)
{
output << firstname << ",";
output << lastname << ",";
output << age << ",";
output << pstcode << "\n";
}
string firstname;
string lastname;
string age;
string pstcode;
};
There may be different methods of printing, which is why I didn't overload operator <<. For example, one data member per line would be another popular scenario.
Edit 1: Why not looping?
The class has separate fields, which is why you can't iterate over the members.
If you want to iterator or loop over the members, you either have to have an iterator for your class or use a container, such as std::vector, that provides iteration.
I am trying this piece of code in vs 2008
#include <stdio.h>
#include <iostream>
#include <string>
typedef struct _first
{
int age;
std::string name;
}first;
typedef struct _second
{
int age;
char name[20];
}second;
void copy_structure()
{
first s;
second f;
f.age = 15;
cout<<"Enter the name"<<endl;
fgets(f.name, 20, stdin);
memcpy(&s,&f,20);
cout << "Name: " << s.name << endl;
cout << "Age: "<< s.age << endl;
}
int main()
{
copy_structure();
return 0;
}
while building I didn't get any error but when I run, name field is empty over here
cout << "Name: " << s.name << endl;
I am not getting any output over here, can somebody help me to solve this issue.
You should use an approach based on member-wise copying. For example
void copy_structure()
{
first f;
^^
second s;
^^
s.age = 15;
cout<<"Enter the name"<<endl;
fgets(s.name, 20, stdin);
f.age = s.age;
f.name = s.name;
cout << "Name: " << f.name << endl;
cout << "Age: "<< f.age << endl;
}
Otherwise the internals of the object name of the type std::string will be overwritten and the program will have undefined behaviour.
This looks like C but not like C++... Your current code will also brick your std::string instance. memcpy is dangerous and should not be used, unless you have a very, very good reason. I never had a reason for this so far.
My suggestion:
#include <iostream>
#include <string>
using namespace std;
struct second
{
int age;
char name[20];
};
struct first
{
int age;
string name;
first& operator=(const second& rhs);
};
// some operator for copying
first& first::operator=(const second& rhs)
{
age = rhs.age;
name = rhs.name;
return *this;
}
int main()
{
first s;
second f;
f.age = 15;
cout << "Enter your name" << endl;
cin >> f.name;
s = f;
cout << "Name: " << s.name << endl;
cout << "Age: " << s.age << endl;
return 0;
}
This is improvable, of course. You would usually rather use classes than structs. And you would might also have an operator>> for second.