Dynamic object array increase - c++

I'm building a domino game and trying to make a function that adds a Stone to a pile.
This is the Stone class:
class Stone
{
public:
Stone(){ left = 0; right = 0; };
Stone(int x, int y){ left = x; right = y; };
void turnStone();
bool comStones(const Stone&);
void printOpen();
void printClosed();
friend class Pile;
friend class Game;
private:
int left, right;
};
And this is the Pile class:
class Pile
{
public:
Pile(){};
Stone indexfun(int);
void printOpen();
void printClosed();
void fillPile();
void randPile();
void addStone(Stone&);
void remStone(Stone&);
friend class Player;
friend class Game;
private:
Stone* list;
int size=0;
};
Now the function I built for adding a stone to the pile is:
void Pile::addStone(Stone& newStone) {
Stone* newList = new Stone[size + 1];
int i;
for (i = 0; i < size; i++)
{
newList[i] = list[i];
}
newList[i] = newStone;
delete[] list;
list = newList;
size++;
}
When I try and build the newlist array it throws me out of the program. can't find the reason. Help anyone?
the previous functions and more classes in the project:
class Game
{
public:
Game(char*);
void run();
private:
Player human, computer;
Pile box, table;
int start, finish;
void playerMove(int);
void checkPile(int);
bool checkMove(int,int);
bool whosFirst();
bool checkGame();
void printTable();
};
class Player
{
public:
Player(){};
void addStone(Stone&);
void remStone(Stone&);
void printPile();
Stone* searchStone();
friend class Game;
private:
char* name;
Pile pie;
};
void Game::run() {
cout << "starting the game" << endl;
box.fillPile();
box.size = 28;
box.randPile();
for (int i = 0; i < 7; i++)
{
human.addStone(box.list[i]);
box.remStone(box.list[i]);
computer.addStone(box.list[i]);
box.remStone(box.list[i]);
}
}
void Player::addStone(Stone& added) {
pie.addStone(added);
}
int main()
{
char name[80];
cout << "enter your name" << endl;
cin >> name;
Game game(name);
game.run();
}

Maybe change the "list" variable name to "list1" or something like that. "list" is a STL container, just like vector.

Related

Constructor in C++ Class

I have two Classes, Player and Game.
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
}
Each index in playersArray consists of pointers to class Player.The following constructor doesn't work, since this message keeps appearing:
error: invalid use of 'Player::Player' playersArray[i]->Player();
Game::Game(int maxPlayer)
{ this->maxPlayer=maxPlayer;
this->playersArray = new Player*[maxPlayer];
for(int i=0;i<maxPlayer;i++)
{
playersArray[i]->Player();
}
}
This is the class Player:
class Player {
private:
char* player_name;
int level;
int life;
int strength;
Weapon player_weapon;
int place;
}
My aim is to set the player_name to NULL and NOT to a random place in the memory. This is what Player() is supposed to do.
You are not populating your Game array correctly. You are trying to call the Player() constructor as if it were a regular class method (which it is not), and worse you are calling it via an uninitialized Player* pointer.
You need to use the new operator instead, eg:
class Game
{
private:
int maxPlayers;
Player** playersArray;
public:
Game(int aMaxPlayers);
~Game();
}
Game::Game(int aMaxPlayers)
{
maxPlayers = aMaxPlayers;
playersArray = new Player*[maxPlayers];
for(int i = 0; i < maxPlayers; ++i)
playersArray[i] = new Player; // <-- here
}
Game::~Game()
{
for(int i = 0; i < maxPlayers; ++i)
delete playersArray[i];
delete[] playersArray;
}
A safer option is to use std::unique_ptr instead of raw pointers:
#include <memory>
class Game
{
private:
int maxPlayers;
std::unique_ptr<std::unique_ptr<Player>[]> playersArray;
public:
Game(int aMaxPlayers);
}
Game::Game(int aMaxPlayers)
{
maxPlayers = aMaxPlayers;
playersArray = std::make_unique<std::unique_ptr<Player>[]>(maxPlayers);
for(int i = 0; i < maxPlayers; ++i)
playersArray[i] = std::make_unique<Player>();
}
That being said, there is no need to use an array of Player* pointers when an array of Player objects will suffice instead:
class Game
{
private:
int maxPlayers;
Player* playersArray;
public:
Game(int aMaxPlayers);
~Game();
}
Game::Game(int aMaxPlayers)
{
maxPlayers = aMaxPlayers;
playersArray = new Player[maxPlayers];
}
Game::~Game()
{
delete[] playersArray;
}
Or:
#include <memory>
class Game
{
private:
int maxPlayers;
std::unique_ptr<Player[]> playersArray;
public:
Game(int aMaxPlayers);
}
Game::Game(int aMaxPlayers)
{
maxPlayers = aMaxPlayers;
playersArray = std::make_unique<Player[]>(maxPlayers);
}
Which you can then simplify further by using std::vector instead:
#include <vector>
class Game
{
private:
std::vector<Player> playersArray;
public:
Game(int maxPlayers);
}
Game::Game(int maxPlayers)
: playersArray(maxPlayers)
{
}

Array of pointers to an object in C++

I am trying to write a super basic program which creates an array of objects under class Receipt. The class includes an int price, string good (name), and a simple function that adds an item to the list. I am stuck because every time I compile it seg faults before it even gets to the add function, meaning something is wrong with my default constructor.
I am still really new to C++ and pointers are probably my biggest struggle. I have looked online and at my lecture notes trying to figure out what I am doing wrong. I feel like it's something small but I cannot figure it out.
Here is my program:
#include <iostream>
#include <string>
using namespace std;
class Receipt {
private:
int price;
string good;
Receipt* goods[500]; //partially filled array
public:
Receipt();
void add(string name, int cost);
string getName();
int getPrice();
void setName(string name_in);
void setPrice(int price_in);
void displayList();
};
Receipt::Receipt()
{
for (int i=0; i < 500; i++)
{
goods[i]->setName("Empty");
goods[i]->setPrice(-1);
}
}
void Receipt::add(string name, int cost)
{
int place=0;
for (int i=0; i <500; i++)
{
if (goods[i]->getName()=="Empty" && goods[i]->getPrice()==-1)
{
place = i;
break;
}
}
goods[place]->setName(name);
goods[place]->setPrice(cost);
}
int Receipt::getPrice()
{
return price;
}
string Receipt::getName()
{
return good;
}
void Receipt::setName(string name_in)
{
good = name_in;
}
void Receipt::setPrice(int price_in)
{
price = price_in;
}
void Receipt::displayList()
{
//just displaying first item in list for debugging purposes
cout << goods[0]->getName() << endl << goods[0]->getPrice();
}
int main()
{
Receipt mine; //seg faults here
mine.add("banana", 50);
mine.displayList();
return 0;
}
your design is wrong, you have array of Receipt inside Receipt so when you initialize the object, it create 500 where each of them create another 500 endlessly. I think you want to create something like this instead
#include <iostream>
#include <string>
using namespace std;
class Receipt {
private:
int price;
string good;
public:
void setName(string name_in);
void setPrice(int price_in);
string getName();
int getPrice();
};
class Receipts {
private:
Receipt* goods[500]; //partially filled array
public:
Receipts();
void add(string name, int cost);
void displayList();
};
Receipts::Receipts()
{
for (int i = 0; i < 500; i++)
{
goods[i] = new Receipt();
goods[i]->setName("Empty");
goods[i]->setPrice(-1);
}
}
void Receipts::add(string name, int cost)
{
int place = 0;
for (int i = 0; i <500; i++)
{
if (goods[i]->getName() == "Empty" && goods[i]->getPrice() == -1)
{
place = i;
break;
}
}
goods[place]->setName(name);
goods[place]->setPrice(cost);
}
int Receipt::getPrice()
{
return price;
}
string Receipt::getName()
{
return good;
}
void Receipt::setName(string name_in)
{
good = name_in;
}
void Receipt::setPrice(int price_in)
{
price = price_in;
}
void Receipts::displayList()
{
//just displaying first item in list for debugging purposes
cout << goods[0]->getName() << endl << goods[0]->getPrice();
}
int main()
{
Receipts mine; //seg faults here
mine.add("banana", 50);
mine.displayList();
return 0;
}

How can I assign class object into a class

I need to creat an object Pokemon in the main()
that assign it into the class PokemonWorld, and let the PokemonWolrd to decide which PokemonStation is this Pokemon need to go
I tired get the data separatly (get name and hp) and get together(get a Pokemon class)
but both fail
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
class Pokemon {
public:
Pokemon() {};
Pokemon(char x[], int n) {
strncpy_s(name, x, 10);
hp = n;
};
private:
char name[10];
int hp;
};
class PokemonStation {
private:
Pokemon **list= new Pokemon*[1000];
public:
PokemonStation() {};
PokemonStation(int x) {
id = x;
};
int id;
void assigntoList(int i,Pokemon x)
{
if (i > 0)
i--;
list[i] = new Pokemon(x);
cout << "creat" << list[i];
};
};
class PokemonWorld {
private:
char name[10];
public:
PokemonStation s1;
PokemonStation s2;
PokemonWorld() {};
PokemonWorld(char x[], int y=1, int z=2) {
strncpy_s(name, x, 10);
PokemonStation s1(y);
PokemonStation s2(z);
};
const char* const getName() const{
return name;
};
void assigntoStation(int i,Pokemon x) {
if (i == 0 || i % 2 == 0)
s1.assigntoList(i, x);
else
s2.assigntoList(i, x);
};
};
void main() {
int number,hp,i;
char name[10];
cout << "What is the World Name ?" <<endl;
cin >> name;
PokemonWorld world(name);
cout << "Please input the number of Pokemon in the " << world.getName() <<" world:" << endl;
cin >> number;
Pokemon **mon = new Pokemon*[number];
cout << "Please input the characteristics of all Pokemon: Name HP" << endl;
for (i = 0;i < number;i++)
{
cin >> name >> hp;
mon[i] = new Pokemon(name, hp);
world.assigntoStation(i,*(mon[i]));
}
for (i = 0;i < number;i++)
cout << "world is " << world.getName() << endl;
system("pause");
};
In C++, you should use std::vectors for dynamic lists of things and std::strings for text. If you know Java, these are like ArrayList and String. (To use these, make sure you #include <vector> and <string>.)
For instance, your Pokemon class, rewritten with name as a string:
class Pokemon {
public:
Pokemon() {}
Pokemon(string name, int hp):name(name), hp(hp) { // construct the fields directly
}
private:
string name;
int hp;
};
And your PokemonStation class, rewritten using a vector for the list of Pokemon:
class PokemonStation {
private:
vector<Pokemon> list;
public:
PokemonStation() {}
PokemonStation(int x):id(x) {}
int id;
void assignToList(Pokemon x)
{
list.push_back(x); // add x to the list
}
};
If you want to print a Pokemon with cout <<, then you'll have to overload the << operator to define what gets printed. Add this into your class:
class Pokemon {
public:
...
friend ostream& operator<<(ostream& out, const Pokemon& p) {
out << p.name; // just print the name
return out;
}
...
};
Just make sure that you're couting a Pokemon, not a pointer-to-Pokemon (Pokemon*), and you won't get an address.

Accessing double pointer from another class

I'd like to access to a double pointer which is located in another class "Board".
class Board
{
public:
Board(void);
Board(unsigned int xSize, unsigned int ySize);
~Board(void);
void SetObjectManager(ObjectManager* pObm);
void SetBlock(Block* block);
void LoadBoard(void);
void InitBoard(void);
//Other Functions...
private:
ObjectManager* m_obm;
Block* m_block;
//pointer to pointer to a int. (for 2 dimensional-array)
int **m_board;
};
First, the Board class. at the last line of class, you can see m_board.
I want to change this value in outside of this class.
Like this,
void Block::InitBlock(void)
{
int randPiece = Random::GIRand().RandInt(0, 1);
int randPos = Random::GIRand().RandInt(0, 10);
switch (randPiece)
{
case 0:
m_piece[2][1] = 1;
m_piece[2][2] = 1;
m_piece[2][3] = 1;
m_piece[3][3] = 1;
break;
//Other cases are here...
}
std::cout << "RandPos : " << randPos << std::endl;
std::cout << "RandPiece : " << randPiece << std::endl;
for (int y = 0; y < m_ySize; ++y)
{
for (int x = 0, pX = randPos; x < m_xSize; ++x, ++randPos)
{
if (m_piece[x][y] != 0)
m_board->SetBoardStatus(randPos, y, 1);
}
}
}
But, When I run this program, It blows up at SetBoardStatus(int, int, int)
SetBoardStatus looks like this,
void Board::SetBoardStatus(int x, int y, int value)
{
m_board[x][y] = value; //Visual Studio breaks the program here.
}
I allocate the double pointer properly.
And I set the board at the outside of this classes.
void Block::SetBoard(Board* board)
{
m_board = board;
}
And this is my block class.
class Block
{
public:
Block(void);
~Block(void);
void SetObjectManager(ObjectManager* pObm);
void LoadBlock (void);
void InitBlock (void);
void UpdateBlock (void);
void ReleaseBlock (void);
void SetBoard(Board* board);
private:
ObjectManager* m_obm;
Board* m_board;
int **m_piece;
int m_xSize;
int m_ySize;
};
Consider inheriting Block in Board; This will eliminate any possible de-referencing errors or bugs, as you can access the pointer right away.

Why isn't this typedef working

This code works if the 7th line down says "typedef char ItemType" but instead I made it typedef to the EventInfo object. The MSVS compiler says some really weird things...
error C2146: syntax error : missing ';' before identifier 'ItemType'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
But I don't understand why it works correctly when it is a char.
I know this is a lot of code but the typedef is on the 7th line. I included the whole thing because I don't know what to expect.
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
const int MaxQueueSize = 8; // Queue Struct can hold up to 8
typedef EventInfo ItemType; // the queue's data type !DOES NOT COMPILE
enum EventType {Arrival, Depart};
class EventInfo
{
public:
EventInfo() : eTime(0), aTime(0), minutes(0) {}
int eventTime();
int duration();
void ScheduleEvent(int eTime, int duration);
bool compare(int eTime);
private:
int eTime; //either the arrival time of the next customer or the departure time of the customer currently at the teller window
int aTime; //either the service time for the arriving customer or the wait time for the customer at the teller window
float minutes;
};
int EventInfo::eventTime()
{
return this->eTime;
}
int EventInfo::duration()
{
return this->aTime;
}
void EventInfo::ScheduleEvent(int eTime, int duration)
{
this->eTime = eTime;
this->aTime = duration;
}
bool EventInfo::compare(int eTime)
{
return (eTime == this->eTime);
}
///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////
////////////////
class CPPQueue
{
public:
CPPQueue() : front(0), rear(0), count(0) { };
ItemType item[MaxQueueSize];
bool IsEmpty() const;
bool IsFull() const;
void Enqueue(ItemType newItem);
void PrintQ();
void PrintQueueInfo();
ItemType Dequeue();
int Count();
private:
int front, rear;
int count;
};
bool CPPQueue::IsEmpty() const
{
return (this->count == 0);
}
bool CPPQueue::IsFull() const
{
return (this->count == MaxQueueSize);
}
void CPPQueue::Enqueue(ItemType newItem)
{
if(this->count == MaxQueueSize)
{
cerr << "Error! Queue is full, cannot enqueue item.\n" << endl;
exit(1);
}
this->item[this->rear] = newItem;
this->rear++;
if (this->rear == MaxQueueSize)
{
this->rear = 0; // adjustment for circular queue
}
this->count++;
}
ItemType CPPQueue::Dequeue()
{
ItemType theItem;
if(this->count == 0)
{
cerr << "Error! Queue is empty, cannot dequeue item.\n" << endl;
exit(1);
}
theItem = this->item[this->front ];
this->front++;
if (this->front == MaxQueueSize)
{
this->front = 0; // adjustment for circular queue
}
this->count--;
return theItem;
}
// Function PrintQ() prints the contents of the queue without changing
// the queue. Printing starts at the "front" index and stops before we
// get to the "rear" index. A decrementing counter controls the loop.
//
void CPPQueue::PrintQ()
{
int i;
int qindex = this->front;
for(i = this->count; i > 0; i--)
{
cout << this->item[qindex] ;
qindex = (++qindex) % MaxQueueSize; // adjustment for circular queue
if(i > 1)
cout << ", ";
}
}
// Helper function for the main program below.
void CPPQueue::PrintQueueInfo()
{
cout << "The queue contains: ";
PrintQ();
cout << endl;
}
int CPPQueue::Count()
{
return this->count;
}
enum TellerStatus {Idle, Busy};
class Teller
{
public:
Teller() : status(Idle), idleTime(0), totalIdleTime(0) {}
void changeStatus(TellerStatus status);
TellerStatus getStatus(void);
private:
TellerStatus status;
int idleTime; //!
int totalIdleTime; //!!
};
void Teller::changeStatus(TellerStatus status)
{
this->status = status;
}
TellerStatus Teller::getStatus()
{
return this->status;
}
class Bank
{
public:
Bank() : Clock(0.0) {}
void RunSimulation();
private:
EventInfo Event[2]; // array of two events - next arrival and next departure
CPPQueue WaitLine; // the customer wait line [with max size = 8]
float Clock; // to keep track of Current Bank Time
Teller theTeller; // the single teller in the bank
ifstream myfile;
void ProcessArrival(), ProcessDeparture(), PrintHeader(), PrintReportLine(), PrintStatsReport();
};
void Bank::RunSimulation()
{
}
void Bank::ProcessArrival()
{
int a, b;
string filename, x;
filename = "P3Data1.txt";
myfile.open(filename);
while (myfile >> a >> b)
{
Event[1].ScheduleEvent(a, b);
WaitLine.Enqueue(Event);
}
}
int main()
{
Bank myBank;
myBank.RunSimulation();
}
The name EventInfo is only usable from its point of declaration forward. Your typedef is too early, and the compiler doesn't yet know what a EventInfo is.
You can move the typedef below the class definition, or you can tell the compiler that EventInfo is a class:
typedef class EventInfo ItemType;
In C++, unlike in Java, you can only use names that have been declared earlier in the file. So just change the order:
class EventInfo { /* ... */ };
typedef EventInfo ItemType;
In fact, it's enough to just declare the class, if you don't want to define it just yet: class EventInfo;
Put the typedef after the class definition. You can't do typedef for unknown types.
First you need to forward declare class EventInfo;
Otherwise your typedef has no idea of what EventInfo is.
THen you have various problems, e.g. you need to overload << for EventInfo class etc.