2 Stimmen

Zeilennummer in einem C++ istream?

Angenommen, ich lese Token von einem std::istream. Wie kann ich auf einfache Weise wissen, wie viele Zeilenumbrüche aus dem Stream gelesen wurden? Dies dient dem Zweck der Fehlermeldung in einem Parser. Ich möchte nicht std::getline zum Lesen der Eingabe verwenden.

Hier ist ein Testfall. Ich suche nach etwas, das funktional ähnlich wie GetLineNumber ist, das in diesem Fall die Zeilennummer des zuletzt gelesenen Tokens zurückgeben würde.

std::stringstream ss;
ss << "1 \n 2 \n 3 \n";

int x;
while (ss >> x) {
    std::cout << "Zeile " << GetLineNumber(ss) << ": " << x << std::endl;
}

Die Ausgabe dieses Beispiels sollte sein:

Zeile 1: 1
Zeile 2: 2
Zeile 3: 3

4voto

James Kanze Punkte 146902

Sie können einen Filterstreambuf verwenden und dort die Zählung beibehalten:

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;
    }
};

Fügen Sie dies einfach in Ihre Eingabe ein:

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

Beachten Sie, dass die Zeilennummern nur die Eingabe widerspiegeln, die über den Streambuf erfolgt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X