Using stringstream to indent/center output
Asked Answered
D

2

6

I'm learning c++ and got the project to send a pascal's triangle to output (after n-rows of calculation)., getting output like this, stored in a stringstream "buffer"

 1
 1 1
 1 2 1
 1 3 3 1

But what I want is rather

    1
   1 1
  1 2 1
 1 3 3 1

My idea was: calculate the difference of the last line and current line length (I know that the last one is the longest). Then pad each row using spaces (half of the line-length-difference). My Problem now is:

  • I didn't get how getLine works, neither how I might extract a specific (-> last) line
  • I don't know and could not find how to edit one specific line in a stringstream

Somehow I got the feeling that I'm not on the best way using stringstream.

So this is rather a common question: How'd you solve this problem and if possible with stringstreams - how?

Davilman answered 4/5, 2012 at 8:12 Comment(5)
cplusplus.com/reference/iostream/manipulators/setw take a look a thisUnwritten
Just to be clear, are you calculating the values your self and printing? Or are you parsing them and then reprinting?Conspectus
I calculate them myself, I'm gonna have a look at setw, seems to be a nice way :-)Davilman
This works very nice but unfortunately I've got my whole triangle stored already in a stringstream (called buffer). setw() is only able to set the width for the current line. How can I set the line with persisting?Davilman
Okay I found out that this isn't possible in an easy way (overloading the << operator is no option here :D). So I decided to read my stringstream out line by line again (using getline)Davilman
A
2

To know the indentation of the first line, you would need to know the number of lines in the input. Therefore you must first read in all of the input. I chose to use a vector to store the values for the convenience of the .size() member function which will give the total number of lines after reading in all input.

#include<iostream>
#include<sstream>
#include<vector>
#include<iomanip> // For setw
using namespace std;
int main()
{
  stringstream ss;
  vector<string> lines;
  string s;

  //Read all of the lines into a vector
  while(getline(cin,s)) 
    lines.push_back(s);

  // setw() - sets the width of the line being output 
  // right  - specifies that the output should be right justified 
  for(int i=0,sz=lines.size();i<sz;++i)
    ss << setw((sz - i) + lines[i].length()) << right << lines[i] << endl;

  cout << ss.str();
  return 0;
}

In this example, I am using setw to set the width of the line to be right justified. The padding on the left side of the string is given by (sz - i) where sz is the total number of lines and i is the current line. Therefore every subsequent line has 1 less space on the left hand side.

Next I need to add in the original size of the line (lines[i].length()), otherwise the line will not contain a large enough space for the resulting string to have the correct padding on the left hand side.

setw((sz - i) + lines[i].length())

Hope this helps!

Abad answered 8/5, 2012 at 20:32 Comment(0)
B
0

If you have access to the code that writes the initial output, and if you know the number of lines N you are writing, you could simply do:

for(int i = 0; i < N; ++i) {
    for(int j = 0; j < N - 1 - i; ++j)
        sstr << " "; // write N - 1 - i spaces, no spaces for i == N.
    // now write your numbers the way you currently do
}
Biologist answered 4/5, 2012 at 8:35 Comment(4)
i doubt it will work when N increases and double digit numbers come into play. Will it?Atonic
@Atonic Sure, you would need to compute width = max(choose(N,k) % 10 to get the number of digits, and write (N - 1 - i) * width whitespaces. My point simply was that it's easier to combine formatting with the computation, rather than to format output after the computation.Biologist
somehow I'd find it nicer to first compute the values and then format the output...Davilman
So go read the stringstream getline reference: cplusplus.com/reference/iostream/istream/getlineBiologist

© 2022 - 2024 — McMap. All rights reserved.