Манипулятор C++
Нужно написать манипулятор, который будет ограничивать количество символов на число до n, и количество цифр после запятой до n. Как указать сколько цифр нужно после запятой, мне удалось найти и всё прекрасно работает. Но как сделать не более n символов на число мне не удаётся найти, возможно ли вообще это сделать ?
#include <iostream>
#include <iomanip>
using std::ostream;
using std::fixed;
using std::cout;
ostream& manipulator(ostream& s)
{
s << fixed;
s.precision(4);
return s;
}
int main()
{
double d = 3241213412.123432;
cout << manipulator << d;
}
Данный код ограничивает количество цифр после запятой.
Ответы (1 шт):
Во первых этот манипулятор не правильный:
- Используется другой(стандартный) манипулятор
std::fixed, что не есть хорошо. - Устанавливается конкретная точность (4), и изменить ее нет возможности.
Такой манипулятор должен выглядеть следующим образом:
ostream& setfp(const size_t w)
{
return //но как?;
}
Для этого придется написать класс манипулятора, который хранит указатель на функцию, принимающую и поток и точность, а потом написать эту функцию и оператор вывода манипулятора:
using std::ostream;
struct My_manip {
using F = ostream&(*)(ostream&, const size_t);
F f;
const size_t n;
My_manip(F func, const size_t width)
: f(func), n(width) {}
};
//функция выполняющая то, что должен делать манипулятор
ostream& set_w(ostream& os, const size_t w)
{
os.setf(os.fixed, os.floatfield);
os.precision(w);
return os;
}
//а манипулятор хранит функцию и точность
My_manip setfp(const size_t w)
{
return { set_w, w };
}
//теперь как запустим в поток манипулятор
//вызывая функцию, выполняющую задачу
ostream&
operator<<(ostream& os, const My_manip& m)
{
return m.f(os, m.n);
}
//теперь можете передать любую точность
void g(size_t k, double d) { cout << setfp(k) << d; }
Чтобы выполнить что то другое, просто нужно написать другую функцию set_w1 и манипулятор setp вернет{ set_w1, n}
По поводу "не более n символов на число" не совсем ясно какое число имеется ввиду(с плавающей точкой или просто вывести ограниченное количество символов?). Проясните, добавлю подсказку.
P.S. Для того, чтобы вывести некоторое ограниченное количество символов, наверное придется написать фасет локализации. Или же написать класс буфера и заменить буфер std::cout (в конце обратно восстановить старый).
Но, конкретно, чтобы вывести некоторое количество символов для числа в поток std::cout, можно изворачиваться манипулятором. Я напишу пример такого манипулятора, а вы потом можете переделать для другого потока или для вывода другого типа(пусть это будет вашим заданием, чтобы лучше понять логику кода).
using std::ostream;
//ссылочный тип. Роли: выполнять код при вводе
//возвращать потока ввода
struct stream {
ostream& os = std::cout;
const size_t N;
stream(const size_t w) : N(w){}
stream& operator<<(int n)
{
//количество цифр в числе
size_t k = static_cast<size_t>(log10(n)) + 1;
while (k-- > N)
n /= 10;
os << n;
return *this;
}
};
//манипулятор для ввода в поток
struct My_manip : stream
{
My_manip(const size_t w)
: stream(w) { }
};
//получение манипулятора
My_manip f(const size_t w)
{
return My_manip(w);
}
//оператор ввода манипулятора
stream operator <<(ostream& os, const My_manip& m)
{
return dynamic_cast<const stream&>(m);
}
//пример использования
int main() {
const size_t n = 3;
std::cout << f(n) << 889667;
std::cout << "\nit is the first " << n
<< " digits of the number\n";
return 0;
}
Здесь есть недоработки, связанное с тем, что выражение с манипулятором, не возвращает ссылку на cout. В данном случаи это не важно, потому что вряд ли кому понадобится такое. Здесь цель обучающий, где заодно выплывают недостатки порядка не переносимости кода для использования где нибудь еще...