putback line

is there a method to put back line after a getline(file, line), like putback(char)?

I mean, I want to read 2 times the same line.
first time to check if last char is punctual, second time to split line into tokens with myGetToken() that takes token of the file.

Not that I know of. But you don't need to do that anyway -- you used getline the first time, now you have the line as a string.
You can check if the last char is punctuation and split the line into tokens using that same string, without reading from the file twice.

If you really needed to go backwards in the file by some amount, you would use seekg after saving the previous location you were at. But again, you really shouldn't have to do this.
Last edited on
I know but I have this method myGetToken() that I need to split line into tokens, checking errors, reading from file..
You can do this with tellg()/seekg() combination. See:

http://www.cplusplus.com/reference/istream/istream/tellg/?kw=tellg

However why do you want read it twice? Just read the string into a local variable and do whatever you want to do with it?
Last edited on
I still don't think you need to read any line from the file twice.
The logic that checking for punctuation operates on can use the same string that the logic for myGetToken operates on, if you structure it correctly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
#include <fstream>
#include <vector>

using namespace std;

bool endsInPunct(const std::string& line)
{
    std::string puncts = { '!', ',', '.', ';' }; // etc.
    return line.size() > 0 && puncts.find(line.back()) != std::string::npos;
}

vector<string> getTokens(const std::string& line)
{
    /// ....
    return vector<string> {"test", "token"}; // TODO
}

int main()
{
    std::ifstream fin("file.txt");
    
    std::string line;
    while (getline(fin, line))
    {
        if (!endsInPunct(line))
        {
            std::cout << "Error: Line does not end in punctuation!\n";
            // [handle error]
        }
        
        vector<string> tokens = getTokens(line);
        
        for (const auto& token : tokens)
        {
            cout << token << '\n';
        }
    }  
}
Last edited on
> I still don't think you need to read any line from the file twice.

Yes.

Nevertheless, just for fun, here is a thin wrapper class that allows put back of one line:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>

struct pb_line_stm
{
    explicit pb_line_stm( std::istream& stm ) : stm(stm) {}

    bool get_line( std::string& str )
    {
        if(put_back_flag)
        {
            put_back_flag = false ;
            str = std::move(last_read) ;
            return true ;
        }

        else if( std::getline( stm, last_read ) )
        {
            str = last_read ;
            return true ;
        }

        else return false ;
    }

    bool put_back() // note: puts back an empty line if no line has been read
    {
        if( !put_back_flag ) return put_back_flag = true ;
        else return false ;
    }

    private:
        std::istream& stm ;
        std::string last_read ;
        bool put_back_flag = false ;
};

int main() // minimal tst driver
{
    std::ifstream this_file(__FILE__) ; // use this file for testing
    pb_line_stm pbstm(this_file) ;

    char c ;
    while( std::cout << "enter g to get line, p to put back: " && std::cin >> c )
    {
        if( c == 'g' || c == 'G' )
        {
            std::string str ;
            if( pbstm.get_line(str) ) std::cout << "got line: " << std::quoted(str) << '\n' ;
            else std::cout << "get line failed\n" ;
        }

        else if( c == 'p' || c == 'P' )
        {
            if( pbstm.put_back() ) std::cout << "putback the last line\n" ;
            else std::cout << "putback failed\n" ;
        }
    }
}

Topic archived. No new replies allowed.