Reading a file

Hello, I have a question about C++. What should I do in order to read file which look like this?
I'm having problem reading two words in a single string. Can someone help me? Maybe even write a simple code which could do that?

1
2
3
4
5
LND01 Njuspeipis          1.00
LND02 Luko žodis          0.59
LND03 Geriausias leidinys 5.99
LND04 Progsio šauksmas    2.50
LND05 Skylė barankoje     1.99
Assuming that performance is not critical (if it is, perhaps use boost spirit), something like this:

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <sstream>
#include <iterator>

struct info
{
    std::string key ; // LND01
    std::string name ; // Geriausias leidinys
    double number ; // 2.50
};

// return <double,true> if str contains a double
// return <0,false> otherwise
std::pair<double,bool> to_double( const std::string& str )
{
    std::istringstream stm(str) ;
    double dbl ;
    if( stm >> dbl && stm.eof() ) return { dbl, true } ;
    else return { 0, false } ;
}

// return <info,true> if line can be parsed correctly
// return < {"","",0},false> otherwise
std::pair<info,bool> parse( const std::string& line )
{
    // split the line into ws delimited tokens
    std::istringstream stm(line) ;
    using iterator = std::istream_iterator<std::string> ;
    std::vector<std::string> tokens { iterator(stm), iterator() } ;

    if( tokens.size() > 2 ) // if the number of tokens is three or more
    {
        const auto pair = to_double( tokens.back() ) ;
        if( pair.second ) // and if the last token is a number
        {
            // the name consists of all tokens except the first and the last
            std::string name = tokens[1] ;
            for( std::size_t i = 2 ; i < tokens.size()-1 ; ++i )
                name += ' ' + tokens[i] ;

            return { info{ tokens[0] /* key */, name, pair.first }, true } ;
        }
    }

    return { info{ "", "", 0 }, false } ; // failed
}

int main()
{
    std::istringstream file
    (
        "KEY01  abcd efgh ijk 23.78\n" // ok
        "KEY02  45.72\n" // error: too few tokens
        "KEY03  abcd efgh ijklmn opq rstu 99.65\n" // ok
        "KEY04  abcdefgh 5.60\n" // ok
        "KEY05  abcd efgh xxx.yy\n" // error: last token is not a number
        "KEY06  abcd efgh 12.68ab\n" // error: last token is not a number
        "KEY06  abcd efgh -0.012340e+03\n" // ok
    );

    std::string line ;
    while( std::getline( file, line ) )
    {
        std::cout << line << '\n' ;
        const auto pair = parse(line) ;
        if( pair.second ) // if the line was parsed sucessfully
        {
            const info& inf = pair.first ;
            std::cout << "    key: " << inf.key
                       << "\n    name: " << inf.name
                       << "\n    number: " << inf.number << "\n\n" ;
        }
        else std::cout << "    ****error: badly formed line\n\n" ;
    }
}

http://coliru.stacked-crooked.com/a/99be871f758cc7ba
Thanks for your answer! Unfortunately that's way too advanced to me right now, going to remember your answer later on if I need something similar. :)
I guess I'll just edit my file for now.
I guess I'll just edit my file for now.
If you could edit your file so that the fields are separated by tabs rather than spaces, it gets easier, in my opinion.

For example instead of LND02 Luko žodis 0.59
we have LND02\tLuko žodis\t0.59

Here I've used the '\t' symbol purely for illustration on this forum, as the tab character itself is invisible (or appears as spaces).

Program code:
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
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>

    using namespace std;

int main()
{
    const char * filename = "D:\\temp\\input1.txt";
    ifstream fin(filename);

    string line;

    cout << left;

    while (getline(fin, line))
    {
        string key;
        string name;
        double value;
        istringstream ss(line);
        ss >> key;
        ss >> ws; // ignore whitespace after key.
        getline(ss, name, '\t');
        ss >> value;
        cout << "Key: " << key << "  Name: " << setw(20) << name << "  value: " << value << endl;
    }
}

Output:
Key: LND01  Name: Njuspeipis            value: 1
Key: LND02  Name: Luko ×odis            value: 0.59
Key: LND03  Name: Geriausias leidinys   value: 5.99
Key: LND04  Name: Progsio Üauksmas      value: 2.5
Key: LND05  Name: Skyle. barankoje      value: 1.99
Oh, thank you for your answer too, I think I'm going to stick with it for now.
You guys are awesome! :)
Topic archived. No new replies allowed.