Xcode error: "2 duplicate symbols for architecture x86_64" - c++

I keep getting this error when I try to compile and have no idea why
Ld /Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug/BATTLESHIP normal x86_64
cd /Users/Itunes/Desktop/Programs/CMPSC122/BATTLESHIP
setenv MACOSX_DEPLOYMENT_TARGET 10.7
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk -L/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug -F/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug -filelist /Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/BATTLESHIP.LinkFileList -mmacosx-version-min=10.7 -stdlib=libc++ -o /Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Products/Debug/BATTLESHIP
duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK5Point in:
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/main.o
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/Board.o
duplicate symbol __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK5Point in:
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/main.o
/Users/Itunes/Library/Developer/Xcode/DerivedData/BATTLESHIP-gefqfgwzntvzlvfyyxoqzmmanjlb/Build/Intermediates/BATTLESHIP.build/Debug/BATTLESHIP.build/Objects-normal/x86_64/Ship.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
My headers and .cpp files are
Board.h
// Board.h - Board class declaration
#pragma once
#include "Point.h"
using namespace std;
#define HIT 'X'
#define SHIP 'S'
#define MISS 'O'
#define WATER '~'
class Board
{
public:
// Constructor
Board();
// Function which prints an image of the board showing hits ( X ) and misses ( O )
void PrintBoard();
// Resets the board for both players before new games begin
void ResetBoard();
// Marks both boards after each guess
void MarkBoard(bool hit, Point guessCoordinate);
// Returns TRUE if the user has guessed the given coordinate
bool CheckGuess( Point guessCoordinate );
private:
// Board used for determining whether the user has guessed a certain position yet or not
bool playerBoard[BOARD_WIDTH][BOARD_LENGTH] = {false};
// Board used soley for output
// KEY: 0 = not yet guessed, 1 = hit, 2 = miss
// intialize all spaces to 0 to show that no guesses have been made yet
int outputBoard[10][10] = { 0 };
};
Board.cpp
// Board.cpp - Board class function implementation
#include "Board.h"
Board::Board()
{
}
// Prints the output board to console
void Board::PrintBoard()
{
// Print column numbers
cout << " \t" << " " << 1;
for( int number = 2; number < 11; number++)
cout << " " << number;
cout << endl;
// Print board itself
// i = row number, j = column number
for( int i = 0; i < 10; i++)
{
// int i can double as a row and column counter for checking if a space has been hit
/*cout << " \t";
// Print row lines
for( int k = 1; k < 11; k++)
cout << " __";*/
cout << endl;
// Print row number
cout << i+1 << " ";
cout << "\t";
// Print columns
for( int j = 0; j < 10; j++)
{
cout << "|";
// INSERT CODE THAT PLACES X OR O IF GUESS IS HIT OR SHIP
if( outputBoard[i][j] == 0 )
cout << WATER;
if( outputBoard[i][j] == 1 )
cout << HIT;
if( outputBoard[i][j] == 2 )
cout << MISS;
}
cout << "|";
cout << endl;
}
cout << endl;
}
void Board::MarkBoard(bool hit, Point guessCoordinate)
{
// First mark the board to show the player has guessed this coordinate
playerBoard[guessCoordinate.X][guessCoordinate.Y] = true;
if( hit == true )
{
// Show that the player hit a ship
outputBoard[guessCoordinate.X][guessCoordinate.Y] = 1;
}
else
{
// Show that the player missed the ship
outputBoard[guessCoordinate.X][guessCoordinate.Y] = 2;
}
}
bool Board::CheckGuess(Point guessCordinate)
{
bool previouslyGuessed = false;
// If the given point has already been guessed, make the function return true
if( playerBoard[guessCordinate.X][guessCordinate.Y] )
{
previouslyGuessed = true;
}
else
{
previouslyGuessed = false;
}
return previouslyGuessed;
}
Ship.h
#pragma once
#include <string>
#include "Point.h"
using namespace std;
#define SHIP_TYPES 5
#define MAX_LENGTH 5
enum DIRECTION {HORIZONTAL,VERTICAL};
class Ship
{
public:
// Constructor
Ship();
// Function to initially set all ship to the correct values
void LoadShips( Ship ship[SHIP_TYPES] );
// Function which gives ships their location points and placement orientation
void FillShipData( DIRECTION direction, Point coordinate );
bool isSunk();
bool isHit( Point guess, Ship ship[SHIP_TYPES] );
string GetName()
{ return Name; }
private:
// Ship name
string Name;
// How many spaces the ship occupies
int Length;
// Determines whether a ship lies vertically or horizontally on the board
DIRECTION Direction;
// Holds the coordinates that the ship occupies
Point spaceOccupied[MAX_LENGTH];
};
Ship.cpp
#include "Ship.h"
Ship::Ship()
{
}
void Ship::LoadShips(Ship ship[SHIP_TYPES])
{
//Sets the default data for the ships
//we plan to include in the game
//IMPORTANT!! > MUST MATCH SHIP_TYPES -Default=5 (0-4)
ship[0].Name = "Cruiser"; ship[0].Length = 2;
ship[1].Name = "Frigate"; ship[1].Length = 3;
ship[2].Name = "Submarine"; ship[2].Length = 3;
ship[3].Name = "Escort"; ship[3].Length = 4;
ship[4].Name = "Battleship"; ship[4].Length = 5;
}
void Ship::FillShipData( DIRECTION direction, Point coordinate )
{
Direction = direction;
int x,y;
// If the ship will be laid horizontally, give it the initial point plus the x-coordinates to its right
if( Direction == HORIZONTAL )
{
while( coordinate.X+Length >= BOARD_WIDTH || coordinate.X < 0 || coordinate.Y < 0 || coordinate.Y >= BOARD_LENGTH )
{
cout << "Your ship will not be entirely on the board when placed this way. Please choose a new row number and column number separated by a space (ex: x y): ";
cin >> x >> y;
coordinate.X = x;
coordinate.Y = y;
}
for( int i = 0; i < Length; i++ )
{
spaceOccupied[i] = coordinate;
coordinate.X++;
}
}
// If the ship will be laid vertically, give it the initial point plus the y-coordinates below it
else
{
// Be sure the give point will contain and the ship
while( coordinate.Y+Length >= BOARD_LENGTH || coordinate.X < 0 || coordinate.Y < 0 || coordinate.X >= BOARD_WIDTH )
{
cout << "Your ship will not be entirely on the board when placed this way. Please choose a new row number and column number separated by a space (ex: x y): ";
cin >> x >> y;
coordinate.X = x;
coordinate.Y = y;
}
for( int i = 0; i < Length; i++ )
{
spaceOccupied[i] = coordinate;
coordinate.Y++;
}
}
}
// use throwaway to call, one user's guess and the other user's ships
//
bool Ship::isHit( Point guess, Ship ship[SHIP_TYPES] )
{
bool hit = false;
// For loop to examine each ship
for( int i = 0; i < SHIP_TYPES && hit==false; i++ )
{
// For loop to go through each point the ship occupies
for( int j = 0; j < ship[i].Length && hit==false; j++ )
{
// If the player's guess matches a point the ship is located on, it has been hit
if( ship[i].spaceOccupied[j] == guess )
{
hit = true;
// Inform player they landed a hit
cout << "Ship: " << ship[i].Name << " has been hit!\n";
}
}
}
// If the player has missed all ships, inform them
if( hit == false )
cout << "Missed.\n";
return hit;
}
And finally Point.h
#pragma once
#include <iostream>
using namespace std;
#define BOARD_LENGTH 10
#define BOARD_WIDTH 10
struct Point
{
// A location on the grid defined
// by X(horizontal) Y(vertical) coordinates
int X;
int Y;
bool operator == (const Point& compareTo) const
{
return ( (X == compareTo.X) && (Y == compareTo.Y) );
}
};
ostream& operator <<(ostream& out, const Point& myPoint)
{
out << "(" << myPoint.X << "," << myPoint.Y << ")";
return out;
}
My main function simply includes Board.h and Ship.h with no function declarations.
Any help would be greatly appreciated!

Stupid one, but make sure you haven't #imported a .m file by mistake somewhere

The problem is that you are redefining the operator<<(ostream&, const Point&) in main.cpp Board.cpp, and Ship.cpp by including Point.h in each.
You can most easily solve this problem by making it inline, in Point.h.
inline ostream& operator <<(ostream& out, const Point& myPoint) // << add inline
When you see those strange symbol names in the error output, a trick is to use c++filt in your Terminal to see more easily what the function name or symbol is that causing the problem. This "unmangles" the symbol name, for example, try this in Terminal:
phillip / $ c++filt __ZlsRNSt3__113basic_ostreamIcNS_11char_traitsIcEEEERK5Point
operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Point const&)
phillip / $

add inline here.
inline ostream& operator <<(ostream& out, const Point& myPoint)
^^^^^^
{
out << "(" << myPoint.X << "," << myPoint.Y << ")";
return out;
}

Chances are that you have object files (.o) in your Xcode project. Xcode doesn't like this. Remove the object files and the code should compile.

Related

Undefined reference for TicTacToe [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Using G++ to compile multiple .cpp and .h files
(13 answers)
Closed last year.
I've got this file where it seems to be an undefined reference but I don't know why, everything it seems correct to me. Someone can help me?
This is the error:
g++ -c driver.cpp -std=c++11 -pedantic -Wall
g++ -o driver driver.o
/usr/bin/ld: driver.o: in function `main':
driver.cpp:(.text+0x23): undefined reference to `TicTacToe::TicTacToe()'
/usr/bin/ld: driver.cpp:(.text+0x2f): undefined reference to `TicTacToe::makeMove()'
collect2: error: ld returned 1 exit status
make: *** [makefile:2: driver] Error 1
And these are the files I'm using:
The driver program:
// driver.cpp: use of TicTacToe class
#include "TicTacToe.h" // include definition of class TicTacToe
int main() {
TicTacToe g; // creates object g of class TicTacToe
g.makeMove(); // invokes function makeMove
}
This is the class:
// TicTacToe.h
#ifndef TICTACTOE_H
#define TICTACTOE_H
#include <array>
class TicTacToe {
private:
enum Status {WIN, DRAW, CONTINUE}; // enumeration constants
std::array<std::array<int, 3>, 3> board;
public:
TicTacToe(); // default constructor
void makeMove(); // make move
void printBoard() const; // print board
bool validMove(int, int) const; // validate move
bool xoMove(int); // x o move
Status gameStatus() const; // game status
};
#endif
These are the class function members:
// TicTacToe.cpp
// Member-function defnitions for class TicTacToe.
#include <iostream>
#include <iomanip>
#include "TicTacToe.h" // include definition of class TicTacToe
using std::cout;
using std::cin;
using std::setw;
TicTacToe::TicTacToe() {
for (int j{0}; j < 3; ++j) { // initialize board
for (int k{0}; k < 3; ++k) {
board[j][k] = ' ';
}
}
}
void TicTacToe::makeMove() {
printBoard();
while (true) {
if (xoMove('X')) {
break;
}
else if (xoMove('O')) {
break;
}
}
}
void TicTacToe::printBoard() const {
cout << " 0 1 2\n\n";
for (int r{0}; r < 3; ++r) {
cout << r;
for (int c = 0; c < 3; ++r) {
cout << setw(3) << static_cast< char > (board[r][c]);
if (c != 2) {
cout << " |";
}
}
if (r != 2) {
cout << "\n ____|____|____\n | | \n";
}
}
cout << "\n\n";
}
bool TicTacToe::xoMove(int symbol) {
int x;
int y;
do {
cout << "Player " << static_cast<char>(symbol) << " enter move: ";
cin >> x >> y;
cout << '\n';
} while (!validMove(x, y));
board[x][y] = symbol;
printBoard();
Status xoStatus = gameStatus();
if (xoStatus == WIN) {
cout << "Player " << static_cast<char>(symbol) << " wins!\n";
return true;
}
else if (xoStatus == DRAW) {
cout << "Game is draw.\n";
return true;
}
else { // CONTINUE
return false;
}
}
bool TicTacToe::validMove(int r, int c) const {
return r >= 0 && r < 3 && c >= 0 && c < 3 && board[r][c] == ' ';
}
// must specify that type Status is part of the TicTacToe class.
TicTacToe::Status TicTacToe::gameStatus() const {
// check for a win on diagonals
if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) {
return WIN;
}
else if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[2][0] == board[0][2]) {
return WIN;
}
// check for win in rows
for (int a{0}; a < 3; ++a) {
if (board[a][0] != ' ' && board[a][0] == board[a][1] && board[a][0] == board[a][2]) {
return WIN;
}
}
// check for win in columns
for (int a{0}; a < 3; ++a) {
if (board[0][a] != ' ' && board[0][a] == board[1][a] && board[0][a] == board[2][a]) {
return WIN;
}
}
// check for a completed game
for (int r{0}; r < 3; ++r) {
for (int c{0}; c < 3; ++c) {
if (board[r][c] == ' ') {
return CONTINUE; // game is not finished
}
}
}
return DRAW; // game is a draw
}
It's probably something stupid but I don't know what I have to look for.
step by step:
g++ -c driver.cpp TicTacToe.cpp -std=c++11 -pedantic -Wall
g++ -o driver driver.o TicTacToe.o
./driver

Is this code to find path into square grid using backtracking is right?

I was reading antti lakesonen's competitive programming handbook and I came across backtracking for finding grid paths with some optimizations applied. In nutshell here are the rules for a valid path across the grid :
0. Path search starts from top left cell and ends at bottom right cell.
1. A valid path has traversed all the cells of the grid once.
2. From current cell you can move right, left, top, bottom and only if the move doesn't leave the grid.
Now I have written this code that works fine with square grid of dimension = 7 with time taken ~400ms and total paths : 111712. I have two queries here :
--> With dimension = 9 its taking like a lot of time to report even the first valid path in its search. Am I stuck into the infinite loop or what?
--> Grid path search for even number of dimension like 2,4,6 are giving answer 0. I tried with finding path for 2*2 and 4*4 grid manually but I see that it's impossible to find such paths, but i don't know how to formally or logically prove that even dimensions square grids cannot have such paths mentioned above.
Here is my code :
#include <bits/stdc++.h>
using namespace std;
#define LOG_PATH 1;
#define ARRAY_BASED_CONSTANT_GRID 1;
struct Cell {
int x,y;
};
const int HORIZONTAL_DIRECTION = 0, VERTICAL_DIRECTION = 1;
long long validPathCount, recursiveCallCount, visitedCellCount, currentDirection;
#ifdef ARRAY_BASED_CONSTANT_GRID
const int DIMENSION = 7;
bool grid[DIMENSION][DIMENSION];
#else
int DIMENSION;
vector<vector<bool>> grid;
#endif
/* *-*-*-*-*-*-*-*- UTILITY FUNCTIONS -*-*-*-*-*-*-*-*-*-*-*-*-*-* */
bool hasPathCompleted(Cell);
bool isPathValid();
void validPathCheckAndUpdate();
void setState(Cell);
void resetState(Cell);
void updateAndLogPathCounter();
void backtrackPathSearching(Cell);
void moveAlongTheGrid(Cell);
bool isOccupied(Cell);
bool canMoveRight(Cell);
bool canMoveLeft(Cell);
bool canMoveUp(Cell);
bool canMoveDown(Cell);
bool isRightBorder(Cell);
bool isLeftBorder(Cell);
bool isUpBorder(Cell);
bool isDownBorder(Cell);
Cell generateRight(Cell);
Cell generateLeft(Cell);
Cell generateUp(Cell);
Cell generateDown(Cell);
bool isThereHorizontalPartition();
bool isThereVerticalPartition();
void printGrid();
/* *-*-*-*-*-*-*-*- UTILITY FUNCTIONS -*-*-*-*-*-*-*-*-*-*-*-*-*-* */
Cell generateRight(Cell position) {
currentDirection = HORIZONTAL_DIRECTION;
return {position.x, position.y + 1};
}
Cell generateLeft(Cell position) {
currentDirection = HORIZONTAL_DIRECTION;
return {position.x, position.y - 1};
}
Cell generateUp(Cell position) {
currentDirection = VERTICAL_DIRECTION;
return {position.x - 1, position.y};
}
Cell generateDown(Cell position) {
currentDirection = VERTICAL_DIRECTION;
return {position.x + 1, position.y};
}
bool isRightBorder(Cell position) { return position.y == DIMENSION - 1; }
bool isLeftBorder(Cell position) { return position.y == 0; }
bool isUpBorder(Cell position) { return position.x == 0; }
bool isDownBorder(Cell position) { return position.x == DIMENSION - 1; }
bool isOccupied(Cell position) { return grid[position.x][position.y]; }
bool canMoveRight(Cell position) { return !isRightBorder(position) && !isOccupied(generateRight(position)); }
bool canMoveLeft(Cell position) { return !isLeftBorder(position) && !isOccupied(generateLeft(position)); }
bool canMoveUp(Cell position) { return !isUpBorder(position) && !isOccupied(generateUp(position)); }
bool canMoveDown(Cell position) { return !isDownBorder(position) && !isOccupied(generateDown(position)); }
bool hasPathCompleted(Cell position) { return position.x == DIMENSION - 1 && position.y == DIMENSION - 1; }
bool isPathValid() { return visitedCellCount == DIMENSION * DIMENSION; }
void validPathCheckAndUpdate() {
if (isPathValid()) { updateAndLogPathCounter(); }
}
void updateAndLogPathCounter() {
validPathCount++;
#ifdef LOG_PATH
cout << "\rFound " << validPathCount << " paths";
cout.flush();
#endif
}
void setState(Cell position) {
recursiveCallCount++;
visitedCellCount++;
grid[position.x][position.y] = true;
}
void resetState(Cell position) {
visitedCellCount--;
grid[position.x][position.y] = false;
}
void printGrid() {
cout << "-------------------------------" << endl;
for (int i = 0; i < DIMENSION; i++) {
for (int j = 0; j < DIMENSION; j++) {
cout << grid[i][j] << " ";
}
cout << endl;
}
}
void moveAlongTheGrid(Cell position) {
if (canMoveRight(position)) {
backtrackPathSearching(generateRight(position));
}
if (canMoveLeft(position)) {
backtrackPathSearching(generateLeft(position));
}
if (canMoveUp(position)) {
backtrackPathSearching(generateUp(position));
}
if (canMoveDown(position)) {
backtrackPathSearching(generateDown(position));
}
}
bool isThereHorizontalPartition(Cell position) {
if (currentDirection == VERTICAL_DIRECTION) {
if (!canMoveUp(position) && !canMoveDown(position)) {
if (canMoveLeft(position) && canMoveRight(position)) {
return true;
}
}
}
return false;
}
bool isThereVerticalPartition(Cell position) {
if (currentDirection == HORIZONTAL_DIRECTION) {
if (!canMoveLeft(position) && !canMoveRight(position)) {
if (canMoveUp(position) && canMoveDown(position)) {
return true;
}
}
}
return false;
}
// OPTIMIZATION : 4 > Direction awareness
// Optimization 3 followed border awareness but this concept can be generalized
// and we can make the grid aware of its direction
// If path can't go forward in current direction but either can turn into both cross axis path
// then there is partition
void backtrackPathSearching(Cell position) {
setState(position);
// printGrid();
// cout << "x : " << position.x << " y : " << position.y << endl;
// cout << "validPathCount : " << validPathCount << endl;
// string s;
// getline(cin, s);
if (hasPathCompleted(position)) {
validPathCheckAndUpdate();
}
else if (!isThereHorizontalPartition(position) && !isThereVerticalPartition(position)) {
moveAlongTheGrid(position);
}
resetState(position);
}
#ifndef ARRAY_BASED_CONSTANT_GRID
void inputFromUser() {
cout << "Give Dimension of box grid : ";
cin >> DIMENSION;
for (int i = 0; i < DIMENSION; i++) grid.push_back(vector<bool>(DIMENSION, false));
}
#endif
int main() {
#ifndef ARRAY_BASED_CONSTANT_GRID
inputFromUser();
#endif
validPathCount = recursiveCallCount = 0;
visitedCellCount = 1;
grid[0][0] = 1;
currentDirection = VERTICAL_DIRECTION;
backtrackPathSearching({1, 0});
cout << endl;
cout << "Paths : " << validPathCount * 2 << endl;
cout << "Calls : " << recursiveCallCount << endl;
return 0;
}
/*
Paths : 111712
Calls : 26790463
real 0m0.281s
user 0m0.281s
sys 0m0.000s
*/
Just comment ARRAY_BASED_CONSTANT_GRID to enable user input for grid dimension.
Can someone help me with this? Thanks in advance :)
PS: Due to my coding practices I had to paste the whole code in order to make it sensible. I know in stackoverflow only minimal required code has to be pasted but here I don't know what's really needed in order to analyze the code!

array of strings inside the object

I've got a problem with creating an array of strings inside the object. I don't know how to patch it around so I'm asking for help. Here lies the problem:
main.h:
#pragma once
#include <iostream>
#include <conio.h>
#include <string>
class tab2D {
protected:
int width;
int height;
string **sTab;
int **iTab;
public:
tab2D();
tab2D(int x, int y, char c);
~tab2D();
tab2D(tab2D&t);
};
class chess: public tab2D {
public:
chess(int x, int y);
~chess();
chess(chess&c);
void init();
bool ifMove();
void show();
};
class matrix: public tab2D {
public:
matrix(int x, int y);
~matrix();
matrix(matrix&m);
};
The compiler says: syntax error : missing ';' before '*' about the line
string **sTab;
I assume that I can't make the dynamic array of strings and it makes further problems with processing this array.. Can you help me? :)
*UPDATE 1*Thanks, I forgot to add line
using namespace std;
Now it works, but I've got another problem.
#include "main.h"
using namespace std;
////// Konstruktor, konstruktor kopiujący oraz destruktor //////
chess::chess(int x = 8, int y = 8) : tab2D(x, y, 'c') {
init();
};
chess::chess(chess&c) {
chess(c.width, c.height);
};
chess::~chess() {
};
////// Metody //////
////// Uzupełnianie kolorów pól oraz rozstawianie figur i pionków //////
void chess::init() {
/// kolory pól: 0 - biały, 1 - czarny///
int last = 0;
for(int i = 0; i < this->height; ++i) {
for(int j=0; j < this->width; ++j) {
if(last = 0) {
this->sTab[i][j] = "1";
last = 1;
}
else if(last = 1) {
this->sTab[i][j] = "0";
last = 0;
}
}
if(last = 0)
last = 1;
else if(last = 1)
last = 0;
};
/// rozstawienie pionków ///
for(int i = 0; i < this->width; ++i) {
sTab[1][i] = sTab[1][i] + "0";
sTab[6][i] = sTab[6][i] + "a";
};
};
////// Wyświetlenie szachownicy //////
void chess::show() {
for(int i = 0; i < (this->height + 1); ++i) {
for(int j=0; j < (this->width + 1); ++j) {
if(i == 0 && j == 0)
cout << " ";
else if (i != 0 && j == 0) {
switch (i) {
case 1:
cout << "A ";
break;
case 2:
cout << "B ";
break;
case 3:
cout << "C ";
break;
case 4:
cout << "D ";
break;
case 5:
cout << "E ";
break;
case 6:
cout << "F ";
break;
case 7:
cout << "G ";
break;
case 8:
cout << "H ";
break;
default:
break;
}
}
else if (i == 0 && j != 0) {
cout << j << " ";
}
else {
cout << this->sTab[i-1][j-1] << " ";
}
}
cout << endl;
};
};
When I run the program, there is a breakpoint in the line
this->sTab[i][j] = "0";
I assume there is something wrong with making the array of strings but I don't understand why exactly there is a breakpoint and can't debug it.
UPDATE 2
Here is the code for tab.cpp:
#include "main.h"
using namespace std;
////// Konstruktor domyślny, konstruktor, konstruktor kopiujący oraz destruktor //////
tab2D::tab2D() {
};
tab2D::tab2D(int x, int y, char c) {
this->width = x;
this->height = y;
if (c == 'm') {
this->iTab = new int*[this->width];
for(int i=0;i<this->height;++i)
this->iTab[i] = new int[this->width];
}
else if (c == 'c') {
this->sTab = new string*[this->width];
for(int i=0;i<this->height;++i)
this->sTab[i] = new string[this->width];
}
else {
}
};
tab2D::tab2D(tab2D&t) {
tab2D(t.width, t.height, 't');
};
tab2D::~tab2D() {
for(int i=0;i<height;++i)
delete [] iTab[i];
delete [] iTab;
for(int i=0;i<height;++i)
delete [] sTab[i];
delete [] sTab;
};
You need to qualify names from the standard library:
std::string **sTab;
^^^^^
If you're doing what I think you're doing and allocating things with new, then you should consider using std::vector to deal with the quagmire of memory management issues you're about to encounter. If you really want to juggle pointers yourself for some reason, don't forget the Rule of Three.
UPDATE Your new problem might be because the copy constructor is horribly broken:
chess::chess(chess&c) {
chess(c.width, c.height);
};
This creates and destroys a temporary object, but doesn't initialise the object being constructed, leaving it in an invalid state. You probably don't want to declare a copy-constructor at all, as long as the base class is correctly copyable. If you did need one, it should should be more like:
chess::chess(chess const & c) : // 'const' so constant objects can be copied
tab2D(c) // copy the base-class subobject
{
// do whatever else needs doing
}
Alternatively, the new problem might be due to errors in the tab2D constuctors which you haven't shown us. The best way to track it down is to step through the program with a debugger, checking that everything is correctly initialised before use.
UPDATE Probably, the runtime error is caused by allocating the wrong number of pointers. You want
iTab = new int*[height]; // Not width
and likewise for sTab.

Really frustrating debug Error with C++

So I am trying to make a pretty basic TicTacToe in C++, and while I have no apparent syntax errors, I am having a lot of Debug errors of : "Unhandled exception at 0x0100142D in Cobra.exe: 0xC0000005: Access violation reading location 0xCCCCC359"
I feel like it is an obvious Error that I am just not processing but it;s definitely starting to grate my nerves. I'll label where the access error is... Right now it;s in my checkwin method but I feel like there is definitely more than one..
In my header I use a private char** board and a private int player.
#include "TicTacToe.h"
#include <iostream>
using namespace std;
int main()
{
int rowChosen,
colChosen;
TicTacToe newGame;
while(newGame.checkWin()==' ' && !newGame.fullBoard())
{
newGame.displayBoard();
do
{
cout << "Player " << newGame.getPlayer() << " choose a row and column.";
cin >> rowChosen >> colChosen;
newGame.setGame(rowChosen,colChosen);
}while(newGame.setGame(rowChosen,colChosen)==false);
newGame.makeMove(rowChosen, colChosen, newGame.getPlayer());
newGame.switchPlayer();
}
newGame.displayBoard();
if(newGame.checkWin()!=' ')
cout << "Player " << newGame.returnWinner() << " wins!";
else if(newGame.fullBoard()==true)
cout << "Cat's Game: This is a Draw!";
return 0;
}
TicTacToe::TicTacToe()
{
player = 1;
char blank = ' ';
for(int row=0;row<3;row++)
for(int col=0;col<3;col++)
board[row][col] = ' ';
}
void TicTacToe::setPlayer(int play)
{
player = play;
}
int TicTacToe::getPlayer()
{
return player;
}
void TicTacToe::switchPlayer()
{
if (player==1)
player++;
else
player--;
}
bool TicTacToe::setGame(int row, int col) //input validation
{
if (row >= 3 || row < 0)
return false;
if (col >= 3 || col < 0)
return false;
if (board[row][col] != ' ')
return false;
return true;
}
char TicTacToe::getBoard(int row, int col)
{
return board[row][col];
}
bool TicTacToe::fullBoard()
{
bool full = true;
for(int row=0;row<3;row++)
for(int col=0;col<3;col++)
{
if(board[row][col]==' ')
{
full=false;
break;
}
}
return full;
}
void TicTacToe::makeMove(int r, int c, int player)
{
char ch;
if (player==1)
ch = 'X';
else
ch = 'O';
board[r][c] = ch;
}
char TicTacToe::checkWin()
{
char b = ' ';
for(int i=0; i<3; i++) //horizontal
{
if((board[i][1]==board[i][0]) && (board[i][1]==board[i][2])) //THIS IS ERROR
{
b=board[i][1];
}
}
for(int j=0; j<3; j++) //vertical
{
if( (board[1][j]==board[0][j]) && (board[1][j]==board[2][j]) )
b=board[1][j];
}
if((board[0][0]==board[1][1] && board[1][1]==board[2][2]) ||
(board[2][0]==board[1][1] && board[1][1]==board[0][2]))
b= board[1][1];
return b;
}
void TicTacToe::displayBoard()
{
for(int row=0;row<3;row++)
{
cout << "|-----|";
for(int col=0;col<3;col++)
{
if(board[row][col]==' ')
cout << "| ";
else
cout << "|" << board [row][col];
}
cout << "|" << endl;
cout << "|-----|";
}
}
int TicTacToe::returnWinner()
{
int winner = 0;
if(checkWin()=='X')
winner = 1;
else if(checkWin()=='O')
winner = 2;
return winner;
}
This is my header TicTacToe.h
class TicTacToe
{
private:
char board[3][3]; //there we go
int player;
public:
TicTacToe();
void setPlayer(int);
int getPlayer();
void switchPlayer();
bool setGame(int,int);
char getBoard(int,int);
bool fullBoard();
void makeMove(int,int,int);
char checkWin();
void displayBoard();
int returnWinner();
};
Assuming you've included all the code, you're missing something essential: the declaration of the class TicTacToe. Of course, there's a TicTacToe.h, so it could be (probably is) hiding in there. That would help.
That all said, I think Mat has it right -- you declare a local named board inside the ctor and initialize it. But that goes out of scope as soon as the ctor is finished, which means all that initialization disappears into the aether.. Assuming you define board in your class, then simply removing that char declaration might be all you need.
Now, here's general advice: if you get an access violation exception, it usually means that you have made a mistake about the scope of something you're referring to. Since the exception happens at a point where you're using board, the slice of the program containing the identified board is the place to look.

Fatal error from incrementing loop

Currently, I'm trying to make a function that sorts a vector full of fighters in the function sortFighters in the Fighter.cpp file. It all seems to compile correctly; However, when it does run, I get a fatal error in one of the lines of the aformentioned .cpp file. I know exactly what the problem is, and put a comment there accordingly.
So, what I'm asking here, is what I might do to fix this problem without adding any other functions and such.
Here's my Fighter.h file:
#ifndef FIGHTER_H
#define FIGHTER_H
#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
class Fighter
{
protected:
std::string name;
int health, level;
//int damage;
public:
int getHealth(int);
void getEnemies(std::vector<Fighter> &);
void printFighter(std::vector<Fighter> &);
void sortFighters(std::vector<Fighter> &);
//friend std::istream & operator >> (std::istream & strm, Fighter & x);
//friend std::ostream & operator << (std::ostream & strm, const Fighter & f);
//void attack();
Fighter();
~Fighter();
};
class Player : public Fighter
{
private:
int experience;
public:
int getHealth(int);
void pri`enter code here`ntFighter();
void getExperience(int);
void playerAttack();
Player();
~Player();
};
//class FightPub
//{
// private:
// Player player;
// Fighter enemy;
// public:
// //void fight();
// //void getStats();
//};
#endif
My Fighter.cpp file:
//dynamically locate an array that holds the number of fighters, and for each fighter in the array, assign from the .txt
//file the name and level from the fighter.
#include "Fighter.h"
#pragma region getEnemies
void Fighter::getEnemies(std::vector<Fighter> &baddie)
{
Fighter x;
std::ifstream inputFile;
inputFile.open("EnemyFighters.txt");
if(!inputFile)
{
std::cout << "error!" << std::endl;
}
else
{
while(!inputFile.eof())
{
std::string line;
inputFile >> line;
if (line == "<fighter>")
{
do
{
inputFile >> line;
x.name = line;
inputFile >> line;
x.level = atoi(line.c_str());
inputFile >> line;
x.health = getHealth(this->level);
baddie.push_back(x);
inputFile >> line;
}while(line != "</fighter>");
}
}
inputFile.close();
}
}
#pragma endregion
#pragma region getHealth
int Fighter::getHealth(int lv)
{
if(lv >= 6)
{
std::cout << "\nHealth Bonus!";
this->health = lv * 2;
}
/*else if (lv > 1)
for (int i = 1; i < lv; i++)
{this->health += 2;}*/
return health;
}
#pragma endregion
#pragma region attack
//void Fighter::attack()
//{
// int randomAttack = rand() % 4 + 1;
//
// switch (randomAttack)
// case 1:
// {
// std::cout << "Enemy uses critical attack!"
// }
//}
#pragma endregion
#pragma region printFighter
void Fighter::printFighter(std::vector<Fighter> &baddie)
{
//std::cout << this;
for (int i=0; i<baddie.size(); i++)
{
std::cout << "\nName: " << baddie[i].name << std::endl
<< "Level: " << baddie[i].level << std::endl
<< "Health: " << baddie[i].health << std::endl;
}
}
#pragma endregion
void Fighter::sortFighters(std::vector<Fighter> &x)
{
Fighter * temp = new Fighter;
bool swap;
do
{
swap = false;
std::cout << x.size() << std::endl;
for (int i=0; i<=(x.size()); i++)
{
//if the level in the first is greater than the level in the next
if(x[i].level > x[i+1].level)//I get a fatal error here when it tries to compare
//the iterator with 1 that's outside its range
{
//assign the stats from the first to temp
temp->name = x[i].name;
temp->health = x[i].health;
temp->level = x[i].level;
//assign the stats from the next to the first
x[i].name = x[i+1].name;
x[i].health = x[i+1].health;
x[i].level = x[i+1].level;
//assign the ones in temp(the first) to the next
x[i+1].name = temp->name;
x[i+1].health = temp->health;
x[i+1].level = temp->level;
swap = true;
}
else if(x[i].level >= x[i+1].level)
{
temp->name = x[i].name;
temp->health = x[i].health;
temp->level = x[i].level;
x[i].name = x[i+1].name;
x[i].health = x[i+1].health;
x[i].level = x[i+1].level;
x[i+1].name = temp->name;
x[i+1].health = temp->health;
x[i+1].level = temp->level;
swap = true;
}
else if (x[i].level < x[i+1].level)
{
//temp->name = x[i].name;
//temp->health = x[i].health;
//temp->level = x[i].level;
//x[i].name = x[i+1].name;
//x[i].health = x[i+1].health;
//x[i].level = x[i+1].level;
//x[i+1].name = temp->name;
//x[i+1].health = temp->health;
//x[i+1].level = temp->level;
swap = false;
}
else if(x[i].level <= x[i+1].level)
{
/*temp->name = x[i].name;
temp->health = x[i].health;
temp->level = x[i].level;
x[i].name = x[i+1].name;
x[i].health = x[i+1].health;
x[i].level = x[i+1].level;
x[i+1].name = temp->name;
x[i+1].health = temp->health;
x[i+1].level = temp->level;*/
swap = false;
}
}
}while (swap);
delete temp;
}
//std::istream & operator >>(std::istream & strm, Fighter x)
//{
// //x.name += strm.c_str();
// //x.level += atoi(strm.c_str());
// strm >> x.name;
// strm >> x.level;
// return strm;
//}
//std::ostream & operator << (std::ostream & strm, const Fighter f)
//{
// strm << "Name: " << f.name << std::endl;
// strm << "Level: " << f.level << std::endl;
// strm << "Health: " << f.health << std::endl;
// return strm;
//}
#pragma region Fighter C&D
Fighter::Fighter()
{
level = 1;
health = 10;
}
Fighter::~Fighter()
{
}
#pragma endregion
//void operator <()
//{
//}
//
//void operator >()
//{
//}
//
//void operator <=()
//{
//}
//
//void operator >=()
//{
//}
//
//
//
int Player::getHealth(int lv)
{
if(lv >= 6)
{
std::cout << "\nHealth Bonus!";
this->health = lv * 2;
}
/*else if (lv > 1)
for (int i = 1; i < lv; i++)
{this->health += 2;}*/
return health;
}
void Player::printFighter()
{
//std::cout << this;
std::cout << "\nPlayer's stats: \n"
<< "Level: " << this->level << std::endl
<< "Health: " << this->health << std::endl
<< "Experience: " << this->experience <<std::endl;
}
void Player::getExperience(int dmg)
{
experience += dmg;
if (experience >= (level * 10))
{
std::cout << "Congratulations, Player! You're up a level!\n";
level ++;
}
}
#pragma region Player C&D
Player::Player()
{
level = 1;
health = getHealth(level);
experience = 0;
}
Player::~Player()
{
}
#pragma endregion
//Player::printFighter()
//{
//
//}
And here's main.cpp:
#include "Fighter.h"
int main()
{
unsigned seed = time(0);
srand(seed);
std::vector<Fighter> baddie;
Fighter * enemy = new Fighter;
Player * me = new Player;
enemy->getEnemies(baddie);
enemy->sortFighters(baddie);
enemy->printFighter(baddie);
me->printFighter();
delete enemy;
delete me;
return 0;
}
for (int i=0; i<=(x.size()); i++)
{
if(x[i].level > x[i+1].level)
{
um.. Size() counts from 1. Indexes count from 0. So you'll want to make that i < x.size(), not <=. But, in the very next line, you say x[i+1], so i can't even reach the last item, it has to stop one before that:
for (int i=0; i < x.size()-1; i++)
You've gotten some advice about how to fix that loop. My advice would be to eliminate it and use std::sort instead.
While we're dealing with loops that don't terminate correctly, however, it's probably also worth mentioning one other (in getEnemies()):
while(!inputFile.eof())
{
std::string line;
inputFile >> line;
if (line == "<fighter>")
{
// ...
This is broken as well. For the loop to terminate correctly, you need to read the data, and then check whether the read succeeded:
std::string line;
while (inputFile >> line) {
if (line == "<fighter>") {
// ...
It's probably also worth noting that this code is pretty fragile -- just for one example, something like: <fighter>fighter1</fighter> will not be read correctly (it requires at least one whitespace before and after <fighter> to read it as a single string).
Try Changing your for loop to this
for (int i=0; i < x.size() - 1; i++) {
... your original content...
}
This way x[i+1] never goes out of bounds
You were trying to access memory that has not been allocated.
Your problem is with this loop:
for (int i=0; i<=(x.size()); i++){
if(x[i].level > x[i+1].level){ //Fatal Error Here
// Do some stuff
}
// Do some more stuff
}
Your condition for terminating the outer loop is i<=(x.size()) this means that when you do the comparision ( x[i+1].level ) that breaks the program, you are comparing outside the bounds of x. Because if i == x.size() then x[i+1] > x.size()
I reccomend changing your loop to terminate at i<(x.size())-1; rather than i<=(x.size());
The problem, as others have said, is this section of code:
for (int i=0; i<=(x.size()); i++)
{
//if the level in the first is greater than the level in the next
if(x[i].level > x[i+1].level)//I get a fatal error here when it tries to compare
//the iterator with 1 that's outside its range
A std::vector can be indexed by values 0 through size() - 1, inclusive. So, for a basic vector loop, you should instead do
for (int i = 0; i < x.size(); i++) {
BUT, in the next line of code, you check element i + 1, so you should instead do
for (int i = 0; i < x.size() - 1; i++) {
BUT, because x.size() is unsigned, if x is empty, then x.size() - 1 will be a very large number (2^32 - 1 on a 32-bit machine). So you should adjust the logic for this. Also, comparing signed values (like int i against unsigned values (like x.size() - 1) may generate compiler warnings (you should turn all such compiler warnings on, if you haven't already done so), so change i to unsigned or size_t:
for (size_t i = 0; i + 1 < x.size(); i++) {
Finally, rather than coding your own bubble sort, it's better to use std::sort. std::sort is faster and more familiar to other C++ developers. Here's an (untested) example of using std::sort:
bool CompareByLevel(const Fighter& a, const Fighter& b) {
return a.level < b.level;
}
sort(x.begin(), x.end(), CompareByLevel);
Other comments: If you're interested in learning more about C++, here are a few other comments that might help.
inputFile >> line;
This statement actually reads a single whitespace- or newline-separated word into line. If that's what you're trying to do, then your choice of variable name (line) doesn't communicate that. And you may want to be able to use whitespace in fighters' names. To read an entire line, use this: (See here for reference.)
getline(inputFile, line);
getEnemies, printFighter, and sortFighters should be static methods, since they don't need a particular instance of a Fighter to operate on. (Right now, because they're not static methods, you have to create an enemy instance of Fighter in order to call those methods, even though none of those methods do anything with enemy.)
C++ lets you create variables on the stack, instead of dynamically allocating them. In other words, instead of saying
Fighter * temp = new Fighter;
just say
Fighter temp;
This is faster and simpler, if you don't need dynamic allocation.
Finally, C++ will create assignment operators for you that copy all of a class's members. So you could simply write
temp = x[i];
instead of manually assigning each of x's members to temp. Using the assignment operator is more robust, since it will continue to work in the future if you later add members to Fighter.
Hope this helps.