7

假设我有一个外部 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.
  }

}
4

2 回答 2

8

You can use seekg method to jump around within the istream.

If you open your file in binary mode, you can use tellg method to mark the position to jump to.

However, if you open your file in text mode, it is better to jump with offset instead (i.e. strm.seekg(offset, strm.cur)), due to how multibyte characters like newline are counted by tellg and seekg in text mode. So if you detect that the next character is going to be "p", then you can read the next n character, then jump back -n character if it's not what you're looking for.

于 2013-12-15T14:09:54.413 回答
5

有多种方法可以实现这一点,但是传统的方法只是在原始文件和“用户”函数之间添加一层:词法分析器。

例如,具有无限缓冲的 Lexer:

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

注意:显然,您可以完美地限制词法分析器的缓冲,或者使其缓冲单词以外的其他内容,等等......自定义类的主要优点是您可以指定语义!

于 2013-12-15T14:20:44.047 回答