Segfault when creating object in C++ - c++

I have the following code:
Card.h:
#include <string>
class Card
{
public:
enum suits {Spades, Diamonds, Hearts, Clubs};
Card(int _suit, int _value);
std::string SuitToString(int suitidx);
Card();
~Card();
private:
int value;
std::string suit;
};
Card.cpp:
#include <string>
#include <vector>
#include "Card.h"
Card::Card() {
}
Card::Card(int _suit, int _value)
{
this->suit=SuitToString(_suit);
this->value=_value;
}
Card::~Card()
{
}
std::string Card::SuitToString(int suitidx)
{
std::vector<std::string> suitStrings = {"Club", "Diamonds", "Hearts", "Spades"};
return suitStrings[suitidx];
}
Deck.h:
#include "Card.h"
#include <vector>
class Deck: public Card {
public:
Deck();
~Deck();
};
Deck.cpp:
#include "Deck.h"
#include <vector>
Deck::Deck()
{
for (int i=1; i<5; i++) {
for (int j=1; j<14; j++) {
Card c(i,j);
AddCard(c);
}
}
}
Deck::~Deck()
{
}
and main.cpp:
#include "Deck.h"
#include <iostream>
using namespace std;
int main()
{
Deck d;
return 0;
}
But when I run this, I get a seg fault. Can anyone help with this?

#tkausl is right, your Problem is in the SuitToString-Method. You call this with an invalid index.

Related

C++ Visual Studio 2015: non-standard syntax; use '&' to create a pointer to member

Card.h
#pragma once
#include <string>
#include "Rank.h"
#include "Suit.h"
using namespace std;
/**
*
*/
class MEMORYWARS_API Card
{
public:
Card(Rank, Suit);
string toString() const;
~Card();
private:
Rank rank;
Suit suit;
};
Card.cpp
#include "MemoryWars.h"
#include "Card.h"
Card::Card(Rank rank, Suit suit)
{
this->rank = rank;
this->suit = suit;
}
string Card::toString() const
{
string s = "Hellow there";
return s;
}
Card::~Card()
{
}
Error
error C3867: 'Card::toString': non-standard syntax; use '&' to create a pointer to member
Deck.h
#pragma once
#include "Card.h"
#include "vector"
class MEMORYWARS_API Deck
{
public:
Deck();
~Deck();
private:
std::vector<Card> deck;
};
Deck.cpp
#include "MemoryWars.h"
#include "Deck.h"
#include <EngineGlobals.h>
#include <Runtime/Engine/Classes/Engine/Engine.h>
Deck::Deck()
: deck(52)
{
int cc = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 13; j++)
{
Rank rank = static_cast<Rank>(j);
Suit suit = static_cast<Suit>(i);
deck[cc] = Card(rank, suit);
cc++;
}
}
string st = deck[2].toString;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Some variable values: x: %s"), st));
}
Deck::~Deck()
{
}
I'm new to C++ with Java experience mainly, I have been struggling with this error.
I'm trying to test the Card::toString method but everytime I call it from deck.cpp I get an error.
This line here is not correct:
string st = deck[2].toString;
The proper way to call a function in C++ (actually Java too I thought) is this:
string st = deck[2].toString();

Undefined Reference Error/ Dynamically Calling Functions

Hi I am working on a program that involves a Main.cpp, Connect4.cpp, and Connect4.h file. When I compile my program I am getting an error in the Main file saying that my playGame function is an undefined reference. I am compiling both files together(main first) I believe something is wrong in the way I am trying to dynamically call the function playGame. Any input would be much appreciated!
Main.cpp
#include <iostream>
#include <array>
#include "Connect4.h"
void playGame();
using namespace std;
int main()
{
Connect4 *ptr;
ptr=new Connect4;
ptr-> playGame();
delete ptr;
}
Connect4.cpp
#include <iostream>
#include <array>
#include "Connect4.h"
char gameBoard[9][7];
int rows;
int columns;
using namespace std;
void playGame()
{
void display();
int selectColumn(bool);
int tokenPlacement(char token, int columns);
bool winOrLose();
cout<<"Welcome to Connect Four.";
for(int i=0; i<rows;++i)
{
for(int j=0; j<columns; ++j)
{
gameBoard[i][j]=' ';
}
}
bool player1Turn=true;
char winner='n';
int column =0;
while(true){
display();
column=selectColumn(player1Turn);
if(player1Turn==true)
{
tokenPlacement('x',column);
player1Turn=false;
}
else
{
tokenPlacement('o', column);
player1Turn=true;
winner= winOrLose();
if(winner!='n')
{
break;
}
}
cout<<"Winner is:"<<winner;
}
Connect4.h
#ifndef CONNECT4_H_
#define CONNECT4_H_
#include
using namespace std;
class Connect4 {
public:
static void playGame();
private:
void display();
int selectColumn(bool);
int tokenPlacement(char, int);
bool winOrLose();
char gameBoard[9][7];
};
#endif /* CONNECT4_H_ */

Segmentation fault on accessing vector class member

I have a segmentation fault on this line in c++ :
vector<TemplateElement*> children = getChildren();
Class That inherits from abstract class TemplateElement
How to fix that ?
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include "strings.h"
#include "aimlthat.h"
using namespace std;
using namespace aiml;
vector<string> That::elements() {
vector<TemplateElement*> children = getChildren();
vector<string> elements;
for (int i = 0, n = children.size(); i < n; i++) {
string text = children[i]->toString();
text = trim(text);
vector<string> vsText = split(text);
for(int j=0, m=vsText.size(); j<m; ++j) {
elements.push_back(vsText[j]);
}
}
return elements;
}
/****************************************************************************/
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <map>
#include "strings.h"
#include "aimltemplateelement.h"
#include "aimltext.h"
using namespace std;
using namespace aiml;
vector<TemplateElement*> TemplateElement::getChildren() {
return m_vtChildren;
}
/***************************************************************************/
#ifndef __AIMLTEMPLATEELEMENT_H__
#define __AIMLTEMPLATEELEMENT_H__
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <map>
#include "strings.h"
#include "aimlelement.h"
using namespace std;
using namespace aiml;
namespace aiml {
class TemplateElement : public AIMLElement {
public:
TemplateElement() {}
TemplateElement(vector<TemplateElement*> elements);
vector<TemplateElement*> getChildren();
virtual string toString() = 0;
private:
vector<TemplateElement*> m_vtChildren;
};
}
#endif
/***********************************************************************/
Here is the class That :
#ifndef __AIMLTHAT_H__
#define __AIMLTHAT_H__
#include <iostream>
#include <ctime>
#include <cstdlib>
#include "aimltemplateelement.h"
using namespace std;
namespace aiml {
class That : public TemplateElement {
public:
That() {}
vector<string> elements();
private:
};
}
#endif
You need to check for null pointer:
for (int i = 0, n = children.size(); i < n; i++) {
if(children[i]) //Be sure that children[i] is not null before dereferencing it
{
string text = children[i]->toString();
text = trim(text);
vector<string> vsText = split(text);
for(int j=0, m=vsText.size(); j<m; ++j) {
elements.push_back(vsText[j]);
}
}
}
[EDIT]
From your comment I see that all you need is initialize the pointer to That before using it, and btw don't forget to delete it when you finish:
That* that = new That();
that->elements();

Virtual keyword seems to be ignored

This is my first "big" C++ project and I am stuck. I am trying to create a simple ASCII roguelike. I have a character class that is inherited by a Player class and a Monster class. The Monster class is inherited by Vampire and Werewolf classes.
In the startGame function of the GameSystem class I submit every element of a Monsters array (that is supposed to be filled with Vampire and Werewolf objects) to the function moveAround. Vampires, Werewolfs, and Monsters all have this function yet only the Monster moveAround function is being accessed. If you notice in the code below I have the virtual keyword provided in the Monster class.
This leads me to think I messed up when I filled the Monster array with the subclasses. I did this in the GameSystem constructor by randomly determining if a particular element of the Monster array was going to be a werewolf or a vampire.
I am using codeblocks and in terms of compiling I have g++ following C++11.
GameSystem.cpp
#include <iostream>
#include <string>
#include "GameSystem.h"
#include "Map.h"
#include "Player.h"
#include "Werewolf.h"
#include "Vampire.h"
#include "conio.h"
#include <cstdio>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <time.h>
GameSystem::GameSystem(string mapName){
srand (time(NULL));
_map.load(mapName);
_map.obtainSpawningLocations(_player.getToken(),_player);
Werewolf werewolf;
Vampire vampire;
for(int i = 0; i < 5; i++){
_spawnValue = rand() % 2; //We generate either 1 or 2
if(_spawnValue==1){
_theMonsters[i] = werewolf;
cout<<"Werewolf"<<endl;
}
else{
_theMonsters[i] = vampire;
cout<<"Vampire"<<endl;
}
_map.obtainSpawningLocations(_theMonsters[i].getToken(),_theMonsters[i]);
}
}
void GameSystem::startGame(){
bool isOver = false;
while(isOver!=true){
_map.print();
movePlayer();
for(int i = 0; i <5; i++){
_theMonsters[i].moveAround(); //prints out Monster.moveAround()
//I need it to print out Vampire.moveAround() and //Werewolf.moveAround
}
}
}
void GameSystem::movePlayer(){
char input;
input = getch();
string clearScreenString(100,'\n'); //Prints out a newLine char 100 times
cout << clearScreenString;
_map.checkMovement(input, _player);
}
char GameSystem::getch(){
char buf=0;
struct termios old={0};
fflush(stdout);
if(tcgetattr(0, &old)<0)
{perror("tcsetattr()");}
old.c_lflag&=~ICANON;
old.c_lflag&=~ECHO;
old.c_cc[VMIN]=1;
old.c_cc[VTIME]=0;
if(tcsetattr(0, TCSANOW, &old)<0)
{perror("tcsetattr ICANON");}
if(read(0,&buf,1)<0)
{perror("read()");}
old.c_lflag|=ICANON;
old.c_lflag|=ECHO;
if(tcsetattr(0, TCSADRAIN, &old)<0)
{perror ("tcsetattr ~ICANON");}
//printf("%c\n",buf);
return buf;
}
GameSystem.h
#pragma once
#include "Map.h"
#include <string>
#include <list>
using namespace std;
class GameSystem
{
public:
GameSystem(string mapName); //Constructor
void startGame(); //Start the game
char getch();
void movePlayer();
private:
//int _numberOfMonsters = 5; //We'll make this a random number later
Map _map;
Player _player;
Monster _monster;
Monster _theMonsters[5];
int _x;
int _y;
int _spawnValue;
};
Character.cpp
#include <string>
#include "Character.h"
using namespace std;
Character::Character(){
}
char Character::getToken(){
return _token;
}
void Character::setLocation(int x, int y){
_x = x;
_y = y;
}
void Character::getLocation(int &x, int &y){
x = _x;
y = _y;
}
Character.h
#pragma once
#include <string>
class Character{
public:
Character();
char getToken();
void setLocation(int x, int y);
void getLocation(int &x, int &y);
protected:
int _x;
int _y;
char _token = '!';
};
Map.cpp
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <cstring>
#include <random>
#include <ctime>
#include <tuple>
#include "Map.h"
#include <time.h>
Map::Map(){
srand (time(NULL));
}
void Map::load(string levelName){
ifstream theStream;
theStream.open(levelName);
if(theStream.fail()){
perror(levelName.c_str());
system("PAUSE");
exit(1);
}
string line;
while(getline(theStream, line)){
_mapData.push_back(line);
}
theStream.close();
}
void Map::obtainSpawningLocations(char characterToken,Character &_character){
/*
Below code provides all the possible spawning locations for the player
and stores them in an array of tuples.
*/
tuple<int,int> myTuple[600]; //Hard coded 600 value is messy. Change later
int numberOfSpawnPoints = 0;
int upperLimitForNumberGenerator = 0;
/*
The for loop below records all of the possible spawning locations and stores them in the tuple array
*/
for(int i = 0; i<_mapData.size();i++){
for(int j = 0; j<_mapData[i].size();j++){
if(_mapData[i][j]=='.'){
get<0>(myTuple[numberOfSpawnPoints]) = j;
get<1>(myTuple[numberOfSpawnPoints]) = i;
numberOfSpawnPoints++;
}
}
}
upperLimitForNumberGenerator = numberOfSpawnPoints;
int characterCoordinates = rand()%upperLimitForNumberGenerator;
int xCoordinate = get<0>(myTuple[characterCoordinates]);
int yCoordinate = get<1>(myTuple[characterCoordinates]);
_mapData[yCoordinate][xCoordinate] = characterToken; //Remember y is first and x is second
_character.setLocation(xCoordinate, yCoordinate);
}
void Map::print(){
for(int i=0;i<_mapData.size(); i++){
printf("%s\n", _mapData[i].c_str());
}
printf("\n");
}
void Map::checkMovement(char input, Player &aPlayer){
int x;
int y;
aPlayer.getLocation(x,y);
char aLocation;
switch(input) {
case 'w':
case 'W': //If 1 up from the player token is a '.' then we move him up
//via a different function
//Otherwise we do nothing.
aLocation = returnLocation(x,y-1);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y-1][x] = '#';
aPlayer.setLocation(x,y-1);
}
else
cout<<"Can't go here!"<<endl;
break;
case 'a':
case 'A':
aLocation = returnLocation(x-1,y);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y][x-1] = '#';
aPlayer.setLocation(x-1,y);
}
else
cout<<"Can't go here!"<<endl;
break;
case 's':
case 'S':
aLocation = returnLocation(x,y+1);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y+1][x] = '#';
aPlayer.setLocation(x,y+1);
}
else
cout<<"Can't go here!"<<endl;
break;
case 'd':
case 'D':
aLocation = returnLocation(x+1,y);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y][x+1] = '#';
aPlayer.setLocation(x+1,y);
}
else
cout<<"Can't go here!"<<endl;
break;
default:
cout<<"Invalid input";
system("PAUSE");
break;
}
}
char Map::returnLocation(int x, int y){
cout<<x<<endl;
cout<<y<<endl;
char aSpot = _mapData[y][x];
return aSpot;
}
Map.h
#pragma once
#include <vector>
#include <fstream>
#include <string>
#include <tuple>
#include <ctime>
#include <random>
#include "Player.h"
#include "Monster.h"
using namespace std;
class Map
{
public:
Map(); //Constructor
void load(string levelName);
void obtainSpawningLocations(char characterToken, Character &aCharacter);
void checkMovementMonsters(char input, Monster &aMonster);
//void obtainSpawningLocationsForMonsters(char characterToken, Monster aMonster);
void print();
void checkMovement(char input, Player &aPlayer);
void movement(char characterToken);
char returnLocation(int x,int y);
// int numberOfSpawnPoints;
private:
vector <string> _mapData;
Player _player;
Monster _monster;
};
Monster.cpp
#include <iostream>
#include <string>
#include "Monster.h"
using namespace std;
Monster::Monster(){
}
void Monster::moveAround(){
cout<<"Monster Mash"<<endl;
}
Monster.h
#pragma once
#include <string>
#include "Character.h"
class Monster: public Character{
public:
Monster();
virtual void moveAround();
protected:
char _token = 'M';
int _x;
int _y;
};
Werewolf.cpp
#include <iostream>
#include <string>
#include "Werewolf.h"
using namespace std;
Werewolf::Werewolf(){
}
void Werewolf::moveAround(){
cout<<"Werewolf moving around"<<endl;
}
Werewolf.h
#pragma once
#include <string>
#include "Character.h" //For inheritance/polymorphism
#include "Monster.h"
class Werewolf: public Monster{
public:
Werewolf();
void moveAround();
private:
char _token = 'W';
};
Vampire.cpp
#include <iostream>
#include <string>
#include "Vampire.h"
using namespace std;
Vampire::Vampire(){
}
void Vampire::moveAround(){
cout<<"Vampire moving around"<<endl;
}
Vampire.h
#pragma once
#include <string>
#include "Character.h" //For inheritance/polymorphism
#include "Monster.h"
class Vampire: public Monster{
public:
Vampire();
virtual void moveAround();
private:
char _token = 'V';
};
Player.cpp
Player::Player(){
}
Player.h
#pragma once
#include <string>
#include "Character.h"
using namespace std;
class Player : public Character {
public:
Player();
protected:
int _x;
int _y;
char _token = '#';
};
Main
#include <iostream>
#include "GameSystem.h"
using namespace std;
int main()
{
GameSystem gameSystem("LevelOne.txt");
gameSystem.startGame();
return 0;
}
The level text file:
############################################
#..........................................#
#..........................................#
#...........................^..............#
#..........................................#
#......................#...................#
#......................#...................#
#......................#...................#
#............^.........#...................#
#......######..........#..&................#
#......\...............#...................#
#......................#...................#
#..........................................#
#..........................................#
############################################
There is no virtual dispatch happening on _theMonsters[i].moveAround(). You need to have an array of pointers to objects of type monster. In fact, there are quite some problems in the way you try to set up the class hierarchy, like, having identically named member variables in derived classes.
There are a couple of issues here.
Monster::_token, Werewolf::_token, and Vampire::_token are all different variables. A Werewolf object has both Monster::_token and Werewolf::_token.
Monster _theMonsters[5] is an array of 5 Monster objects. It will never be a Vampire or a Werewolf, always a Monster. There is no virtual dispatch to be done since the objects will always be the same type: Monster.
Virtual dispatch only applies to pointers and references. To make this work, you'll need to use an array of pointers to Monsters: Monster* _theMonsters[5]. Then you can fill it like _theMonsters[i] = new Vampire(). If you do this, you'll need to remember to delete the objects when you're done with them, or you could use a smart pointer like std::unique_ptr or std::shared_ptr instead of raw Monster*s.

why does push_back vomit a char in the string member in of upcasted object?

i am making a rock paper & scissors game. Contains 3 classes as below:
Human class:- user puts number of games he wants to play and the choices respectively
Computer class:- Plays the same number of game as human but always plays 'ROCK'.
RandomComputer class :- Derived class of computer class, but plays Random Moves or choices.
When i pass any 2 object, a Human and Computer to Refree class it makes a decision by comparing each moves of two players.
Refree Decision method works perfect when (Human, Computer) passed BUT unexpected strange output when passed (Human,RandomComputer).
EXAMPLE:- user input: 3 R P S
output when Refree(Human A, Computer B) : Tie Win Lose
output when Refree(Human A, RandomComputer C): Lose ' ' Win
#ifndef _HUMAN_H
#define _HUMAN_H
#include <string>
#include <iostream>
using namespace std;
class Human{
public:
Human();
Human(int number, string game);
public:
int h_number;
string h_game;
};
#endif //_HUM
//=========HUMAN.CPP=====
#include "human.h"
Human::Human(int number, string game){
h_number = number;
h_game = game;
}
//========COMPUTER.h=====
#ifndef _COMPUTER_H
#define _COMPUTER_H
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Computer{
public:
Computer();
Computer(int number);
int get_c_number();
public:
string c_game;
int c_number;
};
#endif //_COMPUTER_H
//========COMPUTER.CPP=====
#include "computer.h"
Computer::Computer(){
}
Computer::Computer(int number){
c_number = number;
for(int i=0; i<c_number; i++)
{
c_game.push_back('R');
}
}
int Computer::get_c_number()
{
return c_number;
}
//=============RANDOMCOMPUTER.H========
#ifndef _RANDOMCOMPUTER_H
#define _RANDOMCOMPUTER_H
#include "computer.h"
#include <string>
#include <iostream>
#include <time.h>
#include <ctime>
#include <stdlib.h>
using namespace std;
class RandomComputer:public Computer{
public:
RandomComputer();
RandomComputer(int number);
private:
static const char r_games[3];
};
#endif //_RANDOMCOMPUTER_H
//===============RANDOMCOMPUTER.CPP=========
#include "randomcomputer.h"
const char RandomComputer::r_games[3]= {'R','P','S'};
RandomComputer::RandomComputer(){}
RandomComputer::RandomComputer(int number){
c_number = number;
srand ( time(NULL) );
for(int i=0; i<c_number; i++)
{
int RandIndex = rand() % 3;
c_game.push_back(r_games[RandIndex]);
}
}
//==============REFREE.H======
#ifndef _REFREE_H
#define _REFREE_H
#include "computer.h"
#include <iostream>
#include <string>
#include "human.h"
#include "randomcomputer.h"
using namespace std;
class Refree{
public:
Refree();
Refree (Human h_temp, Computer c_temp);
void decision();
Human *x;
Computer *y;
private:
int r_number;
string output;
};
#endif //_REFREE_H
//============REFREE.CPP========
#include "refree.h"
#include <iostream>
#include <string>
Refree::Refree(){}
Refree::Refree (Human h_temp, Computer c_temp){
x = &h_temp;
y = &c_temp;
r_number = x->h_number;
cout<<"HUMAN CHOICES: "<<x->h_game<<" COMPUTER CHOICES: "<<y->c_game<<endl;
}
void Refree::decision(){
for(int i =0; i<r_number; i++){
cout<<x->h_game[i]<<"-----------------------"<<y->c_game[i]<<endl;
}
for(int j =0; j<r_number; j++)
{
cout<<x->h_game[j]<<"---COMPARING WITH---"<<y->c_game[j]<<endl;
if(x->h_game[j] == 'R')
{
if(y->c_game[j] == 'P')
{
output.push_back('L');
output.push_back(' ');
}
else if(y->c_game[j]=='S')
{
output.push_back('W');
output.push_back(' ');
}
else if(y->c_game[j]=='R')
{
output.push_back('T');
output.push_back(' ');
}
}
else if(x->h_game[j] == 'P')
{
if(y->c_game[j] == 'P')
{
output.push_back('T');
output.push_back(' ');
}
else if(y->c_game[j]=='S')
{
output.push_back('L');
output.push_back(' ');
}
else if(y->c_game[j]=='R')
{
output.push_back('W');
output.push_back(' ');
}
}
else if(x->h_game[j] == 'S')
{
if(y->c_game[j] == 'P')
{
output.push_back('W');
output.push_back(' ');
}
else if(y->c_game[j]=='S')
{
output.push_back('T');
output.push_back(' ');
}
else if(y->c_game[j]=='R')
{
output.push_back('L');
output.push_back(' ');
}
}
}//forrr looop
size_t endpos = output.find_last_not_of(" \t");
if( string::npos != endpos )
{
output = output.substr( 0, endpos+1 );
}
cout<<output<<endl;
output.clear();
}
//============================MAIN.CPP====================
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <algorithm>
#include "human.h"
#include "computer.h"
#include "refree.h"
#include "randomcomputer.h"
using namespace std;
int main()
{
string user_input;
getline(cin, user_input);
//converting the numbers in the string to int.
int number_of_games = atoi(user_input.c_str());
//remove the digits and the spaces
user_input.erase(remove_if(user_input.begin(), user_input.end(), ::isdigit), user_input.end());
user_input.erase(remove_if(user_input.begin(), user_input.end(), ::isspace), user_input.end());
Human player_1(number_of_games, user_input); //HUMAN PLAYER OBJECT
Computer computer_1(number_of_games); // COMPUTER PLAYER TAKES ONLY innt number because it will always play ROCK in this class
Refree refree_1(player_1, computer_1);
refree_1.decision();
RandomComputer random_computer(number_of_games);
cout<<"HERE IS THE RANDOM CHOICES FROM COMPUTER AI: "<<random_computer.c_game<<endl; // make random choices instead of only ROCKS.
Refree refree_2(player_1, random_computer);
refree_2.decision();
return 0;
}
You are copying your Human and Computer object when passing them to the Referee:
Refree::Refree (Human h_temp, Computer c_temp){
You should use either const references or pointers here.