如何在C++用Python的input和print?

相信既学过Python也学过c++的年轻开发者们对于Python的print与input都认为非常好用,print一次性打印字典,元组,或者列表的所有元素,input输入同理。一开始从C过度到C++的时候认为cou与cint的流对象重载<< >>方式挺好的,但是现在,我们显然不满足于这些。

1、 首先我们要知道,为什么一个函数可以接收无限的参数调用?

可变参数,得益与可变参数我们可以写出类似于c语言的printf,scnaf,Python的print。c语言作为c++的子集,我们可以使用它的可变参数方案,但是,可以但没必要。

c语言的可变参数是使用宏定义的,效率的确会高,但是使用并不方便。

c++自c++17以来的折叠表达式,让我们对可变参数模板使用变得轻松,我们今天选择更加新式的range,来自于C++20,当然也提供之前的c++17的折叠表达式。学过Python的,对于range相信不会陌生,我们先编写print的代码,如下

namespace show_ {
	template<typename T,size_t i>
	void print(const T(&n)[i], const std::string s=" ") {
		std::copy(std::begin(n),std::end(n), std::ostream_iterator<T, char>(std::cout, s.data()));
		std::cout << std::endl;
	}
	template<typename T,size_t size>
	void print(const std::array<T,size> v, const std::string s = " ") {
		std::copy(std::begin(v), std::end(v), std::ostream_iterator<T, char>(std::cout, s.data()));
		std::cout << std::endl;
	}
	void print(const char* s) {
		std::cout << s << std::endl;											//重载特殊情况,字符串常量输出
	}
	void print(char* s) {
		std::cout << s << std::endl;											//重载特殊情况,字符串常量输出
	}
	template<typename T>
	void print(const std::vector<T>n,const std::string s=" ") {
		std::copy(std::begin(n), std::end(n), std::ostream_iterator<T, char>(std::cout, s.data()));
		std::endl(std::cout);
	}
	template<typename T>
	void print(T v) {
		std::cout << v << std::endl;
	}
	template<typename T>
	void print(const std::list<T>& L,std::string s=" ") {
		for (auto it = L.begin(); it != L.end(); it++) {										//list容器版本
			std::cout << *it << s;
		}
		std::cout << std::endl;
	}
	template<typename _Type1, typename _Type2, typename... _Types>
	void print(_Type1 _Value1, _Type2 _Value2, _Types... _Values)//c++17折叠表达式
		requires (sizeof...(_Types) > 0 || (!std::is_same_v<char*, _Type2> && !std::is_same_v<const char*, _Type2>))//requires是c++20的
	{
		std::cout << _Value1 << " " << _Value2 << " ";
		((std::cout << _Values <<" "), ...);
	}
	namespace object {			//这真是无奈之举,这个匹配,object命名空间内的除了遍历vector和array的数组外,标准数据类型直接打印也可行
		template<typename T>
		std::ostream& operator<<(std::ostream& os, const std::vector<T>& data)
		{
			for (auto& str : data)
			{
				os << str<<" ";
			}
			return os;
		}
		template<typename T, size_t size>
		std::ostream& operator<<(std::ostream& os, const std::array<T, size>& data)
		{
			for (auto& str : data)
			{
				os << str<<" ";
			}
			return os;
		}
		void print() {}
		template<typename T, typename...Types>
		void print(T first, Types...args) {
			std::cout << first << '\n';
			print(args...);
			return;
		}
	}
	namespace range {	//没办法重载多了就是匹配问题,我能这里使用c++20的range
		void print_impl(std::ostream& out, std::ranges::range auto&& r)
		{
			for (auto&& elem : r)
			{
				out << elem << " ";
			}
			std::cout << std::endl;
		}
		void print_impl(std::ostream& out, auto&& elem)
		{
			out << elem << " ";
			std::cout << std::endl;
		}
		void print(auto&&...args)
		{
			(print_impl(std::cout, args), ...);
		}
	}
	namespace rangeClass {		//也可以写成一个类,主要是为了防止让print_impl暴露在外部接口,因为print同名的缘故所以我们无法写在一起
		class print {
		public:
			void operator()(auto&&...args)
			{
				(print_impl(std::cout, args), ...);
			}
		private:
			void print_impl(std::ostream& out, std::ranges::range auto&& r)
			{
				for (auto&& elem : r)
				{
					out << elem << " ";
				}
				std::cout << std::endl;
			}
			void print_impl(std::ostream& out, auto&& elem)
			{
				out << elem << " ";
				std::cout << std::endl;
			}
		};
	}
}

推荐放入头文件内,且我们需要C++的vector,array,ostream,range等标准库

使用的时候可以#include<......>        using namespace show_;

更多的方式还请自己探索,这不是最优解,等我有兴趣的时候或许会重构此代码

namespace input_ {
	template<typename T, size_t size>
	void input(T(&v)[size],std::string str="")//裸数组版本重载
	{
		if (str[0])std::cout << str;
		for (auto& i : v)std::cin >> i;
	}
	template<size_t size>
	void input(char(&v)[size], std::string str = "")//是上一个模板的偏特化,这倒是比之前的print高明
	{
		if (str[0])std::cout << str;
		std::cin.getline(v, size);
	}
	template<typename T>				//string对象的输入
	void input(T &v, std::string str = "")
	{
		if (str[0])std::cout << str;
		std::cin >> v;
	}
	template<typename T>					//vector版本
	void input(std::vector<T>&v, size_t size,std::string str="")
	{
		if (str[0])std::cout << str;
		v.resize(size);
		for (int i = 0; i < size; i++)std::cin >> v[i];
	}
	template<typename T,size_t size>
	void input(std::array<T, size>& v, std::string str = "")
	{
		if (str[0])std::cout << str;
		for (int i = 0; i < size; i++)std::cin >> v[i];
	}
	/*-----------------------------------------------------------------*/
	void print_impl(std::istream& out, std::ranges::range auto&& r)		//不得不承认,得益于C++20,一切皆可
	{
		for (auto&& elem : r)
		{
			out >> elem;
		}
	}
	void print_impl(std::istream& out, auto&& elem)
	{
		out >> elem;
	}
	void input(auto&&...args)
	{
		(print_impl(std::cin, args), ...);
	}
}

input,这个倒是要清晰一点,可以联合在一起使用

#include<....>

using namespace show_;

using namespace input;        

那么就可以开始愉快的使用print与input了

 肯定有小白问了,怎么放到标准库里面用尖括号导入

以vs示范,随便找一个标准库的头文件右击,转到文档

 看这张图最右边,vector,右击它

 打开所在文件夹,然后就可以直接把自己写的头文件复制进去就行了

 环境:msvc(vs2022) x86 debug C++20 未开启优化

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值