Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.03.2021, 14:49   #1
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию Создать манипулятор/эффектор

Здравствуйте!
Присутствует задача:
Цитата:
Мы знаем, что манипулятор setw() позволяет задать минимальное коли*чество вводимых символов. А если размер вводимых данных потребуется ограничить сверху? Напишите эффектор, который бы позволял задать мак*симальное количество вводимых символов. Пусть ваш эффектор также ра*ботает для вывода (выводимые поля должны при необходимости усекаться по ширине).
Я хочу создать манипулятор "setw_()" по аналогии с манипуляторами из библиотки iomanip, но тема оказалась не самой простой. Для строк я сделал: работает, для вывода рабоатет, для ввода не проверял, но как быть с другими типами данных. Обобщение, но тогда нужно в объявлении манипулятора писать setw_, а это не то, чего я хочу.

Такой каркас имеется на данный момент.
https://rextester.com/SDWJ88133



P.S.
Нашёл такой код, но это не совсем то, а чтобы при необходимости урезать выводимые значения нужно получить доступ у буферу потоков ввода/вывода, я правильно понимаю? или всё же данный пример не корректен в моём случае?!
Цитата:
Код:
template<typename T, typename C>
class ManipInfra
{
public:
	ManipInfra(basic_ostream<C>& (*pFun)(basic_ostream<C>&, T), T val) :manipFun_(pFun), val_(val) { }

	void operator()(basic_ostream<C>& os) const
	{
		manipFun_(os, val_);
	}
private:
	T val_;
	basic_ostream<C>& (*manipFun_)(basic_ostream<C>&, T);
};

template<typename T, typename C>
basic_ostream<C>& operator<<(basic_ostream<C>& os, const ManipInfra<T, C>& manip)
{
	manip(os);
	return (os);
}

// Вспомогательная функция, которая вызывается в итоге в классе ManipInfra
ostream& setTheWidth(ostream& os, int n)
{
	os.width(n);
	streambuf* buff = os.rdbuf(); //В случае, если заданное значение n меньше, чем символов в потоке, тогда нужно обрезать чать выводимых данных.
	if (buff->in_avail() > n)
	{
		stringstream st;
		st << buff;
		os << st.str().substr(0, n);
	}
	return { os };
}

// Собственно функция манипулятора. Именно она используется в клиентском 
//программном коде
ManipInfra<int, char> setWidth(int n)
{
	return (ManipInfra<int, char>(setTheWidth, n));
}

//Ещё одна вспомогательная функция, которая принимает аргумент типа char
ostream& setTheFillChar(ostream& os, char c)
{
	os.fill(c);
	return { os };
}

ManipInfra<char, char> setFill(char c)
{
	return (ManipInfra<char, char>(setTheFillChar, c));
}
Чем всё таки отличатся манипулятор от эффектора? Не могу уловить смысл.
Помогите разобраться в этой не самой простой теме!
apofioz вне форума Ответить с цитированием
Старый 24.03.2021, 13:56   #2
apofioz
Форумчанин
 
Регистрация: 22.01.2014
Сообщений: 313
По умолчанию

Не пойму, никому данная тема не интересна или всё такие мегагении, что это для них слишком просто.
Хотя бы скажите, почем во вспомагательную функцию
Код:
ostream& setTheWidth(ostream& os, int n);
передаётся пустой поток. Я пологал, что при вызове оператора
Код:
operator<<()
в буфере потока будет содержаться информация, которая будут выведена, в последующем, на консоль, но, видимо, я ошибся. Не могу понять, что я делаю не так.

Последний раз редактировалось apofioz; 24.03.2021 в 16:49.
apofioz вне форума Ответить с цитированием
Старый 25.03.2021, 14:05   #3
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Цитата:
Сообщение от apofioz Посмотреть сообщение
Не пойму, никому данная тема не интересна
скорее - да. Кому придёт в голову сейчас делать что-то особенное для консоли?

Покажи пример применения данного кода, как должен использоваться манипулятор в коде?

на первый взгляд вот тут есть ошибка (в двух местах)
Код:
return { os };
создаётся временный объект и на него возвращается ссылка - это неопределённое поведение
Алексей1153 вне форума Ответить с цитированием
Старый 25.03.2021, 14:15   #4
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

что-то такое?
Код:
#include <iostream>
#include <sstream>
#include <functional>

template<typename T, typename C>
class ManipInfra
{
public:
    using td_func=std::function<std::basic_ostream<C>&(std::basic_ostream<C>& os, T val)>;
private:
    T val_{};
    td_func manipFun_{};
public:
    ManipInfra()=default;
    ManipInfra(ManipInfra&&)=default;
    ManipInfra(const ManipInfra&)=default;
    ManipInfra& operator=(ManipInfra&&)=default;
    ManipInfra& operator=(const ManipInfra&)=default;
    
    ManipInfra(td_func manipFun_, T val_) :manipFun_(manipFun_), val_(val_)
    {
    }
    
    void operator()(std::basic_ostream<C>& os) const
    {
    	manipFun_(os, val_);
    }
    
    friend std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os, const ManipInfra& manip)
    {
    	manip(os);
    	return os;
    }
};

ManipInfra<int, char> setWidth(const int n)
{
    return (ManipInfra<int, char>([](std::ostream& os, const int n)->std::ostream&
    {
    	os.width(n);
    	std::streambuf* buff = os.rdbuf(); //В случае, если заданное значение n меньше, чем символов в потоке, тогда нужно обрезать чать выводимых данных.
    	if (buff->in_avail() > n)
    	{
    		std::stringstream st;
    		st << buff;
    		os << st.str().substr(0, n);
    	}
    	return os;
    }, n));
}

ManipInfra<char, char> setFill(const char c)
{
    return (ManipInfra<char, char>([](std::ostream& os, const char c)->std::ostream&
    {
    	os.fill(c);
    	return os;
    }, c));
}
 
int main()
{
    std::cout<<setFill('0')<<setWidth(10)<<"123456"<<'\n';
}

Последний раз редактировалось Алексей1153; 25.03.2021 в 14:18.
Алексей1153 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
В чем создать программу (создать софт "Учёт топлива" для внесения данных (в базу) через форму) ? Kostia12 Общие вопросы по программированию, компьютерный форум 1 30.03.2017 14:58
Заполнение символами(использование манипулятор) MoNsTeRmEn Общие вопросы C/C++ 1 18.11.2012 11:10
Собственый манипулятор с параметрами artemoning Общие вопросы C/C++ 5 21.09.2012 17:34
создать форму на форме разработать меню и создать кнопки конец и о программе Андрей_И Помощь студентам 1 23.05.2011 23:42
Создать двоичный файл, записать n целых чисел. Из файла создать массив, элементы числа-палиндромы (на C) Simak63 Помощь студентам 0 30.03.2011 21:06