Vector serialization in ostream - c++

Problem
When I load game and hit ship the game shows the ship is missed.This problem doesnt show up in normal game(without load).
I have serializaiotn for loading game board for user and opponent.
I think the error is about loading in serialzation vector but i have no idea how to do this.
vector is portected object in board class.
Implementation of serialzation
ostream &operator<<(ostream &out, const Board &b) {
for (int row = 0; row < BOARDSIZE; row++) {
for (int col = 0; col < BOARDSIZE; col++) {
out << b.board[row][col]<< ' ';
}
out << '\n';
}
out << '\n';
return out;
}
istream & operator>>(istream & in, Board &b){
for (int row = 0; row < BOARDSIZE; row++) {
for (int col = 0; col < BOARDSIZE; col++) {
in >> b.board[row][col];
}
}
return in;
}
And this is my function for attack made for player:
getSpaceValue return the value of board for example M is miss,X hit etc.
recordHit return boolean,if user hitted the ship it returns true and change board value in this palce to X if not returns false(miss).
void Game::atack(Board &b){
int attemptCounter = 0;
int xEntry, yEntry;
bool goodMove=false;
string entryTemp;
while(!goodMove){
if(attemptCounter>0)
cout << "Wykonales juz ten ruch sprobuj jeszcze raz"<<endl;
cout <<"Wpisz lokalizacje statku ktory chcesz zatakowac "<<endl;
entryTemp = validLoc();
xEntry=static_cast<int>(entryTemp[0]);
yEntry=static_cast<int>(entryTemp[1]);
cout<<"Get value wartoswc: "<<(b.getSpaceValue(xEntry-A_ASCII,yEntry-N_ASCII)!=HITTED && b.getSpaceValue(xEntry-A_ASCII, yEntry-N_ASCII)!=MISSED)<<endl;
if(b.getSpaceValue(xEntry-A_ASCII,yEntry-N_ASCII)!=HITTED && b.getSpaceValue(xEntry-A_ASCII, yEntry-N_ASCII)!=MISSED){
b.recordHit(xEntry-A_ASCII, yEntry-N_ASCII);
goodMove = true;
}
attemptCounter++;
}
}
And thats the recordHit function on the normal game(whiut loading the board) evrything works fine but when we load its returns always false even if ship is hitted.
bool Board::recordHit(int x, int y){
for(int i=0; i<SHIPS_NUM;i++){
if(ship[i].recordHit(x,y)){
board[y][x]=HITTED;
return true;
}
}
board[y][x]=MISSED;
return false;
}
Edit:
Board::Board(){
for(int i=0; i<BOARDSIZE; i++){
for(int j=0; j<BOARDSIZE;j++){
board[i][j]=WATER;
}
}
for(int i=0;i<SHIPS_NUM;i++){
ship.push_back(Ship5(SHIP_LENGTH[i]));
}
}
Board.h
#include <iostream>
#include <vector>
#include "const.h"
#include "ship.h"
using namespace std;
/**
* Klasa planszy oraz jej metody
*/
class Board{
protected:
char board[BOARDSIZE][BOARDSIZE];
vector<Ship5> ship;
public:
Board();
Board& operator=(const Board &board1);
~Board()= default;
void printBoard();
void showUnhiddenBoard();
bool setShip(int shipID, int x, int y, bool horizontal);
bool recordHit(int x, int y);
int HitsNumber();
int HitsMiss();
char getSpaceValue(int x,int y);
friend ostream & operator<<(ostream & out,const Board & b);
friend istream & operator>>(istream & in, Board &b);
};
Posibble values of board
const char WATER = '~';
const char SHIP = '-';
const char MISSED = 'M';
const char HITTED = 'X';
const char UNKNOWN = '?';

Related

Template Class and Auxiliary Streaming In/Out Functions

I'm currently trying to create a template class in C++ and i originally had code that worked with a header file and a CPP file however now that im trying to move my functions from the CPP file to the header file i'm getting some errors. I have two auxiliary functions to stream in and out to the console and the class parameter in the function is showing an error.
ostream& operator<<(ostream& sout, Grid& grid)
{
grid.SaveGrid(sout);
}
void operator>>(istream& sin, Grid &grid)
{
grid.LoadGrid(sin);
}
This is how they originally looked and worked before changing my class to a template class.
The part of the parameters above that doesn't work is this.
"Grid &grid"
FULL CODE
#pragma once
#include <fstream>
using namespace std;
template<class T>
class Grid
{
public:
//Grid();
//~Grid();
Grid::Grid()
{
}
Grid::~Grid()
{
}
//void LoadGrid(const char filename[]);
//void LoadGrid(istream& sin);
void Grid<T>::LoadGrid(const char filename[])
{
ifstream file(filename);
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
file >> m_grid[x][y];
}
}
file.close();
}
void Grid<T>::LoadGrid(istream& sin)
{
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
sin >> m_grid[x][y];
}
}
}
//void SaveGrid(const char filename[]);
//void SaveGrid(ostream& sout);
void Grid<T>::SaveGrid(const char filename[])
{
ofstream file(filename);
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
file << m_grid[x][y] << " ";
}
file << endl;
}
file.close();
}
void Grid<T>::SaveGrid(ostream & sout)
{
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++)
{
sout << m_grid[x][y] << " ";
}
sout << endl;
}
}
private:
T m_grid[9][9];
};
ostream& operator<<(ostream& sout, Grid<T>& grid)
{
grid.SaveGrid(sout);
}
void operator>>(istream& sin, Grid<T>& grid)
{
grid.LoadGrid(sin);
}
ostream& operator<<(ostream& sout, Grid& grid)
does not work because Grid is a class template, not a class. You need to use:
template <typename T>
ostream& operator<<(ostream& sout, Grid<T>& grid)
{
grid.SaveGrid(sout);
}
To make it const correct, use
template <typename T>
ostream& operator<<(ostream& sout, Grid<T> const& grid)
{
grid.SaveGrid(sout);
}
Note that, you'll need to make SaveGrid a const member function for the above change to work.
void Grid::SaveGrid(const char filename[]) const
{
...
}
void Grid::SaveGrid(ostream& sout) const
{
...
}
Make similar changes to the other function.

Hash table doesn't read last line off of test file

I was assigned to create a chained hash table using a vector of vectors. It is designed to hold objects of type Entry. I have written all of the functions and the constructor but when I try to use the constructor that reads an input and then output it back to me in order of keys, whichever string was on the last line of the .txt file its reading from is gone. I think its a problem with my constructor because when I try to use get to get that specific value from the table before printing it its gone. I was hoping for some insight to where I might be going wrong from someone with a little more experience. Thanks. Heres my code:
Entry Header File:
#ifndef entry_h
#define entry_h
// entry.h - defines class Entry
#include <string>
#include <iosfwd>
class Entry {
public:
// constructor
Entry(unsigned int key = 0, std::string data = "");
// access and mutator functions
unsigned int get_key() const;
std::string get_data() const;
static unsigned int access_count();
void set_key(unsigned int k);
void set_data(std::string d);
// operator conversion function simplifies comparisons
operator unsigned int () const;
// input and output friends
friend std::istream& operator>>
(std::istream& inp, Entry &e);
friend std::ostream& operator<<
(std::ostream& out, Entry &e);
private:
unsigned int key;
std::string data;
static unsigned int accesses;
};
#endif /* entry_h */
Table header file:
//
// table.h
//
//
#ifndef table_h
#define table_h
#include <string>
#include <vector>
#include <algorithm>
#include "entry.h"
using namespace std;
class Table {
public:
Table(unsigned int max_entries = 100);
//Builds empty table to hold 100 entries
Table(unsigned int entries, std::istream& input);
//Builds table to hold entries, reads and puts them 1 at a time
~Table();
//Destructor
void put(unsigned int key, std::string data);
//Creates new entry for the table
//Updates if key is used
void put(Entry e);
//Creates a copy of e in the table
string get(unsigned int key) const;
//Returns string associated with key
//Returns empty string if key isnt used
bool remove(unsigned int key);
//Removes entry in given key
//Returns true of removed, false of no entry
int find(Entry e);
//index in second array that e exists, 0 if not found
friend std::ostream& operator<< (std::ostream& out, const Table& t);
//Prints each entry in the table in order of their key
private:
int size;
int num_entries;
unsigned int hashkey(unsigned int key) const;
vector<vector<Entry> > A;
};
#endif /* table_h */
Table Implementation File:
//table.cpp
#include<iostream>
#include<vector>
#include<algorithm>
#include "table.h"
using namespace std;
Table::Table(unsigned int max_entries){
max_entries = 100;
size = max_entries * 2;
A.resize(size);
}
Table::Table(unsigned int entries, std::istream& input){
size = entries*2;
A.resize(size);
num_entries = entries;
Entry temp;
for (size_t i = 0; i < entries; i++) {
input >> temp;
put(temp);
}
}
Table::~Table() {
A.clear();
}
void Table::put(unsigned int key, std::string data){
Entry e;
e.set_key(key);
e.set_data(data);
put(e);
num_entries++;
}
void Table::put(Entry e) {
if (A[hashkey(e.get_key())].empty()) {
A[hashkey(e.get_key())].push_back(e);
}
else {
for(size_t i = 0; i < A[hashkey(e.get_key())].size(); i++) {
if (A[hashkey(e.get_key())][i].get_key() == e.get_key()) {
remove(A[hashkey(e.get_key())][i].get_key());
break;
}
}
A[hashkey(e.get_key())].push_back(e);
}
}
string Table::get(unsigned int key) const {
if( A[hashkey(key)].size() == 0) {
return "";
}
else {
for (size_t i = 0; i < A[hashkey(key)].size(); i++) {
if (A[hashkey(key)][i].get_key() == key) {
return A[hashkey(key)][i].get_data();
}
else {
return "";
}
}
}
}
bool Table::remove(unsigned int key) {
for (size_t i = 0; i < A[hashkey(key)].size(); i++) {
if (A[hashkey(key)][i].get_key() == key) {
swap(A[hashkey(key)][i],A[hashkey(key)][A[hashkey(key)].size() - 1]);
A[hashkey(key)].pop_back();
num_entries--;
return true;
}
else {
return false;
}
}
}
int Table::find(Entry e) {
for (size_t i = 0; i < A[hashkey(e.get_key())].size(); i++) {
if (A[hashkey(e.get_key())][i] == e) {
return i;
}
else {
return 0;
}
}
}
ostream& operator << (ostream& out, const Table& t) {
vector<Entry> order;
for(size_t i = 0; i < t.A.size(); i++) {
for (size_t j = 0; j < t.A[i].size(); j++) {
order.push_back(t.A[i][j]);
}
}
sort(order.begin(), order.end());
for(Entry k: order) {
out << k << endl;
}
return out;
}
unsigned int Table::hashkey(unsigned int key) const{
const double c = 1.61803;
// return key % size;
return (int)(size*((key * c) - (int)(key * c)));
}

[C++]Sorting objects by class member's value

In the code shown below, in the function void printExpensiveThanT(..) i'm supposed to print out the destination, distance and the price for the offers which are more expensive than the offer T in the function, sorted in ascending order by the distance value.
I'm not sure what should i use to sort them, i experimented something with vectors but it didn't work out so i deleted it.
Any help would be appreciated.
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
class Transport {
protected:
char destination[100];
int basePrice;
int distance;
public:
Transport() {}
Transport(char *destination, int basePrice, int distance) {
strcpy(this->destination, destination);
this->basePrice = basePrice;
this->distance = distance;
}
virtual ~Transport() {}
virtual int priceTransport() = 0;
friend bool operator<(const Transport &t1, const Transport &t2) {
return t1.distance<t2.distance;
}
int getDistance(){ return distance; }
char *getDestination() { return destination; }
int getPrice() { return basePrice; }
};
class AutomobileTransport : public Transport {
private:
bool ifDriver;
public:
AutomobileTransport() {}
AutomobileTransport(char *destination, int basePrice,int distance, bool ifDriver) : Transport(destination,basePrice,distance) {
this->ifDriver = ifDriver;
}
void setIfDriver(bool ifDriver) {
this->ifDriver = ifDriver;
}
bool getIfDriver() {
return ifDriver;
}
int priceTransport() {
if(ifDriver) {
basePrice+=basePrice*20/100;
}
return basePrice;
}
friend bool operator<(const AutomobileTransport &a1, const AutomobileTransport &a2) {
return a1.distance<a2.distance;
}
};
class VanTransport: public Transport {
private:
int passengers;
public:
VanTransport() {}
VanTransport(char *destination, int basePrice, int distance, int passengers) : Transport(destination, basePrice, distance) {
this->passengers = passengers;
}
void setPassengers(int passengers) {
this->passengers = passengers;
}
int getPassengers() {
return passengers;
}
int priceTransport() {
for(int i = 0; i < passengers; i++) {
basePrice-=200;
}
return basePrice;
}
friend bool operator<(const VanTransport &k1, const VanTransport &k2) {
return k1.distance<k2.distance;
}
};
void printExpensiveThanT(Transport **offers,int n,AutomobileTransport &T) {
Transport *tmp;
for(int i = 0; i <= n; i++){
if(offers[i]->priceTransport() > T.priceTransport())
cout<<offers[i]->getDestination()<<" "<<offers[i]->getDistance()<<" "<<offers[i]->getPrice()<<endl;
}
}
int main() {
char destination[20];
int type,price,distance,passengers;
bool driver;
int n;
cin>>n;
Transport **offers;
offers=new Transport *[n];
for (int i=0; i<n; i++) {
cin>>type>>destination>>price>>distance;
if (type==1) {
cin>>driver;
offers[i]=new AutomobileTransport(destination,price,distance,driver);
} else {
cin>>passengers;
offers[i]=new VanTransport(destination,price,distance,passengers);
}
}
AutomobileTransport at("Ohrid",2000,600,false);
printExpensiveThanT(offers,n,at);
for (int i=0; i<n; i++) delete offers[i];
delete [] offers;
return 0;
}
Since you're dealing with pointers, the easiest thing to do is to use std::vector and std::sort:
#include <vector>
//...
void printExpensiveThanT(Transport **offers, int n, AutomobileTransport &T)
{
std::vector<Transport*> sortedVect;
for (int i = 0; i < n; i++)
{
if (offers[i]->priceTransport() > T.priceTransport())
sortedVect.push_back(offers[i]); // add this item to the vector
}
// sort the vector based on the dereferenced pointers and their respective
// operator <
std::sort(sortedVect.begin(), sortedVect.end(),
[](Transport* left, Transport* right) { return *left < *right; });
// print out the values
for (auto it : sortedVect)
cout << (*it).getDestination() << " " << (*it).getDistance() << " " << (*it).getPrice() << "\n";
}
Also, your original code looped one more than it should (i <= n was wrong).
Edit:
If your compiler doesn't support the C++ 11 syntax, here is an alternate solution:
#include <vector>
//...
bool Sorter(Transport* left, Transport* right)
{ return *left < *right; }
void printExpensiveThanT(Transport **offers, int n, AutomobileTransport &T)
{
std::vector<Transport*> sortedVect;
for (int i = 0; i < n; i++)
{
if (offers[i]->priceTransport() > T.priceTransport())
sortedVect.push_back(offers[i]); // add this item to the vector
}
// sort the vector based on the dereferenced pointers and their respective
// operator <
std::sort(sortedVect.begin(), sortedVect.end(), Sorter);
// print out the values
std::vector<Transport*>::iterator it = sortedVect.begin();
while (it != sortedVect.end())
{
cout << (*it).getDestination() << " " << (*it).getDistance() << " " << (*it).getPrice() << "\n";
++it;
}
}

Dynamic matrix in class

I have problem with dynamic allocation in c++.
This is my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Wektor {
int rozmiar;
float *TabWe;
friend std::istream& operator >> (std::istream &Strm, Wektor &Wek);
public:
Wektor(int rozmiar) : rozmiar(rozmiar) {
TabWe = new float[rozmiar];
}
Wektor() {
for (int i = 0; i < rozmiar; i++)
{
TabWe[i] = 0;
}
}
~Wektor()
{
for (int i = 0; i <rozmiar; i++)
{
delete[] TabWe;
}
}
};
istream& operator >>(istream &Strm, Wektor &Wek)
{
cout << "Size: ";
Strm >> Wek.rozmiar;
for (int i = 0; i < Wek.rozmiar; i++)
{
Strm >> Wek.TabWe[i];
}
return Strm;
}
int main()
{
Wektor wek;
cin >> wek;
}
After I enter first value to the matrix I get this error:
I think there is problem with default constructor, because you can see on the screenshot that this matrix has no value when program starts. What is wrong with it?

Help Displaying a Vector In int main()

The program I've written creates a deck of card that can be shuffled and player that takes four cards and puts them into for corresponding columns.
I can display a single card by doing this:
int main()
{
Card card;
cout << card << endl;
}
The problem is, I want to display my player class, which is made up of a vector of cards and should display four cards and put them into four separate columns. But using this:
int main()
{
Deck deck;
deck.shuffle();
Player player;
cout << player;
}
does not display anything, in fact, it gives me an error.
How can I properly display my four cards in their corresponding four columns?
Also, here is the entire code I have so far, in case you want to go through it yourself:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
enum suits
{
diamond, club, heart, spade
};
class Card
{
private:
int rank;
suits suit;
public:
Card();
Card(suits, int);
int getRank() { return rank; }
suits getSuit() { return suit; }
void setRank(int rankvalue) { rank = rankvalue; }
void setSuit(suits suitvalue) { suit = suitvalue; }
};
ostream & operator<<(ostream &, Card);
Card::Card()
{
rank = 1;
suit = spade;
}
Card::Card(suits suitvalue, int rankvalue)
{
rank = rankvalue;
suit = suitvalue;
}
ostream & operator<<(ostream & out, Card aCard)
{
switch (int rank = aCard.getRank())
{
case 1: out << "Ace"; break;
case 11: out << "Jack"; break;
case 12: out << "Queen"; break;
case 13: out << "King"; break;
default: out << rank;
}
switch (suits suit = aCard.getSuit())
{
case diamond: out << " of Diamonds"; break;
case spade: out << " of Spades"; break;
case heart: out << " of Hearts"; break;
case club: out << " of Clubs"; break;
}
return out;
}
class RandomInteger
{
public:
RandomInteger();
unsigned int operator() (unsigned int max);
};
RandomInteger::RandomInteger()
{
srand(time(0));
}
unsigned int RandomInteger::operator()(unsigned int max)
{
unsigned int rval = rand();
return rval % max;
}
RandomInteger randomizer;
class Deck
{
Card cards[52];
int topCard;
public:
Deck();
void shuffle();
bool isEmpty() { return topCard <= 0; }
Card draw();
};
extern RandomInteger randomizer;
Deck::Deck()
{
topCard = 0;
for (int i = 1; i <= 13; i++)
{
Card c1(diamond, i), c2(spade, i), c3(heart, i), c4(club, i);
cards[topCard++] = c1;
cards[topCard++] = c2;
cards[topCard++] = c3;
cards[topCard++] = c4;
}
}
Card Deck::draw()
{
if (!isEmpty())
return cards[--topCard];
else
{
Card spadeAce(spade, 1);
return spadeAce;
}
}
void Deck::shuffle()
{
random_shuffle(cards, cards+52, randomizer);
}
class Player
{
public:
Player();
void print();
Card draw(Deck &);
typedef vector<Card> cards;
vector<cards> column;
};
Player::Player()
{
column.push_back(vector<Card>());
column.push_back(vector<Card>());
column.push_back(vector<Card>());
column.push_back(vector<Card>());
}
Card Player::draw(Deck & aDeck)
{
for (int i = 0; i < 4; i++)
column[i].push_back(aDeck.draw());
}
void Player::print()
{
cout << "Col 1 \t Col 2 \t Col 3 \t Col 4 \n";
bool more = true;
for (int j = 0; more; j++)
{
more = false;
for (int i = 0; i < 4; i++)
if (j < column[i].size())
{
cout << column[i][j] << "\t";
more = true;
}
else
cout << "\t\t";
cout << endl;
}
}
int main()
{
Deck deck;
deck.shuffle();
Player player;
while (!deck.isEmpty());
cout << player;
}
Sorry for the amateur question, I know it's something simple, and thanks in advance.
cout << player;
This would not work, because you've not overloaded operator<< for type Player. Please first implement this:
ostream & operator<<(ostream &out, const Player & player)
{
//your implementation
}
If it needs to access private members, then make this friend of Player.
I just noticed that your class Player has a function called print, maybe you would like to call it from operator<<(). If you call it, then I would suggest you to use the following function signature:
void print(ostream &out) const
{
//use `out`, instead of `cout` now!
}
And then call this from operator<<, as:
ostream & operator<<(ostream &out, const Player & player)
{
player.print(out);
return out;
}
Advantage of this implementation is that you can output to console as well as file also.
You need to implement the overloaded operator "<<" for Player:
ostream & operator<<(ostream &, Player&);
to output the relevant information exactly as it was done for Card class.
Well the first call works because of the code "you wrote" here:
ostream & operator<<(ostream &, Card);
in the second player class "you wrote" a print class. So im assuming you can just call player.print(). But I didn't go through print to see if it works.
You need to define an operator << for your Player class as well as your Card class
ostream & operator<<(ostream & out, Player& aPlayer) {
//print out each card in turn
out << "Col 1 \t Col 2 \t Col 3 \t Col 4 \n";
bool more = true;
for (int j = 0; more; j++)
{
more = false;
for (int i = 0; i < 4; i++)
if (j < aPlayer.column[i].size())
{
out << aPlayer.column[i][j] << "\t";
more = true;
}
else
out << "\t\t";
out << endl;
return out;
}