Most efficient possible code for printing a specific board C++ - c++

So I am trying to print a board exactly like this with the multidimensional array
char score[10][10] = {' '};
a b c d e f g h i j
+-------------------+
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7| |
8| |
9| |
+-------------------+
Currently this is my code:
#include <iostream>
using namespace std;
#include <vector>
#include <string.h>
int main() {
char score[10][10] = {' '};
cout << " a b c d e f g h i j" << endl;
cout << " +-------------------+" << endl;
for (int i = 0; i < 10; i++) {
cout << " " << i << "|";
for (int j = 0; j < 10; j++) {
cout << score[i][j];
}
if(i == 0) {
cout << " |";
} else {
cout << " |";
}
cout << endl;
}
cout << " +-------------------+" << endl;
}
As you can see my code is inefficient and lengthy.
What would be the most efficient possible way ( or a more efficient way) of printing the board as exactly shown above with the multidimensional score array?

As the comments have pointed out, your code is almost efficient as possible. Making it shorter would do little to its run-time and instead obscure its meaning. There are however a few things you can do to speed it up.
Avoid an extra call to operator<<, evaluation of std::end, and unnecessary buffer flushes by using \n and including it in your existing string literals (evaluated at compile time).
Use printf instead of cout. See "performance" section of this article.

As already pointed out by others, there are not many ways to make this more efficient, particularly if constrained to use the cout stream.
But for the "lengthy" part, this is a few lines and characters shorter, albeit C++11:
cout << " a b c d e f g h i j\n"
" +-------------------+\n";
for (int i = 0; i < 10; i++) {
cout << ' ' << i << '|';
for (char s : score[i])
cout << s;
cout << " |\n";
}
cout << " +-------------------+\n";
I don't understand why the spaces should be printed at the end instead of aligning the inner columns nicely, but I followed what you did in your code.
I have also got rid of the unnecessary endl which triggers stream flush and changed single letter strings to character constants, but I'm a bit doubtful of the resulting efficiency gain there. After all, it's just printing some output, not a time-critical computation task.

I'm going to assume that when you said you wanted to make it efficient and not lengthy what you really meant was that you wanted it to be correct and readable.
I don't believe what you currently have is "correct". I assume that char score[10][10] will contain a single printable character for each square of the board and perhaps a null character for cells where you don't want to print anything. And you want to print the contents of score into the template shown. As it stands, if you put anything other than a single space into char score[10][10] you will mess up your template.
As for readability, I think what you currently have is reasonably readable, perhaps it would benefit by having some functions extracted with meaningful names but that is just my personal preference. Based on my assumptions about what you were trying to do here is my corrected and refactored version:
#include <iostream>
#include <vector>
#include <string>
void printHeader() {
std::cout << " a b c d e f g h i j\n";
std::cout << " +-------------------+\n";
}
void printFooter() {
std::cout << " +-------------------+\n";
}
void printRowStart(int i) {
std::cout << " " << i << "|";
}
void printRowEnd() {
std::cout << "|\n";
}
void printSquare(char score) {
char printable_score = (score != '\0') ? score : ' ';
std::cout << printable_score;
}
void printRowScore(char (&row_score)[10]) {
printSquare(row_score[0]);
for (int i = 1; i != 10; ++i) {
std::cout << " ";
printSquare(row_score[i]);
}
}
void printScore(char (&score)[10][10]) {
printHeader();
for (int i = 0; i != 10; ++i) {
printRowStart(i);
printRowScore(score[i]);
printRowEnd();
}
printFooter();
}
int main(){
char score[10][10] = { { 0 } };
// Added to test assumed usage
score[4][5] = 'x';
score[4][6] = 'x';
printScore(score);
}
You might also want to consider making the code print to a generic ostream to make it more testable.

Related

toString function from 2D array

Very sorry if this is too long-- I posted a question yesterday about a game program I am trying to write and with the help of some people, I managed to figure everything out pretty quickly.
The very large majority of the program is complete, but I have one last weird task to complete. I have a function written, printGrid, that prints one random element from each 16 bundles of characters from within a char array. For example (It's very ugly-- please excuse my beginner code):
char gameZero[outer_size][inner_size] = {
{'A','A','C','I','O','T'}, {'A','H','M','O','R','S'},
{'E','G','K','L','U','Y'}, {'A','B','I','L','T','Y'}, {'A','C','D','E','M','P'},
{'E','G','I','N','T','V'}, {'G','I','L','R','U','W'}, {'E','L','P','S','T','U'},
{'D','E','N','O','S','W'}, {'A','C','E','L','R','S'}, {'A','B','J','M','O','Q'},
{'E','E','F','H','I','Y'}, {'E','H','I','N','P','S'}, {'D','K','N','O','T','U'},
{'A','D','E','N','V','Z'}, {'B','I','F','O','R','X'}
};
void printGrid() {
mt19937 gen(time(nullptr));
uniform_int_distribution<int> random_inner(0, inner_size - 1);
int n = random_inner(gen);
cout << "+---+---+---+---+\n";
for (int i = 0; i < 4; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 4; i < 8; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 8; i < 12; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 12; i < 16; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
}
This will print a 4x4 game board for the user to see. I am now trying to write a sort of toString function, which takes the random numbers generated in printGrid and prints them out into a single line string with no spaces. The issue I am trying to wrap my head around is, I have this assortment of characters that changes each time the player begins a new game. These 16 characters are coming from a set array of 16 die, holding 6 characters each. Is the only way to make this possible to store these new randomly chosen characters into an empty array so the user can simply print them with the toString function when desired? Another obstacle I would have to then tackle is deleting the array every time the user wants to begin again. If this is the case, could I store them in a vector and use something like vector::clear to solve that?
Current output of printGrid function:
+---+---+---+---+
| T | M | E | L |
+---+---+---+---+
| A | V | L | S |
+---+---+---+---+
| E | A | Qu| F |
+---+---+---+---+
| E | D | N | O |
+---+---+---+---+
Desired output of toString function I would like to create:
TMELAVLSEAQuFEDNO
Very sorry if this is too much to read or too confusing- I've been working on this almost all day and my brain is a bit fried at the moment. Any tips are greatly appreciated!
You have the logic to select the characters, example:
for (int i = 0; i < 4; i++)
cout << "| " << gameZero[i][n] << " ";
You could use std::string and operator += to append the characters to a string:
std::string all_letters;
for (int i = 0; i < 4; ++i)
{
all_letters += gameZero[i][n];
}
Edit 1: Expanding the loop
Since you don't need to print by row, you can iterate through the entire array:
std::string all_letters;
for (int i = 0; i < 16; ++i)
{
all_letters += gameZero[i][n];
}

Display duplicate characters in a string

I wrote some code in C++ to display duplicate characters in a string, but if a character is repeated more than three times, the code prints the repeated character more than once.
For example if the string is aaaddbss, it should only print out ads but it prints aaads instead.
What am I doing wrong?
cout << " Please enter a string" << endl;
cin.getline(input, 100); // example input (ahmad wahidy) the output reads a a h a d instead of a h d
for (int i = 0;input[i]!='\0'; i++)
{
for (int j = i+1;input[j]!='\0'; j++)
{
if (input[i] == input[j])
{
cout << input[i] << " ";
}
}
}
cout << endl;
Instead of using your own custom methods, why not use a short and standard method?
Given an std::string input with the text, this will print the unique chars:
std::set<char> unique(input.begin(), input.end());
for (auto & c : unique)
{
std::cout << c << " ";
}
std::cout << std::endl;
You can use std::count and std::set:
#include <string>
#include <set>
#include <iostream>
using namespace std;
int main()
{
string s = "hellohowareyou";
set<char>the_set(s.begin(), s.end());
for (char i:the_set)
if (count(s.begin(), s.end(), i) > 1)
cout << i << endl;
}
Output:
e
h
l
o
If you are not allowed to use a map (and probably also not allowed to use a set), you could simply use an array of integers to count occurrences, with one entry for each possible char value. Note that a character - when taken as an ASCII value - can be directly used as an index for an array; however, to avoid negative indices, each character value should first be converted to an unsigned value.
#include <iostream>
#include <limits>
int main() {
const char* input = "aaaddbss";
int occurrences[UCHAR_MAX+1] = { 0 };
for (int i = 0;input[i] !='\0'; i++)
{
unsigned char c = input[i];
if (occurrences[c]==0) {
occurrences[c]++;
}
else if (occurrences[c]==1) {
occurrences[c]++;
cout << "duplicate: " << c << endl;
}
}cout << endl;
}

printing 2d arrays in c++

i am trying to make a mach chess board using 2D arrays to draw it this is what i have so far
#include <iostream>
using namespace std;
int main()
{
char table[8][9]={"RkBKQBkR", "pppppppp", " ", " ", " ", " ", "pppppppp", "RkBKQBkR" } ;
for (int rows=0; rows<8; rows++)
{
for (int col=0; col<8; col++)
{
cout << table[rows][col] ;
}
}
return 0;
}
how would i add lines (|) and (-) between the objects of the array ?
the output is
RkBKQBkRpppppppp ppppppppRkBKQBkR
Suggestion: Since it is C++, start by looking at the STL containers, vectors etc since the way you define the array is more the C way.
That aside, to add the aditional text:
std::vector<std::string> table ={"RkBKQBkR", "pppppppp", " ", " ", " ", " ", "pppppppp", "RkBKQBkR" };
for (int rows=0; rows<8; rows++)
{
cout << "|";
for (int col=0; col<8; col++)
{
cout << table[rows][col] << "|";
}
cout << endl;
for(int i = 0; i < 8; ++i) { cout << "--"; }
cout << "-" << endl;
}
My code uses vector of strings since your code with the char[][] did not compile on my computer.
Print | this in the outer for-loop and - this in the inner
for-loop
You should use 2 for-loops (outer & inner) statement with if-else condition to decide to print or not.
Find "|" & "-" character in ASCII table to have the nice chess board.
Hope this help!

generating a box of stars surrounding text with for loops in c++

I'm trying to make a program in c++ which surrounds some given lines of code with a box of stars in which the sentences fit 'neatly'. I've done this for a small text which consists of only the same sentence and it works. But when trying to make this program work for texts with more than only one sentence it fails because the sentences aren't all the same size. How can I fix this issue? Here's my code
#include <iostream>
using namespace std;
int main( int argc, char* argv[] )
{
int r, c;
for( r = 0; r < 5; ++r )
{
for( c = 0; c < 28; ++c )
{
if( r == 0 || r == 4 )
{
cout << "*";
}
else
{
if( c == 0 || c == 27 )
cout << "*";
if(r >= 1 && c == 1){
cout << " this is a test sentence";
}
if(c > 1 && c < 4){
cout << " ";
}
}
}
cout << "\n";
}
return 0;
}
You might change your code, so that it uses variables, not literal constants. After you do that, you have two options based on how you want to calculate the width of the box:
fixed - use cout << std::setw(fixed_width) << std::left << sentences[i]; (in a loop)
variable - use loop or std::max_element to determine the longest sentence and do the same thing as with fixed width
where you'll use std::vector<std::string> sentences.
I'll also add how neat can be what you currently have:
#include <iostream>
#include <string>
#include <iomanip>
using std::cout;
using std::endl;
int main()
{
const int width = 20;
const char c = '*';
std::string horizontal_line(width, c);
std::string horizontal_line_empty(c + std::string(width - 2, c) + c);
cout << horizontal_line << endl << horizontal_line_empty << endl;
cout << c << std::setw(width - 2) << std::left << std::string("hello") << c << endl;
cout << horizontal_line_empty << endl << horizontal_line << endl;
}
I hope you'll get something from it.

Need help printing a sequence, without spaces, on the same line

so here is what i'm working with.
#include <iostream>
using namespace std;
int main()
{
int i, h = -1;
for (i = 0; i < 8; i++) {
h = h + 1;
cout << h << endl;
} // while
return 0;
} // main
I need my output to look like
1 2 3 4 5 6 7
but I am getting
1
2
3
4
...
Is there anything besides endl you can use to print to the same line with spaces? thanks and sorry for the noob question. i'm am slowly learning c++.
It sounds like you want to print every number with a space in between. If so then use an actual space instead of the end of line character
cout << h;
cout << ' ';
Then at the end of the loop explicitly add a new line
cout << endl;
Full Sample
int i;
for (i = 0; i < 8; i++)
{
h = h +1 ;
cout << h << ' ';
}
cout << endl;
cout << h << " "; will do the trick
endl is what prints the newline, so you should place that outside of the loop. Sample:
for (i = 0; i < 8; i++)
{
h = h + 1;
cout << h;
}
cout << endl;