c++ istream中的行号

Line number in a C++ istream?

本文关键字:istream c++      更新时间:2023-10-16

假设我正在从std::istream读取令牌。知道从流中读取的换行数的好方法是什么?这是为了在解析器中报告错误。我不想用std::getline来读取输入

这是一个测试用例。我正在寻找功能类似于GetLineNumber的东西,在这种情况下,它将返回最后读令牌的行号。

std::stringstream ss;
ss << "1 n 2 n 3 n";
int x;
while (ss >> x) {
    std::cout << "Line " << GetLineNumber(ss) << ": " << x << std::endl;
}
这个例子的输出应该是:
Line 1: 1
Line 2: 2
Line 3: 3

您可以使用过滤流buf,并在那里保持计数:

class LineNumberStreambuf : public std::streambuf
{
    std::streambuf* mySource;
    std::istream* myOwner;
    bool myIsAtStartOfLine;
    int myLineNumber;
    char myBuffer;
protected:
    int underflow()
    {
        int ch = mySource->sbumpc();
        if ( ch != EOF ) {
            myBuffer = ch;
            setg( &myBuffer, &myBuffer, &myBuffer + 1 );
            if ( myIsAtStartOfLine ) {
                ++ myLineNumber;
            }
            myIsAtStartOfLine = myBuffer == 'n';
        }
        return ch;
    }
public:
    LineNumberStreambuf( std::streambuf* source )
        : mySource( source )
        , myOwner( nullptr )
        , myIsAtStartOfLine( true )
        , myLineNumber( 0 )
    {
    }
    LineNumberStreambuf( std::istream& owner )
        : mySource( owner.rdbuf() )
        , myOwner( &owner )
        , myIsAtStartOfLine( true )
        , myLineNumber( 0 )
    {
        myOwner->rdbuf( this );
    }
    ~LineNumberStreambuf()
    {
        if ( myOwner != nullptr ) {
            myOwner.rdbuf( mySource );
        }
    }
    int lineNumber() const
    {
        return myLineNumber;
    }
};

把这个插入到你的输入中:

LineNumberStreambuf ln( std::cin );
//  ...
std::cerr << "Error (" << ln.lineNumber << "): ..." << std::endl;

注意,行号只反映输入的值