Как использовать setw с объектами

Я пытаюсь отформатировать вывод, используя библиотеку NTL (библиотека теории чисел). Одним из объектов является объект GF2X, представляющий собой полином, представленный в виде строки коэффициентов. Краткий пример:

GF2X a = GF2X(5,1);
a++;
cout<<a;

даст [1 0 0 0 0 1], что совпадает с x ^ 5 + 1. Мой вопрос касается форматирования этого вывода с помощью setw. Я хочу иметь возможность выводить объекты GF2X различной длины, предваряя их числом и добавляя строку. Я бы хотел, чтобы мой вывод выглядел следующим образом:

  1:    [x x x x x x x x]       string here
 15:    [x x x]                 string here

Я бы также согласился на то, чтобы право ] было выровнено, чего, вероятно, и следует ожидать, если я использую setw. Однако, когда я использую код (имена переменных для простоты опущены):

    cout << setw(3)<< int <<": "<< setw(35) << GF2X << setw(15) << string << endl;

Я получаю вывод, похожий на этот (некоторые пробелы удалены для компактности)

  1:            [x x x x x x x x]   string here
 15:            [x x x]   string here

Другими словами, функция setw, по-видимому, обрабатывает весь вывод <<GF2X как один символ и, похоже, фактически не учитывает размер выходной строки. Как вы можете видеть из вывода, который я вам показал, левая сторона вывода GF2X выравнивается, а правая — нет, в то время как обычно setw выравнивает правую сторону вывода.


person Teofrostus    schedule 29.07.2012    source источник
comment
один из подходов может заключаться в перегрузке оператора ‹‹ для GF2X.   -  person nims    schedule 29.07.2012
comment
@nims: Кажется, он сделал это. io манипуляторы плохо подходят для своей работы. Я предпочитаю использовать пользовательские классы, которые форматируют мои объекты как строки и передают их в потоки и функции, которые создают эти объекты. Будет выглядеть примерно так: cout << FormatWidth(35, GF2X);   -  person Benjamin Lindley    schedule 29.07.2012
comment
Пробовали пройти std::left?   -  person jrok    schedule 29.07.2012
comment
@jrok: у меня такое чувство, что он оставит его с открытой скобкой, за которой следует куча пробелов, а затем остальная часть его вывода. Проблема, конечно, в том, что setw работает только с выводом следующего элемента, и его оператор, вероятно, написан как комбинация операторов вывода.   -  person Benjamin Lindley    schedule 29.07.2012
comment
На самом деле я не хочу возиться с файлами в библиотеке NTL, так как это очень продвинутая библиотека для работы с числами и многочленами, и она проникает в математику, которую я не понимаю. Я посмотрю на std::left.   -  person Teofrostus    schedule 29.07.2012
comment
@BenjaminLindley Я не думаю, что он перегрузил оператор ‹‹ для GF2X, похоже, что он использует тот, который поставляется библиотекой.   -  person paxos1977    schedule 29.07.2012
comment
@jrok std::left делает именно то, что сказал Бенджамин. Это дает мне левую скобку, кучу места, а затем некоторые элементы. Может быть, я мог бы сделать что-то вроде сохранения строки в ostringstream, а затем снова попробовать setw.   -  person Teofrostus    schedule 29.07.2012


Ответы (2)


Вы можете сделать это с модификацией оператора вывода. Я предполагаю, что это написано примерно так (я ничего не знаю об этом классе GF2X, так что это частично псевдокод:

std::ostream & operator<<(std::ostream & os, const GF2X & x)
{
    os << '[';
    for (int i=0; i<x.num_elements; ++i)
        os << x.get_element(i) << ' ';
    return os << ']';
}

Проблема в том, что setw будет работать только с этим первым '[', а не со всем объектом (он не знает, что такое весь объект). Вы можете исправить оператор, записав все это в строку (используя stringstream или каким-либо другим способом) и затем выведя строку. Если изменение оператора не подходит для вас, вам нужно будет использовать отдельную вспомогательную функцию, чтобы сначала преобразовать объект в строку (используя строковый поток), а затем вывести эту строку в поток.

На самом деле, boost::lexical_cast здесь бы вам очень пригодился, так как он сделает это за вас в последнюю очередь:

cout << setw(35) << boost::lexical_cast<std::string>(GF2X);
person Benjamin Lindley    schedule 29.07.2012
comment
Я вижу по вашему последнему комментарию, что вы уже думали об этом. - person Benjamin Lindley; 29.07.2012
comment
Да, к сожалению, на самом деле нет функций-членов для доступа к каждому отдельному элементу класса GF2X. Но обходной путь с использованием временного буфера ostringstream сработал. Было бы разумно ответить на мой собственный вопрос решением, которое я нашел? Или мне просто закрыть этот вопрос? - person Teofrostus; 29.07.2012
comment
@Teofrostus: Ответь на вопрос. - person Benjamin Lindley; 29.07.2012

Вы можете использовать временный объект ostringstream для хранения вывода, а затем использовать setw для предоставленной строки (имена переменных опущены).

    ostringstream oss;
    oss << GF2X;
    cout << setw(3) << x << ": "<< setw(35) << oss.str() << setw(15) << string <<endl;

Это форматирует весь объект ostream, а не только первый символ, и дает правильный вывод.

person Teofrostus    schedule 29.07.2012