C++ operator overloading stream requires cast - c++

I'm overloading some operation on a class and notice that on the ostream overloading one of the values is not as expected. Here is the example:
#include <iostream>
using namespace std;
class Simple{
int x;
public:
Simple() : x(0){}
Simple(int i) : x(i){}
const Simple& operator+(const Simple& s){
return Simple(x + s.x);
}
friend ostream& operator<<(ostream& os, const Simple& s);
};
ostream& operator<<(ostream& os, const Simple& s){
os << s.x;
return os;
}
int main(void){
Simple s1(2);
Simple s2(3);
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s1 + s2 = ";
Simple s3 = s1 + s2;
cout << s1 << " + " << s2 << " = " << s1 + s2 << endl;
cout << s1 << " + " << s2 << " = " << static_cast<Simple>(s1 + s2) << endl;
cout << "s3 = " << s3 << endl;
return 0;
}
It produces the following output:
s1 = 2
s2 = 3
s1 + s2 = 2 + 3 = -872483744
2 + 3 = 5
s3 = 5
Is this an issue with how I am overloading, or will the cast always be required to get my expected output?

Your operator+ returns a reference to a local variable, and a temporary at that.
It's a dangling reference.
operator+ should return by value.

Related

Segmentation Fault with Dynamic Class (homework problem)

I'm attempting to convert a working static String class to a dynamic String class using pointers, but when I implement the pointer it throws a segmentation fault error. Code below:
mystring1.h:
//File: mystring1.h
// Declaration file for user-defined String class.
#ifndef _MYSTRING_H
#define _MYSTRING_H
#include<iostream>
#include <cstring>
using namespace std;
#define MAX_STR_LENGTH 200
class String {
public:
String();
String(const char *s); // a conversion constructor
void append(const String &str);
//deconstructor
~String();
//copy constructor
String (const String & origString);
//assignment operator overload
String operator =(const String &origString);
// Relational operators
bool operator >(const String &str) const;
bool operator <(const String &str) const;
String operator +=(const String &str);
void print(ostream &out) const;
int length() const;
char operator [](int i) const; // subscript operator
private:
char *contents;
int len;
//int capacity;
};
ostream & operator<<(ostream &out, const String & r); // overload ostream operator "<<" - External!
#endif /* not defined _MYSTRING_H */
mystring1.cpp:
//File: mystring1.h
// Implementation file for user-defined String class.
#include "mystring1.h"
String::String()
{
contents[0] = '\0';
len = 0;
}
String::String(const char s[])
{
len = strlen(s);
contents = new char[len + 1];
strcpy(contents, s);
}
void String::append(const String &str)
{
strcat(contents, str.contents);
len += str.len;
}
//deconstructor
String::~String()
{
delete [] contents;
}
//copy constructor
String::String(const String &origString)
{
len = origString.len;
contents = new char[len + 1];
for (int i = 0; i < len; i++)
{
contents[i] = origString.contents[i];
}
}
//assignment operator overload
String String::operator =(const String &origString)
{
if (this != &origString)
{
len = origString.len;
delete [] contents;
contents = new char[len + 1];
for (int i = 0; i < len; i++)
{
contents[i] = origString.contents[i];
}
}
return *this;
}
bool String::operator >(const String &str) const
{
return strcmp(contents, str.contents) > 0;
}
bool String::operator <(const String &str) const
{
return strcmp(contents, str.contents) < 0;
}
String String::operator +=(const String &str)
{
append(str);
return *this;
}
void String::print(ostream &out) const
{
out << contents;
}
int String::length() const
{
return len;
}
char String::operator [](int i) const
{
if (i < 0 || i >= len) {
cerr << "can't access location " << i
<< " of string \"" << contents << "\"" << endl;
return '\0';
}
return contents[i];
}
ostream & operator<<(ostream &out, const String & s) // overload ostream operator "<<" - External!
{
s.print(out);
return out;
}
Assignment 5 Driver:
/**
* cmpsc122 Assignment 5 test file
* File Name: Assign5driver.cpp
*
* Description: This program demonstrates a basic String class that implements
* dynamic allocation and operator overloading.
*
*/
#include <iostream>
#include "mystring1.h"
using namespace std;
/*************************** Main Program **************************/
int main()
{
String str1, str2("dog"); // Using constructor for initial strings
char s1[100], s2[100]; // Some C strings.
// Print out initial strings
cout << "Initial values:" << endl;
cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
// Inputs some new strings in them
cout << "\nEnter a value for str1 (no spaces): ";
cin >> s1;
str1 = s1;
cout << "\nEnter a value for str2 (no spaces): ";
cin >> s2;
str2 = s2;
cout << "\nAfter assignments..." << endl;
cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
// Get some elements...
int i;
cout << "\nEnter which element of str1 to display: ";
cin >> i;
cout << "Element #" << i << " of str1 is '" << str1[i] << "'" << endl;
cout << "\nEnter which element of str2 to display: ";
cin >> i;
cout << "Element #" << i << " of str2 is '" << str2[i] << "'" << endl;
// Concate some strings
cout << "\nEnter a value to append to str1 (no spaces): ";
cin >> s1;
// str1.append(s1); // Actually, the cstring is converted to String object here by the constructor
str1 += s1; // same as above
cout << "\nEnter a value to append to str2 (no spaces): ";
cin >> s2;
str2 += s2;
cout << "\nAfter appending..." << endl;
cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
// Compare strings...
cout << "\nComparing str1 and str2..." << endl;
cout << "\"";
cout<< str1; // test the overloading of ostream operator <<
cout << "\" is ";
if (str1 < str2) { // test the overloading of comparison operator <
cout << "less than";
} else if (str1 > str2) {
cout << "greater than";
} else {
cout << "equal to";
}
cout << " \"";
cout << str2;
cout << "\"" << endl;
cout << "\ntest the = operator, after str1 = str2; "<< endl;
str1 = str2;
cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
str1 += s1;
cout << "\nAfter str1 = str1 + s1: "<< endl;
cout << "str1 holds \"" << str1 << "\" (length = " << str1.length() << ")" << endl;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
String str3(str2);
cout << "\ntest the copy constructor, after str4(str3);"<< endl;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
cout << "str3 holds \"" << str3 << "\" (length = " << str3.length() << ")" << endl;
cout << "\nafter appending str2 by str1" << endl;
str2 += str1;
cout << "str2 holds \"" << str2 << "\" (length = " << str2.length() << ")" << endl;
cout << "str3 holds \"" << str3 << "\" (length = " << str3.length() << ")" << endl;
cout<< "\nstr3 are not changed. Type any letter to quit." << endl;
char q;
cin >> q;
return 0;
}
Any help would be appreciated, I have tried all that I can and my research into segmentation fault causes isn't doing much to help.
There are several immediately obvious bugs in your implementation:
The default constructor uses uninitialized contents pointer.
The ::append() method does not ensure there is sufficient space in the destination buffer before performing strcat.
The copy constructor and the ::operator=() method do not NUL-terminate the contents buffer.
There are likely more.
You should build your test program with g++ -fsanitize=address ... and fix all the bugs it finds.
You should also build your program with -Wall -Wextra flags, and fix all the warning it produces.

Need Help Operator Overloading So I Can Display Functions

I'm stuck trying to figure out how to overload the << operator so I can display my rational class functions.
These are the lines I'm trying to overload:
cout << "Testing the compare() member function, found:" << endl;
if (r1.compare(r2) == 1)
cout << r1.display() << " is greater than " << r2.display() << endl;
else if (r1.compare(r2) == 0)
cout << r1.display() << " is equal to " << r2.display() << endl;
else if (r1.compare(r2) == -1)
cout << r1.display() << " is less than " << r2.display() << endl;
cout << "Testing the four arithmetic member functions:" << endl;
cout << "r1 + r2 = " << r1.display() << " + " << r2.display() << " = " << r1.add(r2) << endl;
cout << "r1 - r2 = " << r1.display() << " - " << r2.display() << " = " << r1.subtract(r2) << endl;
cout << "r1 * r2 = " << r1.display() << " * " << r2.display() << " = " << r1.multiply(r2) << endl;
cout << "r1 / r2 = " << r1.display() << " / " << r2.display() << " = " << r1.divide(r2) << endl;
The errors occur everytime I call a function. Here is the code for the functions:
void rational::display()
{
int gcd = GCD();
if (denom < 0)
{
num = -num;
cout << num / gcd << " / " << denom / gcd << endl;
}
else if (num == 0)
cout << num << endl;
}
rational rational::add(const rational &r2) const
{
rational sum;
sum.num = (num * r2.denom) + (r2.num * denom);
sum.denom = denom * r2.denom;
return sum;
}
The multiply, divide, and subtract functions are as same as the add they just have the symbols and variable name changed to match the operation. My overload operator is set up like this:
ostream& operator<< (ostream& out, rational &robj)
{
out << example code << example code;
return out;
}
Any help would be appreciated. This is my first time posting so if I need to post more of my code I will. Thanks!
First of all, change
ostream& operator<< (ostream& out, rational &robj)
to
ostream& operator<< (ostream& out, rational const& robj)
Then, instead of
cout << r1.display() << " is greater than " << r2.display() << endl;
use
cout << r1 << " is greater than " << r2 << endl;
Since you already have the above operator<< function, I would get rid of the member function display(). It doesn't (should not) give you any more functionality than using the operator<< function.
Given
rational 1
Use of
r.display();
should give you the same output as
cout << r << endl;
See What are the basic rules and idioms for operator overloading? for more details on operator overloading.

String Functions: Strcat()

I'm currently writing a program that uses string functions. I need some advice/hints on how I can display "Hello World" and its length with myStrcat() in main(). I'm new to programming and any support would be greatly appreciated.
My Code:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int myStrlen(char str1[])
{
int i = 0;
for (i=0; str1[i] != '\0'; i++)
str1[i] = '\0';
return i;
}
int myStrcat(char str2[], char str3[])
{
}
int myStrcpy(char str4[], char str5[])
{
int i = 0;
for (i=0; str5[i] != '\0'; i++)
str4[i] = str5[i];
str4[i] = '\0';
return i;
}
int main()
{
const int SIZE = 11;
char s1[SIZE] = "Hello";
char s2[SIZE] = "World";
cout << "s1: " << " " << s1 << endl << endl; ///Should display "Hello"
cout << "The length of s1: " << myStrlen(s1) << endl << endl;
cout << "Doing strcat(s1, s2) " << endl;
myStrcat(s1, s2);
cout << "s1: " << " " << s1 << endl; /// Should display "Hello World"
cout << "The length of s1: " << myStrlen(s1) << endl << endl;
cout << "Doing strcpy(s1, s2) " << endl;
myStrcpy(s1, s2);
cout << "s1: " << " " << s1 << endl; /// Should display "World"
cout << "The length of s1: " << myStrlen(s1) << endl << endl;
My Output:
s1: Hello
The length of s1: 5
Doing strcat(s1, s2)
s1:
The length of s1: 0
Doing strcpy(s1, s2)
s1: World
The length of s1: 5
Line 6 and 7 are suppose to display Hello World and its length (which is 11).
You have a number of not just quite right beginning to each of your functions. Firstly, let's think about the returns for each. myStrlen should return size_t instead of int. C++ designates a size_type for counters, measuring, etc.. The remaining functions should return char* (or nullptr on failure).
Looking at your myStrlen function where you have
for (i=0; str1[i] != '\0'; i++)
str1[i] = '\0';
You are setting every character in str1 to the nul-character because you are applying the loop to the next expression. You should not be worrying about nul-terminating anything within myStrlen -- you are just counting characters. So you can rewrite it as follows:
size_t myStrlen (const char *str)
{
size_t l = 0;
for (; str[l]; l++) {}
return l;
}
Your myStrcpy looks workable, though you should always validate your input parameters are not nullptr before using them -- I leave that to you. Since you have a myStrlen function, you can simply use that along with memcpy to create your myStrcpy function as:
char *myStrcpy (char *dest, const char *src)
{
size_t len = myStrlen(src);
return (char *)memcpy (dest, src, len + 1);
}
(note: traditionally you have source (src) and destination (dest) parameters when copying or concatenating)
For your myStrcat function, you are just using the myStrlen function to find the offset in dest to append src, so you really just need a call to myStrlen and then a call to myStrcpy to copy src to that offset in dest, e.g.
char *myStrcat (char *dest, const char *src)
{
size_t len = myStrlen (dest);
return myStrcpy (dest + len, src);
}
In your main(), if you want a space between "Hello" and "World", then const int SIZE = 11; is one too-low to hold the concatenated string "Hello World" which would require 12-bytes (including the nul-terminating character). Do Not Skimp on buffer size. 128 is plenty small.
Remaining with your main() but updating SIZE = 12; and adding a space between "Hello" and "World" with an additional call to myStrcat, you could do the following:
int main (void)
{
const int SIZE = 12; /* too short by 1 if you add space between */
char s1[SIZE] = "Hello";
char s2[SIZE] = "World";
std::cout << "s1: " << " " << s1 << std::endl << std::endl;
std::cout << "The length of s1: " << myStrlen(s1) << std::endl << std::endl;
std::cout << "Doing strcat(s1, s2) " << std::endl;
myStrcat(s1, " ");
myStrcat(s1, s2);
std::cout << "s1: " << " " << s1 << std::endl;
std::cout << "The length of s1: " << myStrlen(s1) << std::endl << std::endl;
std::cout << "Doing strcpy(s1, s2) " << std::endl;
myStrcpy(s1, s2);
std::cout << "s1: " << " " << s1 << std::endl;
std::cout << "The length of s1: " << myStrlen(s1) << std::endl << std::endl;
}
(note: don't include using namespace std;, it is just bad form in this day and age)
Example Use/Output
$./bin/mystrcpy
s1: Hello
The length of s1: 5
Doing strcat(s1, s2)
s1: Hello World
The length of s1: 11
Doing strcpy(s1, s2)
s1: World
The length of s1: 5
Look things over and let me know if you have further questions.
First you should read Why is “using namespace std;” considered bad practice?
Don't use c style strings if you are starting programming. Use std::string. It's much simpler to use.
#include <iostream>
#include <string>
int myStrlen(const std::string &str) {
return str.length();
}
int myStrcat(std::string &str1, const std::string &str2) {
str1 += str2;
str1.length();
}
int myStrcpy(std::string &str1, const std::string &str2) {
str1 = str2;
return str1.length();
}
int main() {
std::string s1 = "Hello";
std::string s2 = "World";
std::cout << "s1: " << s1 << "\n\n"; ///Should display "Hello"
std::cout << "The length of s1: " << myStrlen(s1) << "\n\n";
std::cout << "Doing strcat(s1, s2) " << '\n';
myStrcat(s1, s2);
std::cout << "s1: " << s1 << '\n'; /// Should display "Hello World"
std::cout << "The length of s1: " << myStrlen(s1) << "\n\n";
std::cout << "Doing strcpy(s1, s2) " << '\n';
myStrcpy(s1, s2);
std::cout << "s1: " << s1 << '\n'; /// Should display "World"
std::cout << "The length of s1: " << myStrlen(s1) << "\n\n";
return 0;
}

Can't get rid of trash while overloading operator << in C++

class point //declaration of class
{
private:
int x, y;
friend std::ostream &operator << (std::ostream &input, point &p);
public:
//constructors and some other methods
};
//definition of overloading <<
std::ostream &operator << (std::ostream &input, point &p)
{
input << std::cout << "x = " << p.x << " y = " << p.y << " ";
return input;
}
And it works but when I use it
std::cout << object;
it shows some trash before my text:
062ACC3E8x = 1 y = 22
So 062ACC3E8X is something that always appears. It is defferent if I restart Visual Studio which I'm working on, so I suppose It's some memory adress. How to get rid of it? Is it something missing or wrong in my code?
You output some adress, since std::ostream has implicit void* conversion operator.
1) Returns a null pointer if fail() returns true, otherwise returns a
non-null pointer. This pointer is implicitly convertible to bool and
may be used in boolean contexts.
Should be just
input << "x = " << p.x << " y = " << p.y << " ";
You are passing std::cout into your output stream. Change your code to:
//definition of overloading <<
std::ostream &operator << (std::ostream &input, point &p)
{
input << "x = " << p.x << " y = " << p.y << " ";
return input;
}

Why are my calculations off?

I'm practically done with this program. My only issue is my calculations, I guess. My numbers are completely off. I am too new to post an image, so here is the link to my output. Example: http://imageshack.us/photo/my-images/62/16902078.jpg/
NumDays.h
#ifndef NUMDAYS_H
#define NUMDAYS_H
#include <iostream>
#include <math.h>
using namespace std;
class NumDays
{
private:
double hours, days;
void calcDays();
public:
// Constructors
NumDays();
NumDays(double);
// Mutator Functions
void setHours(double);
// Accessor Functions
double getHours();
double getDays();
// Overloaded operator functions
NumDays operator + (const NumDays &); // Overloaded +
NumDays operator - (const NumDays &); // Overloaded -
NumDays operator ++ (); // Overloaded Prefix ++
NumDays operator ++ (int); // Overloaded Postfix ++
NumDays operator -- (); // Overloaded Prefix --
NumDays operator -- (int); // Overloaded Postfix --
};
#endif
NumDays.cpp
// Implementation file for the NumDays class
#include <iostream>
#include <math.h>
#include "NumDays.h"
using namespace std;
// Recalculation function
void NumDays::calcDays()
{
days = hours / 8;
}
// Default Constructor
NumDays::NumDays()
{
hours = 0;
days = 0;
}
// Constructor 1
NumDays::NumDays(double h)
{
hours = h;
days = hours * 1 / 8;
}
// Mutatory Functions
void NumDays::setHours(double h)
{
hours = h;
}
// Accessor Functions
double NumDays::getHours()
{
return hours;
}
double NumDays::getDays()
{
NumDays::calcDays();
return days;
}
// Overloaded operator functions
NumDays NumDays::operator + (const NumDays &a)
{
NumDays temp;
temp.hours = this->hours + a.hours;
return temp;
}
NumDays NumDays::operator - (const NumDays &a)
{
NumDays temp;
temp.hours = this->hours + a.hours;
return temp;
}
NumDays NumDays::operator ++ ()
{
++hours;
calcDays();
return *this;
}
NumDays NumDays::operator -- ()
{
--hours;
calcDays();
return *this;
}
NumDays NumDays::operator ++ (int)
{
NumDays temp(*this);
++hours;
return temp;
}
NumDays NumDays::operator -- (int)
{
hours--;
calcDays();
return *this;
}
main.cpp
#include <iostream>
#include "NumDays.h"
using namespace std;
int main()
{
double hours1, hours2;
//Prompt for the data for the first 2 objects
cout << "Enter the number of hours for the the object called One: ";
cin >> hours1;
cout << "Enter the number of hours for the the object called Two: ";
cin >> hours2;
// Define two objects of WorkHours
NumDays one(hours1), two(hours2);
cout << "One: " << one.getDays() << " day(s)" << endl;
cout << "Two: " << two.getDays() << " day(s)" << endl << endl;
// Demonstrate addition and subtraction operators
cout << "Three = One + Two: " << (one - two).getDays() << " day(s)" << endl;
cout << "One - Two: " << (one - two).getDays() << " day(s)" << endl << endl;
// Define a third and fourth object to be used for further operator demonstrations
NumDays three(one + two), four;
// Demonstrate increment and decrement operators
four = three++;
cout << "Four = Three++ " << endl;
cout << " Three: " << three.getDays() << " day(s)" << endl;
cout << " Four: " << four.getDays() << " day(s)" << endl << endl;
four = ++three;
cout << "Four = ++Three: " << endl;
cout << " Three: " << three.getDays() << " day(s)" << endl;
cout << " Four: " << four.getDays() << " day(s)" << endl << endl;
four = three--;
cout << "Four = Three--: " << endl;
cout << " Three: " << three.getDays() << " day(s)" << endl;
cout << " Four: " << four.getDays() << " day(s)" << endl << endl;
four = --three;
cout << "Four = --Three: " << endl;
cout << " Three: " << three.getDays() << " day(s)" << endl;
cout << " Four: " << four.getDays() << " day(s)" << endl;
system("pause");
return 0;
}
So, where is the implementation of your operator << function?
The code you posted contains none. You declared it as a friend in NumDays.h
friend ostream &operator << (ostream &, NumDays &);
but there's no definition for it either in NumDays.cpp or anywhere else.
Obviously, the linker is telling you that it can't find it. Neither can I.
You have to go to your NumDays.cpp and implement your operators << and >> there
ostream &operator << (ostream &s, NumDays &n)
{
// Whatever
return s;
}
istream &operator >> (istream &s, NumDays &n);
{
// Whatever
return s;
}