How to adapt to read a file in different formats?

Hello,

I am in a mess I wouldn't know what to do if I were to retrieve data from a file in different formats. For example :
(1)
Wales 0.12 60
Ronaldo 0.25 140


(2)
Wales,0.12,60
Ronaldo,0.25,140


(3)
Wales , 0.12 , 60
Ronaldo , 0.25 , 140


(4)
Wales
0.12
60
// This newline character here is on purpose
Ronaldo
0.25
140


Could anyone give me the best approach for each situation I have mentioned? I am new to std::ifstream and any help would be very appreciated.

Thanks in advance.
If the first field (name) does not contain embedded commas or white spaces,

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
79
80
81
82
#include <iostream>
#include <cctype>
#include <locale>
#include <vector>
#include <string>
#include <fstream>
#include <iomanip>

namespace utility
{
    // This ctype facet classifies comma as whitespace
    // http://en.cppreference.com/w/cpp/locale/ctype_char
    struct comma_is_ws : std::ctype<char>
    {
        // http://en.cppreference.com/w/cpp/locale/ctype_char/table
        static const mask* classification_table()
        {
            // start with the classic table ( C locale's table )
            static std::vector<mask> table( classic_table(),  classic_table() + table_size ) ;

            static constexpr char comma = ',' ;
            table[comma] = space ; // comma is to be treated as whitespace

            return std::addressof( table.front() ) ;
        }

        // do not delete table, initial reference count == 0
        comma_is_ws() : std::ctype<char>( classification_table() ) {}
    };
}

int main()
{
    const std::string test_file_name = "assorted_formats.txt " ;
    {
        // create a test file
        std::ofstream(test_file_name) <<
            "Wales 0.12 60\n"
            "Ronaldo 0.25 140\n"
            "\n"
            "Wales,0.12,60\n"
            "Ronaldo,0.25,140\n"
            "\n"
            "Wales , 0.12 , 60\n"
            "Ronaldo , 0.25 , 140\n"
            "\n"
            "\n"
            "Wales\n"
            "0.12\n"
            "60\n"
            "\n" // This newline character here is on purpose
            "Ronaldo\n"
            "0.25\n"
            "140\n" ;
    }

    {
        // view the contents of the test file
        std::cout << std::ifstream(test_file_name).rdbuf() << "\n\n----------\n\n" ;
    }

    {
        // open the file for reading
        std::ifstream file(test_file_name) ;
        
        // configure it to treat comma as whitespace
        // http://en.cppreference.com/w/cpp/io/basic_ios/imbue
        file.imbue( std::locale( file.getloc(), new utility::comma_is_ws() ) ) ;

        std::string name ;
        double number1 ;
        int number2 ;

        int rec_cnt = 0 ;

        while( file >> name >> number1 >> number2  )
        {
            std::cout << '#' << ++rec_cnt << ". " << std::setw(10) << std::quoted(name)
                      << "    " << number1 << "    " << std::setw(3) << number2 << '\n' ;
        }
    }
}

http://coliru.stacked-crooked.com/a/0211b909138c2d41
http://rextester.com/QYVTW65760

If you are new to standard streams and locales, this would look intimidating. It is not as esoteric as it appears at first sight.
Topic archived. No new replies allowed.