I'm trying to overload the << operator for the display function call.
Heres my code:
#include <iostream>
#include <cstring>
using namespace std;
// global variable
const int MAX = 3;
// class definition
class CString{
char str[MAX+1];
public:
CString(char* param){
if(param == nullptr){
str[0] = '\0';
return;
}
strncpy(str,param,MAX);
str[MAX] = '\0';
}
void display(ostream& os){
os << str;
}
};
// << operator overloading
ostream& operator << (ostream& os, CString& cs){
static int call = 0;
os << call << ": ";
cs.display(os);
call++;
return os;
}
void process(char* parm){
CString cs(parm);
// here is where my issue is
cs.display(cout);
cout << endl;
}
//----------------------------------------------------------------
int main(int argc,char *argv[]){
cout << "Command Liine : ";
for(int arg = 0; arg < argc ; arg++){
cout << " " << argv[arg];
}
cout << endl;
if( argc == 1){
cout << "Insufffiecentnumber of arguemnts (min1)" << endl;
return 1;
}
cout << " Maxium numver of characters stored: " << MAX << endl;
for(int arg = 1; arg < argc; arg++){
process(argv[arg]);
}
return 0;
}
EDIT:
Here is the correct output and the output I have:
Correct:
Command Line : w1 oop345 btp305
Maximum number of characters stored : 3
0: oop
1: btp
Mine:
Command Line : w1 OOP345 DBS305
Maxium number of characters stored: 3
OOP
DBS
I'm having an issue with my << operator not working, I can't seem to figure it out. The ostream& operator<<(ostream& os, CString& cs) does not seem to be loading its syntax.
Question:
Does anyone know where my mistake has been made?
You wrote a correct overloading of << operator, but in method process() you used a public method display() of class CString instead of using << operator directly.
Just change one line in method process():
cs.display(cout); to: cout << cs;
void process(char* parm){
CString cs(parm);
// here is where my issue is
cout << cs;
cout << endl;
}
P.S. you do not need method CString::display at all as you already overload << operator for this class.
Related
This program uses class and takes the info of employees from a file. I have mentioned the file below too. I have also mentioned the output i received even though there are error. There is something wrong in the output too but I think it is because of the info error that it's getting.
While running this program, I got this error message:
Error: Run-Time Check Failure #2 - Stack around the variable 'info' was corrupted.
There's also this message:
Unhandled exception at 0x00950A89 in employee.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
// The used file for this program is:
A.Smith 20001 25 40
T.Philip 20002 20 35
S.LOng 20003 15 50
G.Santos 20004 30 30
F.Farkas 20005 22 55
// The output after running even with the errors is:
This week's employee history
Name Id Rate Hours
* A.Smith 20001 $25/h 40h
* T.Philip 20002 $20/h 35h
* S.LOng 20003 $15/h 50h
* G.Santos 20004 $30/h 30h
* F.Farkas 20005 $22/h 55h
This week's payment
Name Payment
* ╠╠╠╠╠╠╠╠ $0 <----------There is this error too
* T.Philip $700
* S.LOng $825
* G.Santos $900
* A.Smith $1000
* The average wages of the employees: $685.00
// The code is:
/*
#include "pch.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include<iomanip>
*/
using namespace std;
struct records {
char name[50] = {};
char id[5] = {};
int rate = 0;
int hours = 0;
int pay = 0;
};
void take(records array[], const int a);
int calculator(records array[], const int a);
void swap(records array[], const int a);
double Average(records array[], int a);
ifstream infile;
int main()
{
const int n = 5;
This is the first time info is declared:
struct records info[n];
double averageWages;
int overTime = 0, i;
infile.open("Project 3.dat");
cout << "\n This week's employee history \n" << endl;
if (infile.is_open()) {
cout << " Name Id Rate Hours " << endl;
Here take function uses info of the struct:
take(info, n);
cout << endl << endl;
cout << "This week's payment\n" << endl;
cout << " Name Payment" << endl;
Also here other functions use info:
calculator(info, n);
swap(info, n);
for (i = 0; i < n; i++) {
cout << "*" << setw(10) << info[i].name << setw(10) << "$" << info[i].pay << endl;
}
averageWages = Average(info, n);
cout << "\n\n" << "* The average wages of the employees: $" << averageWages << endl << endl;
}
else {
cerr << "Error! file cannot open." << endl;
exit(1);
}
return 0;
}
// Taking records:
void take(records array[], const int a) {
for (int i = 0; i < a; i++) {
while (infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours) {
cout << "*" << setw(9) << array[i].name << setw(10) << array[i].id << setw(10) << "$" << array[i].rate << "/h" << setw(10) << array[i].hours << "h " << endl;
}
} infile.close();
}
//swap records to arrange it according to total payment received
void swap(records array[], const int a) {
bool tf; //true or false
do {
tf = false;
for (int i = 0; i < a; i++) {
if (array[i].pay > array[i + 1].pay) {
swap(array[i], array[i + 1]);
tf = true;
}
}
} while (tf);
records temp;
for (int i = 0; i < a - 1; ++i)
{
for (int j = i + 1; j < a; ++j)
{
if (array[i].pay > array[j].pay)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
To calculate average:
double Average(records array[], const int a) {
double total = 0;
double average;
for (int i = 0; i < a; i++) {
total = total + (array[i].pay);
average = total / a;
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
return (total / a);
}
// To calculate the salary:
int calculator(records array[], const int a) {
infile.open("Project 3.dat");
if (infile.is_open()) {
for (int i = 0; i < a; i++) {
infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours;
if (array[i].hours > 40) {
int overTime = (array[i].hours - 40)*1.5;
array[i].pay = ((array[i].rate) * 40) + (overTime*(array[i].rate));
}
else {
array[i].pay = (array[i].rate)*(array[i].hours);
}
}
for (int i = 0; i < a; i++) {
return (array[i].pay);
}
}
}
It's hard to find all potential problems with that fragmented code, but you'd be better off using std::strings instead of char[]. They are safer and also has a lot of built-in functions. They also work well with misc. functions in the STL.
Your struct records info[n]; will only hold n (5) elements. Use a standard container, like a std::vector instead in case you'd like to add more entries to the file.
Reading and writing to files can usually be done using custom stream operators and all the free functions you have to deal with a number of records could be collected in a class of its own. I've made one record struct and one Records class to demonstrate how they could be used Together.
#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>
struct record {
std::string name{};
std::string id{};
int rate = 0;
int hours = 0;
int pay = 0;
// stream operators for reading/writing a record
friend std::istream& operator>>(std::istream&, record&);
friend std::ofstream& operator<<(std::ofstream&, const record&);
friend std::ostream& operator<<(std::ostream&, const record&);
};
// populate a record from an istream
std::istream& operator>>(std::istream& is, record& r) {
std::string line;
// get a line and check that it's > 30 chars long
if(std::getline(is, line) && line.size()>30) {
// extract the name and remove trailing spaces
r.name = line.substr(0, 30);
auto pos = r.name.find_last_not_of(' ');
if(pos != std::string::npos)
r.name = r.name.substr(0, pos+1);
// put the rest of the line in a stringstream
std::stringstream ss(line.substr(30));
// and extract the rest of the fields
if(ss >> r.id >> r.rate >> r.hours) {
// calculate pay
r.pay = r.rate * r.hours;
} else { // if extraction fails, set the stream in fail mode
is.setstate(std::ios_base::failbit);
}
} else is.setstate(std::ios_base::failbit);
return is;
}
// streaming a record to an ofstream (like a file)
std::ofstream& operator<<(std::ofstream& os, const record& r) {
os << std::setw(30) << std::left << r.name.substr(0, 30) << r.id << " " << r.rate << " " << r.hours << "\n";
return os;
}
// streaming a record to a generic ostream (like std::cout)
std::ostream& operator<<(std::ostream& os, const record& r) {
os << "* " << std::setw(30) << std::left << r.name << std::right << r.id
<< " $" << r.rate << "/h " << r.hours << "h $" << std::setw(4) << r.pay;
return os;
}
class Records { // a class to maintain a number of "record"s
std::vector<record> m_records{}; // stores all "record"s
public:
Records(const std::string& filename) {
record tmp;
std::ifstream e(filename); // open file
// and extract one record at a time and put it in m_records.
while(e>>tmp) m_records.emplace_back(std::move(tmp));
}
// sum on any member in "record"
template <typename field>
auto Sum(field f) const {
return std::accumulate(m_records.begin(), m_records.end(), 0,
[&](int a, const record& b) { return a + (b.*f); });
}
// average of any member in "record"
template <typename field>
auto Average(field f) const {
return static_cast<double>(Sum(f)) / m_records.size();
}
// sorting on any member in "record"
template <typename field, typename T>
void Sort(field f, const T& cmp) {
std::sort(m_records.begin(), m_records.end(),
[&](const record& a, const record& b){ return cmp(a.*f, b.*f); });
}
// return the number of "record" elements
std::vector<record>::size_type size() const { return m_records.size(); }
// access an element via subscript
record& operator[](std::vector<record>::size_type idx) { return m_records[idx]; }
const record& operator[](std::vector<record>::size_type idx) const { return m_records[idx]; }
// iterators to use in for-loops
std::vector<record>::const_iterator cbegin() const noexcept { return m_records.cbegin(); }
std::vector<record>::const_iterator cend() const noexcept { return m_records.cend(); }
std::vector<record>::const_iterator begin() const noexcept { return cbegin(); }
std::vector<record>::const_iterator end() const noexcept { return cend(); }
std::vector<record>::iterator begin() noexcept { return m_records.begin(); }
std::vector<record>::iterator end() noexcept { return m_records.end(); }
// stream operator to show all records
friend std::ostream& operator<<(std::ostream&, const Records&);
};
std::ostream& operator<<(std::ostream& os, const Records& R) {
os << " Name Id Rate Hrs Pay\n";
for(const auto& r : R) std::cout << r << "\n";
os << std::setprecision(2) << std::fixed;
os << "Average pay : $" << std::setw(7) << R.Average(&record::pay) << "\n";
os << " rate : $" << std::setw(7) << R.Average(&record::rate) << "\n";
os << " hours worked: " << std::setw(7) << R.Average(&record::hours) << "h\n";
return os;
}
int main() {
// create a "Records" entity called "info" by reading a file
Records info("Project 3.dat");
// misc sorting and showing the result
std::cout << "Sorted as read from the file:\n";
std::cout << info;
std::cout << "\nSorted according to name:\n";
info.Sort(&record::name, std::less<std::string>());
std::cout << info;
std::cout << "\nSorted according to id:\n";
info.Sort(&record::id, std::less<std::string>());
std::cout << info;
std::cout << "\nSorted according to pay:\n";
info.Sort(&record::pay, std::greater<int>());
// output example using iterators:
for(auto& rec : info) {
std::cout << rec << "\n";
}
std::cout << "\nSorted according to rate:\n";
info.Sort(&record::rate, std::greater<int>());
std::cout << info;
std::cout << "\nSorted according to hours:\n";
info.Sort(&record::hours, std::greater<int>());
std::cout << info;
// example using subscript, operator[]
if(info.size()>2) {
std::cout << "\ninfo[2] = " << info[2] << "\n";
}
}
o, I am attempting to create an overloaded output operator for a vector. This overloaded output operator is suppose to allow me to print the values in the vector in the form
[Data]^[Index]
so for example if the data at index 3 is 4, it should print 3^4.
However, I can't seem to get it to work correctly. I need it to loop through the entire vector, but I can't seem to detect what I'm doing wrong.
Here is the function within the header.
friend ostream & operator << (ostream &out, const vector<int> &c);
Here is what I have for the function in the source file.
ostream & operator << (ostream &os, const vector<int> &c)
{
for (int i = 0; i < c.size(); i++)
{
os << c.at[i];
os << "^";
os << i;
}
return os;
Finally, here is my main
#include "Polynomial.h"
#include <string>
#include <vector>
#include <utility>
int main()
{
vector<int> poly1(10);
vector<int> poly2(10);
int x;
int y;
int choice;
bool done = true;
std::cout << "What do you wish to do?" << std::endl;
std::cout << "1. Add two polynomials" << std::endl;
std::cout << "2. Multiply two polynomials" << std::endl;
std::cout << "3. Evaluate one polynomial at a given value" << std::endl;
std::cout << "4. Find Coefficent for a given polynomial and given exponent" << std::endl;
std::cout << "5. Find the leading exponent for a given polynomial" << std::endl;
std::cout << "6. Exit "<< std::endl;
std::cin >> choice;
if (choice < 1 || choice > 6)
{
do
{
std::cout << "Invalid entry: please reenter choice" << std::endl;
std::cin >> choice;
} while (choice < 1 || choice > 6);
}
if (choice == 1)
{
std::cout << "Please input the first polynomial in the form of: (non-zero coefficient, exponent) pairs" << std::endl;
do
{
std::cin >> x >> y;
poly1.at(y) = x;
std::cout << "done?" << std::endl;
std::cin >> done;
} while (done == false);
std::cout << poly1 << std::endl;
}
if (choice == 2)
if (choice == 3)
if (choice == 4)
if (choice == 5)
if (choice == 6)
system("pause");
I believe that my issue lies somewhere within my main or within the source file, though I haven't worked with overloaded output operators in a very long time, so I'm not sure exactly what needs to be fixed.
There is no problem with your code except that at is function so you cannot use subscript operator with that,hence correct code for the above problem is :
#include <iostream>
#include <string>
#include <vector>
using namespace std;
ostream & operator << (ostream &os, const vector<int> &c)
{
for (int i = 0; i < c.size(); i++)
{
os << c.at(i);
os << "^";
os << i;
}
return os;
}
int main()
{
std::vector<int> v{1,2,3};
std::cout<<v<<std::endl;
return 0;
}
The problem with your code is somewhere else and it's actually hard to find in the first glimpse.
Here :
os << c.at[i];
std::vector::at is a function and it's the same as std::vector operator [], but it's a function and you can't use it like this. change it to :
os << c.at(i); //or os << c[i];
Two minor things to take care of :
it's better to print some delimiter(like -) when you print each value^index because it's hard to read this way.
in this line for(int i = 0; i < c.size(); i++) to avoid getting '<' : signed/unsigned mismatch warning change it to for(unsigned int i = 0; i < c.size(); i++). std::vector::size returns size_type which is an unsigned integral type.
I'm trying to create a function that will take ostream object as an argument, and then print to it. I plan to pass some of my fstream (files), and cout.
This is my code:
void printTask(int op1, int op2, int len, char operation, std::ostream& os = std::cout)
{
os << endl << " " << setw(len) << op1 << endl;
os << operation << " " << setw(len) << op2 << endl;
os << "-------------" << endl;
os << " ";
for(int i = 0; i < len; i++)
{
os << "?";
}
os << endl;
}
From main(), it goes like this...
ofstream output("output.txt", ios::out);
cout << addition(xyz, output) << endl;
and that function looks like this:
int addition(int xyz, ofstream file)
{
int op1 = ...;
int op2 = ...;
char choice = ...;
printTask(op1, op2, xyz, choice, file);
printTask(op1, op2, xyz, choice, cout); //this cout is not necessary, default parameter
}
I get an error about std::ios::base being private, but I did pass my ostream object by reference so it doesn't try to use copy constructor.
Any ideas?
EDIT: Wanted to update this with an answer. Prototype for addition was wrong, ofstream should be passed by reference, instead of copying it.
This works:
int addition(int xyz, ofstream& file) {...}
Big thanks to #Jarod42
I have this header:
MvProjectQueue & operator >> (char *);
And I have to write a function meeting this spec. (my function should "return" an array of chars using >> operator)
I have to change the passed argument, i.e. I get an array of char when my function is called and I have to modify it (in place).
Normally I would use
MvProjectQueue & operator >> (char **);
got a pointer to char * and I would solved it easily, using something like this:
#include <iostream>
using namespace std;
class SimpleShowcaseObject
{
public:
SimpleShowcaseObject(){};
~SimpleShowcaseObject(){};
SimpleShowcaseObject & operator >> (char ** p_ch)
{
*p_ch = "changed";
cout << "in scope: " << *p_ch << endl;
return *this;
}
};
int main(void)
{
char *ch = new char[10];
ch = "hello";
SimpleShowcaseObject o = SimpleShowcaseObject();
cout << "original: " << ch << endl;
o >> &ch;
cout <<"changed: " << ch << endl;
delete[] ch;
cin.get();
return 0;
}
But this:
#include <iostream>
using namespace std;
class SimpleShowcaseObject
{
public:
SimpleShowcaseObject(){};
~SimpleShowcaseObject(){};
SimpleShowcaseObject & operator >> (char *ch)
{
ch = "changed";
cout << "in scope: " << ch << endl;
return *this;
}
};
int main(void)
{
char *ch = new char[10];
ch = "hello";
SimpleShowcaseObject o = SimpleShowcaseObject();
cout << "original: " << ch << endl;
o >> ch;
cout <<"changed: " << ch << endl;
delete[] ch;
cin.get();
return 0;
}
executes and prints:
original: hello
in scope: changed
changed: hello
and I would like to have
original: hello
in scope: changed
changed: changed
(edited several times, big thanks to everyone for trying to help!)
Your function receive what should be a buffer you can write to:
SimpleShowcaseObject & operator >> (char *ch)
{
//ch = "changed";// with this you are changing the value of the pointer, not what you want
strcpy (ch, "changed");
cout << "in scope: " << ch << endl;
return *this;
}
As other have already pointed out, this is not a good design: your operator >> has to write a string (char[]) in a buffer, without knowing the lenght of input buffer; not a nice scenario.
Hello I've got some troubles to delete a member string of my class which is isn't null and which points to the right location since I can display my string "hello world" just before.
I call the function mystringclass::alloc() from another member function afterwards this->str was supposed to get another string content larger.
The process worked fine a first time when I resized the same way "hello" to get "hello world". But now I want to enlarge it again it doesn't. So I'm confused.
Please help me.
void mystringclass::alloc(long newsize) //newsize includes the +1 char
{
cout << "old size was: " << this->size << endl; //displays "12"
if(this->str) cout << this->str << endl; //displays "hello world" all is right till here
if(this->str) delete [] this->str ; //it crashes here
cout << "str deleted\n"; //never show up on screen
this->str = new char[newsize + 1];
this->size = newsize;
this->str[0] = 0;
}
Thanks for your answers, I tried to clear my code to post it here. My bug disappeared but another one came up and having something to do with the rule of three:
int main()
{
stringclass str = "Hello";
stringclass str2 = str;
return 0;
}
I display info all along procedures So the problem is that str2 is already equal to "hello" even before affecting the content of str in my copy constructor. And is empty after the copy. What's wrong? As some may say, I learned c++ in a magicbox. I'm using codeblocks 10.05
Full code :
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
class stringclass
{
protected :
inline bool success() { failbit = false; return true; }
inline bool fail() { failbit = true; return false; }
public :
bool failbit;
char * mystring;
long memsize;
long length;
void alloc(long newsize);
void reset();
void copy(const stringclass & other);
stringclass() {reset(); }
stringclass(const stringclass & other) {copy(other); }
stringclass(const char str[]);
~stringclass() {delete [] mystring;}
inline long get_length() { if(mystring) length = strlen(mystring); return length;}
inline long get_memsize() const { return memsize; }
friend ostream& operator << (ostream& out, stringclass & sc){out << sc.mystring; return out;}
stringclass & operator = (stringclass & other) { copy(other); return *this;}
};
void stringclass::reset()
{
delete [] mystring;
mystring = NULL;
length = 0;
memsize = 0;
}
void stringclass::alloc(long newsize)
{
cout<< "\nalloc(long newsize)... \n" << endl;
cout << "memsize was : " << memsize << endl;
cout << "length was : " << length << endl;
if(mystring) cout << "mystring = " << mystring << endl;
delete [] mystring;
cout << "mystring deleted...\n";
mystring = new char[newsize];
cout << "mystring has been resized\n";
mystring[0] = 0;
memsize = newsize;
length = strlen(mystring);
cout << "memsize is now : " << memsize << endl;
cout << "length is now : " << length << endl;
cout<< "\nend of alloc()... " << endl;
cout << "\n";
}
void stringclass::copy(const stringclass & other)
{
cout << "\n";
cout << "copy(const stringclass & other)...\n" << endl;
cout << "other.mystring = "<< other.mystring << endl;
if(other.mystring == NULL || other.memsize == 0)
{
reset();
return;
}
alloc(other.memsize);
strcpy(mystring, other.mystring);
cout << "mystring = "<< mystring;
length = strlen(mystring);
cout << "length: " << length << endl;
cout<< "\nend of copy()... " << endl;
cout << "\n";
}
stringclass::stringclass(const char str[]) : mystring(NULL), memsize(0), length(0)
{
if(str == NULL) reset();
else
{
alloc(strlen(str) + 1);
strcpy(mystring, str);
length = strlen(mystring);
}
}
int main()
{
stringclass str = "Hello";
stringclass str2 = str;
cout << "\nback to main()...\n";
cout << "str = " << str << "\n";
cout << "str2 = " << str2 << "\n";
cout << endl;
system("PAUSE");
return 0;
}
Result on screen :
alloc(long newsize)...
memsize was : 0
length was : 0
mystring deleted...
mystring has been resized
memsize is now : 6
length is now : 0
end of alloc()...
copy(const stringclass & other)...
other.mystring = Hello
alloc(long newsize)...
memsize was : 3214960
length was : 2293560
mystring = Hello
mystring deleted...
mystring has been resized
memsize is now : 6
length is now : 0
end of alloc()...
mystring = length: 0
end of copy()...
back to main()...
str =
str2 =
Appuyez sur une touche pour continuer...
I've just realized that the following code isn't necessary for you :
protected :
inline bool success() { failbit = false; return true; }
inline bool fail() { failbit = true; return false; }
public :
bool failbit;
So I put off these two functions and this variable, and guess what.. all worked fine, no bug. They are not even used once. I put it back and the problem came back as well. How could you explain that?! I'm already losing my hairs.
The fact that you can "display" a string says absolutely nothing unfortunately. De-allocating the string will still make it printable, most likely until it's overwritten by a new llocation and initialization.
Just try to print the string after you've delete[]d it and see.