The easy way to approximate this is to just give a maximum width, using <iomanip> and
setw for each cell, however this doesn't scale if you have large numbers like 10000, and can leave excess space if, for example, none of the numbers are negative.
This also doesn't take into account doubles, but the type of your array is of type double, so I'm going to change it to int, and we can adjust it for doubles later.
It's relatively tricky compared to just printing the array in a dumb way because despite printing each row one at a time, you have to look at each column beforehand to see how to align the numbers.
There might be a better way, but: What you need to do is iterate down the first column, find the maximum width of that column, and then then either remember that width or re-calculate it each row. Then, you do the second item in the column, rinse and repeat for each column, then do it all over again for the second row. You could also save the width that each column needs, which requires an extra array, but would reduce redundant calculations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#include <iostream>
#include <string>
#include <vector>
using std::cout;
int numlen(int n)
{
// count number of characters needed for number, +1 if negative
int length = 0;
if (n == 0)
return 1;
if (n < 0)
{
n = -n;
length++;
}
while (n > 0)
{
length++;
n = n / 10;
}
return length;
}
const int nmax = 100;
void fancy_print(int M[nmax][nmax], int n, int m){
int max_len_per_column[nmax] {};
for (int col = 0; col < m; col++)
{
// determine max length needed for individual column
int max_len = -1;
for (int row = 0; row < n; row++)
{
int num_length = numlen(M[row][col]);
if (num_length > max_len)
{
max_len = num_length;
}
}
max_len_per_column[col] = max_len;
}
for (int col = 0; col < m; col++)
{
std::cout << "Column " << (col + 1) << " needs " << max_len_per_column[col] << " width\n";
}
// TODO
}
int main()
{
#if 0
std::cout << numlen(-1) << '\n';
std::cout << numlen(0) << '\n';
std::cout << numlen(1) << '\n';
std::cout << numlen(2) << '\n';
std::cout << numlen(9) << '\n';
std::cout << numlen(10) << '\n';
std::cout << numlen(11) << '\n';
std::cout << numlen(20) << '\n';
std::cout << numlen(21) << '\n';
std::cout << numlen(-11) << '\n';
std::cout << numlen(-20) << '\n';
#endif
int mat[nmax][nmax] = {
{ 2, 1, 2, 1, 6 },
{ 6, -6, 6, 12, 36 },
{ 4, 3, 3, -3, -1 },
{ 2, 2, -1, 1, 10}
};
fancy_print(mat, 4, 5);
}
|
Column 1 needs 1 width
Column 2 needs 2 width
Column 3 needs 2 width
Column 4 needs 2 width
Column 5 needs 2 width |
(Note: Add 1 to each of these numbers for the actual setw amount)
In the "TODO" part of my code, you now have the widths needed for each column. Use
setw like jonnin linked above. You also need to right-justify each number, using the
std::right stream manipulator. See example at:
https://stackoverflow.com/questions/5201619/right-justifying-output-stream-in-c
If you need to handle doubles like 3.003, you will need to decide how many decimal places you want to show, and keep that constant. Remember that floating-point precision is inherently inexact for most numbers, so you have to choose how you want to represent such a number.