Как использовать setw с объектами
-
13-12-2019 - |
Вопрос
Я пытаюсь отформатировать вывод с помощью библиотеки 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 выравнивает правую часть выходных данных.
Решение
Вы можете сделать это, изменив оператор вывода.Полагаю, там написано что-то вроде этого (я ничего не знаю об этом классе 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);
Другие советы
Вы можете использовать временный объект ostringstream для хранения вывода, а затем использовать setw для предоставленной строки (имена переменных опущены).
ostringstream oss;
oss << GF2X;
cout << setw(3) << x << ": "<< setw(35) << oss.str() << setw(15) << string <<endl;
Это форматирует весь объект ostream, а не только первый символ, и дает правильный вывод.