Использование stringstream для отступа/центрирования вывода

Я изучаю С++ и получил проект для отправки треугольника Паскаля на вывод (после n-строк вычислений). Получая такой вывод, хранящийся в "буфере" строкового потока.

 1
 1 1
 1 2 1
 1 3 3 1

Но то, что я хочу, скорее

    1
   1 1
  1 2 1
 1 3 3 1

Моя идея была такова: вычислить разницу длины последней строки и текущей строки (я знаю, что последняя самая длинная). Затем заполните каждую строку пробелами (половина разницы длины строки). Моя проблема сейчас:

  • Я не понял, как работает getLine, и как я могу извлечь конкретную (-> последнюю) строку
  • Я не знаю и не мог найти, как отредактировать одну конкретную строку в строковом потоке

Почему-то у меня возникло ощущение, что я не нахожусь на самом лучшем пути, используя stringstream.

Итак, это довольно распространенный вопрос: как вы решили эту проблему и, если возможно, со строковыми потоками - как?


person AnatraIlDuck    schedule 04.05.2012    source источник
comment
cplusplus.com/reference/iostream/manipulators/setw взгляните на это   -  person v01d    schedule 04.05.2012
comment
Просто для ясности, вы вычисляете значения самостоятельно и печатаете? Или вы их разбираете и потом перепечатываете?   -  person Benj    schedule 04.05.2012
comment
Я их сам вычисляю, посмотрю на setw, вроде хороший способ :-)   -  person AnatraIlDuck    schedule 04.05.2012
comment
Это работает очень хорошо, но, к сожалению, весь мой треугольник уже хранится в строковом потоке (называемом буфером). setw() может установить только ширину текущей строки. Как я могу установить линию с сохранением?   -  person AnatraIlDuck    schedule 04.05.2012
comment
Хорошо, я обнаружил, что это невозможно простым способом (перегрузка оператора ‹‹ здесь не вариант :D). Поэтому я решил снова прочитать свой строковый поток построчно (используя getline)   -  person AnatraIlDuck    schedule 04.05.2012


Ответы (2)


Чтобы узнать отступ первой строки, вам нужно знать количество строк во входных данных. Поэтому вы должны сначала прочитать все входные данные. Я решил использовать вектор для хранения значений для удобства функции-члена .size(), которая даст общее количество строк после чтения всех входных данных.

#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;
}

В этом примере я использую setw, чтобы установить ширину строки по правому краю. Отступ в левой части строки задается как (sz - i), где sz — общее количество строк, а i — текущая строка. Поэтому в каждой последующей строке слева на 1 место меньше.

Затем мне нужно добавить исходный размер строки (lines[i].length()), иначе строка не будет содержать достаточно большого пространства для результирующей строки, чтобы иметь правильный отступ слева.

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

Надеюсь это поможет!

person Jared Sealey    schedule 08.05.2012

Если у вас есть доступ к коду, который записывает начальный вывод, и если вы знаете количество строк N, которые вы пишете, вы можете просто сделать:

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
}
person TemplateRex    schedule 04.05.2012
comment
я сомневаюсь, что это будет работать, когда N увеличивается и в игру вступают двузначные числа. Будет ли он? - person nims; 04.05.2012
comment
@nims Конечно, вам нужно будет вычислить width = max(choose(N,k) % 10, чтобы получить количество цифр, и написать (N - 1 - i) * ширину пробелов. Я просто хотел сказать, что проще совместить форматирование с вычислением, чем форматировать вывод после вычисления. - person TemplateRex; 04.05.2012
comment
как-то мне было бы лучше сначала вычислить значения, а затем отформатировать вывод... - person AnatraIlDuck; 04.05.2012
comment
Итак, прочитайте справку по строковому потоку getline: cplusplus.com/reference/iostream/istream/getline - person TemplateRex; 04.05.2012