Parsing through delimited text file, increment not working for me

Hi there,

I am to read a txt file about cars and without using structs or arrays, obtain the count for how many cars are made with a certain origin country, and a certain weight. I am hoping you can help me out by pointing me in the right direction.

I am using enumerated data types for the country of origin.

Thank you so much in advance.

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
  	while(!infile.eof())
	{
		infile.ignore(256, ';'); 
		infile.ignore(256, ';'); 
		infile.ignore(256, ';'); 
		infile.ignore(256, ';'); 
		infile.ignore(256, ';'); 
		infile >> tempWeight;
		if ((tempWeight >= 1000) && (tempWeight <= 2000))
		{
			w1++;
		}
		else if ((tempWeight >= 2000) && (tempWeight <= 3000))
		{
			w2++;
		}
		else if ((tempWeight >= 3000) && (tempWeight <= 4000))
		{
			w3++;
		}
		else if (tempWeight > 4000)
		{
			w4++;
		}
		infile.ignore(256, ';'); 
		infile.ignore(256, ';'); 
		infile.get(tempOrigin, MAXCHAR, ';');
		if (strcmp(tempOrigin, "US")==0)
		{
			origin = US;
		}
		else if (strcmp(tempOrigin, "Europe")==0)
		{
			origin = EU;
		}
		else if (strcmp(tempOrigin, "Japan") == 0) 
		{
			origin = JAP;
		}
		else
		{
			origin = ILLEGAL;
		}
		infile.ignore('\n');
		writeOrigin(origin, tempOrigin);
		cout << tempOrigin << endl;
	}
		cout << "Cars with w1: " << w1 << endl;
				cout << "Cars with w1: " << w2 << endl;
		cout << "Cars with w1: " << w3 << endl;

		cout << us << ' ' << eu << ' ' << ' ' << jap;
}


A line in this text file would be like this :
1
2
3
Ford Maverick;21.0;6;200.0;85.00;2587.;16.0;70;US
Datsun PL510;27.0;4;97.00;88.00;2130.;14.5;70;Japan
Volkswagen 1131 Deluxe Sedan;26.0;4;97.00;46.00;1835.;20.5;70;Europe

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
#include <iostream>
#include <string>
#include <regex>
#include <sstream>
#include <iomanip>

bool parse_line( const std::string& line, double& weight, std::string& origin )
{
    // http://en.cppreference.com/w/cpp/regex
    // (?:[^;]*;){5} - exactly five fields delimited by ;
    // (\\d+\\.\\d*) - number with at least one digit before the decimal point (capture #1)
    // ; - a semicolon
    // (?:[^;]*;){2} - exactly two fields delimited by ;
    // (.+) - one or more characters (capture #2)
    static const std::regex re( "(?:[^;]*;){5}(\\d+\\.\\d*);(?:[^;]*;){2}(.+)" ) ;

    std::smatch match_results ;
    // http://en.cppreference.com/w/cpp/regex/regex_match
    if( std::regex_match( line, match_results, re ) ) // if the pattern is matched
    {
        // http://en.cppreference.com/w/cpp/string/basic_string/stof
        weight = std::stod( match_results[1] ) ; // convert capture #1 to double to get the weight
        origin = match_results[2] ; // and capture #2 is the origin
        return true ;
    }

    else return false ; // failed to parse the line
}

int main()
{
    std::istringstream file(
            "Ford Maverick;21.0;6;200.0;85.00;2587.;16.0;70;US\n"
            "Datsun PL510;27.0;4;97.00;88.00;2130.;14.5;70;Japan\n"
            "Volkswagen 1131 Deluxe Sedan;26.0;4;97.00;46.00;1835.;20.5;70;Europe\n"
            "Volkswagen 1131 Deluxe Sedan;bad bad bad;1835.;bad bad bad\n"
                           ) ;
    std::string line ;

    // http://en.cppreference.com/w/cpp/string/basic_string/getline
    while( std::getline( file, line ) ) // for each line in the file
    {
        std::cout << line << '\n' ;

        double weight ;
        std::string origin ;

        if( parse_line( line, weight, origin ) ) // if it is successfully parsed
            std::cout << "    weight: " << std::fixed << weight << "  origin: " << std::quoted(origin) << "\n\n" ;

        else std::cout << "    **** error: badly formed line ***\n\n" ;
     }
}

http://coliru.stacked-crooked.com/a/5f31cf9c169dd71a
Thank you so much. Would there be a way to do this without using the string library?

> Would there be a way to do this without using the string library?

Without explicitly including <string> or using std::string in our 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <cstring>
#include <regex>
#include <cstdlib>
#include <strstream> // deprecated, used here for testing
#include <iomanip>

constexpr std::size_t MAX_ORIGIN_SZ = 128 ;

bool parse_line( const char line[], double& weight, char origin[MAX_ORIGIN_SZ] )
{
    static const std::regex re( "(?:[^;]*;){5}(\\d+\\.\\d*);(?:[^;]*;){2}(.+)" ) ;

    std::cmatch match_results ;
    // http://en.cppreference.com/w/cpp/regex/regex_match
    if( std::regex_match( line, match_results, re ) ) // if the pattern is matched
    {
        // http://en.cppreference.com/w/cpp/string/byte/atof
        weight = std::atof( line + match_results.position(1) ) ; // convert capture #1 to double to get the weight
        std::strcpy( origin, line + match_results.position(2) ) ; // and capture #2 is the origin
        return true ;
    }

    else return false ; // failed to parse the line
}

int main()
{
    std::istrstream file( // deprecated, used here for testing
            "Ford Maverick;21.0;6;200.0;85.00;2587.;16.0;70;US\n"
            "Datsun PL510;27.0;4;97.00;88.00;2130.;14.5;70;Japan\n"
            "Volkswagen 1131 Deluxe Sedan;26.0;4;97.00;46.00;1835.;20.5;70;Europe\n"
            "Volkswagen 1131 Deluxe Sedan;bad bad bad;1835.;bad bad bad\n"
                        ) ;

    constexpr std::size_t MAX_LINE_SZ = 4096 ;
    char line[MAX_LINE_SZ] ;

    // http://en.cppreference.com/w/cpp/io/basic_istream/getline
    while( file.getline( line, MAX_LINE_SZ ) ) // for each line in the file
    {
        std::cout << line << '\n' ;

        double weight ;
        char origin[MAX_ORIGIN_SZ] ;

        if( parse_line( line, weight, origin ) ) // if it is successfully parsed
            std::cout << "    weight: " << std::fixed << weight << "  origin: " << std::quoted(origin) << "\n\n" ;

        else std::cout << "    **** error: badly formed line ***\n\n" ;
     }
}

http://coliru.stacked-crooked.com/a/e6a004d9268af447
Topic archived. No new replies allowed.