4
\$\begingroup\$

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|                   |
  +-------------------+

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 shortest possible way (or a shorter way) of printing the board as exactly shown above with the multidimensional score array?

\$\endgroup\$
4
  • 4
    \$\begingroup\$ Does your code do what yuou say it should do? I am suspicious that you have both the j loop, and also print all the blanks in the if(i == 0){..} else {...} blocks. i.e. why are you outputting from score in the j loop at all? \$\endgroup\$
    – rolfl
    May 25, 2014 at 22:21
  • 4
    \$\begingroup\$ Shortest and best practice are usually exclusive. If you are trying to golf this then this is not the forum. \$\endgroup\$ May 26, 2014 at 0:21
  • 1
    \$\begingroup\$ Related Meta Post \$\endgroup\$
    – rolfl
    May 26, 2014 at 18:41
  • \$\begingroup\$ Duplicate Stackoverflow post \$\endgroup\$
    – Chris Drew
    May 28, 2014 at 6:23

2 Answers 2

11
\$\begingroup\$

Bugs

You say:

I am trying to print a board exactly like this with the multidimensional array.

But, in reality, you are not... you only print the first item from the 2D array, and the rest of the board is printed from the constant string values. See this article describing C++ array initialization

char score[10][10] = {' '};

The above code only initializes the first position of the score 2D array, and the remaining cells in the array are left as null-characters.

When those null-characters are printed in the j loop:

    for (int j = 0; j < 10; j++) {
       cout << score[i][j];
    }

The all do nothing (except the very first cell at score[0][0]) because they become zero-length strings.

Thus, only the first line, and the first value get printed. To compensate for this, you are printing an constant-string value to complete the line, but, the first line is one character longer (because you printed score[0][0]) than the others, so the first line has to have a single-char shorter constant to complete it, and you need the if(i == 0){... condition.

I have made this obvious by initializing the array with an x (char score[10][10] = {'x'};) in this ideone which produces:

   a b c d e f g h i j
  +-------------------+
 0|x                  |
 1|                   |
 2|                   |
 3|                   |
 4|                   |
 5|                   |
 6|                   |
 7|                   |
 8|                   |
 9|                   |
  +-------------------+

You need to correctly initialize the array....

char score[10][10] = {};
for (int i = 0; i < 10; i ++) {
    for (int j = 0; j < 10; j++) {
        score[i][j] = ' ';
    }
}

Other

you are using the grid-size 10 as a magic number in a lot of places. You should probably make it a constant.....

Alternative.

C++ is not my primary language, and this is hardly a good example of a C++ program, but I have re-written your program as.... available on ideone as well ... This is the code that you should really be reviewed on ....

#include <iostream>
using namespace std;
#include <vector>
#include <string.h>

int main(){

    char score[10][10] = {};
    for (int i = 0; i < 10; i ++) {
        for (int j = 0; j < 10; j++) {
            score[i][j] = 'x';
        }
    }

    cout<< "   a b c d e f g h i j"<< endl;
    cout <<"  +-------------------+"<< endl;

    for (int i = 0; i < 10; i++) {
        // print the first character as part of the opener.
        cout << " " << i << "|" << score[i][0];
        for (int j = 1; j < 10; j++) {
           // only add spaces for subsequent characters.
           cout << " " << score[i][j];
        }
        cout << "|" << endl;
    }
    cout <<"  +-------------------+"<< endl;

}

because the above code initializes the 2D array with x, it prints the following grid:

   a b c d e f g h i j
  +-------------------+
 0|x x x x x x x x x x|
 1|x x x x x x x x x x|
 2|x x x x x x x x x x|
 3|x x x x x x x x x x|
 4|x x x x x x x x x x|
 5|x x x x x x x x x x|
 6|x x x x x x x x x x|
 7|x x x x x x x x x x|
 8|x x x x x x x x x x|
 9|x x x x x x x x x x|
  +-------------------+
\$\endgroup\$
1
  • 8
    \$\begingroup\$ since C arrays use contigious memory. You could use memset() to fill the array. memset(score, 'x', sizeof(score)); \$\endgroup\$ May 26, 2014 at 1:16
4
\$\begingroup\$

Rather than printing scores from an array, I'd at least consider defining a class that:

  1. holds a 2D array of values, and
  2. formats them correctly for output

The first means the array itself gets hidden inside the class, and the class just gives access to the storage as needed. The second means the class overloads the stream insertion operator to print out the values correctly.

I'd start with something like this:

class scoreboard { 
    size_t columns;
    size_t rows;
    std::vector<char> data;
public:

    scoreboard(size_t columns, size_t rows) : columns(columns), rows(rows) {}

    char &operator()(size_t row, size_t column) {
        assert(row<rows);
        assert(column<columns);
        return data[row * columns + column];
    }

    friend std::ostream &operator<<(std::ostream &os, scoreboard const &s); 
};

The implementation of operator<< would be something on this general order:

void hline(std::ostream &os, size_t n) { 
    os << "\n+" << std::string(n*2, '-') << "+\n";
}

std::ostream &operator<<(std::ostream &os, scoreboard const &s) { 
    static const std::string h = " abcdefghij";

    for (char ch : h)
        os << " " << ch;

    hline(os, s.width());
    for (size_t i = 0; i<s.rows; ++i) {
        os << "\n" << i << " |";
        for (size_t j=0; j<s.columns; ++j) 
           os << " " << s(i,j);
    }
    hline(os, s.width());
    return os;
}

This still needs a little work to be really correct--for example, right now, it always prints out column headers a through j, regardless of the size specified for the scoreboard. Likewise, I haven't tried to get all the alignment correct. Both of these should be fairly straightforward to deal with though.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.