first time posting. Thanks in advance for your correspondence and patience.
I need to prevent the copy of an object, if that object already exists in my array.
I am beyond my depth as how to compare these values and prevent copy.
My next step is trying: unique_ptr or shared_ptr or compare() or iterator.
NO VECTORS.... I NEED TO ALLOCATE AND DE-ALLOCATE EVERYTHING.
ConfirmationSender.h
class ConfirmationSender {
Reservation** ppCon;
size_t cCnt;
public:
ConfirmationSender();
~ConfirmationSender();
ConfirmationSender& operator+=(const Reservation& res);
// ConfirmationSender& operator-=(const Reservation& res);
void display(std::ostream& os) const;
};
std::ostream& operator<<(std::ostream& os, const ConfirmationSender& obj);
ConfirmationSender.cpp
ConfirmationSender& ConfirmationSender::operator+=(const Reservation& res) {
if (cCnt == 0) {
++cCnt;
ppCon = new Reservation* [cCnt];
ppCon[0] = new Reservation(res);
}
else {
Reservation** temp1 = nullptr;
temp1 = new Reservation * [cCnt];
for (size_t i = 0; i < cCnt; i++) {
temp1[i] = ppCon[i];
}
++cCnt;
delete[] ppCon;
ppCon = new Reservation * [cCnt];
for (size_t i = 0; i < cCnt - 1; i++) {
ppCon[i] = temp1[i];
}
ppCon[cCnt - 1] = new Reservation(res);
delete[] temp1;
temp1 = nullptr;
/*
NEED TO IMPLEMENT CONDITION
SO THE VALUE I COPY
CANNOT BE A VALUE ALREADY EXISTING IN ARRAY
*/
}
return *this;
}
class Reservation {
std::string id, name, email;
int seats, day, hour;
public:
Reservation();
Reservation(const std::string& m_res);
void display(std::ostream& os) const;
};
std::ostream& operator<<(std::ostream& os, const Reservation& obj);
Reservation::Reservation() {
seats = 0;
day = 0;
hour = 0;
};
Reservation::Reservation(const std::string& m_res) {
std::string t_str;
t_str = m_res;
t_str.erase(std::remove(t_str.begin(), t_str.end(), ','), t_str.end());
istringstream iss(t_str);
std::string buffer = {};
static int count = 0;
while (iss >> buffer) {
switch (count % 6) {
case 0: id = buffer; break;
case 1: name = buffer; break;
case 2: email = buffer; break;
case 3: seats = atoi(buffer.c_str()); break;
case 4: day = atoi(buffer.c_str()); break;
case 5: hour = atoi(buffer.c_str()); break;
}
count++;
}
buffer.clear();
iss.str(std::string());
}
void Reservation::display(std::ostream& os) const {
string menu_type;
if (hour >= 6 && hour <= 9) { menu_type = "Breakfast"; }
else if (hour >= 11 && hour <= 15) { menu_type = "Lunch"; }
else if (hour >= 17 && hour <= 21) { menu_type = "Dinner"; }
else { menu_type = "Drinks"; }
os << "Reservation "
<< id << " "
<< name << " <"
<< email << "> "
<< menu_type << " on day "
<< day << " # "
<< hour << ":00 for "
<< seats << " people." << '\n';
}
std::ostream& operator<<(std::ostream& os, const Reservation& obj) {
obj.display(os);
return os;
}
main.cpp
// Confirmation Sender
{
std::cout << "CS: Testing Operators\n";
std::cout << "==========================\n";
sender1 += *ppReservations[5];
sender1 += *ppReservations[16];
sender1 += *ppReservations[16];
// THE SECOND [16] SHOULD NOT BE COPIED BY ADDITION OPERATOR
std::cout << sender1;
std::cout << "==========================\n\n";
}
Related
I am creating a dynamic array class that holds polynomials. The problem I am having right now is when I run my code, once it hits the return statement in main it begins to call the destructor and begins to free the memory from each instance starting with C. It deletes C fine, but when it gets to B I get a heap corruption error. I have tried walking through the code, but I cannot see where the corruption is happening. Can anyone help me? The exact error it gives me is "CRT detected that the application wrote to memory after end of heap buffer."
*Edit: I am more than happy to get peoples recommendations to help make my code better, but remember this is for a class and has specific rules. I cannot use anything from STL. I love any criticism you can give me.
///////////////////////////Header/////////////////////////////
class Poly
{
friend std::ostream& operator<<(std::ostream& output, const Poly& pNomial);
public:
Poly();
Poly(const int& coeff, const int& degree = 0);
Poly(const Poly& copy);
~Poly();
void setCoeff(const int& coeff, const int& degree);
bool isEmpty()const;
Poly& operator=(const Poly& pNomial);
private:
int* coeffs;
int highestDegree;
};
///////////////////////////CPP////////////////////////
#include "poly.h"
Poly::Poly()
{
highestDegree = 0;
coeffs = new int[highestDegree+1]();
}
Poly::Poly(const int & coeff, const int & degree)
{
if (degree >= 0)
{
highestDegree = degree;
coeffs = new int[highestDegree + 1]();
coeffs[degree] = coeff;
}
else
{
highestDegree = 0;
coeffs = new int[highestDegree + 1]();
}
}
Poly::Poly(const Poly& copy)
{
highestDegree = copy.highestDegree;
coeffs = new int[highestDegree + 1]();
for (int i = 0; i < copy.highestDegree + 1; i++)
{
coeffs[i] = copy.coeffs[i];
}
}
Poly::~Poly()
{
delete[] coeffs;
}
void Poly::setCoeff(const int& coeff, const int& degree)
{
if (degree > this->highestDegree)
{
Poly temp = *this;
delete[] this->coeffs;
this->highestDegree = degree;
this->coeffs = new int[highestDegree]();
for (int i = 0; i < temp.highestDegree + 1; i++)
{
this->coeffs[i] = temp.coeffs[i];
}
}
if (degree >= 0)
{
this->coeffs[degree] = coeff;
}
}
bool Poly::isEmpty()const
{
bool check = true;
for (int i = 0; i < highestDegree + 1 && check; i++)
{
if (coeffs[i] != 0)
{
check = false;
}
}
return check;
}
Poly & Poly::operator=(const Poly& pNomial)
{
if (this != &pNomial)
{
delete[] this->coeffs;
this->highestDegree = pNomial.highestDegree;
this->coeffs = new int[this->highestDegree + 1]();
for (int i = 0; i < pNomial.highestDegree + 1; i++)
{
this->coeffs[i] = pNomial.coeffs[i];
}
}
return *this;
}
std::ostream& operator<<(std::ostream& output, const Poly& poly)
{
if (!poly.isEmpty())
{
for (int i = poly.highestDegree; i >= 0; i--)
{
if (i == 1 && poly.coeffs[i] != 0)
{
if (poly.coeffs[i] >= 1)
{
output << " +" << poly.coeffs[i] << "x";
}
else
{
output << " " << poly.coeffs[i] << "x";
}
}
else if (i == 0 && poly.coeffs[i] != 0)
{
if (poly.coeffs[i] >= 1)
{
output << " +" << poly.coeffs[i];
}
else
{
output << " " << poly.coeffs[i];
}
}
else if (poly.coeffs[i] != 0)
{
if (poly.coeffs[i] >= 1)
{
output << " +" << poly.coeffs[i] << "x^" << i;
}
else
{
output << " " << poly.coeffs[i] << "x^" << i;
}
}
}
}
else
{
output << " 0";
}
return output;
}``
/////////////////////////////////Main/////////////////////////
#include "poly.h"
#include <iostream>
int main()
{
Poly A, B(5, 7), C(2);
B.setCoeff(2, 10);
B.setCoeff(1, 3);
B.setCoeff(5, 4);
std::cout << A << std::endl;
std::cout << B << std::endl;
std::cout << C << std::endl;
return 0;
}
I must say, that I agree with comments and you should seriously look into proper lifetime management of resources you use in the Poly class.
To answer the problem you're facing now have a look at the setCoeff() function.
this->coeffs = new int[highestDegree]();
should be changed to,
this->coeffs = new int[highestDegree + 1]();
With your current implementation, you allocate the array with highestDegree and in your for loop you access temp.coeffs[highestDegree] which is out of bounds access i.e. you loop till i < temp.highestDegree + 1.
I have written a program which was given to me as a homework assignment (it's a bit longer). The issue is that it compiles in CodeBlocks but it does not compile in Visual Studio 2017 it says - binary '=': no operator found which takes a right-hand operand of type 'CAutomobile' (or there is no acceptable conversion.
I would like to ask why is that because I could not myself find the error? I tried commenting the operator =function but still the error remained.
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
class CVehicle {
string name;
int year;
public:
CVehicle() {
name = "Car";
year = 1990;
}
CVehicle(string n, int y) {
name = n;
year = y;
}
CVehicle(const CVehicle& vc) {
name = vc.name;
year = vc.year;
}
void setName(string n) {
name = n;
}
void setYear(int y) {
year = y;
}
string getName() {
return name;
}
int& getYear() {
return year;
}
virtual void Print(ostream& os) = 0;
};
class CAutomobile :public CVehicle {
double litres;
public:
CAutomobile() :CVehicle() {
litres = 7.2;
}
CAutomobile(string nm, int yr, double l) :CVehicle(nm, yr) {
litres = l;
}
void setLitres(double l) {
l = litres;
}
double& getLitres() {
return litres;
}
void Print(ostream& os) override {
os << getName() << endl;
os << getYear() << endl;
os << litres << endl;
}
friend bool operator< (CAutomobile a1, CAutomobile a2) {
if (a1.litres < a2.litres) {
return true;
}
return false;
}
CAutomobile operator= (CAutomobile& at) {
CAutomobile au;
au.getName() = at.getName();
au.getYear() = at.getYear();
au.getLitres() = at.getLitres();
return au;
}
CAutomobile operator+(CAutomobile aut) {
CAutomobile a;
a.getLitres() = getLitres() + aut.getLitres();
return a;
}
friend ostream& operator<< (ostream& o, CAutomobile a) {
o << a.getName() << endl;
o << a.getYear() << endl;
o << a.getLitres() << endl;
return o;
}
};
int main()
{
CAutomobile a[] = {
CAutomobile(),
CAutomobile("Wolkswagen",1970,80.5),
CAutomobile("Fiat",1979,21.9),
CAutomobile("Opel",1978,13.7)
};
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
cout << "Name" << ' ' << a[i].getName() << endl;
cout << "Year" << ' ' << a[i].getYear() << endl;
cout << "Litres" << ' ' << a[i].getLitres() << endl;
}
int range = 2016 - 1990 + 1;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
a[i].setLitres(rand() % 100 + 1);
a[i].setYear(rand() % range + 1996);
}
//сортираме масива по литри и извеждаме
//най малкия (първия) му елемент
for (int i = 0; i < sizeof(a-1); i++) {
for (int j = 0; j < sizeof(a-1); j++) {
if (a[j].getLitres() > a[j + 1].getLitres()) {
swap(a[j], a[j + 1]);
}
}
}
cout << a[0] << endl;
CAutomobile k = a[0] + a[3];
cout << k.getLitres() << endl;
}
CAutomobile::operator = is completely wrong. It takes a non-const reference and assignes its field to a new object. Instead it should take a const reference and modify current object.
CAutomobile & operator =(CAutomobile const & other)
{
assert(this != ::std::addressof(other)); // check for self-assignment
SetName(other.getName());
SetYear(other.getYear());
SetLitres(other.getLitres());
return *this;
}
This will bring up another problem: getters are not const-qualified, so they should be fixes as well:
string const & getName(void) const {
return name;
}
int const & getYear(void) const {
return year;
}
I am writing a priority queue with a max heap structure as an assignment for school. I can either write it as an array or I can use a vector. I chose a vector. So the assignment is this, the user chooses options from a menu where he either wants to add,print, or view the elements. When the user chooses to add he gets ask who wants to be added, the instructor, student, or TA. He can enter i,I,t,T,S,s. The instructor having the highest priority where if the user chooses the option to print and there is an instructor in the queue he gets to go first. The TA having the second highest priority where if there is a TA and a student in the queue, the TA goes first. If there is is more than one instructor than the queue acts as a normal queue. I have written most of it, or tried. I got my max heap implementation from my textbook since they provide one. Now the problem is this, when I have more than one item in the priority queue and I choose to print, it crashes and gives me a vector subscript out of range exception. I been trying to fix it and no luck. Also, when I try to print the elements in the queue or print them, it needs to say the job# with the name of the person. Can someone help me find a way to implement that.
#pragma once
#include <vector>
struct Heap
{
std::vector<int> m_elements;
void ReHeapDown(int, int);
void ReHeapUp(int, int);
void Swap(int& a, int& b);
};
#include "heap.h"
void Heap::ReHeapDown(int index, int bottom)
{
int maxChild, rightChild, leftChild;
leftChild = index * 2 + 1;
rightChild = index * 2 + 2;
if (leftChild <= bottom)
{
if (leftChild == bottom)
maxChild = leftChild;
else
{
if (m_elements[leftChild] <= m_elements[rightChild])
maxChild = rightChild;
else
maxChild = leftChild;
}
if (m_elements[index] < m_elements[maxChild])
{
Swap(m_elements[index], m_elements[maxChild]);
ReHeapDown(maxChild, bottom);
}
}
}
void Heap::ReHeapUp(int index, int bottom)
{
int parent;
if (bottom > index)
{
parent = (bottom - 1) / 2;
if (m_elements[parent] < m_elements[bottom])
{
Swap(m_elements[parent], m_elements[bottom]);
ReHeapUp(index, parent);
}
}
}
void Heap::Swap(int& a, int& b)
{
int temp;
temp = a;
a = b;
b = temp;
}
#include <iostream>
#include "heap.h"
#pragma once
class PQTYPE
{
private:
Heap m_Items;
public:
bool isEmpty() const;
void Enqueue(int, std::string);
void Dequeue(int, std::string);
void printElements();
};
#include "pqtype.h"
bool PQTYPE::isEmpty() const
{
return m_Items.m_elements.empty();
}
void PQTYPE::Enqueue(int newItem, std::string lName)
{
if (lName == "Student")
{
m_Items.m_elements.push_back(newItem);
m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
}
else if (lName == "TA")
{
m_Items.m_elements.push_back(newItem);
m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
}
else if (lName == "Instructor")
{
m_Items.m_elements.push_back(newItem);
m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
}
}
void PQTYPE::Dequeue(int item, std::string lName)
{
if (isEmpty())
std::cout << "No jobs to print\n";
else
{
m_Items.m_elements[0] = m_Items.m_elements.back();
std::cout << "Now printing Job#" << m_Items.m_elements[item - 1] << " " << lName.c_str() << std::endl;
m_Items.m_elements.pop_back();
m_Items.ReHeapDown(0, item - 1);
}
}
void PQTYPE::printElements()
{
if (isEmpty())
std::cout << "No jobs to print\n";
else
{
for (int i = 0; i < m_Items.m_elements.size(); i++)
{
std::cout << "Job#" << m_Items.m_elements[i] << std::endl;
}
}
}
#include"pqtype.h"
struct Person
{
int m_priority;
std::string m_name;
Person()
{
m_priority = 0;
m_name = " ";
}
};
int showMenu();
void addJobs(PQTYPE&, Person&);
void printJobs(PQTYPE&, Person&);
void viewJobs(PQTYPE&);
int main()
{
int option;
Person p;
PQTYPE pq;
do
{
option = showMenu();
switch (option)
{
case 1: addJobs(pq, p);
break;
case 2: printJobs(pq, p);
break;
case 3: viewJobs(pq);
break;
case 4:
break;
default: std::cout << "Wrong input\n";
break;
}
} while (option != 4);
return 0;
}
int showMenu()
{
int choice;
std::cout << " 1.)Add Job\n";
std::cout << " 2.)Print Job\n";
std::cout << " 3.)View Jobs\n";
std::cout << " 4.)Exit\n";
std::cout << " Enter Choice: ";
std::cin >> choice;
return choice;
}
void addJobs(PQTYPE& pq, Person& per)
{
char jobChoice;
std::cout << "Who is the job for ( Instructor(i or I), TA(t or T), Student(s or S) :";
std::cin >> jobChoice;
if (jobChoice == 'S' || jobChoice == 's')
{
per.m_priority++;
per.m_name = "Student";
pq.Enqueue(per.m_priority, per.m_name);
}
else if (jobChoice == 'T' || jobChoice == 't')
{
per.m_priority++;
per.m_name = "TA";
pq.Enqueue(per.m_priority, per.m_name);
}
if (jobChoice == 'I' || jobChoice == 'i')
{
per.m_priority++;
per.m_name = "Instructor";
pq.Enqueue(per.m_priority, per.m_name);
}
}
void printJobs(PQTYPE& pq, Person& p)
{
pq.Dequeue(p.m_priority, p.m_name);
}
void viewJobs(PQTYPE& pq)
{
pq.printElements();
}
In your original code the index used inside Dequeue() for accessing the vector doesn't seem to be initialised in the right way. Let's assume that you have added two entries to your list. In this case the value of P.m_priority inside your main() is 2. Now you're calling printJobs() for the first time. printJobs() calls pq.Dequeue(p.m_priority, p.m_name), so Dequeue() gets p.m_priority as its parameter item. Keep in mind that item has the value 2.
m_Items.m_elements[0] = m_Items.m_elements.back();
std::cout << "Now printing Job#" << m_Items.m_elements[item - 1] << " " << lName.c_str() << std::endl;
m_Items.m_elements.pop_back();
You're accessing your std::vector using an index of item - 1. This works for the first time, as there are two elements in your list. In this call, there is also a pop_back() done on your list, which decreases its size by one. The next time you call printJobs(), the given parameter item won't have changed, it still has the value 2. When you access your Itemlist, there is no longer an index of 1, and an subscript out of range exception will be thrown.
There were no fixed priorities assigned to the three entry types in your original version, so I added these (see addJobs() ).
So a possible solution to store the person's name could look like this:
struct Person
{
int m_priority;
std::string m_name;
Person()
{
m_priority = 0;
m_name = " ";
}
};
struct Heap
{
std::vector<Person> m_elements;
void ReHeapDown(int, int);
void ReHeapUp(int, int);
void Swap(Person& a, Person& b);
};
void Heap::ReHeapDown(int index, int bottom)
{
int maxChild, rightChild, leftChild;
leftChild = index * 2 + 1;
rightChild = index * 2 + 2;
if (leftChild <= bottom)
{
if (leftChild == bottom)
maxChild = leftChild;
else
{
if (m_elements[leftChild].m_priority <= m_elements[rightChild].m_priority)
maxChild = rightChild;
else
maxChild = leftChild;
}
if (m_elements[index].m_priority < m_elements[maxChild].m_priority)
{
Swap(m_elements[index], m_elements[maxChild]);
ReHeapDown(maxChild, bottom);
}
}
}
void Heap::ReHeapUp(int index, int bottom)
{
int parent;
if (bottom > index)
{
parent = (bottom - 1) / 2;
if (m_elements[parent].m_priority < m_elements[bottom].m_priority)
{
Swap(m_elements[parent], m_elements[bottom]);
ReHeapUp(index, parent);
}
}
}
void Heap::Swap(Person& a, Person& b)
{
Person temp;
temp = a;
a = b;
b = temp;
}
#include <iostream>
class PQTYPE
{
private:
Heap m_Items;
public:
bool isEmpty() const;
void Enqueue(Person);
void Dequeue();
void printElements();
};
bool PQTYPE::isEmpty() const
{
return m_Items.m_elements.empty();
}
void PQTYPE::Enqueue(Person newItem)
{
if (!newItem.m_name.compare("Student"))
{
m_Items.m_elements.push_back(newItem);
m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
}
else if (!newItem.m_name.compare("TA"))
{
m_Items.m_elements.push_back(newItem);
m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
}
else if (!newItem.m_name.compare("Instructor"))
{
m_Items.m_elements.push_back(newItem);
m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
}
}
void PQTYPE::Dequeue()
{
if (isEmpty())
std::cout << "No jobs to print\n";
else
{
Person front = m_Items.m_elements.front();
std::cout << "Now printing Job#" << front.m_priority << " " << front.m_name.c_str() << std::endl;
m_Items.m_elements.erase(m_Items.m_elements.begin());
m_Items.ReHeapDown(0, m_Items.m_elements.size() - 1);
}
}
void PQTYPE::printElements()
{
if (isEmpty())
std::cout << "No jobs to print\n";
else
{
for (int i = 0; i < m_Items.m_elements.size(); i++)
{
std::cout << "Job#" << m_Items.m_elements[i].m_priority << " " << m_Items.m_elements[i].m_name.c_str() << std::endl;
}
}
}
int showMenu();
void addJobs(PQTYPE&, Person&);
void printJobs(PQTYPE&, Person&);
void viewJobs(PQTYPE&);
int showMenu()
{
int choice;
std::cout << " 1.)Add Job\n";
std::cout << " 2.)Print Job\n";
std::cout << " 3.)View Jobs\n";
std::cout << " 4.)Exit\n";
std::cout << " Enter Choice: ";
std::cin >> choice;
return choice;
}
void addJobs(PQTYPE& pq, Person& per)
{
char jobChoice;
std::cout << "Who is the job for ( Instructor(i or I), TA(t or T), Student(s or S) :";
std::cin >> jobChoice;
if (jobChoice == 'S' || jobChoice == 's')
{
per.m_priority = 0;
per.m_name = "Student";
pq.Enqueue(per);
}
else if (jobChoice == 'T' || jobChoice == 't')
{
per.m_priority = 1;
per.m_name = "TA";
pq.Enqueue(per);
}
if (jobChoice == 'I' || jobChoice == 'i')
{
per.m_priority = 2;
per.m_name = "Instructor";
pq.Enqueue(per);
}
}
void printJobs(PQTYPE& pq)
{
pq.Dequeue();
}
void viewJobs(PQTYPE& pq)
{
pq.printElements();
}
int main()
int option;
Person p;
PQTYPE pq;
do
{
option = showMenu();
switch (option)
{
case 1: addJobs(pq, p);
break;
case 2: printJobs(pq);
break;
case 3: viewJobs(pq);
break;
case 4:
break;
default: std::cout << "Wrong input\n";
break;
}
} while (option != 4);
return 0
}
Are you sure that the methods ReHeapUp and ReHeapDown meet your requirements? And shouldn't there be a distinction between job number and priority?
i am really stuck on following problem:
2 classes:
class Article
{
char* _code;
char* _name;
double _price;
int _quantity;
public:
Article(char* code = "code", char * name = "name", double price = 0){
setCode(code);
setName(name);
_price = price;
_quantity = 0;
}
Article(Article & a){
setCode(a._code);
setName(a._name);
_price = a._price;
_quantity = a._quantity;
}
~Article(){
delete[] _code; _code = nullptr;
delete[] _name; _name = nullptr;
}
/*******SETTERS********/
void setCode(char* code){
int vel = strlen(code);
_code = new char[vel + 1];
strncpy_s(_code, vel + 1, code, _TRUNCATE);
}
void setName(char* name){
int vel = strlen(name);
_name = new char[vel + 1];
strncpy_s(_name, vel + 1, name, _TRUNCATE);
}
void setPrice(double c){ _price = c; }
/*******GETTERS********/
int getquantity(){ return _quantity; }
double getprice(){ return _price; }
//operator =
Article operator = (Article& a){
setName(a._name);
setCode(a._code);
_price = a._price;
_quantity = a._quantity;
return *this;
}
//operator-= decrease qnty for passed value.
bool operator-=(int v){
if (_quantity > v)
{
_quantity = _quantity - v;
return true;
}
cout << "Operacija nije moguca, stanje je manje nego vrijednsot za koju se umanjuje";
return false;
}
// operator ++ increase Qnty for 1.
Article operator++(int){
//Article A(_code, _name, _price);
this->_quantity++;
return *this;
}
//Preklopiti operator -- decrease value for 1.
Article operator--(){
if (_quantity >= 1)
{
_quantity--;
}
return *this;
}
//compare articles based on code.
bool operator==(Article & a){
if (strncmp(_code, a._code, strlen(_code)) == 0)
{
return true;
}
return false;
}
//operator <<
friend ostream & operator<<(ostream & COUT, Article & a);
};
ostream & operator<<(ostream & COUT, Article & a){
COUT << "code: " << a._code << endl << "name: " << a._name << endl << "price: " << a._price << ", Qnty: " << a._quantity << "\n ----------------------- \n\n";
return COUT;
}
class Item
{
Article _Article;
int* _quantity;
public:
Item(Article & a, int quantity) :_Article(a){
_quantity = new int(quantity);
}
Item() :_Article("StavkaR", "nameR", 0){
_quantity = new int(0);
}
Item(Item& s) :_Article(s._Article){
_quantity = new int(*s._quantity);
}
~Item(){
delete _quantity; _quantity = nullptr;
}
int getquantity(){ return *_quantity; }
void setquantity(int v) { *_quantity += v; }
Article getArticle() { return _Article; }
friend ostream & operator << (ostream & COUT, Item & obj);
};
ostream & operator << (ostream & COUT, Item & obj){
COUT << "quantity: " << *obj._quantity << endl << obj._Article;
return COUT;
}
First class is article with constructors, destructs and overloaded operators, second class ITEM is simple it holds article and quantity.
For test in main i have following code:
Article a;
Article b("code", "name", 1.5);
Article c(b);
cout << a;
cout << b;
c++;
c++;
c.setPrice(10);
cout << c;
cout << "\n ************************************** \n";
Item _stavke[100];
for (size_t i = 0; i < 3; i++)
{
_stavke[i].getArticle().setPrice(100);
cout << _stavke[i];
cout << "\n \t\t\t ---- \n";
}
First part of code where i test Article class and some of overloaded operators it works fine but second part where i have Item _stavke[100]; array i can list members of array - no problem but any invoked change is not accepted basicly code
_stavke[i].getArticle().setPrice(100);
does not do anything it seems ...
Can anyone point me where i am going wrong and why i can not change members of array?
Thank you in advance
Your getArticle() call returns _Article by value. That is, a copy of article. Your setPrice() is invoked on the copy, so it is not reflected in the original Item's article, which remains unchanged.
I have some C++ code dealing with a card game and it's segfaulting and I can't figure out why. I tried running it in MSVS 2012 to get a more clear error and it threw a "Vector is not dereferencable." I tried doing some research but I'm lost on where the error is coming from. I'm guessing the bug isn't in the push_back but rather somewhere else as the problem line works most of the time. The error occurs in Table::hit(). After looking through the code I think the bug may possibly lie in Hand::split() but I am not sure and I am even less sure how to fix it. Thanks!
class Hand
{
public:
std::vector<Card> hand;
bool active, doubled, isBlackjack, busted;
Hand() : active(true), doubled(false), isBlackjack(false), busted(false) { }
Hand(const Hand& _hand);
void removeCard(Card card) { hand.erase( hand.begin() ); }
Card split();
void clear();
int cards() const { return hand.size(); }
int getHandValue() const;
Card at(int pos) { return hand[pos]; }
friend std::ostream& operator<< (std::ostream& out, const Hand& hand);
friend std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands);
};
Hand::Hand(const Hand& _hand)
: hand(_hand.hand), active(_hand.active), doubled(_hand.doubled), isBlackjack(_hand.isBlackjack), busted(_hand.busted)
{ }
Card Hand::split()
{ //COULD THE BELOW CODE BE CAUSING ISSUES?
Card card = hand[0];
hand.erase( hand.begin() );
return card;
}
void Hand::clear()
{
active = true;
hand.clear();
}
int Hand::getHandValue() const
{
int value(0), aces(0);
for(std::vector<Card>::const_iterator it = hand.cbegin(); it != hand.cend(); ++it)
{
value += getCardValue(it->getRank());
if(it->getRank() == ACE)
++aces;
}
while(aces > 0 && value > 21)
{
value -= 10;
--aces;
}
return value;
}
std::ostream& operator<< (std::ostream& out, const Hand& hand)
{
for(std::vector<Card>::const_iterator it = hand.hand.begin(); it != hand.hand.end(); ++it)
{
out << *it << " ";
}
out << hand.getHandValue();
return out;
}
std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands)
{
for(std::vector<Hand>::const_iterator it = hands.begin(); it != hands.end(); ++it)
{
out << *it << " ";
}
return out;
}
class Table
{
protected:
Shoe shoe;
Strategy strat;
Hand dealer;
std::vector< Hand > player;
double balance, blackjackPayoff;
bool hitSoft17;
void deal();
void hit(int split=0);
void split(int split=0);
double stand();
Action getUserAction();
bool isCurrentGame();
public:
Table(int decks, int _balance);
double bet;
void play();
void print();
void simulate(std::string fileName, int hands);
};
Table::Table(int decks, int _balance)
: shoe(decks), balance(_balance), blackjackPayoff(1.5), hitSoft17(true), bet(10)
{}
bool Table::isCurrentGame()
{
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
if(it->active)
return true;
}
return false;
}
void Table::deal()
{
dealer.clear();
player.clear();
dealer.addCard( shoe.pullCard(true) );
dealer.addCard( shoe.pullCard() );
player.push_back(Hand());
player[0].addCard( shoe.pullCard() );
player[0].addCard( shoe.pullCard() );
if(player[0].getHandValue() == 21 && dealer.getHandValue() == 21)
{
player[0].active = false;
}
else if(player[0].getHandValue() == 21)
{
player[0].active = false;
}
else if(dealer.getHandValue() == 21)
{
player[0].active = false;
}
}
void Table::hit(int split)
{
player[split].hand.push_back( shoe.pullCard() ); //SEGFAULT HERE
if(player[split].getHandValue() > 21)
{
player[split].active = false;
}
}
void Table::split(int split)
{
player.push_back(Hand());
player[player.size() - 1].hand.push_back( player[split].split() );
player[split].hand.push_back( shoe.pullCard() );
player[player.size() - 1].hand.push_back( shoe.pullCard() );
if(player[split].getHandValue() == 21)
{
player[split].active = false;
}
else if(player[player.size() - 1].getHandValue() == 21)
{
player[player.size() - 1].active = false;
}
}
double Table::stand()
{
double winnings(0.0);
bool allNats(true);
//dealer.push_back( shoe.pullCard() );
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
if(it->cards() == 2 && it->getHandValue() == 21)
{
winnings += bet * blackjackPayoff;
it->isBlackjack = true;
}
else
{
allNats = false;
if(it->getHandValue() > 21)
it->busted = true;
}
}
if(!allNats)
{
while(dealer.getHandValue() <= 17)
{
if(dealer.getHandValue() == 17)
{
//dealer has 17 and doesnt hit soft 17s so hes not going to draw anymore cards
if( !hitSoft17 || dealer.cards() != 2 || !(dealer.hand.at(0) == ACE || dealer.hand.at(1) == ACE) )
break;
}
dealer.addCard( shoe.pullCard() );
}
}
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
{
if(!it->isBlackjack)
{
if(it->busted)
{
if(it->doubled)
winnings -= 2.0 * bet;
else
winnings -= bet;
}
else if(dealer.getHandValue() > 21 || dealer.getHandValue() < it->getHandValue())
{
if(it->doubled)
winnings += 2.0 * bet;
else
winnings += bet;
}
else if(dealer.getHandValue() > it->getHandValue())
{
if(it->doubled)
winnings -= 2.0 * bet;
else
winnings -= bet;
}
}
}
//only other scenario is a push which we dont do anythign for
return winnings;
}
void Table::simulate(std::string fileName, int hands)
{
int i(0), countHL;
double trueCountHL;
std::ofstream ofs(fileName);
Action action;
while(i < hands)
{
deal();
VisibleCards vc(player[0].at(0), player[0].at(1), dealer.at(0));
while(isCurrentGame())
{
int j(0), q(1);
countHL = shoe.getCountHL();
trueCountHL = shoe.getTrueCountHL();
for(int l = 0; l < q; ++l)
{
while(player[l].active)
{
if(player[l].cards() == 2)
action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue(),
player[l].at(0).getCardValue(), player[l].at(1).getCardValue());
else
action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue());
switch(action)
{
case HIT:
hit(j);
break;
case DOUBLE:
hit(j);
if(player[l].cards() == 3)
{
player[l].doubled = true;
player[l].active = false;
}
break;
case SPLIT:
if(player.size() <= 4)
{
split(j);
++q;
}
else
hit(j);
break;
case STAND:
player[l].active = false;
break;
}
++j;
}
}
}
double winnings = stand();
balance += winnings;
ofs << std::endl << std::fixed << vc << "," << winnings << "," << std::setprecision(2) << trueCountHL
<< "," << balance << "," << std::setprecision(0) << countHL << "," << shoe.getRemainingDecks();
ofs << std::endl << 1;
//BlackjackData bjd(winnings, balance, shoe.getTrueCountHL(), shoe.getCountHL(), HIT);
//strat.addData(vc, bjd);
++i;
}
strat.print(fileName);
}
Looks like you're trying to get the first card from hand with hand[0] and hand.erase(hand.begin()) without first checking that there IS a first card. If hand is empty (as is the case with a newly created Hand from the constructor), this causes undefined behavior, which may well manifest as a crash at some later time.
I stared at this for a day and couldn't figure it out, stepped out and realize I had an old variable "j" that I was using to access the vector instead of "l" when I was calling the "hit" function.... Thanks everyone for the help.