问题描述
假设我正在从std::istream
读取令牌.知道从流中读取换行符数量的好方法是什么?这是为了在解析器中报告错误.我不想使用std::getline
读取输入.
Suppose I'm reading tokens from a std::istream
. What is a good way to know the number of newlines that have been read from the stream? This is for the purpose of error reporting in a parser. I don't want to use std::getline
to read input.
这是一个测试用例.我正在寻找功能类似于GetLineNumber
的东西,在这种情况下,它将返回最后读取的令牌的行号.
Here is a test case. I am looking for something functionally similar to GetLineNumber
, which in this case would return the line number of the last read token.
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
推荐答案
您可以使用过滤streambuf,并在此保持计数:
You can use a filtering streambuf, and keep count there:
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;
}
};
只需将其插入您的输入中即可
Just insert this into your input:
LineNumberStreambuf ln( std::cin );
// ...
std::cerr << "Error (" << ln.lineNumber << "): ..." << std::endl;
请注意,行号将仅反映输入通过streambuf放置.
Note that line numbers will only reflect the input which takesplace through the streambuf.
这篇关于C ++ istream中的行号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!