几天前,我决定编写一个streambuf使用mmap和预读的子类会很有趣.我看了一下我的STL(SGI)如何实现filebuf和实现basic_filebuf包含a FILE*.所以继承basic_filebuf是不可能的.
所以我继承了basic_streambuf.然后我想把我绑mmapbuf到一个fstream.
我认为我唯一需要做的就是复制filebuf...... 的隐式接口,但这是一个明显的错误.在SGI,basic_fstream拥有一个basic_filebuf.无论我是否打电话basic_filestream.std::::ios::rdbuf( streambuf* ),文件流都完全忽略它并使用它自己的filebuf.
所以现在我有点困惑......当然,我可以创建我自己的mmfstream,这将是确切的复制/粘贴,fstream但听起来真的不是面向DRY的.
我无法理解的是:为什么fstream这么紧密地耦合在一起filebuf,所以除了一个以外什么都不可能使用filebuf?分离流和bufs的关键在于可以使用具有不同缓冲区的流.
解决方案:
=> filestream应该依赖于隐式接口filebuf.也就是说,fstream应该由streambuf类进行模板化.这将允许每个人提供自己的streambuf子类,fstream只要它实现了filebuf隐式接口.问题:我们无法添加模板参数,fstream因为它会在fstream用作模板模板参数时破坏模板选择器.
=> filebuf应该是一个没有任何附加属性的纯虚拟类.这样一个人就可以从中继承而不携带所有的FILE*垃圾.
你对这个问题的想法?
basic_streambuf设置streambuf的三个"gptrs" 的成员setg被声明为:
protected:
void setg(char_type *gback, char_type *gptr, char_type *egptr);
Run Code Online (Sandbox Code Playgroud)
我想知道:为什么每个gptr的类型char_type*而不是const char_type*?const_cast在这里使用const char指针这些gptrs 是否安全?
我将C++ streambuf类用于编译器项目,并且需要一种方便的方法来获取流中的当前位置.
有两个成员函数,streambuf::pubseekpos和一个streambuf::pubseekoff,来修改位置,我很困惑没有streambuf::pubgetpos成员函数(或类似的东西)来阅读它.
似乎有两种可能的解决方法:
我可以将当前位置保存在单独的变量中,并在每次从流中读取字符时手动修改它.
我可以调用streambuf::pubseekoff(0, ios_base::cur),返回新的流位置.
对于这样一个微不足道的任务,第二种选择似乎是可用的,但是效率低下且不美观.有没有更好的方法呢?
为了理解输入流的工作原理,我设计了以下两个类:
#include <iostream>
class my_streambuf: public std::streambuf
{
private:
std::streambuf* buffer;
char ch;
protected:
virtual std::streambuf::int_type underflow()
{
std::streambuf::int_type result = buffer->sbumpc();
if (result != traits_type::eof())
{
ch = traits_type::to_char_type(result);
setg(&ch, &ch, &ch + 1);
}
return result;
}
public:
my_streambuf(std::streambuf* buffer) : buffer(buffer) {};
virtual ~my_streambuf() {};
};
class my_istream: public std::istream
{
public:
my_istream(std::istream& stream) : std::istream(new my_streambuf(stream.rdbuf())) {};
virtual ~my_istream()
{
delete rdbuf();
}
};
int main()
{
char s[32];
my_istream is(std::cin);
is >> s;
std::cout << …Run Code Online (Sandbox Code Playgroud) std::ostream有一个flush()方法:
将未提交的更改写入基础输出序列。
这对 a 意味着什么std::stringstream?如果我理解正确,这意味着对于这样的流没有什么可做的。这是真的?
我正在尝试实现一个流缓冲区,我在制作overflow()工作时遇到了麻烦.我将缓冲区调整了10个以上的字符并使用重置缓冲区setp.然后我将指针递回到我们离开的地方.由于某种原因,输出不正确:
template <class charT, class traits = std::char_traits<charT>>
class stringbuf : public std::basic_stringbuf<charT, traits>
{
public:
using char_type = charT;
using traits_type = traits;
using int_type = typename traits::int_type;
public:
stringbuf()
: buffer(10, 0)
{
this->setp(&buffer.front(), &buffer.back());
}
int_type overflow(int_type c = traits::eof())
{
if (traits::eq_int_type(c, traits::eof()))
return traits::not_eof(c);
std::ptrdiff_t diff = this->pptr() - this->pbase();
buffer.resize(buffer.size() + 10);
this->setp(&buffer.front(), &buffer.back());
this->pbump(diff);
return traits::not_eof(traits::to_int_type(*this->pptr()));
}
// ...
std::basic_string<charT> str()
{
return buffer;
}
private:
std::basic_string<charT> buffer;
}; …Run Code Online (Sandbox Code Playgroud) 我正在使用streambuf的async_read.但是,我想将读取的数据量限制为4,因此我可以在转到正文之前正确处理标题.
我怎么能用async_read做到这一点?
std::cout我想扩展使用我自己的控制台/cout 包装类的用法。
理想情况下,我会有 2 个 ostream,一个用于常规打印,另一个用于附加新行。
std::ostream Write;
Write << "Hello, I am " << 99 << " years old.";
Run Code Online (Sandbox Code Playgroud)
印刷Hello, I am 99 years old.
std::ostream WriteLine;
WriteLine << "Hello, I am " << 99 << " years old.";
Run Code Online (Sandbox Code Playgroud)
打印Hello, I am 99 years old.\n(一个实际的新行,而不仅仅是转义)
然后,我想扩展它以具有错误流(例如Error和),该错误流在消息之前添加前缀并以不同的颜色打印。ErrorLine"ERROR: "
我知道我必须创建自己的流来添加此功能,并且我遵循C++ cout 并使用前缀作为前缀std::cout,这几乎是我想要的,但不完全是。我不知道如何在流的末尾添加新行,并且前缀不可靠,特别是当我要执行多个打印语句时。
我还应该提到我不想使用重载运算符来实现这种效果,因为我希望能够以菊花链方式连接事物。
什么不起作用
如果我WriteLine >> "First";这样做,WriteLine << "Second";我会得到奇怪的结果,例如SecondFirst\n或Second\nFirst。我理想的输出是First\nSecond\n. …
让我们想象一下我的程序需要用户在不同时间输入。我希望这个输入可以防止刷新cout缓冲区。我可以在不同的流缓冲区上设置cin和吗?cout
相关示例:一个程序读取一行中的两个数字 , n1 n2,并且取决于第一个数字是0, 1, 或2:
n1 = 0:将第二个数字写入n2向量vn1 = 1:输出v[n2]在coutn1 = 2:pop_back()在vMWE 为:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int size, n1, n2;
vector<int> v;
cin >> size;
while(size--){
cin >> n1;
if (n1 == 0)
{
cin >> n2;
v.push_back(n2);
}
else if (n1 == 1)
{ …Run Code Online (Sandbox Code Playgroud)