Vous pouvez créer un tampon de flux de filtrage, c'est-à-dire une classe dérivée de std::streambuf
. Pour prendre en charge la lecture mise en mémoire tampon, vous devez remplacer underflow()
pour remplir le prochain tampon de caractère une fois les caractères saisis. Pour soutenir une recherche limitée, le tampon précédent ne serait pas rejeté mais plutôt retenu en partie. En outre, vous devez remplacer seekoff()
.
Quelque chose comme ça devrait faire l'affaire:
#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";
}
}
}
Le code ci-dessus fonctionne avec un couple de cas de tests simples. Il démontre les utilisations du positionnement relatif et absolu. Génériquement, je trouve inutile de chercher dans les flux car généralement tout lexique intéressant peut être fait avec un seul caractère anticipé. En conséquence, j'ai peut-être manqué quelque chose dans le contexte de la position. Cependant, je m'attends à ce que le code ci-dessus fonctionne correctement.
Je recommanderais * La bibliothèque standard C++ * de Nicolai Josuttis. Ayant écrit la section pertinente du chapitre sur IOStreams, je peux être partial, cependant. La seule autre alternative que je connaisse est la bibliothèque * IOStreams and Locales * d'Angelika Langer & Klaus Kreft. Les * IOStreams * de Steve Teale sont plutôt périmés (j'ai aussi appris les bases). –