Error C2440: 'initializing': cannot convert from 'CTable' to 'CTable' - c++

Honestly, I have no idea why CTable cannot convert to CTable? I'm trying to make overload operator + which returns concatenated two tables.
Error C2440 'initializing': cannot convert from 'CTable' to 'CTable'
Second error: Error (active) E0334 class "CTable" has no suitable copy constructor
#include <iostream>
#include <string>
#include "CTable.h"
int main() {
CTable c_tab_1, c_tab_0;
c_tab_0.vSetValueAt(0, 1);
c_tab_0.vPrint();
c_tab_0.bSetNewSize(4);
c_tab_0.vPrint();
c_tab_1.bSetNewSize(4);
c_tab_0.vSetValueAt(0, 1);
c_tab_0.vSetValueAt(1, 2);
c_tab_0.vSetValueAt(2, 3);
c_tab_0.vSetValueAt(3, 4);
c_tab_0.vPrint();
c_tab_1.vSetValueAt(0, 2);
c_tab_1.vSetValueAt(1, 3);
c_tab_1.vSetValueAt(2, 4);
c_tab_1.vSetValueAt(3, 5);
c_tab_1.vPrint();
c_tab_1.vSetValueAt(2, 123);
c_tab_0.vPrint();
c_tab_1.vPrint();
CTable c_tab_3 = c_tab_0 + c_tab_1; //Error C2440! <-----------------------
c_tab_3.vPrint();
return 0;
}
#include <iostream>
#include <string>
using namespace std;
class CTable {
public:
CTable();
CTable(CTable& pcOther);
CTable* pcClone();
~CTable();
bool bSetNewSize(int iTableLen);
void vSetValueAt(int iOffset, int iNewVal);
void vPrint();
CTable operator+(const CTable& pcNewTable);
private:
string s_name;
int i_size;
int* piTable;
const int SIZE = 10;
const string NAME = "Name";
};
#include <iostream>
#include <string>
#include "CTable.h"
using namespace std;
CTable::CTable() {
s_name = NAME;
cout << "bezp: " << s_name << endl;
piTable = new int[SIZE];
i_size = SIZE;
}
///
CTable::CTable(CTable& pcOther) {
s_name = pcOther.s_name + "_copy";
piTable = new int[pcOther.i_size];
i_size = pcOther.i_size;
for (int i = 0; i < pcOther.i_size; i++) {
piTable[i] = pcOther.piTable[i];
}
cout << "kopiuj: " << s_name << endl;
}
CTable::~CTable() {
delete[] piTable;
cout << "usuwam " << s_name << endl;
}
////
bool CTable::bSetNewSize(int iTableLen) {
if (iTableLen <= 0) {
return false;
}
int* pi_newTable = new int[iTableLen];
memcpy(pi_newTable, piTable, iTableLen);
delete this->piTable;
this->i_size = iTableLen;
this->piTable = pi_newTable;
return true;
}
///
void CTable::vSetValueAt(int iOffset, int iNewVal) {
if (iOffset >= this->i_size) {
return;
}
piTable[iOffset] = iNewVal;
}
void CTable::vPrint() {
for (int i = 0; i < i_size; i++) {
cout << piTable[i] << " ";
}
cout << endl;
}
CTable CTable::operator+(const CTable& pcNewTable) {
CTable result;
int greater_len = i_size < pcNewTable.i_size;
int smaller_len = i_size > pcNewTable.i_size;
int* greater_table = i_size > pcNewTable.i_size ? piTable : pcNewTable.piTable;
int* smaller_table = i_size <= pcNewTable.i_size ? piTable : pcNewTable.piTable;
result.i_size = greater_len;
result.piTable = new int[greater_len];
memcpy(result.piTable, greater_table, greater_len * sizeof(int));
for (int i = 0; i < smaller_len; i++) {
result.piTable[i] += smaller_table[i];
}
return result;
}
What should I correct?

Try to define
CTable(const CTable& pcOther)
{
.......
}

Related

Assigment and adding operator overloading (concatenation of 2 tables and int)

I'm trying to concatenate two arrays and at the end concatenate int, for example: result = arg + arg + 2;
I'm getting "read access violation" at + operator overloading.
I wrote the error and warning in comments below.
My code:
Main:
#include <iostream>
#include <string>
#include "CTable.h"
int main() {
CTable c_tab1, c_tab0;
c_tab0.SetNewSize(3);
c_tab1.SetNewSize(2);
c_tab0.SetValueAt(0, 22);
c_tab0.SetValueAt(1, 23);
c_tab0.SetValueAt(2, 24);
c_tab0.Print();
c_tab1.SetValueAt(0, 31);
c_tab1.SetValueAt(1, 32);
c_tab1.Print();
CTable c_tab3 = (c_tab0 + c_tab1 + 111);
c_tab3.Print();
return 0;
}
Class CTable:
#include <iostream>
#include <string>
using namespace std;
class CTable {
public:
CTable();
CTable(string sName, int iTableLen);
CTable(const CTable& pcOther);
CTable* pcClone();
~CTable();
void ShowName();
void ShowSize();
void SetName(string sName);
bool SetNewSize(int iTableLen);
void SetValueAt(int iOffset, int iNewVal);
void Print();
CTable& operator+(const CTable& pcNewTable);
CTable operator+(int iNewVal) const;
CTable& operator=(const CTable& pcNewVal) {
if (this != &pcNewVal) {
for (int i = 0; i < i_size; i++) {
this->piTable[i] = pcNewVal.piTable[i];
}
}
return *this;
}
private:
string s_name;
int i_size;
int* piTable;
const int SIZE = 10;
const string NAME = "Name";
};
#include <iostream>
#include <string>
#include "CTable.h"
#include <algorithm>
using namespace std;
CTable::CTable() {
s_name = NAME;
cout << "bezp: " << s_name << endl;
piTable = new int[SIZE];
i_size = SIZE;
}
CTable::CTable(string sName, int iTableLen) {
s_name = sName;
cout << "parametr: " << sName << endl;
piTable = new int[iTableLen];
i_size = iTableLen;
}
CTable::CTable(const CTable& pcOther) {
s_name = pcOther.s_name + "copied";
piTable = new int[pcOther.i_size];
i_size = pcOther.i_size;
for (int i = 0; i < pcOther.i_size; i++) {
piTable[i] = pcOther.piTable[i];
}
}
CTable::~CTable() {
delete[] piTable;
}
void CTable::SetName(string sName) {
s_name = sName;
}
bool CTable::SetNewSize(int iTableLen) {
if (iTableLen <= 0) {
cout << "Length has to be greater than 0" << endl;
return false;
}
int* pi_newTable = new int[iTableLen];
for (int i = 0; i < iTableLen; i++) {
pi_newTable[i] = piTable[i];
}
delete this->piTable;
this->i_size = iTableLen;
this->piTable = pi_newTable;
return true;
}
CTable* CTable::pcClone() {
CTable* ct = new CTable(s_name, i_size);
return ct;
}
void CTable::ShowName() {
cout << "Name: " << s_name << endl;
}
void CTable::ShowSize() {
cout << "Size: " << i_size << endl;
}
void CTable::SetValueAt(int iOffset, int iNewVal) {
if (iOffset >= this->i_size) {
return;
}
piTable[iOffset] = iNewVal;
}
void CTable::Print() {
for (int i = 0; i < i_size; i++) {
cout << piTable[i] << " ";
}
cout << endl;
}
CTable& CTable::operator+(const CTable& pcNewTable) {
CTable result("new_int", this->i_size);
result.i_size = (i_size + pcNewTable.i_size);
result.piTable = new int[i_size + pcNewTable.i_size];
for (int i = 0; i < i_size; i++) {
result.piTable[i] = piTable[i];
}
for (int i = 0; i < (pcNewTable.i_size); i++) {
result.piTable[i+i_size] = pcNewTable.piTable[i];
}
return result; //Warning C4172 returning address of local variable or temporary: result
}
CTable CTable::operator+(int iNewVal) const {
CTable result("new_int", this->i_size);
result.i_size = (i_size + 1);
result.piTable = new int[i_size + 1];
for (int i = 0; i < i_size; i++) {
result.piTable[i] = piTable[i]; //Exception thrown: read access violation. **this->piTable** was 0x1110122.
}
result.piTable[i_size + 1] = iNewVal;
return result;
}
What should I correct? I'm not sure about assigment operator overload, is it okay?
The member function SetNewSize has undefined behavior. In this loop
int* pi_newTable = new int[iTableLen];
for (int i = 0; i < iTableLen; i++) {
pi_newTable[i] = piTable[i];
}
it 1) uses uninitialized values because the array was not initialized and 2) iTableLen can be gretaer than the current value of i_size. You should at least zero initialize the array in constructors.
The copy assignment operator aslo has undefined behabior because the number of elements of the array of the object pcNewVal can be less than the number of elements of the array in the assigned object.
The first overloaded operator + also have undefined behavior. For starters as the warning says the operator returns reference to the local object result that will not be alive after exiting the operator. Secondly, there is a memory leak necause the array of the object is allocated anew and the previuous allocated memory in the constructor is not freed.
CTable result("new_int", this->i_size);
result.i_size = (i_size + pcNewTable.i_size);
result.piTable = new int[i_size + pcNewTable.i_size];
//...
The second overloaded operator + also has undefined behavior. As in the previous operator there is a memory leak.
In this statement
result.piTable[i_size + 1] = iNewVal;
there is an access memory outside the allocated array. There should be
result.piTable[i_size] = iNewVal;

Segmentation fault after everything executes-dynamic memory allocation: c++

I am fairly new to dynamic memory allocation and am having trouble. I'm thinking the problem is within my allocation function but I could be wrong. Here is the MyString.cpp file.
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "MyString.h"
using namespace std;
MyString::MyString()
{
m_size = 0;
buffer_allocate(0);
}
MyString::MyString(const char * str)
{
m_size = strlen(str);
buffer_allocate(m_size);
for(int i = 0; i < m_size; i++)
{
m_buffer[i] = str[i];
}
}
MyString::MyString(const MyString & other_myStr)
{
m_size = other_myStr.size();
buffer_allocate(other_myStr.size());
for(int i = 0; i < other_myStr.size(); i++)
{
m_buffer[i] = other_myStr.c_str()[i];
}
}
void MyString::buffer_deallocate()
{
delete[] m_buffer;
m_size = 0;
}
void MyString::buffer_allocate(size_t size)
{
try
{
m_buffer = new char[size];
}
catch(bad_alloc& ex)
{
delete[] m_buffer;
}
}
MyString::~MyString()
{
buffer_deallocate();
}
size_t MyString::size() const
{
return m_size;
}
size_t MyString::length() const
{
return m_size - 1;
}
const char* MyString::c_str() const
{
char * arr = (char*) malloc(m_size + 1);
int i;
for(i = 0; i < m_size; i++)
{
arr[i] = m_buffer[i];
}
arr[i] = '\0';
return arr;
}
bool MyString::operator== (const MyString & other_myStr) const
{
for(int i = 0; (i < m_size) && (i < other_myStr.size()); i++)
{
if(m_buffer[i] != other_myStr.c_str()[i])
{
return false;
}
}
if(m_size != other_myStr.size())
{
return false;
}
return true;
}
MyString & MyString::operator= (const MyString & other_myStr)
{
buffer_deallocate();
buffer_allocate(other_myStr.size());
for(int i = 0; i < other_myStr.size(); i++)
{
m_buffer[i] = other_myStr.c_str()[i];
}
return *this;
}
MyString MyString::operator+ (const MyString & other_myStr) const
{
int length = this->size() + other_myStr.size();
char * temp = (char*)malloc(length);
int j = 0;
for(int i = 0; i < length; i++)
{
if(i < this->size())
{
temp[i] = m_buffer[i];
}
else
{
temp[i] = other_myStr.c_str()[j];
j++;
}
}
MyString rhs = MyString(temp);
return rhs;
}
char & MyString::operator[] (size_t index)
{
return m_buffer[index];
}
const char & MyString::operator[] (size_t index) const
{
return m_buffer[index];
}
std::ostream & operator<<(std::ostream & os, const MyString & myStr)
{
for(int i = 0; i < myStr.size(); i++)
{
os << myStr[i];
}
os << endl;
}
Like I said, the segmentation fault is happening after the entire program is being executed so my guess is that there is some memory leak issue. I appreciate the help in advance.
And here is the main function:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "MyString.h"
using namespace std;
int main(void)
{
MyString dft;
if(dft.size() == 0)
{
cout << "Successful Default c-tor" << endl;
}
MyString param("Successful Parameter c-tor");
MyString copy(dft);
cout << param;
MyString ms_size_length("Size and length test:");
cout << ms_size_length;
cout << "Size of MyString: " << ms_size_length.size() << endl;
cout << "Length of MyString: " << ms_size_length.length() << endl;
MyString ms_toCstring("C-String equivalent successfully obtained!");
cout << ms_toCstring.c_str() << endl;
MyString ms_same1("The same"), ms_same2("The same");
if (ms_same1==ms_same2)
{
cout << "Same success" << endl;
}
MyString ms_different("The same (NOT)");
if (!(ms_same1==ms_different))
{
cout << "Different success" << endl;
}
MyString ms_assign("Before assignment");
ms_assign = MyString("After performing assignment");
MyString ms_append1("The first part");
MyString ms_append2(" and the second");
MyString ms_concat = ms_append1 + ms_append2;
cout << ms_concat;
MyString ms_access("Access successful (NOT)");
ms_access[17] = 0;
cout << ms_access;
}
One problem that I noticed is:
m_size = strlen(str);
buffer_allocate(m_size);
That allocates one less than the number of characters you need. As a consequence, you end up not copying the terminating null character to the object's m_buffer.
I suggest changing the constructor to:
MyString::MyString(const char * str)
{
m_size = strlen(str)+1;
buffer_allocate(m_size);
strcpy(m_buffer, str);
}
PS I did not look for other problems in your code. There may be more, or none.

C++ none of the 3 overloads could convert all the argument types line 39 1

So after coding this I got an error : C++ none of the 3 overloads could convert all the argument types line 39 1 in w5.cpp
do you know where is the problem? and could you help me to fix it? I actually dont know why it is showing this because I got the default constructor for this code.
//w5.h
#define MAX_LINE_LENGTH 256
#define MAX_PURCHASES 5
// w5.cpp
#include <iostream>
#include <cstring>
#include "w5.h"
#include "CreditStatement.h"
using namespace std;
void sort(CreditStatement* statement, int n);
int main()
{
double price;
int n = 0;
CreditStatement statement[MAX_PURCHASES];
cout << "Credit Statement Processor\n";
cout << "==========================\n";
do
{
cout << "Item price (0 to quit): ";
cin >> price;
if (cin.fail() || (cin.get() != '\n'))
{
cin.ignore(2000, '\n');
cerr << "Bad character. Try again." << endl;
cin.clear();
}
else if ((int)price != 0)
{
cout << "Statement item: ";
char item[MAX_LINE_LENGTH];
cin.getline(item, MAX_LINE_LENGTH);
if (strlen(item) > 0)
{
statement[n] = CreditStatement(item, price);
n++;
}
}
} while ((int)price != 0 && n < MAX_PURCHASES);
cout << endl;
sort(statement, n);
cout << " Credit Statement\n\n";
cout << " Item Price\n";
cout << "----------------------------------\n";
for (int i = 0; i < n; i++)
{
statement[i].display();
}
cout << endl;
return 0;
}
// sort sorts the elements of Credit Card Statement[n] in ascending order
//
void sort(CreditStatement* s, int n)
{
int i, j;
CreditStatement temp;
for (i = n - 1; i > 0; i--)
{
for (j = 0; j < i; j++)
{
if (s[j].isGreaterThan(s[j + 1]))
{
temp = s[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
}
//CreditStatement.h
class CreditStatement{
bool _valid;
double* _price;
char* _item;
public:
CreditStatement();
CreditStatement(char*, double*);
CreditStatement(const CreditStatement&);
CreditStatement& operator=(const CreditStatement&);
//output
void display() const;
//mutators
bool isGreaterThan(const CreditStatement&) const;
};
//CreditStatement.cpp
#include <iostream>
#include <new>
#include "CreditStatement.h"
using namespace std;
void CreditStatement::display() const{
cout << " Something" << _price << _item;
}
bool CreditStatement::isGreaterThan(const CreditStatement&) const{
return _valid;
}
CreditStatement::CreditStatement(){
_item = NULL;
_price = NULL;
}
CreditStatement::CreditStatement(char* iP, double* pP){
_price = NULL;
_item = NULL;
if (pP != NULL){
int sizepP = sizeof(pP) / sizeof(pP[0]);
_price = new (nothrow) double[sizepP];
if (_price){
for (int i = 0; i <sizepP; i++){
_price[i] = pP[i];
};
}
if (iP != NULL){
int sizeiP = sizeof(iP) / sizeof(iP[0]);
_item = new (nothrow) char [sizeiP];
if (_item){
for (int i = 0; i < sizeiP; i++){
_item[i] = iP[i];
};
}
}
}
}
CreditStatement::CreditStatement(const CreditStatement& otherCS){
*this = CreditStatement(otherCS._item, otherCS._price);
}
CreditStatement& CreditStatement::operator=(const CreditStatement& otherCS){
if (this != &otherCS)
{
if (_item){
delete[] _item;
_item = NULL;
}
if (_price){
delete[] _price;
_price = NULL;
}
else{
if (otherCS._price != NULL){
int sizepP = sizeof(otherCS._price) / sizeof(otherCS._price[0]);
_price = new (nothrow) double[sizepP];
if (_price){
for (int i = 0; i < sizepP; i++){
_price[i] = otherCS._price[i];
};
}
if (otherCS._item != NULL){
int sizeiP = sizeof(otherCS._item) / sizeof(otherCS._item[0]);
_item = new (nothrow) char[sizeiP];
if (_item){
for (int i = 0; i < sizeiP; i++){
_item[i] = otherCS._item[i];
};
}
}
}
}
}
return *this;
}
I also got this error
"no instance of constructor "CreditStatement::CreditStatement" matches the argument list
argument types are: (char [256], double) c:*\Project1\w5.cpp 38 20.
I think the problem is your call statement[n] = CreditStatement(item, price);
Here, price is a double, but there's a constructor CreditStatement(char*, double*); but none with signature CreditStatement(char*, double);
You might want to fix that.

Crashing when objects are deleted

It's crashing at the very end of the main() function where it needs to delete the starters objects. The error message that pops up when I run the program says: Debug assertion failed! Expression: _BLOCK_IS_VALID(pHead->nBlockUse). How do i fix it from crashing when deleting the starters objects?
#include <iostream>
#include <fstream>
#include "olympic.h"
using namespace std;
ofstream csis;
int main() {
const int lanes = 4;
Ranker rank(lanes);
csis.open("csis.txt");
// First make a list of names and lane assignments.
Competitor* starters[lanes];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
// The race is run; now assign a time to each person.
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
// Put everyone into the ranker.
for (int i = 0; i < lanes; i++)
rank.addList(starters[i]);
// Now print out the list to make sure its right.
cout << "Competitors by lane are:" << endl;
csis << "Competitors by lane are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
// Finally, show how they finished.
cout << "Rankings by finish are:" << endl;
csis << "Rankings by finish are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for (int i = 0; i < lanes; i++)
delete starters[i];
csis.close();
}
ranker.cpp:
#include "ranker.h"
#include "competitor.h"
#include <stdlib.h>
Ranker::Ranker(int lanes) {
athlete = new Competitor*[lanes];
numAthletes = 0;
maxAthletes = lanes;
}
int Ranker::addList(Competitor* starter) {
if (numAthletes < maxAthletes && starter != NULL) {
athlete[numAthletes] = starter;
numAthletes++;
return numAthletes;
}
else
return 0;
}
Competitor* Ranker::getLane(int lane) {
for (int i = 0; i < numAthletes; i++) {
if (athlete[i]->getLane() == lane) {
return athlete[i];
}
}
return NULL;
}
Competitor* Ranker::getFinish(int position) {
switch(position) {
case 1:
return athlete[3];
break;
case 2:
return athlete[2];
break;
case 3:
return athlete[1];
break;
case 4:
return athlete[0];
break;
}
return NULL;
}
int Ranker::getFilled() {
return numAthletes;
}
Ranker::~Ranker() {
delete [] athlete;
}
competitor.h:
#ifndef _COMPETITOR_H
#define _COMPETITOR_H
class Competitor {
private:
char* name;
int lane;
double time;
public:
Competitor(char* inputName, int inputLane);
Competitor();
void setTime(double inputTime);
char* getName();
int Competitor::getLane();
double getTime();
void print();
~Competitor();
};
#endif
competitor.cpp:
#include "competitor.h"
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
Competitor::Competitor(char* inputName, int inputLane) {
name = inputName;
lane = inputLane;
}
Competitor::Competitor() {
name = 0;
lane = 0;
time = 0;
}
void Competitor::setTime(double inputTime) {
time = inputTime;
}
char* Competitor::getName() {
return name;
}
int Competitor::getLane() {
return lane;
}
double Competitor::getTime() {
return time;
}
void Competitor::print() {
cout << setw(20) << name << setw(20) << lane << setw(20) << setprecision(4) << time << endl;
}
Competitor::~Competitor() {
delete [] name;
}
Call stack:
before crash: http://i.imgur.com/d4sKbKV.png
after crash: http://i.imgur.com/C5cXth9.png
After you've added Competitor class, it seems the problem is that you delete its name in Competitor's destructor. But you assign it from string literal which can't really be deleted. I'm sure the stack trace leading to assertion will prove that.
One way of solving the problem would be using std::string to store the name.
Problem is when deleting the char* value on destructor, which is assigned with const char instead new char. So i have slightly changed the constructor to copy the const char to new char.
Competitor::Competitor(char* inputName, int charlen, int inputLane)
{
name = new char[charlen + 1];
memcpy(name , inputName, charlen );
name [charlen] = '\0';
lane = inputLane;
}

Strange Seg Fault

I'm sorry, I know this is the umpteenth seg fault post on Stack Overflow, but I've tried for a few days to fix this code and I'm stumped, so I decided to turn to you guys. I hope you can help!
Anyway, I'm getting a strange segfault in this code:
account.h (Note, I'm not allowed modify the account.h file in anyway, as per the assignment. :)
class account
{
public:
typedef char* string;
static const size_t MAX_NAME_SIZE = 15;
// CONSTRUCTOR
//account();
account (char* i_name, size_t i_acnum, size_t i_hsize);
account (const account& ac);
// DESTRUCTOR
~account ( );
// MODIFICATION MEMBER FUNCTIONS
void set_name(char* new_name);
void set_account_number(size_t new_acnum);
void set_balance(double new_balance);
void add_history(char* new_history);
// CONSTANT MEMBER FUNCTIONS
char* get_name () const;
size_t get_account_number ( ) const;
double get_balance( ) const;
size_t get_max_history_size( ) const;
size_t get_current_history_size ( ) const;
string* get_history() const;
friend std::ostream& operator <<(std::ostream& outs, const account& target);
private:
char name[MAX_NAME_SIZE+1]; //name of the account holder
size_t ac_number; //account number
double balance; //current account balance
string* history; //Array to store history of transactions
size_t history_size; //Maximum size of transaction history
size_t history_count; //Current size of transaction history
};
account.cxx:
#include <string.h>
#include <cassert>
#include <cstdlib>
#include <iostream>
#include "account.h"
using namespace std;
account::account(char* i_name, size_t i_acnum, size_t i_hsize)
{
assert(strlen(i_name) <= MAX_NAME_SIZE);
strcpy(name, i_name);
ac_number = i_acnum;
history_size = i_hsize;
balance = 0;
history_count = 0;
history = new string[history_size];
}
account::account(const account& ac)
{
strcpy(name, ac.name);
ac_number = ac.ac_number;
balance = ac.balance;
history = new string[ac.history_size];
for(size_t i = 0; i < ac.history_count; i++)
{
history[i] = new char[strlen(ac.history[i]) + 1];
strcpy(history[i], ac.history[i]);
}
history_count = ac.history_count;
history_size = ac.history_size;
}
account::~account()
{
delete[] history;
}
void account::set_name(char* new_name)
{
assert(strlen(new_name) <= MAX_NAME_SIZE);
strcpy(name, new_name);
}
void account::set_account_number(size_t new_acnum) {ac_number = new_acnum;}
void account::set_balance(double new_balance) {balance = new_balance;}
void account::add_history(char* new_history)
{
assert(history_count < history_size);
history[history_count] = new char[strlen(new_history) + 1];
strcpy(history[history_count], new_history);
history_count++;
}
char* account::get_name() const
{
char* blah = new char[MAX_NAME_SIZE + 1];
strcpy(blah, name);
return blah;
}
size_t account::get_account_number ( ) const {return ac_number;}
double account::get_balance( ) const{return balance;}
size_t account::get_max_history_size( ) const {return history_size;}
size_t account::get_current_history_size ( ) const {return history_count;}
account::string* account::get_history() const
{
string* blah = new string[history_size];
for(size_t i = 0; i < history_count; i++)
{
blah[i] = new char[strlen(history[i]) + 1];
strcpy(blah[i], history[i]);
}
return blah;
}
std::ostream& operator<< (std::ostream& outs, const account& target)
{
outs << "Name: " << target.name << "\n"
<< "Account Number: " << target.ac_number << "\n"
<< "Balance: " << "$" << target.balance << "\n"
<< "History: ";
for(size_t i = 0; i < target.history_count; i++)
{
outs << target.history[i] << "\n";
}
outs << "Current History Size: " << target.history_count << "\n";
outs << "Max History Size: " << target.history_size << "\n";
return outs;
}
bankledger.h
class bank_ledger
{
public:
static const int MAX_ACC_SIZE = 15;
bank_ledger(int mo, int mc);
bank_ledger(const bank_ledger& copyledger);
~bank_ledger();
void create_account(char* i_name, size_t i_acnum, size_t i_hsize);
void close_account(double accnum);
double balance_of(double accnum);
void deposit(double accnum, double money);
void withdraw(double accnum, double money);
void transfer(double accnum1, double accnum2, double money);
void print_account_history(double accnum);
void print_account_details(double accnum);
void print_current_details();
void print_closed_details();
account* lookup(double accnum);
private:
account** open;
account** closed;
int max_open;
int max_closed;
int num_open;
int num_closed;
};
bankledger.cxx:
#include <cstdlib>
#include <iostream>
#include <cassert>
#include "account.h"
#include "bank_ledger.h"
using namespace std;
bank_ledger::bank_ledger(int mo = 30, int mc = 30)
{
max_open = mo;
max_closed = mc;
open = new account*[max_open];
closed = new account*[max_closed];
num_open = 0;
num_closed = 0;
}
bank_ledger::bank_ledger(const bank_ledger& copyledger)
{
int i;
max_open = copyledger.max_open;
max_closed = copyledger.max_closed;
num_open = copyledger.num_open;
num_closed = copyledger.num_closed;
open = new account*[num_open];
closed = new account*[num_closed];
for(i = 0; i < max_open; i++)
{
if (i < num_open)
open[i] = copyledger.open[i];
}
for(i = 0; i < max_closed; i++)
{
if (i < num_closed)
closed[i] = copyledger.closed[i];
}
}
bank_ledger::~bank_ledger()
{
for(int i = 0; i < num_open; i++)
{
delete open[i];
}
for(int i = 0; i < num_closed; i++)
{
delete closed[i];
}
delete[] open;
delete[] closed;
}
account* bank_ledger::lookup(double accnum)
{
for(int i = 0; i < num_open; i++)
{
if(open[i]->get_account_number() == accnum)
{
return *open + i;
}
if(closed[i]->get_account_number() == accnum)
{
return *closed + i;
}
}
}
void bank_ledger::create_account(char* i_name, size_t i_acnum, size_t i_hsize)
{
assert(num_open < max_open);
open[num_open] = new account(i_name, i_acnum, i_hsize);
open[num_open]->add_history("Account Created");
num_open++;
}
void bank_ledger::close_account(double accnum)
{
int i;
double temp = -1;
cout << *(open[0]) << endl << "Good Idea" << endl;
account* acc = lookup(accnum);
for(i = 0; i < num_open; i++)
{
if(open[i]->get_account_number() == acc->get_account_number())
{
temp = i;
closed[num_closed] = open[i];
for(i = temp; i < num_open - 1; i++)
{
open[i] = open[i+1];
}
closed[num_closed]->add_history("Account Closed");
num_open--;
num_closed++;
return;
}
}
}
double bank_ledger::balance_of(double accnum)
{
return lookup(accnum)->get_balance();
}
void bank_ledger::deposit(double accnum, double money)
{
account* acc = lookup(accnum);
acc->set_balance(acc->get_balance() + money);
acc->add_history("Deposited $");
}
void bank_ledger::withdraw(double accnum, double money)
{
account* acc = lookup(accnum);
acc->set_balance(acc->get_balance() - money);
acc->add_history("Withdrew $");
}
void bank_ledger::transfer(double accnum1, double accnum2, double money)
{
withdraw(accnum2, money);
deposit(accnum1, money);
}
void bank_ledger::print_account_history(double accnum)
{
account* acc = lookup(accnum);
account::string *hist = acc->get_history();
cout << "History of " << acc->get_name() << "'s account: " << endl;
for (int i = 0; i < acc->get_current_history_size(); i++) cout << hist[i] << endl;
}
void bank_ledger::print_account_details(double accnum)
{
account* acc = lookup(accnum);
cout << *acc;
cout << "\n";
}
void bank_ledger::print_current_details()
{
for(int i = 0; i < num_open; i++)
{
cout << *open[i] << "\n";
}
}
void bank_ledger::print_closed_details()
{
for(int i = 0; i < num_closed; i++)
{
cout << *closed[i] << "\n";
}
cout << "\n";
}
sample_test_input2.cxx
#include <cstdlib>
#include <iostream>
#include "account.h"
#include "bank_ledger.h"
using namespace std;
int main()
{
bank_ledger bl(30, 30);
bl.create_account("name1", 1, 30);
bl.create_account("name2", 2, 30);
bl.create_account("name3", 3, 30);
bl.create_account("name4", 4, 30);
bl.print_current_details();
bl.close_account(2);
return 0;
}
Valgrind and GDB both say that *(open[i]) is uninitialized. Here's the exact output from Valgrind:
==7082== Use of uninitialised value of size 8
==7082== at 0x1000018C6: account::get_account_number() const (account.cxx:74)
==7082== by 0x10000246B: bank_ledger::lookup(double) (bank_ledger.cxx:85)
==7082== by 0x1000027D0: bank_ledger::close_account(double) (bank_ledger.cxx:105)
==7082== by 0x100003117: main (sample_test_input2.cxx:17)
==7082==
==7082== Invalid read of size 8
==7082== at 0x1000018C6: account::get_account_number() const (account.cxx:74)
==7082== by 0x10000246B: bank_ledger::lookup(double) (bank_ledger.cxx:85)
==7082== by 0x1000027D0: bank_ledger::close_account(double) (bank_ledger.cxx:105)
==7082== by 0x100003117: main (sample_test_input2.cxx:17)
==7082== Address 0x10 is not stack'd, malloc'd or (recently) free'd
It goes from main to bankledgrer::close_account, to bankledger::lookup and then it crashes at if(open[i]->get_account_number() == accnum)
If I stick cout << *(open[i]) right before that line, it prints it out fine.
I'm afraid I'm at a loss. Any help would be appreciated. If you want me to include the header files, or clarify anything please let me know.
PS. Also, I know this code is very C, but that's the way my professor wants it, even though it's a C++ class. Go figure. :\
In this method:
account* bank_ledger::lookup(double accnum)
{
for(int i = 0; i < num_open; i++)
{
if(open[i]->get_account_number() == accnum)
{
return *open + i;
}
if(closed[i]->get_account_number() == accnum)
{
return *closed + i;
}
}
}
You are assuming there are at least the same amount of closed accounts than the amount of open accounts. You should iterate through the open and closed arrays in different loops, since you're trying to access closed[i], being i = 1,2,3..., and closed does not contain any valid pointers(just a bunch of NULL pointers). This should work(unless i'm missing something else):
account* bank_ledger::lookup(double accnum) {
for(int i = 0; i < num_open; i++) {
if(open[i]->get_account_number() == accnum)
return open[i];
}
for(int i = 0; i < num_closed; i++) {
if(closed[i]->get_account_number() == accnum)
return closed[i];
}
return 0;
}