C++ Deck and Card Class Error with bad alloc - c++

Just started learn to code in school. Our assignment requires us to create a card game with card,deck and hand class. I am having troubles with it now and i keep getting exception: std::bad_alloc at memory location. Here are my codes right now
CardType h:
#ifndef cardType_h
#define cardType_h
#include <string>
using namespace std;
class cardType{
public:
void print();
int getValue() const;
string getSymbol() const;
string getSpecial() const;
string getSuit() const;
int checkSpecial(int gscore) const;
cardType();
cardType(string suit,int value);
private:
int value;
string special;
string symbol;
string suit;
};
#endif
CardType cpp:
#include "cardType.h"
#include <iostream>
#include <string>
using namespace std;
void cardType::print()
{
cout << getSymbol() << " of " << getSuit() << ", having the value of " << getValue() << "."<< endl <<"This card's special is " << getSpecial() << endl;
}
int cardType::getValue() const
{
return value;
}
string cardType::getSymbol() const
{
return symbol;
}
string cardType::getSpecial() const
{
return special;
}
string cardType::getSuit() const
{
return suit;
}
cardType::cardType(){
value=0;
symbol="?";
special='?';
suit='?';
}
cardType::cardType(string s, int v){
suit = s;
value = v;
switch(v){
case 1: // Ace cards have a value of 1 and have no special type
symbol="Ace";
special="None";
break;
case 2: // 2 cards have a value of 2 and have no special type
symbol="2";
special="None";
break;
case 3:
symbol="3"; // 3 cards have a value of 3 and have no special type
special="None";
break;
case 4:
symbol="4"; // 4 cards have a value of 0 and have a special type "Reverse" which reverses the flow of the game
special="Reverse";
value=0;
break;
case 5:
symbol="5"; // 5 cards have a value of 5 and have no special type
special="None";
break;
case 6:
symbol="6"; // 6 cards have a value of 6 and have no special type
special="None";
break;
case 7:
symbol="7"; // 7 cards have a value of 7 and have no special type
special="None";
break;
case 8:
symbol="8"; // 8 cards have a value of 8 and have no special type
special="None";
break;
case 9:
symbol="9"; // 9 cards have a value of 0 and have a special type "Pass" which does not add any value to the game and lets the player skip his turn.
special="Pass";
value=0;
break;
case 10:
symbol="10"; // 10 cards have a value of 10 and have a special type "subtract" which instead of adding the 10 value to the total game it is subtracted instead.
special="Subtract";
value=10;
break;
case 11: // Jack cards have a value of 10 and have no special type
symbol="Jack";
special="None";
value=10;
break;
case 12: // Queens cards have a value of 10 and have no special type
symbol="Queen";
special="None";
value=10;
break;
case 13:
symbol="King"; // King cards have a value of 0 and have a special type "NinetyNine" which changes the total game score to 99 reguardless what number it was previously
special="NinetyNine";
value=0;
break;
}
}
int cardType::checkSpecial(int gscore) const{
if(special=="Pass"){
return gscore;
}
if(special=="Reverse"){
return gscore;
}
if(special=="Subtract"){
return gscore - value;
}
if(special=="NinetyNine"){
return 99;
}
else{
return gscore + value;
}
}
DeckType h:
#ifndef deckType_h
#define deckType_h
#include "cardType.h"
#include <string>
using namespace std;
class deckType
{
public:
void shuffle();
cardType dealCard();
deckType();
private:
cardType *deck;
int current;
};
#endif
DeckType cpp:
#include <iostream>
#include "deckType.h"
using namespace std;
deckType::deckType()
{ int index = 0;
int current=0;
deck = new cardType[52];
string suit[] = {"Hearts","Diamonds","Clubs","Spades"};
int value[] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
for ( int i = 0; i <= 3; i++ ) {
for ( int j = 1; j <= 13; j++ ) {
deck[index] = cardType(suit[i],value[j]);
index++;
}
}
}
cardType deckType::dealCard()
{
return deck[current];
current++;
}
Main cpp :
#include "deckType.h"
#include <iostream>
using namespace std;
int main()
{
deckType gamedeck;
cout << "1" <<endl;
cardType currentCard;
cout << "2" <<endl;
currentCard = gamedeck.dealCard();
cout << "3" <<endl;
return 0;
}
I keep getting bad_alloc at the currentCard = gamedeck.dealCard();
I really do not know what i have done wrong.

In the constructor, you should use string literals for strings:
cardType::cardType(){
value=0;
symbol="?";
special="?";
suit="?";
}
and current which is used in dealCard might not have been initialized.
deckType::deckType()
{ int index = 0;
int current=0;
deck = new cardType[52];
....
here, you initialize a local variable current, this hides the member current.
#drescherjm's comment is very important:
for ( int j = 1; j <= 13; j++ ) { That can't work. Remember c++
indexes start at 0.

Related

Insert a card into a deck of cards

So i have this program and i want to implement an insert void function. Basically i want to insert a card into the deck. The output should be a deck of cards and the shuffled version and then insert a card and sort it again. How can i accomplish that?
Deck.cpp
#include "deck.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
#include <chrono>
using namespace std;
/**
* Help function to convert Suit enum to string
*/
const string SuitToString(Suit s) {
switch (s) {
case Suit::Hearts:
return "H";
case Suit::Diamonds:
return "D";
case Suit::Spades:
return "S";
case Suit::Clubs:
return "C";
}
return "";
}
Card::Card(int rank, Suit suit)
{
this->rank = rank;
this->suit = suit;
}
/**
* Overload of << operator for Card class
*/
ostream & operator << (ostream &out, const Card &c)
{
string r;
switch(c.rank) {
case 1:
r = 'A';
break;
case 11:
r = 'J';
break;
case 12:
r = 'Q';
break;
case 13:
r = 'K';
break;
default:
r = to_string(c.rank);
break;
}
out << r << SuitToString(c.suit);
return out;
}
/**
* Create a deck of 52 cards
*/
Deck::Deck() {
for (Suit s = Suit::Hearts; s <= Suit::Clubs; s = Suit(s + 1)) {
for (int r=1; r<14; r++) {
cards.push_back(Card(r, s));
}
}
}
/**
* Overload of << operator for Deck class
*/
ostream & operator << (ostream &out, const Deck &d)
{
string separator;
for (auto i: d.cards) {
out << separator << i;
separator = ", ";
}
return out;
}
/**
* Return number of cards in deck
*
*/
int Deck::size()
{
return this->cards.size();
}
/**
* Shuffle all the cards in deck in ranom order.
*/
void Deck::shuffle()
{
auto rng = std::default_random_engine(std::chrono::system_clock::now().time_since_epoch().count());
std::shuffle(this->cards.begin(),this->cards.end(), rng);
}
/**
* Sort the deck according to card rank. All aces, the all two's, then all threes, ...
*/
void Deck::sort()
{
vector<Card> sorted_cards; // Empty temporary deck
while (this->size() > 0) {
// Go through the deck from left to right, insert the deck in the appropriate spot
Deck::insert(sorted_cards, this->take()); //Take a card from the old deck, insert it into the new one
}
this->cards = sorted_cards;
}
/**
* Take the top card from the deck
*/
Card Deck::take() {
Card c = this->cards.back();
this->cards.pop_back();
return c;
}
/**
* Put a card on top of the deck
*/
void Deck::put(Card card) {
cards.push_back(card);
}
void Deck::insert(vector<Card> &cardlist, Card card) {
/**
* My insert code here!
*/
return;
}
Deck.h
#include <iostream>
#include <vector>
#include <string>
using namespace std;
enum Suit {
Hearts,
Diamonds,
Spades,
Clubs
};
class Card
{
private:
int rank;
Suit suit;
public:
Card(int rank, Suit suit);
bool operator == (Card const &other)
{
return rank == other.rank;
}
bool operator < (Card const &other)
{
return rank < other.rank;
}
bool operator > (Card const &other)
{
return rank > other.rank;
}
friend ostream & operator << (ostream &out, const Card &c);
};
class Deck
{
private:
vector<Card> cards;
public:
Deck();
friend ostream & operator << (ostream &out, const Deck &d);
int size();
void shuffle();
void sort();
Card take();
void put(Card card);
static void insert(vector<Card> &cardlist, Card card);
};
main.cpp
#include "deck.h"
#include <iostream>
using namespace std;
main() {
Deck deck = Deck();
cout << "Fresh deck: " << deck << endl;
deck.shuffle();
cout << "Shuffled deck: " << deck << endl;
deck.sort();
cout << "Sorted deck: " << deck << endl;
}
For now i just have written the function itself.
Since Deck::insert is being called from the Deck::sort method, I think the aim is to insert the new card in order with respect to the previously inserted (and therefore already sorted) cards.
So it seems you need something like this
void Deck::insert(vector<Card> &cardlist, Card card) {
// starting from zero
size_t i = 0;
// find the index of the first card in the list that is >= to the card to insert
for (; i < cardList.size(); ++i)
{
if (card < cardList[i])
break;
}
// insert the new card before that index
cardList.insert(cardList.begin() + i, card);
}
This is bad code, for a couple of reasons (efficiency and design) but the above is my take on what you are being asked to do.

Output a Vector Element of Enum Class Type in C++

I have created card and deck classes for use in a C++ poker game, however, I'm trying to check that my assignment of vector elements are correct and having issues displaying them on the console. I have an enumerated class for the suits and integer values for the ranks. I see that my deck vector is generating with 52 cards, but I'm not sure how to correctly get this to display on the screen using the card class display() function for each vector element. Any help would be appreciated.
Note: I'm also guessing an alternate method would be to overload the output stream operator to display a vector element that is an object with an enumerated class parameter, but also not sure on what that syntax would look like.
int main(){ Deck deck();}
Card.h
#pragma once
#include <stdlib.h>
#include <iostream>
using namespace std;
enum class Suit { Hearts, Diamonds, Spades, Clubs };
class Card
{
private:
Suit m_suit;
int m_rank;
public:
Card();
Card(int r, Suit s);
void display();
int getRank();
void setRank(int);
Suit getSuit();
void setSuit(Suit);
};
Card.cpp
#include "Card.h"
#include <iostream>
#include <string>
Card::Card(): m_rank(0), m_suit(Suit::Hearts)
{
}
Card::Card(int r, Suit s)
{
m_rank = r;
m_suit = s;
}
void Card::display()
{
if (m_rank == 1) // for number cards, show value
{
std::cout << "Ace";
}
else if ((2 <= m_rank) && (m_rank <= 10))
{
std::cout << m_rank;
}
else
{
switch (m_rank)
{
case 11:
std::cout << "Jack";
break;
case 12:
std::cout << "Queen";
break;
case 13:
std::cout << "King";
break;
default:
std::cout << "INVALID RANK";
}
}
switch (m_suit) // display suit
{
case Suit::Hearts:
std::cout << " of Hearts";
break;
case Suit::Diamonds:
std::cout << " of Diamonds";
break;
case Suit::Spades:
std::cout << " of Spades";
break;
case Suit::Clubs:
std::cout << " of Clubs";
break;
};
}
int Card::getRank()
// return the numeric value of a card
{
return (m_rank);
}
Deck.h
#pragma once
#include <vector>
#include "Card.h"
class Deck
{
private:
Card card;
std::vector<Card> m_deck;
public:
Deck();
void shuffle();
void grabCard();
};
Deck.cpp
#include "Deck.h"
#include "Card.h"
#include <vector>
Deck::Deck()
{
for (int i = 1; i < 14; i++)
{
for (int j = int(Suit::Hearts); j <= int(Suit::Clubs); j++)
{
m_deck.push_back(Card(int(i), Suit(j))); //passing the card constructor to create a card object, then store it as a vector element
int counter = 0; // use to print out each element
std::cout << m_deck[card.display()]; //output each card obect via display method
std::cout << "\t\n";
counter++;
}
}
}
void Deck::shuffle()
{
}
void Deck::grabCard()
{
}
To display vector element, you should call display() of the vector element to display.
std::cout << m_deck[card.display()];
should be
m_deck.back().display();
to have it display the last pushed card.
Also int main(){ Deck deck();} is a main function with only function declaration and Deck::Deck() won't be called.
To call the constructor, it should be int main(){ Deck deck;}.

(C++) Not able to create objects different objects even when I give different constructor parameters [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am making a basic card system in C++. It is object-oriented, of course. All I did was a class for the card stack, another for the card itself and the main class. But as I was trying to make this project, I noticed that all the cards that I made were the same! It seems to me that the problem lays on the creating of the object itself. Check it out, guys:
Main.cpp
#include "Header.h"
using namespace std;
char cardTypes[4] = { CARD_TYPE_HEARTS,CARD_TYPE_SPADES,CARD_TYPE_CLUBS,CARD_TYPE_DIAMONDS };
int main(void) {
setlocale(LC_ALL, "Portuguese");
srand((unsigned)time(NULL));
CardStack stack;
for (int i = 0; i < 4; i++) {
char type = cardTypes[i];
for (int j = 0; j <= 13; j++) {
stack.add(&Card(j, type));
}
}
stack.shuffle();
cout << stack.getCard(0)->translateMe() << endl;
cout << stack.getCard(1)->translateMe() << endl;
cout << stack.getCard(2)->translateMe() << endl;
return 0;
}
Header.h
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
#include <vector>
#include <time.h>
#include <random>
#include <string>
using namespace std;
#define CARD_POS_STACK 0
#define CARD_TYPE_HEARTS 'H'
#define CARD_TYPE_SPADES 'S'
#define CARD_TYPE_CLUBS 'C'
#define CARD_TYPE_DIAMONDS 'D'
#define CARD_TYPE_NONE ' '
#define CARD_JOKER 0
#define CARD_ACE 1
#define CARD_2 2
#define CARD_3 3
#define CARD_4 4
#define CARD_5 5
#define CARD_6 6
#define CARD_7 7
#define CARD_8 8
#define CARD_9 9
#define CARD_10 10
#define CARD_JACK 11
#define CARD_QUEEN 12
#define CARD_KING 13
class Card {
private:
char type; /* type can be H (hearts), S (spades), C (clubs) or D (diamonds) */
short num; /* coringa = 0, J = 11, Q = 12 and K = 13*/
int pos; /* 0 = stack */
public:
/* > Creates a card */
Card(short num, char type);
/* > Recieves the card's type */
char getType();
/* > Recieves the card's number */
short getNum();
/* > Translates the number */
string translateMe();
/* > Recieves the card's position on the table */
int getPos();
/* > Checks if a card is equal to another */
bool isEqual(Card* another);
};
class CardStack {
private:
vector<Card*> cards;
int numOfCards;
public:
int getSize();
/* > Checks if there is any item in the stack */
bool isEmpty();
/* > Add a card to the top of the stack */
void add(Card* theCard);
/* > Remove a card from the stack */
void remove(Card* theCard);
/* > Shuffles randomly the card */
void shuffle();
/* > Get a certain card */
Card* getCard(int i);
/* > Gets the card at the top of the stack */
Card* getTopCard();
/* > Generates an empty stack */
CardStack();
};
#endif
Card.cpp
#include "Header.h"
Card::Card(short cardNum, char cardType){
num = cardNum;
if (cardNum = CARD_JOKER)
type = CARD_TYPE_NONE;
else
type = cardType;
pos = CARD_POS_STACK;
}
string Card::translateMe() {
string message = "";
switch (num) {
case 0:
message.append("Coringa");
break;
case 11:
message.append("Valete de");
break;
case 12:
message.append("Rainha de ");
break;
case 13:
message.append("Rei de ");
break;
default:
message.append(to_string(num)+" de ");
}
switch (type) {
case CARD_TYPE_CLUBS:
message.append("Paus");
break;
case CARD_TYPE_DIAMONDS:
message.append("Ouros");
break;
case CARD_TYPE_HEARTS:
message.append("Copas");
break;
case CARD_TYPE_SPADES:
message.append("Espadas");
break;
}
return message;
}
char Card::getType() { return type; }
short Card::getNum() { return num; }
int Card::getPos() { return pos; }
bool Card::isEqual(Card* another) { return this == another; }
CardStack.cpp
#include "Header.h"
#include <algorithm>
bool CardStack::isEmpty() {
return numOfCards == 0 ? true : false;
}
void CardStack::add(Card* theCard) {
cards.push_back(theCard);
}
void CardStack::remove(Card* theCard) {
for (int i = 0; i < cards.size(); i++)
if (theCard->isEqual(cards[i]))
cards.erase(cards.begin() + i);
}
CardStack::CardStack() {
numOfCards = 0;
}
void CardStack::shuffle() {
random_shuffle(cards.begin(), cards.end());
}
Card* CardStack::getCard(int i) {
return cards.at(i);
}
Card* CardStack::getTopCard() {
return cards.front();
}
int CardStack::getSize() {
numOfCards = cards.size();
return numOfCards;
}
And the output is the following:
"Rei de Ouros"
"Rei de Ouros"
"Rei de Ouros"
In this part:
stack.add(&Card(j, type));
You are taking the address of a temporary object.
Change that line to:
stack.add(new Card(j, type));
and it works!
But it will leak memory. Instead, you should probably make the CardStack hold cards instead of card pointers.

Compile-time error building a simple partial array class in C++

I'm having trouble getting my Partial Arrays class to compile. In one of my member functions I call for a previous member function and get the error "member reference base type 'ITEM_TYPE [255]' is not a structure or union".
I'm not entirely sure that my member variable declarations are up to snuff, as this is my first time dealing with arrays in C++.
Here is my header:
#ifndef PARTIALARRAY_H
#define PARTIALARRAY_H
#include <iostream>
#include <string.h>
using namespace std;
typedef int ITEM_TYPE;
ITEM_TYPE const MAX = 255;
class PartialArray
{
public:
//-----------------------------------------ctors:-----------------------------------------
PartialArray();
PartialArray(ITEM_TYPE MAX, int numUsed);
//-----------------------------------------member functions:-----------------------------------------
void PrintArray(int a[], int numUsed);
int Search(int a[], int numUsed, ITEM_TYPE key);
int Append(ITEM_TYPE appendMe);
int ShiftRight(int shiftHere);
int ShiftLeft(int shiftHere);
int InsertBefore(ITEM_TYPE insertThis, int insertHere);
int InsertAfter(ITEM_TYPE insertThis, int insertHere);
int Delete(int deleteHere);
string ErrorDescr(int failCode);
private:
//-----------------------------------------member vars:-----------------------------------------
ITEM_TYPE a[MAX];
int numUsed;
};
#endif // PARTIALARRAY_H
And my class declaration (NOTE: the error function and return values are not complete, so those can be ignored):
#include "partialarray.h"
#include <iostream>
#include <string.h>
using namespace std;
//-----------------------------------------ctors:-----------------------------------------
PartialArray::PartialArray()
{
numUsed=0;
}
PartialArray::PartialArray(ITEM_TYPE MAX, int numUsed)
{
numUsed = MAX;
}
//-----------------------------------------member functions:-----------------------------------------
//Prints the array up to its last used element
void PartialArray::PrintArray(ITEM_TYPE a[], int numUsed)
{
for(int i=0; i<numUsed; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
//Searches the array for a particular value and returns the index at which the value first appears
int PartialArray::Search(ITEM_TYPE a[], int numUsed, ITEM_TYPE key)
{
for(int i=0; i<numUsed; i++)
{
if(a[i]==key)
{
return i;
break;
}
else
;
}
return -1; //placeholder for error
}
//Takes a number and appends it to the end of the array after the last interesting element
int PartialArray::Append(ITEM_TYPE appendMe)
{
if(a[numUsed==0])
a[numUsed] = appendMe;
else
return 0; //placeholder for error
return 1; //placeholder for error
}
//Shifts all elements of the array to the right starting at a particular index
int PartialArray::ShiftRight(int shiftHere)
{
ITEM_TYPE save = a[numUsed-1];
for(int i=numUsed; i>=shiftHere; i--)
{
a[i] = a[i-1];
}
a[0] = save;
return 1; //error placeholder
}
//Shifts all elements of the array to the left starting at a particular index
int PartialArray::ShiftLeft(int shiftHere)
{
ITEM_TYPE save = a[0];
for(int i=shiftHere; i<numUsed; i++)
{
a[i] = a[i+1];
}
a[numUsed-1] = save;
return 1; //error placeholder
}
//Takes a number and a position and inserts the number at that position in the array shifting the elements to the right
int PartialArray::InsertBefore(ITEM_TYPE insertThis, int insertHere)
{
a.ShiftRight(insertHere);
a[insertHere] = insertThis;
return 1; //error placeholder
}
//Takes a number and a position and inserts the number at that position in the array shifting the elements to the left
int PartialArray::InsertAfter(ITEM_TYPE insertThis, int insertHere)
{
a.ShiftLeft(insertHere);
a[insertHere] = insertThis;
return 1; //error placeholder
}
//Takes a position and removes that item from the array, shifting all the elements to the left
int PartialArray::Delete(int deleteHere)
{
a[deleteHere] = 0;
a.ShiftLeft(deleteHere);
return 1; //error placeholder
}
string PartialArray::ErrorDescr(int failCode)
{
switch(failCode)
{
case 1:
return "ERROR: etc";
break;
case 2:
return "ERROR: etc";
break;
case 3:
return "ERROR: etc";
break;
case 4:
return "ERROR: etc";
break;
case 5:
return "ERROR: etc";
break;
default:
return "ERROR: etc";
break;
}
}
I have previously built a Rationals class, and I felt solid on that material, but doing something similar with arrays has proven to be a major headache. Any help would be much appreciated!
Most of your code seems ok. However, a is a C-style array, and thus has no member functions.
Thus, the following lines are incorrect:
a.ShiftRight(insertHere);
...
a.ShiftLeft(insertHere);
As you try to use this array with a syntax meaningul only for struct or class variables, the compiler issues here the error message you observe: "member reference base type 'ITEM_TYPE [255]' is not a structure or union"

Access Violation(Segmentation Fault )

I have two classes (appointment, schedule), and a driver (main).
main.cpp:
#include <iostream>
#include "schedule.h"
#include "appointment.h"
using namespace std;
int main()
{
schedule mySch2("hello");
appointment myAppt(100002,"appointment",10,1,2013);
myAppt.printS(cout,2);
mySch2.addtoSchedule(myAppt);
system("PAUSE");
return EXIT_SUCCESS;
}
schedule.h
#ifndef SCHEDULE_H
#define SCHEDULE_H
#include<iostream>
#include "appointment.h"
using namespace::std;
const int SCH_ENTRIES = 10;
class schedule
{
public:
schedule(void);
schedule(const char *p);
bool addtoSchedule(const appointment &);
private:
char title[40];
int count;
appointment appointmentArray[SCH_ENTRIES];
};
#endif
schedule.cpp
#include "schedule.h"
#include "appointment.h"
#include <iostream>
using namespace::std;
schedule::schedule(void)
{
}
schedule::schedule(const char *p)
{
strcpy(title, p);
count = 0;
cout << title << endl;
cout << count << endl;
cout << "----" << endl;
}
bool schedule::addtoSchedule(const appointment & myAppt)
{
cout << appointmentArray[0].getDay();
return false;
}
appointment.h (I did not write this, this was provided) - not super important for this question
#ifndef APPOINTMENT_H
#define APPOINTMENT_H
#include <fstream>
#include <cstring>
using std::ostream;
// The Designer decides upon the following data and actions (i.e. Functions)
// and places the class in the file appointment.h
class appointment
{
public:
appointment(void); // default constructor
appointment(long, const char [],int d, int m, int y); // 5 argument constructor
appointment(const appointment &); // copy constructor
void keyBoardInput(void); // Assume no blanks in the desc
long getSource(void) const; // return source
void setSource(long); // change source
void setMonth(int);
void setDay(int);
void setYear(int);
int getMonth(void) const;
int getDay(void) const;
int getYear(void) const;
const char *getDescription(void) const; // return the address of the description
void changeDescription(const char *) ; // change an existing description
void copyTo(appointment &) const; // copy invoking instance to parameter
void incrementDate (void); // advance the date by ONE day
// You can assume 30 days in each month
void printS(ostream &, int dateFormat) const; // print all fields
// dateFormat == 1 month/day/year
// dateFormat == 2 day/month/year
~appointment(); // destructor - indicate the address
// of the variable that is leaving
private:
void setDescription(const char *); // used to allocated memory
// data
long source; // id of the person scheduling the appointment
char * desc; // description of the appointment - Dynamic Data
int day; // day, month, and year when the appointment
int month; // will happen
int year;
};
#endif
appointment.cpp (I did not write this, this was provided) - not super important for this question
#include "appointment.h"
#include <iostream>
using std::cin;
using std::cout;
appointment::appointment()
{
day = 0;
cout << "default appt\n";
}
appointment::appointment(long lSource, const char cDescription[], int d, int m, int y)
{
source = lSource;
day = d;
month = m;
year = y;
setDescription(cDescription);
}
appointment::appointment(const appointment & aToCopy)
{
source = aToCopy.getSource();
day = aToCopy.getDay();
month = aToCopy.getMonth();
year = aToCopy.getYear();
setDescription(aToCopy.getDescription());
}
void appointment::setDescription(const char * cSource)
{
if (desc != NULL) free (desc);
if (cSource == NULL)
return;
desc = (char *)malloc (strlen (cSource) + 1);
strcpy(desc, cSource);
}
long appointment::getSource(void) const
{
return source;
}
void appointment::setSource(long lSource)
{
source = lSource;
}
void appointment::setMonth(int iMonth)
{
month = iMonth;
}
void appointment::setDay(int iDay)
{
day = iDay;
}
void appointment::setYear(int iYear)
{
year = iYear;
}
int appointment::getMonth(void) const
{
return month;
}
int appointment::getDay(void) const
{
return day;
}
int appointment::getYear(void) const
{
return year;
}
//return the address of the description
const char * appointment::getDescription(void) const
{
return desc;
}
//change an existing description
void appointment::changeDescription(const char * cDescription)
{
setDescription(cDescription);
}
void appointment::copyTo(appointment &p) const
{
p.source = source;
p.day = day;
p.month = month;
p.year = year;
p.setDescription(desc);
}
void appointment::incrementDate(void)
{
int days;
switch (month)
{
case 1: // Jan: 31 Days
case 3: // Mar: 31 Days
case 5: // May: 31 Days
case 7: // Jul: 31 Days
case 10: // Oct: 31 Days
case 12: // Dec: 31 Days
days = 31;
break;
case 4: // Apr: 30
case 6: // Jun: 30
case 8: // Aug: 30
case 9: // Sep: 30
case 11: // Nov: 30
days = 30;
break;
case 2: // Feb: 28/29 Days (Depends on year modulus 4 a modulus 100).
days = !(year % 4) || !(year % 100) ? 29 : 28;
break;
}
day++;
if (day > days)
{
month++;
day = 1;
if (month > 12)
{
month = 1;
year++;
}
}
}
void appointment::printS(ostream &out, int dateFormat) const
{
if (dateFormat == 1)
{
out << month << "/" << day << "/" << year << "\n";
}
else if (dateFormat == 2)
{
out << day << "/" << month << "/" << year << "\n";
}
else
out << "Unsupported dateFormat parameter specified (should be 1 or 2).";
}
appointment::~appointment()
{
if (desc != NULL)
{
free (desc);
desc = NULL;
}
}
void appointment::keyBoardInput()
{
char temp[1024];
cout << "Please type the description: ";
cin.getline (temp, sizeof(temp) - 1, '\n');
cout << std::endl;
setDescription(temp);
}
My error occurs when the main driver calls mySch2.addtoSchedule(myAppt);
If I uncomment out the line inside of schedule appointmentArray[0].getDay() then everything runs and works fine with no segmentation error. As soon as that line gets uncommented, it throws the error during runtime (after a crash and I go into the debugger and step through the program).
You never initialize desc to nullptr for class appointment before invoking setDescription. This happens in both constructors. Learn to use an initializer list:
appointment::appointment()
: source(), desc(), day(), month(), year()
{
cout << "default appt\n";
}
appointment::appointment(long lSource, const char cDescription[], int d, int m, int y)
: source(lSource), desc(), day(d), month(m), year(y)
{
setDescription(cDescription);
}
appointment::appointment(const appointment & aToCopy)
: source(aToCopy.getSource())
, desc()
, day(aToCopy.getDay())
, month(aToCopy.getMonth())
, year(aToCopy.getYear())
{
setDescription(aToCopy.getDescription());
}
Why did it fault?
Without initialization the value in desc is indeterminate and therefore undefined behavior to dereference, and certainly so to pass to free.
void appointment::setDescription(const char * cSource)
{
if (desc != NULL) free (desc); // desc contains non-null garbage.
if (cSource == NULL)
return;
desc = (char *)malloc (strlen (cSource) + 1);
strcpy(desc, cSource);
}
That said, I would strongly encourage using a std::string instead. It would make the copy-consructor for this class completely disappear, and the default constructor trivial.
Comments about using malloc() in a C++ program reserved, as that opinion is all-but beat to death already on this forum (and I agree with te prevailing opinion).