Questions about C++ operators overloading - c++

I am a beginner of C++ learning, and I have some questions about the '<<' and '>>'.
Why the results of cout are not correct? At the same time, after I input the coordinate of c, the program froze.
Code:
class Vector
{friend istream &operator >> (istream &is,Vector &vec );
friend ostream &operator << (ostream &os,Vector &vec );
private:
int num;
double *cor;
public:
Vector(int n=0,double *c=NULL);//
};
int main()
{ double b[5]={1,2,3,4,5};
Vector a(5,b);
cout<<a;
Vector c(2);
cin>>c;
}
Vector::Vector(int n,double *c)
{
num=n;
double *cor=new double[num];
if (c) {
for (int i=0;i<n;i++) {cor[i]=c[i];cout<<cor[i]<<endl;}
}
}
istream &operator >> (istream &is,Vector &vec )
{ cout<<"Input the coordinate:";
for (int i=0;i<vec.num;i++)
is>>vec.cor[i];
return is;
}
ostream &operator << (ostream &os,Vector &vec )
{
for (int i=0;i<vec.num;i++){
os<<vec.cor[i];}
return os;
}

double *cor=new double[num];
You're declaring a local variable named cor, not initializing the member cor. It should be:
cor = new double[num];
However in real code, you would use an unique_ptr to a double array, which deletes the array automatically (with no additional overhead):
#include <iostream>
#include <memory> // for unique_ptr
using namespace std;
class Vector {
public:
Vector(int = 0, double* = nullptr);
private:
friend istream& operator>>(istream&, Vector& vec);
friend ostream& operator<<(ostream&, Vector& vec);
int num;
unique_ptr<double[]> array;
};
int main() {
double b[] = {1, 2, 3, 4, 5};
Vector a(5, b);
cout << a;
Vector c(2);
cin >> c;
}
Vector::Vector(int n, double* c) {
num = n;
array = make_unique<double[]>(n); // in C++14
//array = unique_ptr<double[]>(new double[n]); // in C++11
if (!c) return;
for (int i = 0; i < n; i++) {
array[i] = c[i];
cout << array[i] << endl;
}
}
istream& operator>>(istream& is, Vector& vec) {
cout << "Input the coordinates: ";
for (int i = 0; i < vec.num; i++)
is >> vec.array[i];
return is;
}
ostream& operator<<(ostream& os, Vector& vec) {
for (int i = 0; i < vec.num; i++)
os << vec.array[i];
return os;
}

Small but important tip:
using 'const':
> ostream &operator << (ostream &os,const Vector &vec)
since vec is received by reference and you are not going to change it.

Related

I have a problem with reading & printing my class

I have a problem with printing my class. I want this class to read a binary number and then print it. I am a Beginner, so here can be a really dumb mistake.
This code has a wrong output, but a correct input.
I tried to fix this, but I couldn't. I hope you will find the mistake.
Please help. Thanks!
Here is the code:
#include <iostream>
using namespace std;
class Binary
{
int len;
bool* arr;
public:
Binary();
Binary(const Binary&);
friend istream& operator >> (istream&, Binary&);
friend ostream& operator << (ostream&, const Binary&);
};
Binary::Binary()
{
len = 0;
arr = new bool[0];
}
Binary::Binary(const Binary& b)
{
len = b.len;
arr = new bool[len];
for (int i = 0; i < len; i++) {
arr[i] = b.arr[i];
}
}
istream& operator>>(istream& in, Binary& b)
{
char line[101];
in.getline(line, 100);
b.len = strlen(line);
b.arr = new bool[b.len];
for (int i = 0; i < b.len; i++) {
b.arr[i] = (line[i] == '0' ? 0 : 1);
}
return in;
}
ostream& operator<<(ostream& out, const Binary& b)
{
for (int i = 0; i < b.len; i++) {
out << b.arr;
}
return out;
}
int main() {
Binary a;
cin >> a;
cout << a;
return 0;
}
The problem is with this line of code:
out << b.arr;
You are printing the array pointer, b.arr, instead of a value in the array.
This will work:
out << b.arr[i] ? '1' : '0';
You should also consider writing a destructor to free your previously allocated memory, and also free the previous array before overwriting it's pointer on this line:
b.arr = new bool[b.len];

Apply operator overriding to classes with dynamic allocation pointers

I have defined the MyString class, and now I want to implement the addition operation. It's horrible for memory leaks to occur, so I've taken care of releasing the dynamically allocated pointers from the destructor.
#include <iostream>
class MyString {
private:
int _size;
char* _str;
public:
MyString() {
_size = 0;
_str = nullptr;
}
MyString(int size, char* str) {
_size = size;
_str = new char[size + 1];
strcpy(_str, str);
}
~MyString() {
delete[] _str;
}
void print() {
std::cout << _str << std::endl;
}
friend MyString operator+(const MyString& lhs, const MyString& rhs);
};
MyString operator+(const MyString& lhs, const MyString& rhs) {
char* temp = new char[lhs._size + rhs._size + 1];
strcpy(temp, lhs._str);
strcat(temp, rhs._str);
MyString ret(lhs._size + rhs._size, temp);
delete[] temp;
return ret;
}
int main() {
MyString first(5, "first");
MyString second(6, "second");
MyString add = first + second;
first.print();
second.print();
add.print();
}
However, if I compile the code and run it, the first.print() and second.print() is printed well, but the add.print() will print the garbage value, and crashes (Debug Assertion Failed!).
Output:
first
second
硼硼硼硼硼硼硼硼?흚 (and creashes :(.. )
If I annotate and run the destructor, it prints well, but a memory leak occurs. Why is this happening? I have looked at several examples of operator overriding, but I have not found an example of this dynamic allocation of pointers.
Any suggestion will be highly appreciated!
MyString operator+(const MyString& lhs, const MyString& rhs) {
char* temp = new char[lhs._size + rhs._size + 1];
strcpy(temp, lhs._str);
strcat(temp, rhs._str);
MyString ret(lhs._size + rhs._size, temp);
delete[] temp;
return ret;
}
At the end of this function 'ret' is destroyed which calls the destructor and deletes the buffer. What is returned is a new instance of MyString that was copied from 'ret', and its buffer points to the same memory location as the original. Since this has been deleted you are now printing out garbage.
To fix this you can add a copy constructor to ensure the buffer is copied:
class MyString {
// Other class details
public:
MyString(const MyString & other) : MyString(other._size, other._str) {}
// Other class details
}
This will ensure the buffer is copied when one MyString is assigned to another MyString.
#include<iostream>
using namespace std;
class Mystring{
private:
int size;
char *str;
public:
friend Mystring operator*(const Mystring &a, const int &d);
friend Mystring operator+(const Mystring &a, const Mystring& b);
friend ostream& operator << (ostream &os, const Mystring a);
friend istream& operator >> (istream &is, const Mystring a);
Mystring (int a, char b) {
this->size = a;
this->str = new char(a);
for (int i = 0; i < a; i++) {
this->str[i] = b;
}
}
~Mystring() {}
};
Mystring operator+(const Mystring &a, const Mystring& b) {
Mystring c(a.size + b.size, { 0 });
for (int i = 0; i < a.size; i++)
{
c.str[i] = a.str[i];
}
for (int i = 0; i < b.size; i++)
{
c.str[a.size + i] = b.str[i];
}
return c;
}
Mystring operator*(const Mystring& a,const int &d){
int z = a.size*d;
Mystring c(z, { 0 });
int k=0;
for (int j = 0; j < d; j++)
{
for (int i = 0; i < a.size; i++)
{
c.str[k+i] = a.str[i];
}
k = a.size + k;
}
return c;
}
ostream& operator << (ostream &os, const Mystring a) {
os << "[";
int i;
for ( i = 0; i < a.size; i++)
{
os << a.str[i];
}
os << "]";
return os;
}
istream& operator >> (istream &is, const Mystring a) {
for (int i = 0; i < a.size; i++)
{
cout << i << "번째 문자 : ";
is >> a.str[i];
}
return is ;
}
int main()
{
int aSize, bSize, iter;
char aInit, bInit;
cout << "문자열A의 크기와 초기문자를 입력: ";
cin >> aSize >> aInit;
Mystring str1(aSize, aInit);
cout << str1 << endl;
cout << "문자열A 입력" << endl;
cin >> str1;
cout << str1 << endl;
cout << "문자열B의 크기와 초기문자를 입력: ";
cin >> bSize >> bInit;
Mystring str2(bSize, bInit);
cout << str2 << endl;
cout << "문자열B 입력" << endl;
cin >> str2;
cout << str2 << endl;
cout << "문자열A와 문자열B 합치기 : ";
Mystring str3 = str1 + str2;
cout << str3 << endl;
cout << "문자열A 반복횟수 입력 : ";
cin >> iter;
Mystring str4 = str1*iter;
cout << str4 << endl;
}
enter code here
why error
~Mystring(){}

Dynamic matrix in class

I have problem with dynamic allocation in c++.
This is my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Wektor {
int rozmiar;
float *TabWe;
friend std::istream& operator >> (std::istream &Strm, Wektor &Wek);
public:
Wektor(int rozmiar) : rozmiar(rozmiar) {
TabWe = new float[rozmiar];
}
Wektor() {
for (int i = 0; i < rozmiar; i++)
{
TabWe[i] = 0;
}
}
~Wektor()
{
for (int i = 0; i <rozmiar; i++)
{
delete[] TabWe;
}
}
};
istream& operator >>(istream &Strm, Wektor &Wek)
{
cout << "Size: ";
Strm >> Wek.rozmiar;
for (int i = 0; i < Wek.rozmiar; i++)
{
Strm >> Wek.TabWe[i];
}
return Strm;
}
int main()
{
Wektor wek;
cin >> wek;
}
After I enter first value to the matrix I get this error:
I think there is problem with default constructor, because you can see on the screenshot that this matrix has no value when program starts. What is wrong with it?

c++ getting error trying to call a function that reads a file

I have a function Readf I'm trying to call to fill in an array inside each constructor, I tried only with the default constructor with a code statement ReadF(cap,*point,counter);.
The second argument is what's giving me a problem in figuring out, I would get an error with '&' beside it or ' '. And I get an external error with the '*', I'm still new to c++ so I'm not experienced in dealing with classes.
I have to use the ReadF member function, are there other ways instead of calling it to get the results I need.
Also some of the code for the functions I have might not be perfect, but I would like to deal with this problem first before I move on to another.
array.h:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class AR {
public:
AR();
AR(int);
AR(const AR&);
//~AR();
void ReadF(const int, string&, int);
AR& operator=(const AR&);
friend ostream& operator<<(ostream&, AR&);
friend ifstream & operator>>(ifstream&, AR&);
private:
string* point;
int counter;
int cap;
};
array.cpp:
#include "array.h"
AR::AR() {
counter = 0;
cap = 2;
point = new string[cap];
}
AR::AR(int no_of_cells) {
counter = 0;
cap = no_of_cells;
point = new string[cap];
}
AR::AR(const AR& Original) {
counter = Original.counter;
cap = Original.cap;
point = new string[cap];
for(int i=0; i<counter; i++) {
point[i] =Original.point[i];
}
}
// AR::~AR() {
// delete [ ]point;
//}
ostream& operator<<(ostream& out, AR& Original) {
cout << "operator<< has been invoked\n";
for (int i=0; i< Original.counter; i++) {
out << "point[" << i <<"] = " << Original.point[i] << endl;
}
return out;
}
AR& AR::operator=(const AR& rhs) {
cout << "operator= invoked\n";
if (this == &rhs)
return *this;
point = rhs.point;
return *this;
}
void ReadF(const int neocap, string& neopoint, int neocounter) {
ifstream in;
in.open("sample_strings.txt"); //ifstream in; in.open("sample_data.txt");
if (in.fail())
cout<<"sample_data not opened correctly"<<endl;
while(!in.eof() && neocounter < neocap) {
in >> neopoint[neocounter];
neocounter++;
}
in.close();
}
ifstream& operator>>(ifstream& in, AR& Original) {
Original.counter = 0;
while(!in.eof() && Original.counter < Original.cap) {
in >> Original.point[Original.counter];
(Original.counter)++;
}
return in;
}
It appears you are missing AR:: in the ReadF definition.
On second thought you are reading into an index of neopoint that likely isn't allocated yet. You could change ReadF to read:
void ReadF(const int neocap, string& neopoint,int neocounter)
{
ifstream in;
in.open("sample_strings.txt"); //ifstream in; in.open("sample_data.txt");
if (in.fail())
{
cout<<"sample_data not opened correctly"<<endl;
return;
}
neopoint.resize(neocap);
while(neocounter < neocap && in >> neopoint[neocounter])
{
neocounter++;
}
in.close();
}
Although you probably want to look into stringstream
std::ifstream in("sample_strings.txt");
if (in)
{
std::stringstream buffer;
buffer << in.rdbuf();
in.close();
inneopoint= buffer.str();
}

Need help getting a function that removes a string from an array to work

I have a function look that looks through a string array and returns a value that then gets called into the Delete function. Which from that value gets deleted.
I put up a lot of the code here, just look at the operator+ function implemented to the Delete function. And see their use in the main function.
The operator + adds strings into an array, it takes up four spots int the array.
The Delete function is supposed match the first word in the first string to Delete it, but it's telling me there is no word found.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class AR
{
public:
AR();
AR(int );
AR(const AR &);
~AR(){delete []con;}
bool Full(){return counter==cap;}
int Look(const string & );
AR & operator+(const string );
void Delete(const string &);
AR & operator=(const AR &);
friend ostream & operator<<(ostream &, AR &);
friend ifstream & operator>>(ifstream & , AR &);
void Double_size();
private:
string *con;
int counter;
int cap;
};
#include "ar.h"
AR::AR()
{
counter = 0; //initializing state of class
cap = 2;
con = new string[cap];
}
AR::AR(int no_of_cells)
{
counter = 0;
cap = no_of_cells;
con = new string[cap];
}
AR::AR(const AR & Original)
{
counter = Original.counter;
cap = Original.cap;
con = new string[cap];
for(int i=0; i<counter; i++)
{
con[i] =Original.con[i];
}
}
ostream & operator<<(ostream & out, AR & Original)
{
for(int i=0; i< Original.counter; i++)
{
out<<"con[" << i <<"] = "<< Original.con[i]<<endl;
}
return out;
}
AR & AR::operator=(const AR &rhs)
{
if(this != &rhs)
{
delete []con;
counter= rhs.counter;
cap = rhs.cap;
con= new string[cap];
for(int i=0;i<counter;i++)
{
con[i]= rhs.con[i];
}
}
return *this;
}
ifstream & operator>>(ifstream & in, AR & Original)
{
Original.counter = 0;
while(!in.eof() && Original.counter<Original.cap)
{
in>>Original.con[Original.counter];
(Original.counter)++;
}
return in;
}
AR & AR::operator+(const string word)
{
if(Full()) //conditions if array is full or empty
{
Double_size(); // capacity get's doubled
}
con[counter]=word;
counter++;
return *this;
}
void AR::Double_size()
{
cap *= 2;
string *tmp = new string[cap];
for(int i=0;i<counter;i++)
{
tmp[i]= con[i];
}
delete []con;
con = tmp;
}
int AR::Look(const string & word)
{
for(int i=0;i<counter;i++)
{
if( con [i] == word)
return i;
}
return -1;
}
void AR::Delete(const string & word)
{
int loc = Look(word);
if (loc == -1)
{
cout<<"word not found\n";
}
else
{
for(int i=0;i<counter-1,i++;)
{
con[i]= con[i+1];
}
}
}
#include <iostream>
#include <string>
#include "ar.h"
using namespace std;
int main()
{
cout<<"invoking the default constructor"<<endl;
AR myAr;
cout<<"Output after default constructor called\n";
cout<<myAr<<endl<<endl;
cout<<"invoking the explicit-value constructor "<<endl;
AR yourAr(5);
cout<<"Output after explicit-value constructor called\n";
cout<<yourAr<<endl<<endl;
cout<<"invoking the copy constructor "<<endl;
AR ourAr = myAr;
cout<<"Output after copyconstructor called\n";
cout<<ourAr<<endl<<endl;
cout<<"testing overloaded operator= with chaining as a member "<<endl;
AR X, Y, Z;
X = Y = ourAr;
cout<<"Output after operator= called\n";
cout<<X<<endl<<endl;
cout<<"testing overloaded operator<< overloaded as a friend with chaining "<<endl;
cout<<X<<Y<<Z;
cout<<endl<<endl;
cout<<"testing overloaded operator+ as a member function with chaining, Double_size "
<<" and Full."<<endl;
AR theirAr(1);
theirAr + "Overload the +" + " operator as a member function " + "with chaining to add a string " + "to an Arrary object.";
cout<<theirAr<<endl<<endl;
cout<<"testing Delete and Look. <<endl;
theirAr.Delete("XXXXXX");
theirAr.Delete("Overload");
cout<<"Output after Delete and Look called\n";
cout<<theirArray<<endl<<endl;
return 0;
}
you are looking for a COMPLETE string equals to "Overload" here
theirAr.Delete("Overload");
but you have the string "Overload the +" stored in the array of string so the comparation between them is false, because "Overload" and "Overload the +" are differents. If you want to find a subString inside a string, then you need to use something like std::string::find in the following way:
int AR::Look(const std::string & word)
{
int result = -1;
for(int i=0; i<counter; ++i)
{
if( con[i].find(word) != std::string::npos)
result = i;
}
return result;
}