Exception thrown: read access violation. **_Right_data** was 0x4. C++ - c++

I tried everything and looked everywhere but I keep getting
Exception thrown: read access violation.
**_Right_data was 0x4.**
What is wrong with the code? I am not very good with C++ and don't like it at all but working on this school project and trying to figure out why I get the exception. Any help is appreciated
#include "Roster.h"
#include "Student.h"
#include "NetworkStudent.h"
#include "SecurityStudent.h"
#include "SoftwareStudent.h"
#include <iostream>
#include <string>
#include<vector>
#include<sstream>
#include<regex>
// Separates Data on basis of ,
template <class Container>
void splitString(const std::string& str, Container& cont)
{
char delim = ',';
std::stringstream ss(str);
std::string token;
while (std::getline(ss, token, delim)) {
cont.push_back(token);
}
}
// Checks and returns if email is valid or not
bool Email(std::string email)
{
const std::regex pattern("(\\w+)(\\.|_)?(\\w*)#(\\w+)(\\.(\\w+))+");
return regex_match(email, pattern);
}
// Main Function
int main()
{
Roster classRoster;
// Data Array
const std::string studentData[] = { "A1,John,Smith,John1989#gm ail.com,20,30,35,40,SECURITY",
"A2,Suzan,Erickson,Erickson_1990#gmailcom,19,50,30,40,NETWORK",
"A3,Jack,Napoli,The_lawyer99yahoo.com,19,20,40,33,SOFTWARE",
"A4,Erin,Black,Erin.black#comcast.net,22,50,58,40,SECURITY",
};
for (unsigned int i = 0;i < 5;i++)
{
std::vector<std::string> words;
std::string s = studentData[i];
// Splits Input
splitString(s, words);
// if Student belongs to Security
if (words.at(8) == "SECURITY")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i] = new SecurityStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, SECURITY);
}
// IF Student Belongs to Software
else if (words.at(8) == "SOFTWARE")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i]=new SoftwareStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, SOFTWARE);
}
// If Student Belongs to Network
else if (words.at(8) == "NETWORK")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i] = new NetworkStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, NETWORK);
}
}
std::cout << "\n---------Print All Student's Data------------\n";
classRoster.printAll();
std::cout << "\n---------------------------------------------\n";
std::cout << "Invalid Emails\n";
classRoster.printInvalidEmails();
std::cout << "\n--------------Days in Course------------------\n";
classRoster.printDaysInCourse("A2");
std::cout << "\n--------------By Degree Program------------------";
classRoster.printByDegreeProgram(3);
std::cout << "\n--------------Removes A3------------------\n";
classRoster.remove("A3");
classRoster.remove("A3");
return 0;
}
// Adds Student to Roster
void Roster::add(std::string studentID, std::string firstName, std::string lastName, std::string emailAddress, int age, int daysInCourse1, int daysInCourse2, int daysInCourse3, degree d)
{
if (d == SOFTWARE)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new SoftwareStudent(studentID, firstName, lastName, emailAddress, age,a, d);
}
else if (d == NETWORK)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new NetworkStudent(studentID, firstName, lastName, emailAddress, age, a, d);
}
else if (d == SECURITY)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new SecurityStudent(studentID, firstName, lastName, emailAddress, age, a, d);
}
}
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID){
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID()<<"\n";
classRosterArray[i] = NULL;
}
}
std::cout << "Student ID Does not Exist \n";
}
// Prints All Data Of Array
void Roster::printAll()
{
for (unsigned i = 0;i < 5;i++)
{
std::cout << i + 1 << "\t";
classRosterArray[i]->print();
std::cout << "\n";
}
}
// Prints Average Days in Course for a specific Student
void Roster::printDaysInCourse(std::string studentID)
{
int sum = 0;
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID)
{
int *p = classRosterArray[i]->getStudentDaysofCourses();
for (unsigned int j = 0;j < 3;j++)
sum += p[j];
delete[]p;
break;
}
}
std::cout << sum / 3.0;
}
// Prints Invalid Emails
void Roster::printInvalidEmails()
{
for (unsigned i = 0;i < 5;i++)
{
std::string email = classRosterArray[i]->getStudentEmail();
if (!Email(email))
{
std::cout << classRosterArray[i]->getStudentEmail();
//classRosterArray[i]->print();
std::cout << "\n";
}
}
}
// Prints By Degree Program
void Roster::printByDegreeProgram(int degreeProgram)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getDegreeProgram()==degreeProgram)
classRosterArray[i]->print();
std::cout << "\n";
}
}
// Destructor
Roster::~Roster()
{
for (unsigned i = 0; i < 5; i++)
{
if (classRosterArray[i]!=NULL)
delete classRosterArray[i];
}
}

Figured it out!
This part was causing the error
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID){
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID()<<"\n";
classRosterArray[i] = NULL;
}
}
std::cout << "Student ID Does not Exist \n";
}
Changed to
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0; i < 5; i++)
{
if (classRosterArray[i] != NULL && classRosterArray[i]->getStudentID() == studentID) {
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID() << "\n";
delete classRosterArray[i];
classRosterArray[i] = NULL;
return;
}
}
std::cout << "Student ID Does not Exist \n";
}

Related

VS Code not showing local variables at all

I am using VS code for coding in C++. The problem arises when I try to debug a code and set a breakpoint. The local variables pane doesn't show any variables at all. Sometimes it does show some variables but not all of them.
Also when I try to close the debugger and click on the stop button, it does not stop. It requires me to click on it multiple times, which I think means, that multiple debuggers are opened or something like that.
To reproduce this problem, save this text as input_static.txt.
T1 1 2 5
T2 2 4
T3 2 3
T4 1 2 4
T5 1 3
T6 2 3
T7 1 3
T8 1 2 3 5
T9 1 2 3
And debug the following code by setting a breakpoint at line number 201.
#include <bits/stdc++.h>
using namespace std;
ifstream fin;
ofstream fout;
typedef struct fptnode
{
int item, count;
fptnode *next;
map<int, fptnode *> children;
fptnode *parent;
fptnode(int item, int count, fptnode *parent)
{
this->item = item;
this->count = count;
this->parent = parent;
}
} * FPTPTR;
map<int, int> frequency;
bool isMoreFrequent(int a, int b)
{
if (frequency[a] == frequency[b])
return a < b;
return frequency[a] > frequency[b];
}
class FPTREE
{
public:
FPTPTR root;
map<int, list<FPTPTR>> headers;
// map<int, int> frequency;
FPTREE()
{
this->root = new fptnode(-1, 0, NULL);
}
// class isMoreFrequent
// {
// public:
// FPTREE *T;
// isMoreFrequent(FPTREE *T)
// {
// this->T = T;
// }
// bool operator()(int item1, int item2)
// {
// return T->frequency[item1] > T->frequency[item2];
// }
// };
FPTPTR getNewNode(int item, int count, fptnode *parent)
{
FPTPTR T = new fptnode(item, count, parent);
this->headers[item].push_back(T);
return T;
}
void add(vector<int> &transaction)
{
stack<int> S;
std::sort(transaction.begin(), transaction.end(), isMoreFrequent);
for (int i = transaction.size() - 1; i >= 0; i--)
{
S.push(transaction[i]);
}
insert(root, S);
}
int insert(FPTPTR T, stack<int> &S)
{
T->count++;
if (S.empty())
return 0;
int top = S.top();
S.pop();
if (T->children[top] == NULL)
{
T->children[top] = getNewNode(top, 0, T);
}
insert(T->children[top], S);
return 0;
}
void printPreOrder(ofstream &fout)
{
printPreOrder(fout, this->root);
}
void printPreOrder(ofstream &fout, FPTPTR T)
{
if (T)
{
fout << "[" << T->item << ", " << T->count << "]" << ' ';
for (auto p : T->children)
{
printPreOrder(fout, p.second);
}
}
}
void printTree(ofstream &fout)
{
printTree(fout, this->root);
}
void printTree(ofstream &fout, FPTPTR T, int level = 0)
{
if (T)
{
for (int i = 0; i < level; i++)
fout << "\t";
fout << "[" << T->item << ", " << T->count << "]" << endl;
for (auto p : T->children)
{
printTree(fout, p.second, level + 1);
}
}
}
void generatePath(FPTPTR node, vector<int> &path)
{
if (node && node->item >= 0)
{
path.push_back(node->item);
generatePath(node->parent, path);
}
}
FPTREE newTree(int item)
{
list<FPTPTR> &nodes = this->headers[item];
vector<int> patternBase;
FPTREE f;
for (auto node : nodes)
{
patternBase.clear();
generatePath(node->parent, patternBase);
for (int j = 0; j < node->count; ++j)
f.add(patternBase);
}
return f;
}
int clear()
{
return this->clear(this->root);
}
int clear(FPTPTR T)
{
for (auto p : T->children)
{
clear(p.second);
}
return 0;
}
bool isEmpty()
{
// return this->root->count == 0;
return this->root->children.empty();
}
} F;
ofstream tempout;
map<set<int>, int> mine(FPTREE f, int r = -1)
{
map<set<int>, int> M;
if (!f.isEmpty())
{
// if (f.root->children.empty())
// M[{}] += f.root->count;
tempout << "\nOn removing " << r << ":\n";
f.printTree(tempout);
for (auto p : frequency)
{
FPTREE subF = f.newTree(p.first);
map<set<int>, int> m = mine(subF, p.first);
for (auto q : m)
{
auto itemset = q.first;
itemset.insert(p.first);
M[itemset] += q.second;
}
subF.clear();
}
return M;
}
// tempout << "\nTerminated.\n";
return {};
}
int main(int argc, char const *argv[])
{
fin.open("input_static.txt");
fout.open("output_static.txt");
tempout.open("temp");
string str, s;
while (fin >> s)
{
if (s.front() != 'T')
{
frequency[stoi(s)]++;
}
}
vector<int> transaction;
stringstream st;
fin.clear();
fin.seekg(0);
while (std::getline(fin, str))
{
st.clear();
st.str(str);
transaction.clear();
while (st >> s)
{
if (s.front() != 'T')
{
transaction.push_back(stoi(s));
}
}
F.add(transaction);
}
fout << "Preorder:\n";
F.printPreOrder(fout);
fout << endl
<< endl;
fout << "Tree in directory form:\n";
F.printTree(fout);
// printPrefixes(5);
map<set<int>, int> frequentItemsets = mine(F);
fout << endl;
for (auto p : frequentItemsets)
{
fout << "Frequency=" << p.second << "\t";
for (int item : p.first)
{
fout << item << ' ';
}
fout << endl;
}
// for (int i = 1; i <= 5; ++i)
// {
// fout << i << ":\n";
// FPTREE f = F.newTree(i);
// f.printTree();
// }
// F.newTree(1).newTree(2).printTree(fout);
return 0;
}
If it helps this is a program to generate and mine an FP-tree to find frequent itemsets in a transactional database.

Copy Constructor for dynamically allocated array

Trying to familiarize myself with the "Rule of 3" and Im having trouble getting a Copy Constructor to work. One of the class private members is returning 0 when it should have a value of 3.
Im not sure as to why when the Copy Constructor function is performed, a value of 0 is supplied to that classes private member. The member in question is theSize which is returned via the size() function in class.cpp.
class.h
class Catalog {
public:
Catalog (int maxCapacity = 100)
int size() const;
int capacity() const;
void add (Book b);
Catalog(const Catalog& c);
~Catalog();
Catalog& operator= (constCatalog& c) {
if (this != &c) {
delete[] books;
books = new Book[theCapacity];
*books = *(c.books);
}
return *this;
}
private:
Book* books;
int theCapacity;
int theSize;
};
class.cpp
Catalog::Catalog(int maxCapacity) {
theCapacity = maxCapacity;
theSize = 0;
books = new Book[theCapacity];
}
int Catalog::size() const {
return theSize();
}
int Catalog::capacity() const {
return theCapacity;
}
void Catalog::add (Book b)
{
if (theSize < theCapacity || contains(b.getID())) {
if (theSize == 0) {
books[0] = b;
theSize++;
}
else {
if (!contains(b.getID())) {
int i = theSize;
for (; i && b < books[i-1]; --i) {
books[i] = books[i - 1];
}
books[i] = b;
for (; i; --i) {
books[i - 1] = books[i - 1];
}
theSize++;
}
else {
for (int i = 0; i < theSize; ++i) {
if (b == books[i]) {
books[i] = b;
}
}
}
}
// Debugging only
/*for (int i = 0; i < theSize; i++) {
//cout << books[i] << endl;
}*/
}
}
bool Catalog::contains(std::string bookID) const
{
for (int i = 0; i < theSize; ++i)
{
if (books[i].getID() == bookID)
return true;
}
return false;
}
Catalog::Catalog(const Catalog& c) {
books = new Book[c.theSize];
for (int i = 0; i < c.theSize; i++) {
books[i] = c.books[i];
}
Catalog::~Catalog() {
delete[] books;
}
Later in main.cpp when I call c1.size() where c1 is the result of return c in another function that through use of the debugger comes from the Copy Constructor and then goes to the Destructor. However, c1.size() is returning as 0 though the Copy Constructor theSize = c.size() has a value of 3 when stepped through.
book.cpp
using namespace std;
/**
* Create a book.
*
* #param id the Gutenberg ID for this book
* #param authorInfo the author of the book
* #param title the title of the book
*/
Book::Book (std::string theId, std::string authorInfo, std::string theTitle)
: id(theId), authorName(authorInfo), title(theTitle)
{
}
bool Book::operator< (const Book& b) const
{
return id < b.id;
}
bool Book::operator== (const Book& b) const
{
return (id == b.id);
}
std::ostream& operator<< (std::ostream& out, const Book& b)
{
cout << b.getID() << "\t"
<< b.getAuthor() << "\t"
<< b.getTitle();
return out;
}
std::istream& operator>> (std::istream& in, Book& b)
{
string line;
getline (in, line);
if (!in.good())
return in;
int tab1 = line.find ("\t");
int tab2 = line.find ("\t", tab1+1);
string id = line.substr(0, tab1);
string author = line.substr (tab1+1, tab2-tab1-1);
string title = line.substr(tab2+1);
b.setID (id);
b.setAuthor (author);
b.setTitle (title);
return in;
}
main.cpp
using namespace std;
Catalog readCatalog(const string& fileName)
{
Catalog c;
ifstream in (fileName);
in >> c;
in.close();
return c;
}
Catalog mergeCatalogs (const Catalog& cat1, const Catalog& cat2)
{
Catalog result (cat1.size() + cat2.size());
int i = 0;
int j = 0;
while (i < cat1.size() && j < cat2.size())
{
Book b1 = cat1.get(i);
Book b2 = cat2.get(j);
if (b1.getID() < b2.getID())
{
result.add(b1);
++i;
}
else
{
result.add(b2);
++j;
}
}
while (i < cat1.size())
{
result.add(cat1.get(i));
++i;
}
while (j < cat2.size())
{
result.add(cat2.get(j));
++j;
}
return result;
}
void mergeCatalogFiles (const string& catalogFile1, const string& catalogFile2)
{
Catalog c1, c2;
c1 = readCatalog(catalogFile1);
cout << catalogFile1 << " contained " << c1.size() << " books." << endl;
c2 = readCatalog(catalogFile2);
cout << catalogFile2 << " contained " << c2.size() << " books." << endl;
Catalog c3 = mergeCatalogs (c1, c2);
cout << "Their merge contains " << c3.size() << " books." << endl;
cout << c3 << flush;
}
int main (int argc, char** argv)
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] <<
"catalogFile1 catalogFile2" << endl;
return -1;
}
string file1 = argv[1];
string file2 = argv[2];
mergeCatalogFiles (file1, file2);
if (Counted::getCurrentCount() == 0)
{
cout << "No memory leak detected." << endl;
return 0;
}
else
{
cout << "Memory leak detected: " << Counted::getCurrentCount() << endl;
return -2;
}
}
Follow rule of zero: use std::vector<Book> to replace the array pointer and the size.
Your capacity is a limit on the size.
When at capacity. use equal range to find where to insert, replace last element then std rotate.
Managing both resources and business logic in the same class is bug prone. Do one thing at a time.
Try something more like this instead:
class Catalog
{
public:
Catalog (int maxCapacity = 100);
Catalog(const Catalog& c);
~Catalog();
int size() const;
int capacity() const;
void add (const Book &b);
Book* find(const std::string &bookID) const;
Catalog& operator= (Catalog c);
private:
Book* books;
int theCapacity;
int theSize;
void swap(Catalog &c);
};
#include "class.h"
#include <algorithm>
Catalog::Catalog(int maxCapacity)
{
theCapacity = maxCapacity;
theSize = 0;
books = new Book[theCapacity];
}
Catalog::Catalog(const Catalog& c)
{
theCapacity = c.theCapacity;
books = new Book[theCapacity];
for(int i = 0; i < c.theSize;; ++i)
books[i] = c.books[i];
theSize = c.theSize;
}
Catalog::~Catalog()
{
delete[] books;
}
Catalog& Catalog::operator= (const Catalog &c)
{
if (this != &c)
Catalog(c).swap(*this);
return *this;
}
void Catalog::swap(Catalog &c)
{
std::swap(books, c.books);
std::swap(theSize, c.theSize);
std::swap(theCapacity, c.theCapacity);
}
int Catalog::size() const
{
return theSize;
}
int Catalog::capacity() const
{
return theCapacity;
}
void Catalog::add (const Book &b)
{
Book *book = find(b.getID());
if (book) {
*book = b;
}
else if (theSize < theCapacity)
{
int i;
for (i = theSize; i && b < books[i-1]; --i) {
books[i] = books[i - 1];
}
books[i] = b;
++theSize;
}
// Debugging only
/*
for (int i = 0; i < theSize; ++i) {
cout << books[i] << endl;
}
*/
}
Book* Catalog::find(const std::string &bookID) const
{
for (int i = 0; i < theSize; ++i)
{
if (books[i].getID() == bookID)
return &books[i];
}
return 0;
}
That being said, this would be much simpler and easier to manage if you use std::vector and STL algorithms. Let the STL do the hard work for you:
#include <vector>
class Catalog
{
public:
Catalog (int initialCapacity = 100);
int size() const;
int capacity() const;
void add (const Book &b);
Book* find(const std::string &bookID) const;
private:
std::vector<Book> books;
};
#include "class.h"
#include <algorithm>
Catalog::Catalog(int initialCapacity)
{
books.reserve(initialCapacity);
}
int Catalog::size() const
{
return books.size();
}
int Catalog::capacity() const
{
return books.capacity();
}
void Catalog::add (const Book &b)
{
Book *book = find(b.getID());
if (book) {
*book = b;
}
else {
books.insert(std::upper_bound(books.begin(), books.end(), b), b);
}
// Debugging only
/*
for (Book &book: books) {
cout << book << endl;
}
*/
}
Book* Catalog::find(const std::string &bookID) const
{
auto iter = std::find_if(books.begin(), books.end(), [&bookID](const Book &b){ return (b.getID() == bookID); });
if (iter != books.end())
return &*iter;
return 0;
}

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