假设我正在从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
答案 0 :(得分:4)
您可以使用过滤streambuf,并在那里继续计数:
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;
请注意,行号仅反映所需的输入 穿过streambuf。