您可以創建一個過濾流緩衝區,即從std::streambuf
派生的類。爲了支持緩衝讀取,一旦輸入字符被消耗,您將覆蓋underflow()
以填充字符的下一個緩衝區。爲了支持有限的尋求,以前的緩衝區不會被丟棄,而是被部分保留。另外,你會覆蓋seekoff()
。
像這樣的東西應該做的伎倆:
#include <iostream>
#include <streambuf>
#include <string>
#include <cstdlib>
#include <cstring>
class bufferbuf
: public std::streambuf {
enum { size = 2000, half = size/2 };
char buffer[size];
std::streambuf* sbuf;
std::streamoff base;
public:
bufferbuf(std::streambuf* sbuf): sbuf(sbuf), base() {
auto read = sbuf->sgetn(this->buffer, size);
this->setg(this->buffer, this->buffer, this->buffer + read);
}
int underflow() {
if (this->gptr() == this->buffer + size) {
std::memmove(this->eback(), this->eback() + half, half);
base += half;
auto read = sbuf->sgetn(this->eback() + half, half);
this->setg(this->eback(), this->eback() + half, this->eback() + half + read);
}
return this->gptr() != this->egptr()
? traits_type::to_int_type(*this->gptr())
: traits_type::eof();
}
std::streampos seekoff(off_type offset,
std::ios_base::seekdir whence,
std::ios_base::openmode which) override {
if (this->gptr() - this->eback() < -offset
|| this->egptr() - this->gptr() < offset
|| whence != std::ios_base::cur
|| !(which & std::ios_base::in)) {
return pos_type(off_type(-1));
}
this->gbump(offset);
return pos_type(this->base + (this->gptr() - this->eback()));
}
std::streampos seekpos(pos_type pos, std::ios_base::openmode which) override {
if (off_type(pos) < this->base
|| this->base + (this->egptr() - this->eback()) < off_type(pos)
|| !(which & std::ios_base::in)) {
return pos_type(off_type(-1));
}
this->setg(this->eback(), this->eback() + (off_type(pos) - this->base), this->egptr());
return pos_type(base + (this->gptr() - this->eback()));
}
};
int main() {
bufferbuf buf(std::cin.rdbuf());
std::istream in(&buf);
// ...
std::string s0, s1;
bool relative(false);
if (relative) {
while (in >> s0
&& (in.seekg(-int(s0.size()), std::ios_base::cur), in >> s1)) {
std::cout << "read "
<< "s0='" << s0 << "' " << "s1='" << s1 << "'\n";
}
}
else {
for (std::streampos pos = in.tellg();
in >> s0 && (in.seekg(pos), in >> s1); pos = in.tellg()) {
std::cout << "read "
<< "s0='" << s0 << "' " << "s1='" << s1 << "'\n";
}
}
}
上面的代碼與幾個簡單的測試情況下工作。它演示了相對和絕對定位的用法。一般來說,我發現在流中尋找是沒有用的,因爲通常每個有趣的選擇都可以通過一個字符來完成。結果,我可能在位置上錯過了一些東西。不過,我期望上面的代碼正常工作。
我推薦Nicolai Josuttis的* C++標準庫*。雖然已經寫了關於IOStreams的章節的相關部分,但我可能會有偏見。我唯一知道的其他選擇是Angelika Langer&Klaus Kreft的* IOStreams和Locales Library *。 Steve Teale的IOStreams *已經過時了(我也在那裏學習了基礎知識)。 –