Operator Overloading solution - c++

i have made a c++ code. An MList that holds items in it. I overloaded the << operator to print the values in MList in a particular format. Here is the code:
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
string s = "";
s += "Size " + to_string(m.size_) + "\n";//out << m.size() << endl;
s += "Cap " + to_string(m.capacity_) + "\n"; //out << m.capacity() << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
s += m.ary[i].element + ",";//out << m.ary[i].element << ",";
else
s += m.ary[i].element;
}
//cout << "String : " << s;
return out << s;
}
But it does not print correct value. It prints the size and capacity right but not the values. Instead of values, it prints some signs like heart:
You can see it prints size and capacity right but not the values. Here is the relevant code. I am executing case 2 only right now:
#include<iostream>
using std::cout; using std::endl;
using std::ostream; using std::cin; using std::boolalpha;
#include<string>
using std::string;
using namespace std;
template <class V>
struct SetElement
{
V element;
int cnt;
SetElement() = default;
SetElement(V v) : element(v){}
};
template <class V>
ostream &operator<<(ostream & o,const SetElement<V> &p)
{
return o << p.element;
}
template <class V>
class MSet
{
private:
SetElement<V> *ary;
size_t capacity_;
size_t size_;
public:
MSet(V val)
{
capacity_ = 2;
ary = new SetElement<V>[capacity_];
ary[0].element = val;
ary[0].cnt = 1;
size_ = 1;
}
SetElement<V>* find(V val)
{
SetElement<V> *found = nullptr;
bool yes = false;
for (int i = 0; i < size_ && !yes; i++)
{
if (ary[i].element == val)
{
found = &ary[i];
yes = true;
}
}
return found;
}
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
string s = "";
s += "Size " + to_string(m.size_) + "\n";//out << m.size() << endl;
s += "Cap " + to_string(m.capacity_) + "\n"; //out << m.capacity() << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
s += m.ary[i].element + ",";//out << m.ary[i].element << ",";
else
s += m.ary[i].element;
}
//cout << "String : " << s;
return out << s;
}
};
int main(){
int test;
long l1, l2, l3;
cin >> test;
cout << boolalpha;
switch (test){
// ...
case 2: {
cin >> l1 >> l2;
MSet<long> m_l(l1);
auto p = m_l.find(l1);
if (p != nullptr)
cout << *p << endl;
else
cout << "Val:" << l1 << " not found " << endl;
p = m_l.find(l2);
if (p != nullptr)
cout << *p << endl;
else
cout << "Val:" << l2 << " not found " << endl;
//cout << "MList \n";
cout << m_l;
break;
}
// ...
}
}

You're adding the values into a temporary string, which may involve implicit conversions depending of the template type (here your numerical values were converted into characters).
Just print the values, without the temporary string:
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
out << "Size " << m.size_ << endl;
out << "Cap " << m.capacity_ << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
out << m.ary[i].element << ",";
else
out << m.ary[i].element;
}
return out;
}

Related

Why is the 'info[]' of the struct records giving errors?

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";
}
}

C++ Delete[] causing program crash [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
My program works fine while I don't have a call to delete[] buf in the destructor. However, when I include it the program crashes at the start of the output.
Here are my files.
//string.cpp
#include "String.h"
#include
#include
extern ofstream csis;
String::String() {
buf = "\0";
length = 0;
}
String::String(const char* tar) {
int temp = strlen(tar);
length = temp;
buf = new char[length + 1];
buf[length] = '\0';
for (int i = 0; i < length; i++){
buf[i] = tar[i];
}
}
String::String(char a) {
length = 1;
buf = new char[length+1];
buf[length] = '\0';
buf[0] = a;
}
String::String(int x) {
int alloc = x;
if (x < 0) {
alloc = 0;
}
buf = new char[alloc+1];
length = x;
buf[0] = '\0';
}
String::String(const String& a) {
length = a.length;
buf = new char[length+1];
for (int i = 0; i < length; i++) {
buf[i] = a.buf[i];
}
}
String::String(char a, int x) {
buf = new char[x+1];
for (int i = 0; i < x; i++) {
buf[i] = a;
}
buf[x] = '\0';
length = strlen(buf);
}
String::~String() {
delete buf;
}
String& String::operator=(const String& tar) {
buf = new char[tar.length+1];
strcpy(buf, tar.buf);
length = tar.length;
buf[length] = '\0';
return *this;
}
String& String::operator=(const char* chr) {
buf = (char*)chr;
length = int(strlen(chr));
return *this;
}
String operator+(const String& a, const String& b) {
String sum;
int size = a.length + b.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < a.length; i++) {
sum.buf[i] = a.buf[i];
}
int j = 0;
for (int i = a.length; i < size; i++) {
sum.buf[i] = b.buf[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(const String& tar, const char* c) {
String sum;
int size = int(strlen(c)) + tar.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < tar.length; i++) {
sum.buf[i] = tar.buf[i];
}
int j = 0;
for (int i = tar.length; i < size; i++) {
sum.buf[i] = c[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(const char* c, const String& tar) {
String sum;
int size = int(strlen(c)) + tar.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < int(strlen(c)); i++) {
sum.buf[i] = c[i];
}
int j = 0;
for (int i = strlen(c); i < size; i++) {
sum.buf[i] = tar.buf[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(const String& tar, char c) {
String sum;
int size = 1 + tar.length;
sum.buf = new char[size];
sum.length = size;
for (int i = 0; i < tar.length; i++) {
sum.buf[i] = tar.buf[i];
}
int j = 0;
for (int i = tar.length; i < size; i++) {
sum.buf[i] = c;
j++;
}
sum.buf[size] = '\0';
return sum;
}
String operator+(char c, const String& tar) {
String sum;
int size = 1 + tar.length;
sum.buf = new char[size+1];
sum.length = size;
for (int i = 0; i < 1; i++) {
sum.buf[i] = c;
}
int j = 0;
for (int i = 1; i < size; i++) {
sum.buf[i] = tar.buf[j];
j++;
}
sum.buf[size] = '\0';
return sum;
}
String& String::operator+=(const String& tar) {
String temp = *this;
temp = temp + tar;
*this = temp;
return *this;
}
String& String::operator+=(const char c) {
String temp = *this;
temp = temp + c;
*this = temp;
return *this;
}
String String::operator+() const {
String sum;
sum.length = length;
sum.buf = new char[sum.length+1];
strcpy(sum.buf, buf);
for (int i = 0; i < length; i++) {
sum.buf[i] = toupper(buf[i]);
}
sum.buf[length] = '\0';
return sum;
}
int operator==(const String & tar, const String& tar2) {
int check = 0;
if (strcmp(tar.buf, tar2.buf) == 0) {
check += 1;
}
else if (strcmp(tar.buf, tar2.buf) != 0) {
check = 0;
}
return check;
}
int operator!=(const String& tar, const String& tar2) {
int check = 0;
if (!(strcmp(tar.buf, tar2.buf) == 0)) {
check += 1;
}
else if (!(strcmp(tar.buf, tar2.buf) != 0)) {
check = 0;
}
return check;
}
int operator<(const String& a, const String& b) {
int check = 0;
if (a.length < b.length) {
check += 1;
}
return check;
}
int operator<=(const String& a, const String& b) {
int check = 0;
if (a.length <= b.length) {
check += 1;
}
return check;
}
int operator>(const String& a, const String& b) {
int check = 0;
if (a.length > b.length) {
check += 1;
}
return check;
}
int operator>=(const String& a, const String& b) {
int check = 0;
if (a.length >= b.length) {
check += 1;
}
return check;
}
char& String::operator[](int x) {
int out;
if (x >= 0 && x < length) {
out = x;
}
else if (!(x >= 0 && x < length)) {
int output = NULL;
cout << "ERROR: Invalid Index with [] operator." << endl;
csis << "ERROR: Invalid Index with [] operator." << endl;
out = NULL;
}
return buf[out];
}
char* operator+(const String& a, int x) {
return &a.buf[x];
}
char* operator+(int x, const String& a) {
return &a.buf[x];
}
String String::operator++(int val) {
String temp;
temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = temp.buf[i] + 1;
}
return temp;
}
String String::operator--(int val) {
String temp;
temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = temp.buf[i] - 1;
}
return temp;
}
String String::operator++() {
String temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = (temp.buf[i] + 1);
}
return temp;
}
String String::operator--() {
String temp = *this;
for (int i = 0; i < temp.length; i++) {
temp.buf[i] = (temp.buf[i] - 1);
}
return temp;
}
int String::getLength() {
return length;
}
String String::substr(int a, int b) {
String temp = *this;
char *fill = new char[b+1];
int i = a;
int x = 0;
while (x <= b) {
fill[i] = temp.buf[i];
i++;
x++;
}
temp.buf = fill;
temp.buf[length] = '\0';
return temp;
}
void String::print() {
cout << """";
csis << """";
for (int i = 0; i < length; i++) {
cout << buf[i];
csis << buf[i];
}
cout << """";
csis << """";
cout << " Length: " << length << endl;
csis << " Length: " << length << endl;
}
ostream& operator<<(ostream& o, const String& tar) {
for (int i = 0; i < tar.length; i++) {
o << tar.buf[i];
}
return o;
}
Here is string.h
//string.h
#ifndef _STRING_H
#define _STRING_H
#include <iomanip>
#include <stdlib.h>
#include <iostream>
using namespace std;
class String {
protected:
int length;
char* buf;
public:
String();
String(const char*);
String(char a);
String(int x);
String(const String&);
String(char a, int x);
~String();
// Operator Overload
String& operator=(const String& tar);
String& operator= (const char*);
friend String operator+(const String& a, const String& b);
friend String operator+(const String&, const char*);
friend String operator+(const char* c, const String& tar);
friend String operator+(const String&, char c);
friend String operator+(char c, const String& tar);
String& operator+=(const String& tar);
String& operator+=(const char c);
String operator+() const;
friend int operator==(const String&, const String&);
friend int operator!=(const String&, const String&);
friend int operator<(const String&, const String&);
friend int operator<=(const String&, const String&);
friend int operator>(const String&, const String&);
friend int operator>=(const String&, const String&);
char& operator[](int);
friend char* operator+(const String&, int);
friend char* operator+(int, const String&);
String operator++();
String operator--();
String operator++(int);
String operator--(int);
int getLength();
String substr(int a, int b);
void print();
friend ostream& operator<<(ostream&, const String&);
};
#endif
Here is StringDriver.cpp
// StringDriver.cpp
// MATTHEW BUTNER
// ID: 011029756
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "StringDriver.h"
using namespace std;
ofstream csis;
int main() {
csis.open("csis.txt");
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
test10();
test11();
test12();
test13();
test14();
test15();
test16();
test17();
test18();
test19();
test20();
csis.close();
}
void test1() {
cout << "1. Testing S1: String default ctor." << endl << endl;
csis << "1. Testing S1: String default ctor." << endl << endl;
String s1;
s1.print();
wait();
}
void test2() {
cout << "2. Testing S2: String one arg (char *) ctor." << endl << endl;
csis << "2. Testing S2: String one arg (char *) ctor." << endl << endl;
String s2("ABC");
s2.print();
wait();
}
void test3() {
cout << "3. Testing S3: String one arg (char) ctor." << endl << endl;
csis << "3. Testing S3: String one arg (char) ctor." << endl << endl;
String s3('Z');
s3.print();
wait();
}
void test4() {
cout << "4. Testing S4: String one arg (int) ctor." << endl << endl;
csis << "4. Testing S4: String one arg (int) ctor." << endl << endl;
String s4(10);
s4.print();
wait();
}
void test5() {
cout << "5. Testing S5, T5: String copy ctor." << endl << endl;
csis << "5. Testing S5, T5: String copy ctor." << endl << endl;
String s5("Purple Rain");
s5.print();
String t5(s5);
t5.print();
wait();
}
void test6() {
cout << "6. Testing S6: String two arg (char, int) ctor." << endl << endl;
csis << "6. Testing S6: String two arg (char, int) ctor." << endl << endl;
String s6('*', 10);
s6.print();
wait();
}
void test7() {
cout << "7. Testing S7, T7, U7: String assignment." << endl << endl;
csis << "7. Testing S7, T7, U7: String assignment." << endl << endl;
String s7("Sally Ride"), t7, u7;
t7 = u7 = s7;
s7.print();
t7.print();
u7.print();
wait();
}
void test8() {
cout << "8. Testing S8: String assignment." << endl << endl;
csis << "8. Testing S8: String assignment." << endl << endl;
String s8("ABC");
s8 = s8;
s8.print();
wait();
}
void test9() {
cout << "9. Testing S9: Implicit type conversion." << endl << endl;
csis << "9. Testing S9: Implicit type conversion." << endl << endl;
String s9;
s9 = "ABC";
s9.print();
wait();
}
void test10() {
cout << "10. Testing S10, T10, U10: String concatenation." << endl << endl;
csis << "10. Testing S10, T10, U10: String concatenation." << endl << endl;
String s10("DEF");
String t10('H');
String u10("ABC" + s10 + "G" + t10 + 'I');
u10.print();
String v10('X' + u10);
v10.print();
wait();
}
void test11() {
cout << "11. Testing S11, T11: String concatenation." << endl << endl;
csis << "11. Testing S11, T11: String concatenation." << endl << endl;
String s11('A');
String t11("BC");
s11 += s11 += t11 += 'D';
s11.print();
t11.print();
wait();
}
void test12() {
cout << "12. Testing S12, T12: String unary operator." << endl << endl;
csis << "12. Testing S12, T12: String unary operator." << endl << endl;
String s12("Unary +");
String t12(+s12);
s12.print();
t12.print();
s12 = +s12;
s12.print();
wait();
}
void test13() {
cout << "13. Testing S13, T13: String comparison operators." << endl << endl;
csis << "13. Testing S13, T13: String comparison operators." << endl << endl;
String s13("ABC"), t13("ABCD");
s13.print();
t13.print();
cout << endl;
cout << "== " << (s13 == t13 ? "True" : "False") << endl;
cout << "!= " << (s13 != t13 ? "True" : "False") << endl;
cout << "< " << (s13 < t13 ? "True" : "False") << endl;
cout << "<= " << (s13 <= t13 ? "True" : "False") << endl;
cout << "> " << (s13 > t13 ? "True" : "False") << endl;
cout << ">= " << (s13 >= t13 ? "True" : "False") << endl;
csis << endl;
csis << "== " << (s13 == t13 ? "True" : "False") << endl;
csis << "!= " << (s13 != t13 ? "True" : "False") << endl;
csis << "< " << (s13 < t13 ? "True" : "False") << endl;
csis << "<= " << (s13 <= t13 ? "True" : "False") << endl;
csis << "> " << (s13 > t13 ? "True" : "False") << endl;
csis << ">= " << (s13 >= t13 ? "True" : "False") << endl;
wait();
}
void test14() {
cout << "14. Testing S14: Overloaded subscript operator." << endl << endl;
csis << "14. Testing S14: Overloaded subscript operator." << endl << endl;
String s14("C++ is fun.");
for (int i = -1; i <= s14.getLength(); i++) {
char& ch = s14[i];
if (ch != '\0')
++ch;
}
s14.print();
wait();
}
void test15() {
cout << "15. Testing S15: Pointer notation." << endl << endl;
csis << "15. Testing S15: Pointer notation." << endl << endl;
String s15("ABCDE");
for(int i = 0; i < s15.getLength(); i++)
++(*(s15+i));
for (int j = 0; j < s15.getLength(); j++) {
cout << *(j + s15);
csis << *(j + s15);
}
cout << endl;
csis << endl;
wait();
}
void test16() {
cout << "16. Testing S16, T16, U16, V16, W16, X16, Y16, Z16: Increment and decrement operators." << endl << endl;
csis << "16. Testing S16, T16, U16, V16, W16, X16, Y16, Z16: Increment and decrement operators." << endl << endl;
String s16("ABC");
String t16(++s16);
s16.print();
t16.print();
String u16("ABC");
String v16(u16++);
u16.print();
v16.print();
String w16("ABC");
String x16(--w16);
w16.print();
x16.print();
String y16("ABC");
String z16(y16--);
y16.print();
z16.print();
wait();
}
void test17() {
cout << "17. Testing S17, T17: Substr function." << endl << endl;
csis << "17. Testing S17, T17: Substr function." << endl << endl;
String s17("All You Need Is Love"), t17;
t17 = s17.substr(4, 8);
s17.print();
t17.print();
wait();
}
void test18() {
cout << "18. Testing S18, T18: Output function." << endl << endl;
csis << "18. Testing S18, T18: Output function." << endl << endl;
String s18("Red-");
String t18("Green-");
String u18("Blue");
cout << s18 << t18 << u18;
csis << s18 << t18 << u18;
cout << endl;
csis << endl;
wait();
}
void test19() {
cout << "19. Testing S19, T19, U19: ReverseString class." << endl << endl;
csis << "19. Testing S19, T19, U19: ReverseString class." << endl << endl;
ReverseString s19("Computer");
ReverseString t19;
t19 = ~s19;
s19.print();
t19.print();
ReverseString u19(~~s19);
u19.print();
wait();
}
void test20() {
cout << "20. Testing S20, T20, U20: CaseString class." << endl << endl;
csis << "20. Testing S20, T20, U20: CaseString class." << endl << endl;
CaseString s20("BaLLooN");
CaseString t20;
t20 = s20;
s20.print();
t20.print();
CaseString u20(s20);
u20.print();
wait();
}
void wait() {
char buf;
cout << endl << "Press any key to continue." << endl;
csis << endl << endl;
cin.get(buf);
}
The problem is with the destructor in string.cpp, when I have an empty destructor, everything goes fine and well, but when I include the delete buf, it'll crash the program. Also, here are the other .h and .cpp files:
//ReverseString.h
#ifndef _REVERSESTRING_H
#define _REVERSESTRING_H
#include "String.h"
#include <iostream>
class ReverseString : public String {
public:
ReverseString();
ReverseString(const ReverseString& tar);
ReverseString(const char* c);
ReverseString& operator=(const ReverseString&);
ReverseString operator~();
};
#endif
next file,
//ReverseString.cpp
#include "ReverseString.h"
extern ostream csis;
ReverseString::ReverseString() : String() {
}
ReverseString::ReverseString(const ReverseString& tar) : String(tar) {
}
ReverseString::ReverseString(const char* c) : String(c) {
}
ReverseString& ReverseString::operator=(const ReverseString& tar) {
length = tar.length;
buf = tar.buf;
buf[length] = '\0';
return *this;
}
ReverseString ReverseString::operator~() {
ReverseString reverse;
reverse.length = length;
reverse.buf = new char[length];
int j = length - 1;
for (int i = 0; i < length; i++) {
reverse.buf[i] = buf[j];
j--;
}
return reverse;
}
CaseString.h
#ifndef _CASESTRING_H
#define _CASESTRING_H
#include "String.h"
#include <iostream>
class CaseString : public String {
protected:
char* upper;
char* lower;
public:
CaseString();
CaseString(const CaseString& tar);
CaseString(const char* c);
CaseString& operator=(const CaseString& c);
void print();
~CaseString();
};
#endif
CaseString.cpp
#include "CaseString.h"
#include <fstream>
extern ofstream csis;
CaseString::CaseString() : String() {
}
CaseString::CaseString(const CaseString& tar) : String(tar) {
upper = tar.upper;
lower = tar.lower;
buf = tar.buf;
length = tar.length;
}
CaseString::CaseString(const char* c) : String(c) {
lower = new char[int(strlen(c))];
upper = new char[int(strlen(c))];
int losize = strlen(c);
char* getLow = new char[losize];
for (int i = 0; i < losize; i++) {
getLow[i] = tolower(c[i]);
}
char* getHi = new char[losize];
for (int i = 0; i < losize; i++) {
getHi[i] = toupper(c[i]);
}
lower = getLow;
upper = getHi;
lower[losize] = '\0';
upper[losize] = '\0';
}
CaseString& CaseString::operator=(const CaseString& tar) {
if (&tar != this) {
String::operator=(tar);
buf = tar.buf;
length = tar.length;
lower = tar.lower;
upper = tar.upper;
}
return *this;
}
void CaseString::print() {
cout << "\"" << buf << "\"" << " " << "Length = " << length << " |" << "Lower = " << lower << " |" << "Upper = " << upper << endl;
csis << "\"" << buf << "\"" << " |" << "Length = " << length << " |" << "Lower = " << lower << " |" << "Upper = " << upper << endl;
}
CaseString::~CaseString() {
}
There are several issues that I see.
The main problem is that you sometimes assign a pointer to a character string to buf (your default constructor is one such place, and there is at least one other). This is a pointer you do not want to delete. You need to either always allocate memory for buf, or have some way to tell if you own the pointer and it should be deleted.
The other issue is that since you use new [], you need to use delete [] buf in your destructor.
In your copy constructor, you do not copy the nul byte at the end of the coped buffer.

how to update individual elements in this OOP case?

I have this "movie store.cpp"
#include "List.h"
#include <iomanip>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cmath>
using namespace std;
//****************************************************************************************************
const static char* FILE_NAME = "Movies.csv";
int totalCheckedIn1 = 0;
int totalCheckedOut1 = 0;
//****************************************************************************************************
struct Movie
{
int MPAC;
int year;
int runtime;
int checkedIn;
int checkedOut;
string title;
Movie()
{
}
Movie(int m, int y, int r, int ci, int co, string t)
{
MPAC = m;
year = y;
runtime = r;
checkedIn = ci;
checkedOut = co;
title = t;
}
bool operator == (const Movie& rhs) const
{
return (MPAC == rhs.MPAC);
}
Movie& operator =(const Movie& rhs)
{
MPAC = rhs.MPAC;
year = rhs.year;
runtime = rhs.runtime;
checkedIn = rhs.checkedIn;
checkedOut = rhs.checkedOut;
title = rhs.title;
return *this;
}
friend ostream& operator <<(ostream& os, const Movie& m);
};
void setInventory(List<Movie> z, double f)
{
}
//****************************************************************************************************
ostream& operator<<(ostream& os, const Movie& m)
{
os << setw(7) << left << m.MPAC
<< setw(25) << left << m.title
<< setw(7) << left << m.year
<< setw(10) << left << m.runtime
<< setw(7) << left << m.checkedIn
<< setw(7) << left << m.checkedOut;
return os;
}
//****************************************************************************************************
void getData(List<Movie>& Movies);
void displayList(List<Movie>& Movies);
void findMovies(List<Movie> Movies);
//****************************************************************************************************
int main()
{
List<Movie> WebsterMovies;
getData(WebsterMovies);
cout << "CHECK";
displayList(WebsterMovies);
// findMovies(WebsterMovies);
setInventory(WebsterMovies, 10.5);
cout << "The following data is the updated Webster Movies store\n";
//displayList(WebsterMovies);
system("PAUSE");
return 0;
}
//****************************************************************************************************
void getData(List<Movie>& Movies)
{
ifstream infile(FILE_NAME);
if (!infile)
{
cout << "Problem opening file" << endl;
exit(99);
}
while (!infile.eof())
{
Movie m;
if (infile.peek() == EOF)
break;
infile >> m.MPAC;
infile.ignore();
infile >> m.year;
infile.ignore();
infile >> m.runtime;
infile.ignore();
infile >> m.checkedIn;
infile.ignore();
infile >> m.checkedOut;
infile.ignore();
getline(infile, m.title);
Movies.insert(m);
}
infile.close();
}
//****************************************************************************************************
void displayList(List<Movie>& Movies)
{
int totalCheckedIn = 0;
int totalCheckedOut = 0;
cout << "The Webster Movie Store list includes : " << endl;
cout << setw(7) << left << "MPAC"
<< setw(25) << left << "Title"
<< setw(7) << left << "Year"
<< setw(10) << left << "RunTime"
<< setw(7) << left << "In"
<< setw(7) << left << "Out" << endl;
cout << "-------------------------------------------------------------------------------" << endl;
double totalRunTime = 0;
for (int i = 0, size = Movies.getNumber();
i < size; ++i)
{
Movie m = Movies.getNext();
cout << m << endl;
totalRunTime += m.runtime;
totalCheckedIn += m.checkedIn;
totalCheckedOut += m.checkedOut;
}
cout << "The average run time for the " << Movies.getNumber()
<< " movies is " << fixed << setprecision(1)
<< totalRunTime / Movies.getNumber() << endl;
cout << "There are " << totalCheckedIn << " movies checked in " << endl;
cout << "There are " << totalCheckedOut << " movies checked out" << endl;
totalCheckedIn1 = totalCheckedIn;
}
//****************************************************************************************************
void findMovies(List<Movie> Movies)
{
while (true)
{
cout << "Enter the MPAC of a movie to locate:";
int input;
cin >> input;
if (input == 0)
break;
Movie m;
m.MPAC = input;
if (Movies.getMember(m))
{
cout << setw(7) << left << "MPAC"
<< setw(25) << left << "Title"
<< setw(7) << left << "Year"
<< setw(10) << left << "RunTime"
<< setw(7) << left << "In"
<< setw(7) << left << "Out" << endl;
cout << "-------------------------------------------------------------------------------" << endl;
cout << m << endl;
}
else
{
cout << "That movie is not in the store" << endl;
}
}
}
this is "list.h"
#ifndef LIST_H
#define LIST_H
#include <iostream>
//********************************************************************************
template <typename T>
class List
{
public:
List();
List(int size);
List(const List &obj);
~List();
void insert(T);
T getNext(); // Returns the next element in the array.
bool getMember(T&); // Returns true if we can find the member, false otherwise.
int getNumber(); // Returns the number of items in the list.
private:
T *pList;
int numberInList; // Number of elements in the list.
int listSize; // Size of the list.
int nextIndex; // Index that points to the next element in the array.
};
//********************************************************************************
// Default Constructor
template <typename T>
List<T>::List()
{
numberInList = 0;
listSize = 100;
nextIndex = 0;
pList = new T[listSize];
}
//********************************************************************************
// Overloaded Constructor
template <typename T>
List<T>::List(int size)
{
numberInList = 0;
listSize = size;
nextIndex = 0;
pList = new T[listSize];
}
//********************************************************************************
// Copy Constructor
template <typename T>
List<T>::List(const List &obj)
{
numberInList = obj.numberInList;
listSize = obj.listSize;
nextIndex = obj.nextIndex;
pList = new T[listSize];
for (int i = 0; i < listSize; i++)
{
pList[i] = obj.pList[i];
}
}
//********************************************************************************
// Destructor
template <typename T>
List<T>::~List()
{
delete[]pList;
}
//********************************************************************************
template <typename T>
void List<T>::insert(T item)
{
int temp = numberInList++;
pList[temp] = item;
}
//********************************************************************************
template <typename T>
T List<T>::getNext()
{
return pList[nextIndex++];
}
//********************************************************************************
template <typename T>
bool List<T>::getMember(T& item)
{
for (int i = 0; i < numberInList; ++i)
{
if (item == pList[i])
{
item = pList[i];
return true;
}
}
return false;
}
//********************************************************************************
template <typename T>
int List<T>::getNumber()
{
return numberInList;
}
#endif
Problem i have is that setInventory function needs to update the checkedIn member of each list element using the formula (CheckedIn + CheckedOut) * ( f /100.0). Can someone guide me how can i update individual element using this function.help i got said" In order to update each element of the List, you need modify the template to include a setItem function that sets the associated element in the List object to the item that is passed to the setItem function. HINT: This function should only contain one C++ statement."
if someone can guide me syntax of how i can update individual elements.
this is something i wrote for setInventory()
void setInventory(List<Movie> WebsterMovies , double f)
{
Movie m = WebsterMovies.getNext();
cout << m << endl;
cout << "Check again" << endl << endl;
int size = WebsterMovies.getNumber();
int increment = 0;
for (int i = 0 ; i < size; ++i)
{
cout << m << endl;
increment = trunc(((m.checkedIn + m.checkedOut) * f )/ 100);
m.checkedIn = m.checkedIn + increment;
cout << "updated checkin is : " << m.checkedIn << endl;
WebsterMovies.setItem(m);
Movie m = WebsterMovies.getNext();
}
}
this is setItem i wrote
template <typename T>
void List<T>::setItem(T item)
{
pList[numberInList] = item;
}
p.s beginner here so sorry for bad English or any other mistake.
To update an element in a container, such as std::list, you need to find the element, then update the fields.
An example:
std::list<Movie> database;
// Search by title
std::list<Movie>::iterator iter;
const std::list<Movie>::iterator end_iter = database.end();
for (iter = database.begin();
iter != end_iter;
++iter)
{
if (iter->title == search_title)
{
Update_Movie(*iter);
}
}

Errors within Main program using classes

I just have a few errors of the same type in my main program. My college professor is not answering my emails so I have to resort to asking you guys. In my main program I have several errors somewhat similar to this: "request for member which is of non-class type." Program01 is basically testing every function in ListType.h, OListType.h, and UListType.h to make sure everything works correctly. Any help you can provide in a timely fashion will be appreciated.
Here is ListType.h:
#ifndef LISTTYPE_H_INCLUDED
#define LISTTYPE_H_INCLUDED
#include <iostream>
class ListType {
public:
ListType(size_t=10);
ListType(const ListType&);
virtual ~ListType();
virtual bool insert(int)=0;
virtual bool eraseAll();
virtual bool erase(int)=0;
virtual bool find(int) const=0;
size_t size() const;
bool empty() const;
bool full() const;
friend std::ostream& operator << (std::ostream&, const ListType&);
const ListType& operator= (const ListType&);
protected:
int *items;
size_t capacity;
size_t count;
};
#endif // LISTTYPE_H_INCLUDED
Here is ListType.cpp:
#include "ListType.h"
ListType::ListType (size_t a) {
capacity = a;
count = 0;
items = new int [capacity];
}
ListType::ListType(const ListType& newlist) {
capacity = newlist.capacity;
count = newlist.count;
items = new int [capacity];
for (size_t i = 0; i < count; ++i)
items[i] = newlist.items[i];
}
ListType::~ListType() {
delete [] items;
}
bool ListType::eraseAll() {
count = 0;
return 0;
}
size_t ListType::size() const {
return (count);
}
bool ListType::empty() const {
return (count == 0);
}
bool ListType::full() const {
return (count == capacity);
}
std::ostream& operator << (std::ostream& out, const ListType& my_list) {
if (!my_list.empty()) {
for (size_t i = 0; i < my_list.count; ++i){
out << my_list.items[i] << ',';
}
}
return out;
}
const ListType& ListType::operator= (const ListType& rightObject) {
if (this != & rightObject) {
delete [] items;
capacity = rightObject.capacity;
count = rightObject.count;
items = new int[capacity];
for (size_t i = 0; i < count; ++i) {
items[i] = rightObject.items[i];
}
}
return *this;
}
Here is UListType.h:
#ifndef ULISTTYPE_H_INCLUDED
#define ULISTTYPE_H_INCLUDED
#include <iostream>
class UListType: public ListType {
public:
UListType(size_t=10);
bool insert(int);
bool erase(int);
bool find(int) const;
};
#endif // ULISTTYPE_H_INCLUDED
Here is UListType.cpp:
#include "ListType.h"
#include "UListType.h"
UListType::UListType (size_t c): ListType(c) {}
bool UListType::insert(int item) {
if (full()) {
int *newitems;
capacity *=2;
newitems = new int[capacity];
for (size_t i =0; i < count; ++i){
newitems[i] = items[i];
}
delete [] items;
items = newitems;
}
items[count++] = item;
return true;
}
bool UListType::erase(int item) {
bool result = false;
size_t i=0;
while ( i < count && items [i] != item) {
++i;
}
if (i < count) {
items[i] = items[-- count];
result = true;
}
return result;
}
bool UListType::find(int item) const {
size_t i = 0;
while (i < count && items [i] != item) {
++i;
}
return i < count;
}
Here is OListType.h:
#ifndef OLISTTYPE_H_INCLUDED
#define OLISTTYPE_H_INCLUDED
#include <iostream>
class OListType: public ListType {
public:
OListType(size_t=10);
bool insert(int);
bool erase(int);
bool find(int) const;
};
#endif // OLISTTYPE_H_INCLUDED
Here is OListType.cpp:
#include "ListType.h"
#include "OListType.h"
OListType::OListType(size_t c): ListType(c) {}
bool OListType::insert(int item) {
size_t i = count;
if (full()) {
int *newitems;
capacity *=2;
newitems = new int[capacity];
for(size_t j=0; j < count; ++j) {
newitems[j] = items[i];
}
delete [] items;
items = newitems;
}
while (i > 0 && items[i-1] > item){
items[count++] = item;
}
return true;
}
bool OListType::erase(int item) {
bool found=false;
size_t i=0, j= count-1, mid;
while (i <= j && !(found)){
mid = (i + j)/2;
if (item < items [mid])
j = mid - 1;
else if (item > items [mid])
i = mid + 1;
found = items [mid] == item;
}
if (found) {
for (i = mid; i < count - 1; ++i) {
items [i] = items [i +1];
}
--count;
}
return found;
}
bool OListType::find (int item) const {
bool found=false;
size_t i=0, j= count-1, mid;
while (i <= j && !(found)){
mid = (i + j)/2;
if (item < items [mid])
j = mid - 1;
else if (item > items [mid])
i = mid + 1;
found = items [mid] == item;
}
return found;
}
Here is Program01.cpp:
#include "ListType.h"
#include "UListType.h"
#include "OListType.h"
#include <iostream>
using namespace std;
int main() {
OListType list[5] = {165, 16, 118, 212, 104};
UListType ranlist[10] = {243, 300, 154, 153, 592, 124, 195, 217, 289, 405};
UListType UListAssignmentTest;
OListType OListAssignmentTest;
cout << "The Ordered List before operations:" << endl;
cout << list << endl << endl;
if(list.empty()) **<-- HERE BE THE ERROR**
cout << "The list is empty, therefore it is true.";
else
cout << "The list is full or partially full, therefore it is false";
cout << endl << endl;
if(list.full())
cout << "The list is full, therefore it is true.";
else
cout << "The list is partially full or empty, therefore it is false";
cout << endl << endl;
list.insert(25);
cout << endl << endl;
cout << "The Ordered list after Insert:" << endl;
cout << list << endl << endl;
list.find(25);
cout << endl << endl;
list.find(30);
cout << endl << endl;
list.erase(25);
cout << endl << endl;
cout << "The Ordered List after Erase:" << endl;
cout << list << endl << endl;
cout << "The Unordered List before operations:" << endl;
cout << ranlist << endl << endl;
if(ranlist.empty())
cout << "The list is empty, therefore it is true.";
else
cout << "The list is full or partially full, therefore it is false";
cout << endl << endl;
if(ranlist.full())
cout << "The list is full, therefore it is true.";
else
cout << "The list is partially full or empty, therefore it is false";
cout << endl << endl;
ranlist.insert(25);
cout << endl << endl;
cout << "The Unordered List after Insert:" << endl;
cout << ranlist << endl << endl;
ranlist.find(25);
cout << endl << endl;
ranlist.find(30);
cout << endl << endl;
ranlist.erase(25);
cout << endl << endl;
cout << "The Unordered List after Erase:" << endl;
cout << ranlist << endl << endl;
cout << "Testing Ordered List Assignment Operator" << endl;
OListAssignmentTest = list;
cout << OListAssignmentTest << endl << endl;
cout << "Testing Unordered List Assignment Operator" << endl;
UListAssignmentTest = ranlist;
cout << UListAssignmentTest << endl << endl
cout << "Testing Ordered List Copy Constructor" << endl;
OListType OListVariable = list;
cout << OListVariable << endl << endl;
cout << "Testing Unordered List Copy Constructor" << endl;
UListType UListVariable = ranlist;
cout << UListVariable << endl << endl;
cout << "Testing Erase All for OList" << endl;
list.eraseAll();
cout << "OList values now: " << list.empty() << endl << endl;
cout << "Testing Erase All for UList" << endl;
ranlist.eraseAll();
cout << endl << "UList values now: " << ranlist.empty() << endl;
return 0;
}
OListType list[5] = {165, 16, 118, 212, 104};
This line declares an array of 5 OListType types. This doesn't seem correct.
You want to declare one OLIstType and insert 5 values into it. If not, please clarify what that line is supposed to denote.
Here is probably what you are supposed to do:
OListType list;
list.insert(165);
list.insert(16); // etc...

C++ Heap Corruption in Template array

As the title already says, I have a problem with a heap corruption in my C++ code.
I know there are a lot of topics that cover heap corruption problems, and I have visited a lot of them, I read up on a lot of sites about these matters and I've even used Visual Leak Detector to find the location of the memory leak. I still can't seem to figure out why I have a heap corruption.
My code:
#include <iostream>
#include "stdafx.h"
#include "cstdlib"
#include <vld.h>
#include <math.h>
using namespace std;
template <class T>
class PrioQueue
{
private:
int size_;
int tempIndex;
public:
T *bottom_;
T *top_;
PrioQueue(int n =20){
size_ = n;
bottom_ = new T[size_];
top_ = bottom_;
}
void push(T c){
//add the item to the list
*top_ = c;
top_++;
//Save the old stack values in the temp memory
T* values = bottom_;
T tempItem;
int index = num_items();
cout << "Num items: " << index << endl;
cout << "1" << endl;
while(index > 1){
cout << "2" << endl;
if(values[index-1] > values[index-2])
{
cout << "2b" << endl;
tempItem = values[index-2];
values[index-2] = c;
values[index-1] = tempItem;
}
cout << "3" << endl;
index--;
}
cout << "4" << endl;
}
// + operator
PrioQueue* operator+ (PrioQueue que2)
{
PrioQueue<T>* temp = new PrioQueue<T>();
cout << "Created temporary queue" << endl;
for(int i = 0; i <num_items(); i++)
{
cout << "Element in list: " << bottom_[i] << endl;
temp->push(bottom_[i]);
cout << "Temp is now: ";
temp->print();
}
for(int i = 0; i < que2.num_items(); i++)
{
cout << "Element in list: " << que2.bottom_[i] << endl;
temp->push(que2.bottom_[i]);
cout << "Temp is now: ";
temp->print();
}
cout << "Ran loop" << endl;
return temp;
}
// * operator
PrioQueue* operator* (PrioQueue que2)
{
PrioQueue<T>* temp = new PrioQueue<T>();
for(int i = 0; i < num_items(); i++)
{
for(int j = 0; j < que2.num_items(); j++)
{
if(bottom_[i] == que2.bottom_[j])
{
temp->push(bottom_[i]);
break;
}
}
}
return temp;
}
friend ostream& operator<< (ostream& output, PrioQueue& q) {
for(T *element = q.bottom_; element < q.top_; element++)
output << *element << " | ";
return output;
}
int num_items() {
return (top_ - bottom_ );
}
T pop(){
top_--;
return *top_;
}
int full() {
return (num_items() >= size_);
}
int empty() {
return (num_items() <= 0);
}
void print(){
cout << "Print function..." << endl;
cout << "Stack currently holds " << num_items() << " items: " ;
for (T *element=bottom_; element<top_; element++) {
cout << " " << *element;
}
cout << "\n";
}
~PrioQueue(){ // stacks when exiting functions
delete [] bottom_;
}
};
int main()
{
PrioQueue<int> *p1 = new PrioQueue<int>(20);
p1->push(5);
p1->push(2);
p1->push(8);
p1->push(4);
p1->print(); cout << "\n";
PrioQueue<int> *p2 = new PrioQueue<int>(5);
p2->push(33);
p2->push(66);
p2->push(8);
p2->push(5);
p2->print(); cout << "\n";
//add them together
p1->print();
p2->print();
((*p1) + (*p2))->print();
((*p1) * (*p2))->print();
PrioQueue<float> *f1 = new PrioQueue<float>(5);
f1->push(1.1f);
f1->push(5.2f);
f1->push(8.3f);
f1->push(14.4f);
f1->push(17.5f);
f1->print(); cout << "\n";
PrioQueue<float> *f2 = new PrioQueue<float>(4);
f2->push(2.2f);
f2->push(6.7f);
f2->push(10.3f);
f2->push(15.6f);
f2->print();
cout << "\n";
//add them together
((*f1) + (*f2))->print();
// Multiply them.
((*f1) * (*f2))->print();
cout << "\n";
cout << p1 << endl;
cout << f1 << endl;
cout << "Press any key to exit...";
cin.get();
cin.get();
delete p1;
delete p2;
delete f1;
delete f2;
return 0;
}
I already tried removing everything and start at the beginning.
It seemed that changing:
delete [] bottom_;
To:
delete bottom_;
Fixed it, but that was before I pushed a value to the array.
Could some of you please enlighten me on what is wrong. It would be very much appreciated.
Thank you in advance,
Greatings Matti Groot.
The change you mention leads to undefined behavior. If you got something with new[] you must pass it to delete[]. Plain delete is only good for what you got with plain new.
Your operator + and * creates new objects and return pointer to it. I don't see any attempt to delete those objects, so no wonder you have leaks. (It counts as bad design to return pointers-with-obligation for no good reason, even more so from operators on objects that should produce objects.)
1. Stop using new everywhere.
If you want a new Object to work with, create one on the stack.
PrioQueue *p1 = new PrioQueue(20); // NO!
PrioQueue q1(20); // YES!
2. Consider to use unsigned values where usigned values are appropriate.
3. In your operator+() you'll have to set the size of the new temporary Queue appropriately.
4. See Blastfurnace's answer regarding resource managment and operator design.
5. Try to find out what resource acquisition is initialization (RAII) is and use this knowledge.
I addressed some of your issues
template <class T>
class PrioQueue
{
private:
size_t size_;
T *bottom_;
T *top_;
public:
PrioQueue (void)
: size_(20U), bottom_(new T[20U]), top_(bottom_)
{
}
PrioQueue(size_t n)
: size_(n), bottom_(new T[n]), top_(bottom_)
{
}
PrioQueue(PrioQueue<T> const & rhs)
: size_(rhs.size_), bottom_(new T[rhs.size_]), top_(bottom_)
{
for (size_t i=0; i<size_; ++i)
{
bottom_[i] = rhs.bottom_[i];
}
}
PrioQueue<T> & operator= (PrioQueue<T> rhs)
{
swap(rhs);
}
void push (T c)
{
// check if its full
if (full()) throw std::logic_error("full");
//add the item to the list
*top_ = c;
top_++;
// there is no point operating on a new pointer named "values" here
// your still addressing the same memory, so you can just operate on bottom_ instead
for (size_t index = num_items()-1; index > 0; --index)
{
if(bottom_[index] > bottom_[index-1])
{
std::swap(bottom_[index], bottom_[index-1]);
}
}
}
// + operator
PrioQueue<T> operator+ (PrioQueue<T> const & que2)
{
// you need a temporary queue that is large enough
// so give it the proper size (sum of both sizes)
PrioQueue<T> temp(num_items() + que2.num_items());
std::cout << "Created temporary queue" << std::endl;
for(size_t i = 0; i <num_items(); i++)
{
std::cout << "Element in list: " << bottom_[i] << std::endl;
temp.push(bottom_[i]);
std::cout << "Temp is now: ";
temp.print();
}
for(size_t i = 0; i < que2.num_items(); i++)
{
std::cout << "Element in list: " << que2.bottom_[i] << std::endl;
temp.push(que2.bottom_[i]);
std::cout << "Temp is now: ";
temp.print();
}
std::cout << "Ran loop" << std::endl;
return temp;
}
// * operator
PrioQueue<T> operator* (PrioQueue<T> const & que2)
{
size_t que1_items = num_items(), que2_items = que2.num_items();
PrioQueue<T> temp(que1_items);
for (size_t i = 0U; i < que1_items; ++i)
{
for(size_t j = 0U; j < que2_items; ++j)
{
if(bottom_[i] == que2.bottom_[j])
{
temp.push(bottom_[i]);
}
}
}
return temp;
}
friend std::ostream& operator<< (std::ostream& output, PrioQueue<T> & q)
{
for(T *element = q.bottom_; element < q.top_; element++)
output << *element << " | ";
return output;
}
size_t num_items(void) const
{
return size_t(top_ - bottom_ );
}
T pop (void)
{
// you actually popped of the last element and returned the next
// i think it is likely you want to return the element you pop off
return *(top_--);
}
// why int? full or not is a rather boolean thing i guess
bool full (void) const
{
// num_items() > size_ must not happen!
return (num_items() == size_);
}
bool empty(void) const
{
// an unsigned type cannot be < 0
return (num_items() == 0);
}
void swap (PrioQueue<T> & rhs)
{
std::swap(size_, rhs.size_);
std::swap(bottom_, rhs.bottom_);
std::swap(top_, rhs.top_);
}
void print (void) const
{
cout << "Print function..." << endl;
cout << "Stack currently holds " << num_items() << " items: " ;
for (T * element=bottom_; element<top_; ++element)
{
cout << " " << *element;
}
cout << endl;
}
~PrioQueue()
{
delete [] bottom_;
}
};
int main()
{
PrioQueue<int> q1;
q1.push(5);
q1.push(2);
q1.push(8);
q1.push(4);
q1.print();
PrioQueue<int> q2;
q2.push(33);
q2.push(66);
q2.push(8);
q2.push(5);
q2.print();
std::cout << "Plus: " << std::endl;
PrioQueue<int> q_plus = q1+q2;
q_plus.print();
std::cout << "Multi: " << std::endl;
PrioQueue<int> q_multi = q1*q2;
q_multi.print();
}
Your class manages a resource (memory) but you don't correctly
handle copying or assignment. Please see: What is The Rule of
Three?.
The design of your operator+() and operator*() is unusual and
leaks memory. Returning PrioQueue* makes it cumbersome or
impossible to properly free temporary objects. Please see: Operator
overloading
You might be interested in The Definitive C++ Book Guide and List to learn the language basics and some good practices.
I suggest you try re-writing this without using new or delete. Change your * and + operators to return a PrioQueue. Change the PrioQueue to use a vector<T> instead of an array. You can then focus on writing your own priority queue. Make sure you use the standard priority queue if you actually need one though.
((*p1) + (*p2))->print();
and statements like these .. Your + & * operator returns a new'ed PrioQueue . So you are not deleting it anywhere .
So try to take return value in a temp PrioQueue pointer and call delete on it as well .