Overload <<, returning ostream gives error. C++ - c++

I'm having an issue with overloading the << operator. Everything prints and enters fine, but when I try and return the ostream, I get this error:
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
I've also already overloaded another << operator in this project that has returned an ostream just fine. This operator isn't used in the following code. Here's the code:
#include "header1.h"
#include <iostream>
using namespace std;
class Car
{
public:
friend class Extras;
friend int main();
friend ostream& operator<< (ostream& os, const Car& in);
Car();
Car(string in_name, int in_year, string in_color, float in_cost);
private:
string name, color;
int year, extr_num;
float cost;
Extras *extr;
};
int main()
{
Car c1;
cout << c1;
return 0;
}
//Default Constructor
Car::Car()
{
name = "TEMP";
color = "BLUE";
year = 0;
cost = 0;
extr = new Extras[3];
extr_num = 0;
}
//Constructor
Car::Car(string in_name, int in_year, string in_color, float in_cost)
{
name = in_name;
color = in_color;
year = in_year;
cost = in_cost;
extr = new Extras[3];
extr_num = 0;
}
//Overloaded << operator for Car class
//This function is the one that fails.
ostream& operator<< (ostream& os, const Car& in)
{
os.precision(2);
os << in.name << ", " << in.year << ", "
<< in.color << ", $"<< in.cost << ", ";
os << "extras include: ";
os << endl;
return os; //Line of code in question
}
This bit of code in the other header works perfectly fine:
ostream& operator<< (ostream& os, Extras const &in)
{
os << in.ex_list;
return os;
}
Everything prints to the screen fine before the return. And these two functions look the same to me, can someone more experience with C++ tell me otherwise?

There's nothing in the shown code that will cause the problem you describe. The "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)" error is an indication that the heap was corrupted at an earlier point, it's being detected at your return statement but isn't otherwise related to the code in your operator<<

You've hosed your heap. It may or may not have anything to do with the code currently running. Don't see anything immediately apparent in what you've decided to show us that would cause it though I'd start with any use of raw pointers.

Related

I am having problem with the << operator in the owner file

I have made a programme that has two types of classes that implements owner as well as dogs , I am having a problem with the iterator part in the << operator in the Owner.h file, I know that we can't use an iterator for an STL container having its type as a custom class , but then what is the alternative to do so ?
I am attaching the files for you reference with the main file
I know this is a lot to ask from you guys , but just recommend me a way and i'll figure it out
Thanks
Main File
#include <iostream>
#include "Owner.h"
#include "Dog.h"
using namespace std;
void Purchase(Owner& owner, Dog& dog) {
owner.AddDog(dog);
dog.SetOwner(owner);
}
int main() {
Owner owner1("Michael Hagley", "14 Brentwood Terrace");
Owner owner2("Oliver Walter", "299 Mill Road");
Dog dog1("Cheeto", 5, 2000.00);
Dog dog2("Mavrick", 8, 1800.00);
Dog dog3("Biglet", 4, 2100.00);
Dog dog4("Snoopy", 11, 600.00);
Dog dog5("Leggo", 2, 500.00);
Dog dog6("Bugsy", 4, 1100.00);
Purchase(owner1, dog1);
Purchase(owner1, dog5);
Purchase(owner2, dog2);
Purchase(owner2, dog3);
Purchase(owner2, dog6);
cout<<owner1.GetName()<<" Has the following dogs"<<std::endl;
cout<<std::endl;
cout<<owner2.GetName()<<"has the following dogs"<<std::endl;
// cout << owner1;
//
// cout << owner2;
Owner* owner = dog1.GetOwner();
if (owner) cout << dog1.GetName() << " belongs to " << owner->GetName() << endl;
owner = dog4.GetOwner();
if (owner){
cout << dog4.GetName() << " belongs to " << owner->GetName() << endl;
}
else{
cout<<dog4.GetName()<<" Has no owner"<<endl;
}
return 0;
}
Owner File
//
// Created by Kannav Sethi on 21/04/22.
//
#ifndef FINALS_OWNER_H
#define FINALS_OWNER_H
#include <iostream>
#include <vector>
//Wwe'll be using the concept of association and aggregation here
class Dog;
class Owner{
// provided the variables for the Owner here
// the only viable STL container here is vectors of type dogs
//but there is a problem with it , I wont be able to iterate over the dogs vector due to it being of a custom type
//Lets try that out here
std::string name;
std::string address;
std::vector<Dog> dogs;
int size=0;
public:
// constructor
Owner(){
name="";
address="";
};
//constructor
Owner(std::string name,std::string address){
this->name=name;
this->address=address;
};
// tried out making a copy assignment but it was futile
// Owner& operator=(Owner& oTemp){
// this->name=oTemp.name;
// this->address=oTemp.address;
// for(auto i = oTemp.dogs.begin();i!=oTemp.dogs.end();i++){
// this->dogs.push_back(i);
// }
// return *this;
// }
//add dog
void AddDog(Dog& dog){
dogs.push_back(dog);
size++;
}
//get name function
std::string GetName(){
return this->name;
}
friend std::ostream& operator<<(std::ostream& os,Owner& owner);
};
std::ostream& operator<<(std::ostream& os,Owner& owner){
std::vector<Dog>::iterator it;
os<<owner.name<<"of "<<owner.address<<" has the following dogs"<<std::endl;
double sum=0;
for(auto it=owner.dogs.begin();it!=owner.dogs.end();it){
it.operator++();
sum+=it.cost;
}
std::cout<<"the total costs of all the dogs are $"<<sum<<std::endl;
#endif //FINALS_OWNER_H
Dog file
//
// Created by Kannav Sethi on 21/04/22.
//
#ifndef FINALS_DOG_H
#define FINALS_DOG_H
#include <iostream>
#include "Owner.h"
class Owner;
class Dog{
// the variables
std::string name;
int age;
double cost;
Owner* owner;
public:
// constructors
Dog(std::string name,int age,double cost){
this->name=name;
this->age=age;
this->cost=cost;
}
// set owner
void SetOwner(Owner& _owner){
this->owner=(&_owner);
}
// get owner
Owner* GetOwner(){
return this->owner;
}
// getName
std::string GetName(){
return this->name;
}
// this streaming operator works but not the one I used in Owner
friend std::ostream& operator<<(std::ostream& os, Dog dog);
};
std::ostream& operator<<(std::ostream& os, Dog dog){
os<<dog.name<<" is "<<dog.age<<" years old and costs "<<dog.cost<<std::endl;
}
#endif //FINALS_DOG_H
You need
std::ostream& operator<<(std::ostream& os, Owner& owner) {
os << owner.name << "of " << owner.address << " has the following dogs" << std::endl;
double sum = 0;
for (auto it = owner.dogs.begin(); it != owner.dogs.end(); it++) {
sum += it->cost;
std::cout << it->name << std::endl;
}
std::cout << "the total costs of all the dogs are $" << sum << std::endl;
return os;
}
You didnt seem to realize that you have to use '->' with an iterator
You also need to make this a friend of Dog (cost is private)
// this streaming operator works but not the one I used in Owner
friend std::ostream& operator<<(std::ostream& os, Dog dog);
friend std::ostream& operator<<(std::ostream& os, Owner& o);

Overloading operator<< twice in same class for different member variables

Sorry if this question has been asked before, but I'm struggling with overloading the << operator to stream different data into multiple files.
I have a Player class, which has the following attributes:
char* name;
char* password;
int hScore;
int totalGames;
int totalScore;
int avgScore;
I want to overload the << operator twice: one to stream the name, password and hScore to a "Players.txt" file, and a second overload to stream the totalGames, totalScore and avgScore to a different .txt file which is based off each player's name, e.g. "Player1.txt".
Here's what my operator looks like in the Player class:
friend ostream& operator<< (std::ostream& os, Player& player)
{
os << player.name << "\n" << player.encryptPassword((player.password), 3) << "\n" << player.hScore << "\n";
return os;
}
And here's where I am calling it, from a PlayerLibrary class which contains a vector of Players:
ofstream out("Yahtzee.txt");
if (out.is_open())
{
for_each(playerList.begin(), playerList.end(), [&out](Player* player) {out << (*player);});
}
else
{
cout << "THERE WAS AN ERROR WRITING TO FILE\n";
}
Basically, I want to stream the other variables into another file which is named after the player name, and contains a scorecard for each game they've played. So far it looks like:
for (auto it = playerList.begin(); it != playerList.end(); ++it)
{
auto position = it - playerList.begin();
string filename(playerList[position]->getName());
filename = filename + ".txt";
ofstream out2(filename);
for (int i = 0; i < playerList[position]->getNumberOfScorecards(); i++)
{
out2 << *playerList[position]->getScorecard(i);
}
}
This only streams the scorecard and not the totalGames, totalScore and avgScore, like I want it to.
I have tried just moving those variables into the scorecard class, but I feel that it makes more sense to have them where they are.
I understand that I can't overload operator<< twice if both overloads have the same parameters, is there another way of going about this? Is there anyway perhaps in the overloaded function to use the output stream and check the name of the .txt file or something.
Hope the question makes sense.
Rather than defining an operator<< for Player itself, create a couple of utility types that refer to the Player and have their own operator<<s, let them decide which portions of the Player to stream, eg:
class Player
{
private:
std::string name;
std::string password;
int hScore;
int totalGames;
int totalScore;
int avgScore;
...
public:
...
std::string getName{} const { return name; }
...
std::string EncryptPassword(int arg) const { return ...; }
int getNumberOfScorecards() const { return ...; }
Scorecard* getScorecard(int index) const { return ...; }
class Info
{
const Player &m_player;
void print(std::ostream &os) const {
os << m_player.name << "\n" << m_player.encryptPassword(3) << "\n" << m_player.hScore << "\n";
}
public:
Info(const Player &player) : m_player(player) {}
friend std::ostream& operator<<(std::ostream &os, const Info &info)
{
info.print(os);
return os;
}
};
friend class Info;
struct Stats
{
const Player &m_player;
void print(std::ostream &os) const
{
os << m_player.totalGames << "\n" << m_player.totalScore << "\n" << m_player.avgScore << "\n";
}
public:
Stats(const Player &player) : m_player(player) {}
friend std::ostream& operator<<(std::ostream &os, const Stats &stats)
{
stats.print(os);
return os;
}
};
friend class Stats;
};
And then you can use them like this:
ofstream out("Yahtzee.txt");
if (out.is_open())
{
for(auto *player : playerList)
out << Player::Info(*player);
}
else
{
cout << "THERE WAS AN ERROR WRITING TO FILE\n";
}
for (auto *player : playerList)
{
ofstream out2(player->getName() + ".txt");
out2 << Player::Stats(*player);
for (int i = 0; i < player->getNumberOfScorecards(); ++i)
{
out2 << *player->getScorecard(i);
}
}
Online Demo

How can I overload the << operator so I can write the data of an object to a file?

I have an object of type piggyBank and I need to write data of this object into a file and then read it. I am aware of how to write/read to a text file but how can I overload the << operator so I can write data about the object into a file?
My code for the class here:
piggyBank.h
#include <string>
#ifndef PIGGYBANK_H
#define PIGGYBANK_H
class PiggyBank
{
private:
std::string owner;
int balance;
bool broken;
int id;
static int nrOfObjects;
public:
PiggyBank(void);
PiggyBank(std::string name);
std::string getOwnerName() const;
void setOwnerName(std::string name);
bool isBroken() ;
int getBalance(int & amount) ;
};
#endif /* PIGGYBANK_H */
piggyBank.cpp
#include "PiggyBank.h"
#include "readWrite.h"
#include <string>
#include <iostream>
using namespace std;
int PiggyBank::nrOfObjects = 0; // outside constructor
PiggyBank::getNrOfObjects(){
return nrOfObjects;
}
PiggyBank::PiggyBank(void){
{this->owner="";this->balance=0;this->broken=false;}
id = ++nrOfObjects;
}
PiggyBank::PiggyBank(std::string name, int startBalance){
{this->owner=name;this->balance=startBalance;this->broken=false;}
id = ++nrOfObjects;
}
string PiggyBank::getOwnerName() const{
return this->owner;
}
void PiggyBank::setOwnerName(string name){
this->owner = name;
}
bool PiggyBank::isBroken() {
return this->broken;
}
int PiggyBank::getBalance(int & amount) {
if(!broken){
amount = balance;
return 0;
}else{
return -1;
}
}
You want the << operator to be a friend to the class and to return ostream&.
Here is a simple example to get an idea about how it works.
friend ostream& operator << (ostream& os, const PiggyBank& obj)
{
// For example something like this
os << "Information that you want to output to the file:\n";
os << "Owner: " << obj.owner << "\n";
return os;
}
And then you can use it like this:
PiggyBack obj;
ofstream fout("file.txt");
// also check to see if the file opened correctly
if(fout.fail())
{
cout << "File failed to open\n";
return 0;
}
fout << obj;
// now you have written the owner information onto the file as well as the message before it
// inside the operator<< overload
// close the resource at the end
fout.close();
The cool part is that you can use it to print to the console too by changing fout to be cout.
For example:
cout << obj; // will print to the console
Very simple. Overload the inserter operator. Write this into your class:
friend std::ostream& operator << (std::ostream& os, const PiggyBank& pb) {
return os << pb.owner << . . . // Whatever you want
Then you can use the inserter operator as for any other data type:
int main() {
PiggyBank pb;
if (std::ofstream os("FileName"); os) {
os << pb << "\n";
}
return 0;
}

creating a display function

I am working on this for an assignment and cannot figure out how to even get started to write the function for the following program.
The code given is:
#include <iostream>
#include <string>
#include "BACCOUNT.H"
using namespace std;
void display(const bankAccount & anAcct)
{
}
int main()
{
bankAccount a("Annie Hill", 123.00);
bankAccount b("Becker" , 45.60);
display(a);
display(b);
return 0;
}
and I need to write a display function that will make the name and balance for bankAccount a and bankAccount b display.
I've been working on this for about 3 days now, and cannot figure out how to even start.
my output needs to be:
bankAccount: Hill, Annie, $123.00
bankAccount: Becker, Bob, $45.00
what I've got so far is;
anAcct.name();
string name = anAcct.name();
int space = name.find("5");
name.substr(0, 5);
name.substr(5, 9);
name.length();
cout << name;
Which I know is way off, I've just been trying trial and error.
You can overload << operator in your bankAccount class and let that operator print the content of your class from display function.
e.g. code for reference
friend std::ostream& operator<<(std::ostream& os, bankAccount& a)
{
os << a.name() << ":" << a.accountBalance();
}
void display(const bankAccount & anAcct)
{
std::cout << anAcct;
}
bankAccount is you class and you should have at leat 2 variables in it !. is the name and second will be the amount and you need a diolay() function that display those variable using getters
void bankAccount::display(){
std::cout << this->getname() <<this->getamount<< "$ "<< std::endl;
}
in the main function using a.display() and there you go

Allocating memory for class in C++

This is my class:
using namespace std;
Class Book {
public:
Book();
Book(vector<string>*, string, int);
Book(const Book&);
~Book();
Book& operator=(const Book&);
void update(vector<string>*);
void update(string);
void update(int);
int getYear() const{
return year;
};
string getTitle() const{
return title;
};
bool operator==(const Book&);
bool operator!=(const Book&);
friend std::ostream& operator<<(std::ostream&, const Book&);
void getAuthors();
private:
vector<string>* authors;
string title;
int year;
};
#endif /* BOOK_H */
Here is the source for it:
#include "Book.h"
using namespace std;
Book::Book():year(0), title(NULL), authors(NULL){}
Book::Book(vector<string>* bookauthors,string booktitle, int bookyear ){
authors = bookauthors;
title = booktitle;
year = bookyear;
}
Book::Book(const Book& aBook){
authors = aBook.authors;
title = aBook.title;
year = aBook.year;
}
Book::~Book(){
delete authors;
delete &title;
delete &year;
}
bool Book::operator==(const Book &aBook){
if(getYear() == aBook.getYear() && getTitle() == aBook.getTitle())
return true;
else return false;
}
bool Book::operator != (const Book &aBook){
if(getYear() != aBook.getYear() && getTitle() != aBook.getTitle())
return true;
else return false;
}
Book& Book::operator =(const Book& rhs){
if(this != &rhs){
authors = rhs.authors;
title = rhs.title;
year = rhs.year;
}
return *this;
}
void Book::update(int newyear){
year = newyear;
}
void Book::update(string newtitle){
title = newtitle;
}
void Book::update(vector<string>* newauthors){
authors = newauthors;
}
std::ostream& operator <<(std::ostream& os, const Book& b){
os<<b.getTitle()<<", "<<b.getYear();
return os;
}
Here is the main file where it runs:
#include "Book.h"
#include <iostream>
#include <limits.h>
//This is the test funcion posted on the class website
using namespace std;
int main(){
//testing constructor
vector<string> authors;
authors.push_back("Ritchie");
authors.push_back("Kernighan");
Book a(&authors, "C", 1990);
authors.push_back("Whatever");
cout << "Book a is: " << a << endl;
cout << "Expected: (C, 1990, Ritchie & Kernighan)" << endl;
//testing copy constructor
Book b(a);
a.update(&authors);
cout << "Book b is: " << b << endl;
cout << "Expected: (C, 1990, Ritchie & Kernighan)" << endl;
//testing constructor
vector<string> authors2;
authors2.push_back("Crockford");
Book c(&authors2, "JavaScript", 2008);
cout << "Book c is: " << c << endl;
cout << "Expected: (JavaScipt, 2008, Crockford)" << endl;
//testing assignment operator
authors2.push_back("whatever");
a=c;
cout << "Book a is changed to: " << a << endl;
cout << "Expected: (JavaScipt, 2008, Crockford)" << endl;
for(int i=0; i < 200000000; i++)
b=c;
cout << "Book b is changed to: " << b << endl;
cout << "Expected: (JavaScipt, 2008, Crockford)" << endl;
}
I keep getting this when I run it:
bookclass(58316) malloc: * error for object 0x7fff522d78b0: pointer being freed was not allocated* set a breakpoint in malloc_error_break to debug
I'm new to C++ so I'm not sure how to allocate the memory. I tried using malloc and it didn't work.
The members are located inside the object, i.e., the memory for them is allocated with the Book object and neither can nor need to delete the memory explicitly. Basically, you need to match your explicit allocations using new with calls to delete but you never need to release something which isn't allocated somewhere explicitly.
That is, you get the error when you try to delete title or delete year. It may also happen when trying to delete authors depending on where authors is coming from. In general, you don't want to delete objects you haven't allocated. Your Book class possibly unreasonably takes ownership of the authors vector.
This is probably a good time to learn to use Valgrind, which will give you much richer debugging facilities for this kind of error.
In your destructor, you are destroying title and year via a pointer. You do not actually need to do this, as they are allocated statically (i.e. you didn't create them using new), so it's complaining that you are trying to delete something you did not create dynamically.
In addition, you are deleting your std::vector, which can refer to the same std::vector contained within another class. Since it's possible you have two classes containing the same reference, you need to find a smarter way to delete this so you don't invoke a double free.