Reputation: 784
I am writing a tic-tac-toe game to learn C++.
I would like to store the game board in a 2D char array:
char playerBoard[5][14] {
{'2',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n'},
{'1',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n'},
{'0',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n'},
{' ',' ',' ',' ','^',' ',' ',' ','^',' ',' ',' ','^','\n'},
{' ',' ',' ',' ','0',' ',' ',' ','1',' ',' ',' ','2','\n'}
};
I would like to print the array with cout:
for (int i = 0; i < 5; i++) {
cout << playerBoard[i];
}
When I try, the entire contents of playerboard
, starting at the first array, are printed with each iteration:
2 > _ | _ | _
1 > _ | _ | _
0 > _ | _ | _
^ ^ ^
0 1 2
1 > _ | _ | _
0 > _ | _ | _
^ ^ ^
0 1 2
0 > _ | _ | _
^ ^ ^
0 1 2
^ ^ ^
0 1 2
0 1 2
The entire contents of playerBoard is printed with:
cout << playerBoard[0];
What is going on here?
Upvotes: 2
Views: 436
Reputation: 51815
None of your five array sub-elements is a nul
-terminated string (except possibly the last one, but that relies on undefined behaviour).
The std::cout <<
operation with a char*
operand (or a char[]
operand, which decays into a char*
) assumes a nul
-terminated string; in your case, as the terminators are missing, the buffer is printed until one is found, somewhere. This would appear to be after the entire array block.
To fix this, increase the size of the sub-arrays to 15 characters and add the required nul
(zero) terminators:
int main()
{
char playerBoard[5][15]{
{'2',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n','\0'},
{'1',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n','\0'},
{'0',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n','\0'},
{' ',' ',' ',' ','^',' ',' ',' ','^',' ',' ',' ','^','\n','\0'},
{' ',' ',' ',' ','0',' ',' ',' ','1',' ',' ',' ','2','\n','\0'}
};
for (int i = 0; i < 5; i++) {
std::cout << playerBoard[i];
}
return 0;
}
Upvotes: 2
Reputation: 40791
You have undefined behaviour, since std::cout << playerBoard[i];
expects playerBoard[i]
to be (a pointer to the first element of) a null terminated array, and there is no null character (char{0}
).
To fix this, use std::cout.write(s, count)
or std::string_view
which work for non-null terminated character arrays:
for (int i = 0; i < 5; i++) {
std::cout.write(playerBoard[i], std::size(playerBoard[i]));
// Or
std::cout << std::string_view(playerBoard[i], std::size(playerBoard[i]));
}
Or alternatively, add a single null terminator at the end:
char playerBoard[][14] {
{'2',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n'},
{'1',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n'},
{'0',' ','>',' ','_',' ','|',' ','_',' ','|',' ','_','\n'},
{' ',' ',' ',' ','^',' ',' ',' ','^',' ',' ',' ','^','\n'},
{' ',' ',' ',' ','0',' ',' ',' ','1',' ',' ',' ','2','\n'},
{0}
};
// Print the whole array
std::cout << *playerBoard;
// (You can still print individual lines the same way like as above)
Upvotes: 1