Help with formatting to a max width or wrapping text

Hey guys, I'm trying to figure out how to format my output with a max width so everything is lined up nicely. I am printing various strings x amount of times depending on the value at i in a vector.

For example, if M=3, D=5, R=13, then I want it to display like
---------------------------------
| M | M | M | D | D | D | D | D |
---------------------------------
| R | R | R | R | R | R | R | R |
---------------------------------
| R | R | R | R | R |
`---------------------

where the max width of '-' is 35 or max string/chars is 8 per row.

My code however prints like this
---------------------------------
| M | M | M | D | D | D | D | D | R | R | R | R | R | R | R | R | R | R | R | R | R |

Where it just continues straight instead of wrapping around like a grid.
I have tried placing more setw()'s for each string but I'm not getting it right. I'm not sure to approach this mathematically or continue using iomanip functions.


Here's my code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<int> totalM = {3, 6, 2};
vector<int> totalD = {5, 7, 9};
vector<int> totalR = {13, 22, 17};
int numSetsTotal = 3;       // amount per vector

for (i=0; i < numSetsTotal; i++) {
cout  << setfill('-') << setw(35) << endl;
cout << "\n|";
			
    for (j = 0; i < totalM.at(i); j++) {
        cout << setfill(' ') << " M |";
	// FIXME: I want the string/char to output sizeatvect times with a max output width of 35
    }
    for (j = 0; j < totalD.at(i); j++) {
	cout << " D |";
    }
    for(j = 0; j < totalR.at(i); j++) {
	cout << " R |";
    }
}
Last edited on
4 * 8 + 1 is 33, not 35.

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
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;


string operator * ( int n, const string &s )
{
   string result;
   while (n--) result += s;
   return result;
}


void nicePlot( string s, size_t maxlength )
{
   int length = min( s.size(), maxlength );
   cout << string( length, '-' ) << '\n';
   while( s.size() > 0 )
   {
      if ( s[0] != '|' ) s = '|' + s;
      length = min( s.size(), maxlength );
      cout << s.substr( 0, length ) << '\n';
      cout << string( length, '-' ) << '\n';
      s = s.substr( length );
   }
}


int main()
{
   const string M = " M |", D = " D |", R = " R |";
   vector<int> totalM = {3, 6, 2};
   vector<int> totalD = {5, 7, 9};
   vector<int> totalR = {13, 22, 17};
   int numSets = totalM.size();
   for ( int s = 0; s < numSets; s++ ) nicePlot( '|' + totalM[s] * M + totalD[s] * D + totalR[s] * R, 33 );
}


---------------------------------
| M | M | M | D | D | D | D | D |
---------------------------------
| R | R | R | R | R | R | R | R |
---------------------------------
| R | R | R | R | R |
---------------------
---------------------------------
| M | M | M | M | M | M | D | D |
---------------------------------
| D | D | D | D | D | R | R | R |
---------------------------------
| R | R | R | R | R | R | R | R |
---------------------------------
| R | R | R | R | R | R | R | R |
---------------------------------
| R | R | R |
-------------
---------------------------------
| M | M | D | D | D | D | D | D |
---------------------------------
| D | D | D | R | R | R | R | R |
---------------------------------
| R | R | R | R | R | R | R | R |
---------------------------------
| R | R | R | R |
-----------------
Last edited on
@lastchance

Wow, thank you so much! I am not too familiar with the algorithm library, is there a way to do this without it?
The code just use the min function. You can write your own (given two values, return the minimum value).
Last edited on
Here's a version that doesn't use as much string manipulation.
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
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>

using std::vector;
using std::cout;
using std::string;

// Print ch to cout n times.
void printN(char ch, unsigned n)
{
    while (n--) {
	cout << ch;
    }
}

int main()
{
    vector<int> totalM = {3, 6, 2};
    vector<int> totalD = {5, 7, 9};
    vector<int> totalR = {13, 22, 17};
    int numSetsTotal = totalM.size();
    constexpr size_t MaxPerLine=8;   // max characters per line
    
    for (int i=0; i < numSetsTotal; i++) {
	// Create a single string of the chars to print
	string str = string(totalM[i], 'M') + string(totalD[i], 'D') + string(totalR[i], 'R');

	cout << "\n";		// print separator between data sets
	printN('-', std::min(MaxPerLine, str.size()) * 4 + 1);	// Top border.
	cout << '\n';

	// Now print each line and its bottom border
	for (unsigned j=0; j<str.size();) { // j is index of character to print
	    int chars = std::min(MaxPerLine, str.size()-j); // num chars to print on this line
	    cout << '|';		 // left border

	    unsigned limit = chars+j;
	    for (; j<limit; ++j) { // for each character on this line
		// Print the cell and the cell's right border
		cout << ' ' << str[j] << " |";
	    }
	    cout << '\n';	// end of the line of characters

	    printN('-', chars*4+1); // bottom border of the line
	    cout << '\n';
	}
    }
}

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
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

string line( int length ){ return string( 1 + length * 4, '-' ) + '\n'; }


void nicePlot( const string &s, int charsPerLine )
{
   int N = s.size();
   if ( N ) cout << line( min( N, charsPerLine ) );
   for ( int i = 0, length = 0; i < N; i++ )
   {
      cout << "| " << s[i] << " ";
      if ( (++length) == charsPerLine || i == N - 1 )
      {
         cout << "|\n" << line( length );
         length -= charsPerLine;
      }
   }
}


int main()
{
   vector<int> totalM = { 3, 6, 2 };
   vector<int> totalD = { 5, 7, 9 };
   vector<int> totalR = { 13, 22, 17 };
   for ( int s = 0; s < totalM.size(); s++ ) nicePlot( string( totalM[s], 'M' ) + string( totalD[s], 'D' ) + string( totalR[s], 'R' ), 8 );
}
Last edited on
Topic archived. No new replies allowed.