simple race game with dynamic array in c++ - c++

I was doing homework for a C++ game that we have to do from CO SCI 136 class and the instructions states:
Modify your Homework 4 Problem 1 solution thus:
Replace the array with a dynamic array
Read the winning points M from a file
Read the number of players N from a file
Read the player names from a file.
I am using Visual Studio 2017 and I am having trobule with these errors:
Error C2664 'void Player::setName(std::string &)': cannot convert argument 1 from 'const std::string' to 'std::string &' player.cpp 7
Error C2511 'void Player::setName(const std::string &)': overloaded member function not found in 'Player' player.cpp 18
Error C2597 illegal reference to non-static member 'Player::name' player.cpp 19
Is there any way to fix these errors?
Here are my codes of
player.h
#pragma once
#include <string>
using namespace std;
class Player
{
private:
string name;
int points;
bool skipturn = false;
public:
Player(const string& new_name = "No Name");
string getName() const;
int getPoints() const;
void setName(string& new_name);
void setPoints(int new_points);
void setLossHalfPoints();
void setSkipTurn(bool isSkip);
bool isSkipTurn();
};
player.cpp
#include <string>
using namespace std;
#include "player.h"
Player::Player(const string& new_name)
{
setName(new_name);
}
string Player::getName() const
{
return name;
}
int Player::getPoints() const
{
return points;
}
void Player::setName(const string& new_name)
{
name = new_name;
}
void Player::setPoints(int new_points)
{
points = new_points;
}
void Player::setLossHalfPoints()
{
this->points /= 2;
}
void Player::setSkipTurn(bool isSkip)
{
this->skipturn = isSkip;
}
bool Player::isSkipTurn()
{
return this->skipturn;
}
source.cpp
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <iomanip>
#include <random>
#include<fstream>
#include "player.h"
using namespace std;
int main()
{
int M;
int N;
Player *player; //Declaring as a dynamic array
player = new Player[N];
string *names;
names = new string[N];
ifstream file, file1, file2; //opening the file in read mode
string line;
file.open("Mdata.dat");
file >> M; //Reading the M data from the file
file.close();
file1.open("Ndata.dat");
file1 >> N; //Reading the N data from the file
file1.close();
file2.open("names.dat");
if (file2.is_open()) //if the file is open
{
while (!file2.eof()) //while the end of file is NOT reached
{
getline(file2, line); //get one line from the file
for (int i = 0; i<N; i++)
{
names[i] = line; //reading names from file into names array
}
}
file2.close();
}
for (int i = 0; i < N; i++) //setting the player names from names array
{
player[i].setName(names[i]); player[i].setPoints(0);
}
default_random_engine dre(17890714);
uniform_int_distribution<int> player_uid(0, N - 1);
uniform_int_distribution<int> dice_uid(1, 6);
int index = player_uid(dre);
do
{
index = (index + 1) % N;//implements circular array
if (player[index].isSkipTurn())
{
cout << player[index].getName() << '/' << setw(2) << "skip turn" << endl;
player[index].setSkipTurn(false);// clear skip turn
index = (index + 1) % N;//implements circular array
}
int die1 = dice_uid(dre);
int die2 = dice_uid(dre);
int points = player[index].getPoints();
player[index].setPoints(points + die1 + die2);
if (player[index].getPoints() > M)
{
player[index].setLossHalfPoints();// set half of then points
player[index].setSkipTurn(true);// set skip turn
cout << player[index].getName() << '/' << setw(2) << player[index].getPoints() << '/' << setw(2) << player[index].getPoints() * 2 << endl;
}
else {
cout << player[index].getName() << '/' << setw(2) << die1 + die2 << '/' << setw(2) << player[index].getPoints() << endl;
}
} while (player[index].getPoints() != M);
cout << player[index].getName() << " wins" << endl;
system("pause");
return 0;
}

Let's look at the compiler error.
Error C2664 'void Player::setName(std::string &)': cannot convert argument 1 from 'const std::string' to 'std::string &' player.cpp 7
It is complaining that it cannot convert const std::string to std::string when calling the setName() function at line 7 of player.cpp. But we have a setName function in the player class, right? What's wrong?
If you look at it more carefully in your Player.h, the declaration of the function setName is missing the const attribute.
void setName(string& new_name);
If you add const to this that will solve it.

Related

C++ not allowing me to use a private member variable in a public function

I am trying to develop a game in C++. For some reason, I can't access and update other variables as the value of the private member variables within a member public function of the class. Why is this the case? The variables mentioned are the ones prefixed with m_. Is this something that is not allowed in C++? I thought this would be allowed!
Player.cpp
#include "Player.h"
#include "lib/json.hpp"
using namespace std;
void Player::createPlayer(std::string name, std::string playerFilePath)
{
m_name = name;
m_playerFilePath = playerFilePath;
json j;
j["name"] = m_name;
j["health"] = 100;
j["levelOn"] = 1;
j["damageDone"] = 10;
std::string dataString = j.dump();
std::string filename = playerFilePath + m_name + ".json";
std::ofstream out(filename);
out << dataString;
out.close();
cout << "Savegame file " << filename << " created" << endl;
}
void Player::loadPlayerData(std::string playerFilePath)
{
std::ifstream t(playerFilePath);
std::string str ((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
auto j = json::parse(str);
m_name = j["name"];
m_health = j["health"];
m_levelOn = j["levelOn"];
m_damageDone = j["damageDone"];
cout << "Player data loaded" << endl;
}
void Player::levelUp()
{
m_levelOn++;
m_health += 10;
m_damageDone += 5;
}
void savePlayerData()
{
std::ifstream t(m_playerFilePath);
std::string str ((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
auto j = json::parse(str);
j["name"] = m_name;
j["health"] = m_health;
j["levelOn"] = m_levelOn;
j["damageDone"] = m_damageDone;
std::string stringToWrite = j.dump();
std::string filename = m_playerFilePath + m_name + ".json";
std::ofstream out(filename);
out << stringToWrite;
out.close();
cout << "Game saved" << endl;
}
Player.h
#pragma once
#ifndef PLAYER_H
#define PLAYER_H
#include <fstream>
#include "Enemy.h"
#include <iostream>
#include <streambuf>
#include "lib/json.hpp"
using json = nlohmann::json;
class Player {
private:
int m_health;
int m_damageDone;
int m_levelOn;
std::string m_playerFilePath;
std::string m_name;
public:
void createPlayer(std::string name, std::string playerFilePath);
void dealDamage();
void takeDamage();
void levelUp();
std::string getPlayerFilePath();
void loadPlayerData(std::string playerFilePath);
void savePlayerData();
};
#endif
The g++ error message
Player.cpp: In function ‘void savePlayerData()’:
Player.cpp:53:21: error: ‘m_playerFilePath’ was not declared in this scope
std::ifstream t(m_playerFilePath);
^
Player.cpp:59:17: error: ‘m_name’ was not declared in this scope
j["name"] = m_name;
^
Player.cpp:60:19: error: ‘m_health’ was not declared in this scope
j["health"] = m_health;
^
Player.cpp:61:20: error: ‘m_levelOn’ was not declared in this scope
j["levelOn"] = m_levelOn;
^
Player.cpp:62:23: error: ‘m_damageDone’ was not declared in this scope
j["damageDone"] = m_damageDone;
^
Player.cpp:66:28: error: ‘m_playerFilePath’ was not declared in this scope
std::string filename = m_playerFilePath + m_name + ".json";
The function savePlayerData doesn't belong to the Player class. Insert Player:: before your savePlayerData function.

Calling member function with reference to pointer

I have a class CaloReader that creates a pointer _calo to an object called Calorimeter containing a grid of cells with an ID number. This pointer is then used to set an ID number to each cell. Futhermore, I have a accessor const Calorimeter& calo() that returns a reference of this pointer. Now, I want to create a function dumpReadoutMap() that prints out all ID numbers of all cells. The function is called from my main file as follows:
#include <iostream>
#include "CaloCell.hh"
#include "CaloGrid.hh"
#include "Point.hh"
#include "Calorimeter.hh"
#include "CaloReader.hh"
int main(){
CaloReader r("calo.dat");
r.calo().dumpReadoutMap();
}
The problem with my code is that the complirer gives the following error:
error: ‘const class Calorimeter’ has no member named ‘dumpReadoutMap’
r.calo().dumpReadoutMap();
The only relevant file for this question is the below as the other ones are correct and cannot be changed.
#ifndef CALOREADER_HH
#define CALOREADER_HH
#include <iostream>
#include <fstream>
#include "Calorimeter.hh"
#include "CaloReaderException.hh"
#include <string>
#include <iomanip>
class CaloReader {
public:
CaloReader(const char* file): _file(file) {
Calorimeter* _calo = 0;
ifstream _file(file);
std::string word;
_file >> word;
_file >> word; //Reads in next word.
if(word=="SIZE") {
int size_x;
int size_y;
_file >> size_x;
_file >> size_y;
_calo = new Calorimeter(size_x,size_y);
}
_file >> word;
while(word=="POSITION") {
int readoutID;
int ix;
int iy;
_file >> readoutID >> ix >> iy;
//std::cout << word << " " << readoutID << " " << ix << " " << iy << std::endl;
_calo->grid().cell(ix,iy)->setID(readoutID);
_file >> word;
}
}
~CaloReader() {}
const Calorimeter& calo() const {
return *_calo;
}
void dumpReadoutMap(std::ostream& os = std::cout) {
for(int x =0; x<size_x; x++) {
for(int y=0; y<size_y; y++) {
os << std::setw(6) << grid().cell(x,y)->getID();
}
os << std::endl;
}
}
private:
Calorimeter* _calo;
std::ifstream _file;
std::string word;
};
#endif
dumpReadoutMap is a method in CaloReader class. So it must be called from a CaloReader object. You should use:
CaloReader r("calo.dat");
r.dumpReadoutMap();
Since calo() returns a const reference, you can't call a non-const member function with it. It's disappointing the error message doesn't explain clearly what the error is.

C++: error 'std::string' is private

So, for class, I have to write a program that simulates a horse race. It's our first major project involving classes. I'm stuck receiving the error mentioned in the subject. Now, I have struggled with pointers since they were introduced, so I have zero doubt this is where my overall problem lies. I've asked my professor for help, but he's not replying to my emails. I've also contacted friends, etc. and no one is getting back to me.
This is my header file (Horse.h):
#ifndef HORSE_H
#define HORSE_H
#include <string>
class Horse
{
private:
std::string name;
std::string jockey;
int maxSpeed;
int distanceTraveled;
int racesWon;
public:
Horse(std::string, std::string);
void runOneSecond(int);
void sendToGate();
void displayHorse (double);
};
#endif // HORSE_H
Here is my Horse.cpp:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "Horse.h"
using namespace std;
Horse::Horse(string name, string jockey)
{
srand (time(NULL));
int maxSpeed = rand() % 30 + 1;
distanceTraveled = 0;
};
void Horse::runOneSecond(int maxSpeed)
{
srand (time(NULL));
distanceTraveled = rand() % maxSpeed;
};
void Horse::sendToGate()
{
distanceTraveled = 0;
};
void Horse::displayHorse(double raceDistance)
{
int percentage;
for (int i = 0; i < numberOfHorses; i++)
{
cout << "|";
}
};
And here is my main.cpp:
#include <iostream>
#include <string>
#include <cctype>
#include "Horse.h"
using namespace std;
int main()
{
double raceDistance = 0;
int numberOfHorses = 0;
char choice = 'Y';
string name;
string jockey;
cout << "Enter the number of horses for the race: ";
cin >> numberOfHorses;
Horse** horsePtr = new Horse* [numberOfHorses];
// Trouble section.
for (int i = 0; i < numberOfHorses; i++)
{
cout << "Fill in the name of the horse: ";
cin >> horsePtr[i]->name;
cout << "Fill in the name of the jockey: ";
cin >> horsePtr[i]->jockey;
}
cout << "How long should the race be (in meters): ";
cin >> raceDistance;
cout << endl;
cout << "Start!" << endl;
for (int i = 0; i < numberOfHorses; i++)
{
horsePtr[i]->sendToGate();
}
for (int i = 0; i < numberOfHorses; i++)
{
horsePtr[i]->displayHorse(raceDistance);
}
cout << "Show the next second of the race? ";
cin >> choice;
while(toupper(choice) == 'Y')
{
if (toupper(choice) == 'Y')
{
for (int i = 0; i < numberOfHorses; i++)
{
horsePtr[i]->runOneSecond(maxSpeed);
horsePtr[i]->displayHorse(raceDistance);
}
}
}
return 0;
}
Here is the error:
Horse.cpp: In member function ‘void Horse::displayHorse(double)’:
Horse.cpp:29:23: error: ‘numberOfHorses’ was not declared in this scope
for (int i = 0; i < numberOfHorses; i++)
^
In file included from main.cpp:4:0:
Horse.h: In function ‘int main()’:
Horse.h:8:17: error: ‘std::string Horse::name’ is private
std::string name;
^
main.cpp:25:25: error: within this context
cin >> horsePtr[i]->name;
^
In file included from main_dmj8t6.cpp:4:0:
Horse.h:9:17: error: ‘std::string Horse::jockey’ is private
std::string jockey;
^
main.cpp:27:25: error: within this context
cin >> horsePtr[i]->jockey;
^
main.cpp:55:35: error: ‘maxSpeed’ was not declared in this scope
horsePtr[i]->runOneSecond(maxSpeed);
^
You cannot access a private member of a class. In your example, your Horse class contains 5 private members:
class Horse
{
private:
std::string name;
std::string jockey;
int maxSpeed;
int distanceTraveled;
int racesWon;
public:
};
These private members can be accessed within the Horse class methods, and by any friend classes; however: nothing else can access them.
int main()
{
// Trouble section.
for (int i = 0; i < numberOfHorses; i++)
{
cout << "Fill in the name of the horse: ";
cin >> horsePtr[i]->name; <--
cout << "Fill in the name of the jockey: ";
cin >> horsePtr[i]->jockey; <--
}
}
On the two lines marked, you are attempting to access the private members of Horse and the compiler won't allow it.
Consider making those variables public to Horse, or providing setter functions for them:
class Horse
{
private:
std::string name;
std::string jockey;
int maxSpeed;
int distanceTraveled;
int racesWon;
public:
void SetName(std::string s) { name = s; }
void SetJockey(std::string s) { jockey = s; }
};
int main()
{
std::string jockeyName;
std::cout << "Enter a name for the jockey: ";
std::cin >> jockeyName;
Horse* h = new Horse;
h->SetJockey(jockeyName);
}
You are providing a public constructor for Horse that takes two std::string though (neither which you are using) so you could just pass the relevant information to the Horse:
Horse::Horse(std::string n, std::string j) : name(n), jockey(j)
{
// Other things...
}
int main()
{
Horse* h = new Horse("Phar Lap", "Jim Pike");
}
Note that my two examples are just matching your current code. Your arrays should be replaced by std::vector and pointers, if required, should be replaced by std::unique_ptr (or std::shared_ptr, whichever suits your needs).

Read Files using a function C++

I'd like to know how to read a file using streams but also using them inside a function.
So far my code is;:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
void burbuja(int[]);
void imprimeArreglo (int[],int);
void leeArchivo(string&);
int arreglo[10];
int i;
void burbuja (int a[])
{
int i,j;
for(i=0;i<10;i++)
{
for(j=0;j<i;j++)
{
if(a[i]>a[j])
{
int temp=a[i]; //swap
a[i]=a[j];
a[j]=temp;
}
}
}
}
void imprimeArreglo(int a[],int tam)
{
for(int i=0;i<tam;i++)
cout << a[i] << " ";
}
void leeArchivo(string& nombre)
{
string filename = nombre;
ifstream myfile(filename);
string line;
if (myfile.is_open()) {
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
}
int main()
{
string nombre = "arr.txt";
leeArchivo(nombre);
cin >> i ;
return 0;
}
I'd like to be able to call leeArchivo("arr.txt") from the main method.
With this I get the errors:
Error: bubble.cpp(37,14):'ifstream' is not a member of 'std'
Error: bubble.cpp(37,19):Statement missing ;
Error: bubble.cpp(39,20):Undefined symbol 'file'
Error: bubble.cpp(39,25):Could not find a match for 'std::getline(undefined,std::basic_string<char,std::string_char_traits<char>,std::allocator<char>>)'
What am I missing here? (I'm new to C++)
The file I'm trying to read has the following structure:
<number>
<number> <number> <number> ...
E.G.:
5
19 28 33 0 1
=========================================
EDIT:
I'm using Borland C++ 5.02
EDIT 2:
Updated code, using Geany Now error is: BUBBLE.cpp:38:25: error: no matching function for call to 'std::basic_ifstream<char>::basic_ifstream(std::string&)'
That's particularly odd behavior with ifstream. Try this edit:
void leeArchivo(const string&);
void leeArchivo(const string& nombre)
{
ifstream file(nombre.c_str());
string line;
while(getline(file,line)) {
cout << line << endl;
}
}
int main()
{
leeArchivo("arr.txt");
return 0;
}
Also, use:
#include <cstdlib>
Instead of:
#include <stdlib.h>

crazy C++ compiler error messages about a copy constructor from MinGW32

I'm a beginning C++ student and I'm using jGRASP and have installed MinGW32 because we turn our assignments remotely into a Linux machine so this helps ensure that it'll work properly by simulating a Linux environment in Windows or something. For MinGW32 I installed the "base package" and then manually selected the C++ compiler option. In jGRASP I went to settings>>PATH/CLASSPATH>>workspace and added a new PATH directory to C:\MinGW\mingw32\bin so that it'll know where the g++ compiler is.
I get these crazy error messages upon compiling in jGRASP that I can't make much sense of. I think it has something to do with my header because of the iostream.
#include <string.h>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
Here are the compiler error messages:
ios:42:0,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\ostream:38,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\iostream:39,
from lab1.cpp:6:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\ios_base.h: In copy constructor 'std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)':
ios_base.h:786:5: error: 'std::ios_base::ios_base(const std::ios_base&)' is private
ios_base(const ios_base&);
^
ios:44:0,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\ostream:38,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\iostream:39,
from lab1.cpp:6:
basic_ios.h:66:11: error: within this context
class basic_ios : public ios_base
^
In file included from lab1.cpp:8:0:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\fstream: In copy constructor 'std::basic_ifstream<char>::basic_ifstream(const std::basic_ifstream<char>&)':
fstream:427:11: note: synthesized method 'std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)' first required here
class basic_ifstream : public basic_istream<_CharT, _Traits>
^
ios:43:0,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\ostream:38,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\iostream:39,
from lab1.cpp:6:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\streambuf: In copy constructor 'std::basic_filebuf<char>::basic_filebuf(const std::basic_filebuf<char>&)':
streambuf:802:7: error: 'std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]' is private
basic_streambuf(const basic_streambuf& __sb)
^
In file included from lab1.cpp:8:0:
fstream:72:11: error: within this context
class basic_filebuf : public basic_streambuf<_CharT, _Traits>
^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\fstream: In copy constructor 'std::basic_ifstream<char>::basic_ifstream(const std::basic_ifstream<char>&)':
fstream:427:11: note: synthesized method 'std::basic_filebuf<char>::basic_filebuf(const std::basic_filebuf<char>&)' first required here
class basic_ifstream : public basic_istream<_CharT, _Traits>
And here is my code so far:
// ----------------------------------------------------------------------------
// You write meaningful doxygen comments and assumptions
#include <string.h>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int const MAXSIZE = 100; // maximum number of records in total
int const MAXLENGTH = 31; // maximum string length
int const MAXGRADE = 100; // highest possible grade
int const LOWGRADE = 0; // lowest possible grade
int const GROUP = 10; // group amount
int const HISTOGRAMSIZE = (MAXGRADE-LOWGRADE)/GROUP + 1; // grouped by GROUP
struct StudentType { // information of one student
int grade; // the grade of the student
char last[MAXLENGTH]; // last name (MAXLENGTH-1 at most)
char first[MAXLENGTH]; // first name (MAXLENGTH-1 at most)
};
// prototypes go here
bool sortInput(ifstream, StudentType, int);
void displayList(StudentType, int);
/*setHistrogram();
displayHistogram();
findAverage();*/
//------------------------------- main ----------------------------------------
int main() {
StudentType students[MAXSIZE]; // list of MAXSIZE number of students
int size = 0; // total number of students
int histogram[HISTOGRAMSIZE]; // grades grouped by GROUP
int average = 0; // average exam score, truncated
// creates file object and opens the data file
ifstream infile("data1.txt");
if (!infile) {
cout << "File could not be opened." << endl;
return 1;
}
// read and sort input by last then first name
bool successfulRead = sortInput(infile, students, size);
// display list, histogram, and class average
if (successfulRead) {
displayList(students[], size);
// setHistogram(... you figure parameters ...);
// displayHistogram(... you figure parameters ...);
// average = findAverage(... you figure parameters ...);
cout << "Average grade: " << average << endl << endl;
}
return 0;
}
bool sortInput(ifstream infile, StudentType students[], int size)
{
while(infile)
{
StudentType temp;
infile >> temp.last >> temp.first >> temp.grade;
//for(int i = MAXSIZE-1; i > MAXSIZE-1-size; i--)
for(int i = size; i > 0; i--)
{
if(strcmp(temp.last, students[i].last) < 0)
{
//copy current name and grade down
//strcopy(students[i+1].last, students[i].last);
students[i+1] = students[i];
}
else if(strcmp(temp.last, students[i].last) == 0 && strcmp(temp.first, students[i].first) < 0))
{
//copy/assign current name and grade down
students[i+1] = students[i];
}
else
{
//found right place, break out of loop
break;
}
}
//now that you've made room, insert (copy) new name into correct sorted position
students[i] = temp;
}
return true;
}
void displayList(StudentType students[], int size)
{
cout << "List of names sorted:" << end1;
for(int i = 0; i < size; i++)
{
cout << " " << student[i].grade << " " << students[].last << " " << students[i].first << end1;
}
}
// ----------------------------------------------------------------------------
// functions with meaningful doxygen comments and assumptions go here
I ran into this myself. The problem is that sortInput takes an ifstream by value, instead of by reference. ifstreams don't like to be copied. Just change the declaration to:
bool sortInput(ifstream&, StudentType, int);
Note the &