假设我想 rot13 传递给 cout (或另一个 ostream)的每个字符串,这样,说cout<<"Foo Bar Baz.;"
(或什至cout<<rot13<<"Foo Bar Baz.";
)输出Sbb One Onm.
我该怎么做呢?
(我的第一个想法是用一个可以完成所有工作的 streambuf 派生类替换 cout 的 streambuf。但是看到原始的 streambuf 负责将内容引导到控制台......这根本没有解决。)
您可以编写自己的流,为 char*、std::string 和其他重载 operator<< 并打印转换后的文本。
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
using namespace std;
class ostream_rot13 : public basic_ostream <char, char_traits<char> >
{
public:
ostream_rot13(std::basic_streambuf<char, char_traits<char> >* sb)
: basic_ostream<char, char_traits<char> >(sb) {}
ostream_rot13& operator<<(const char* text)
{
std::string s(text);
int rot=13;
std::transform(std::begin(s), std::end(s), ostream_iterator<char>(*this), [rot] (char c) {
if(c >= 'a' && c <= 'z')
return 'a' + (c + rot - 'a') % 26;
else if(c >= 'A' && c <= 'Z')
return 'A' + (c + rot - 'A') % 26;
return (int)c;
});
return *this;
}
};
下一步是声明一个这种类型的全局变量,然后声明一个用新变量替换 cout 的宏。
ostream_rot13 cout_rot13(std::cout.rdbuf());
#define cout cout_rot13
然后所有的 cout 实例都会变成 cout_rot13。
int main()
{
cout << "Foo Bar Baz";
return 0;
}
你不能自己包装 cout 的 streambuf,将所有调用转发到包装的缓冲区吗?
您只需要在将“put”调用转发到包装的 streambuf 之前进行一些编码。
不过,对于一个小 rot13 来说,这是很多工作。