Допустим, у меня есть внешний цикл while для чтения каждого символа и вывода его на консоль. Я также хочу пометить слово, если оно найдено, и с помощью метода peek я могу найти первый экземпляр слова. Есть ли способ посмотреть несколько мест впереди. Например, если я ищу слово «день выплаты жалованья». Я знаю, что могу ввести это в строку и найти строку, но я хочу читать файлы в двоичном режиме и не хочу убирать какие-либо значения из внешнего цикла. Если у меня есть внутренний цикл с методом чтения, эти значения не отображаются через внешний цикл.
Спасибо
int main()
ifstream strm;
char *chr = new char;
strm.open("mytext.txt",ios::out | ios::binary);
while (strm.read(chr,1)
{
if (strm.peek() == 'p';
{
cout << "found a word beginning with 'p'" << endl;
//what if I want to read multiple characters ahead. Peek will read only one.
}
}
Ты можешь использовать seekg метод, чтобы прыгать в пределах istream.
Если вы открываете свой файл в двоичном режиме, вы можете использовать tellg метод, чтобы отметить позицию, чтобы перейти к.
Однако, если вы открываете свой файл в текстовом режиме, вместо этого лучше перейти со смещением (то есть strm.seekg (offset, strm.cur)), поскольку многобайтовые символы, такие как символ новой строки, подсчитываются с помощью Tellg и seekg в текстовом режиме. Поэтому, если вы обнаружите, что следующим символом будет «p», тогда вы можете прочитать следующий n символов, а затем перейти назад на -n символ, если это не то, что вы ищете.
Есть несколько способов добиться этого, однако общепринятым является просто добавить еще один слой между исходным файлом и «пользовательскими» функциями: лексер.
Например, лексер с неограниченной буферизацией:
class Lexer {
public:
Lexer(std::istream& s): source(s) { this->read(); }
explicit operator bool() const {
return not queue.empty();
}
Lexer& operator>>(std::string& s) {
assert(*this and "Test for readiness before calling this method");
s = queue.front();
queue.pop_front();
if (queue.empty()) { this->read(); }
return *this;
}
std::string const* peek(size_t const i) {
while (source and queue.size() < i) { this->read(); }
return queue.size() >= i ? &queue[i] : nullptr;
}
private:
void read() {
queue.emplace_back();
if (not (source >> queue.back())) { queue.pop_back(); }
}
std::istream& source;
std::deque<std::string> queue;
}; // class Lexer
Примечание: очевидно, что вы можете идеально ограничить буферизацию лексера или сделать его буфером для чего-то другого, кроме слов и т. Д. … главное преимущество пользовательского класса заключается в том, что вы диктовать семантику!