让我们假设我想要为输入和输出编写自己的机械手。
cin >> mymanip >> str;或
cout << mymanip << str;我想要的是我要做的是切换案例,我从输入中读取的字符,并将结果分配给一个字符串。
所以,如果我输入"QwErTy“,就会在字符串中得到"qWeRtY”。
这是一个非常基本的任务,只有一个功能,但我想了解更多关于机械手的知识。
有人能给点线索吗?
谢谢。
发布于 2016-11-27 23:14:21
这种方法有点棘手--但可以做到,您可以为流添加自己的机械手。
首先,你需要你的开关:
class toggle_t {};
constexpr toggle_t toggle;下一步- ostream的版本( istream的情况非常相似.):
在将toggle放到ostream之后-您需要一些特殊的对象:
struct toggled_ostream
{
std::ostream& os;
};
inline toggled_ostream operator << (std::ostream& os, toggle_t)
{
return { os };
}注意,有人可能把toggle放在了错误的位置:cout << toggle << 123 -所以它应该像普通流那样适用于所有其他类型:
template <typename T>
std::ostream& operator << (toggled_ostream tos, const T& v)
{
return tos.os << v;
}因此,对于char类型(如char、const char*、std::string),编写切换重载。我给您提供了char的版本--为“更长”类型编写版本应该不会有问题:
std::ostream& operator << (toggled_ostream tos, char v)
{
char c = std::isupper(v) ? std::tolower(v)
: std::islower(v) ? std::toupper(v) : v;
return tos.os << c;
}工作演示。
发布于 2016-11-27 22:25:51
操纵者所做的就是在std::ios_base基类中设置相应的位。
例如,std::setprecision()操作器简单地将基数::精度()放在被操纵的流上。
在gcc的标题中,std::setprecision()的实现几乎是可读的(对于C++库模板实现来说,这是非常罕见的):
inline _Setprecision setprecision(int __n)
{ return { __n }; }std::setprecision()返回一个内部std::_Precision对象。然后,为>> (和类似的<<操作符)为std::_Precision对象提供一个简单的模板重载,处理其余的魔术:
template<typename _CharT, typename _Traits>
inline basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, _Setprecision __f)
{
__is.precision(__f._M_n);
return __is;
}在您的示例中,std::ios_base类中没有实现所需输入/输出转换的位。因此,操纵者本身不会在这里工作。
你想要做的事情需要一种完全不同、更复杂的方法:
std::[io]stream的一个自定义子类,它使用std::streambuf的自定义子类。std::streambuf子类从一个链式流中读取或写入,如您所描述的那样转换输入或输出。发布于 2016-11-27 22:27:08
你不能那样做。相反,您可以做的是以字符串为参数的操纵器,即
std::cout << toggle(str);
std::cin >> toggle(str);操纵者仅仅是所谓的句法糖,也就是说,它比其他人做事情更方便。例如,
std::cout << std::setw(5) << x <<;也会像
std::cout.width(5);
std::cout << x;但是更方便,因为它允许与其他<<操作链接在一起。
现在,您所需要的东西(交换小写字符和大写字符)没有格式化支持,因此也无法为此提供语法糖。
但是,如果机械手可以将您的字符串作为参数,那么当然,您可以实现您想要的,以标准的方式实现机械手。例如,
struct toggle_output
{ std::string const&str; }
inline toggle_output toggle(std::string const&str)
{ return {str}; }
inline std::ostream& operator<<(std::ostream&out, toggle_output const&t)
{
for(auto c:t.str)
if (std::islower(c)) out<<std::toupper(c);
else if(std::isupper(c)) out<<std::tolower(c);
else out<<c;
return out;
}
struct toggle_input
{ std::string &str; }
inline toggle_input toggle(std::string&str)
{ return {str}; }
inline std::istream& operator>>(std::istream&in, toggle_input &t)
{
in >> t.str;
for(auto&c:t.str)
if (std::islower(c)) c=std::toupper(c);
else if(std::isupper(c)) c=std::tolower(c);
return in;
}您还可能需要(以避免混淆)
inline std::ostream& operator<<(std::ostream&out, toggle_input const&t)
{ return out<<toggle_output(t.str); }https://stackoverflow.com/questions/40834544
复制相似问题