2013-12-15 3 views
4

Допустим, у меня есть внешний цикл while, чтобы читать каждый символ и выводить его на консоль. Я также хочу отметить слово, если оно найдено, и с помощью метода peek я могу найти первый экземпляр слова. Есть ли способ заглянуть в несколько мест вперед. Например, если я ищу слово «payday». Я знаю, что могу вводить это в строку и искать строку, но я хочу читать файлы в двоичном режиме, и я не хочу убирать любые значения из внешнего цикла. Если у меня есть внутренний цикл с методом чтения, эти значения затем не отображаются через внешний цикл.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. 
    } 

} 
+0

Почему вы используете динамическое распределение? – Shoe

ответ

5

Вы можете использовать метод seekg прыгать в IStream.

Если вы открываете файл в двоичном режиме, вы можете использовать метод tellg, чтобы отметить позицию для перехода.

Однако, если вы открываете файл в текстовом режиме, лучше перепрыгивать со смещением (т. Е. Strm.seekg (offset, strm.cur)), из-за того, как многобайтовые символы, такие как newline, подсчитываются tellg и seekg в текстовом режиме. Поэтому, если вы обнаружите, что следующий символ будет «p», вы можете прочитать следующий n-й символ, а затем вернуться назад -n символ, если это не то, что вы ищете.

+0

Спасибо оба. Любое решение будет работать здесь, но я никогда не использовал seekg раньше и теперь, когда я его обнаружил, он делает именно то, что мне нужно. Огромное спасибо. – domonica

+0

@domonica: обратите внимание, что наличие правильного анализатора, как правило, является лучшим решением в долгосрочной перспективе, поскольку правильный анализ с правильными обработками ошибок, устойчивость к изменениям пробелов и безопасное экранирование означает, что работа по синтаксическому анализу может быстро возрастать по сложности. Еще лучше использовать хорошо установленный формат, например xml или json или csv, вместо определения собственного формата и использовать хорошо отлаженную библиотеку для их записи и загрузки. –

4

Существует несколько способов достижения этой цели, однако обычный способ состоит в том, чтобы добавить еще один слой между исходным файлом и «пользовательскими» функциями: лексер.

Например, Лексер с неограниченной буферизацией:

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 

Примечания: Очевидно, вы вполне могли бы ограничить буферизацию лексера, или сделать его буфер что-то другое, чем слова, и т.д ... главное Преимущество пользовательского класса в том, что вы диктуете семантику!

Смежные вопросы