[solved]-112 Line Oriented File Input Lab Implement Simple Class Called Countrydata Stores Populati Q38992501
11.2 Line-oriented file input
In this lab, you will implement a very simple class calledCountry_data that stores some population data for a country, and(more importantly) write functions to:
- parse a line of text and convert it to a Country_dataobject
- read a file line by line and return avector<Country_data> containing all the valid data in thefile
The Country_data class contains three data members:
- The name of the country.
- The population of the country in 1980
- The population of the country in 2010
This data will be read from a file calledpopulation_by_country.csv, each line of which looks like this:
Canada,24.5933,24.9,25.2019,25.4563,25.7018,…,32.65668,32.93596,33.2127,33.48721,33.75974
(I’ve elided some data to make it fit on one line.)
The data consists of fields separated by commas – thus it’sreferred to as a “comma-separated values” file. (Spreadsheets canread these directly – try it.) The first field is the name of thecountry, and the others are the population values in millions from1980 to 2010.
I’ve provided a header file containing the declaration of theCountry_data class; all you need to do is to fill in the details.The class itself should be easy; all you need to do is:
- Finish the constructor
- Implement get_name(), which simply returns the countryname
- Implement calc_growth(), which calculates the population growthfrom 1980-2010
Each of these can actually be done in one line, though takingmore than one line may help readability.
The hard part will be the two functions that actually read thedata. The first is parse_country_data(), whose signature is:
Country_data parse_country_data(const std::string & line);
The line argument is one line of the file. The function needs tosplit the data into separate fields (using a split() function thatI’ll provide), and then return a Country_data object. The countyname is the first field, the 1980 population is the second, and the2010 population is the last.
The population data will need to be converted from std::stringto double. I’ve provided a function called field_to_double() that Irecommend you use rather than writing your own.
The field_to_double() function that I provide will throw anexception for invalid floating-point data. The exception should NOTbe caught in parse_country_data(); see below.
The second function is read_country_data(), whose signatureis:
std::vector<Country_data> read_country_data(const std::string & filename);
This function needs to open the file as an ifstream, and usegetline() to read the file line by line. It should callparse_country_data() to convert this line of data to a Country_dataobject, and store each valid line in a vector<Country_data>.This vector is the return value of the function.
The call to parse_country_data() should be wrapped in a tryblock. Recall that the syntax is:
try { // call parse_country_data() // add this Country_data to the vector } catch (std::runtime_error & e) { // ignore the error; just don’t add this one to the vector }
Provided functions
I’ve provided utilities.h and utilities.cpp which declare/definethese functions:
double field_to_double(const std::string & field);
field_to_double() converts the given std::string to a floatingpoint value, which is returned as a double. It does some basicerror checking, and throws an exception if the field cannot beconverted.
std::vector<std::string> split(const std::string & s, char sep);
split() separates the given std::string into individual fieldsbased on the given separator character. The fields are returned asa vector<string>.
I’ve also provided Title_ratings.cpp from the IMDB project thatI’m working on and which I talked about in class. You can use thatas a guide for writing your parse_country_data() function.
—————————-Country_data.cpp———————–
#include “Country_data.h”
#include <fstream>
#include <string>
#include “utilities.h”
// Finish the constructor.
Country_data::Country_data(const std::string & n, double p1,double p2)
{
}
std::string Country_data::get_name() const
{
// Fill in code here
}
double Country_data::calc_growth() const
{
// Fill in code here to calculate the population
// growth from 1980 to 2010.
}
Country_data parse_country_data(const std::string &line)
{
// Fill in code to:
// (1) Call split to split the line into comma-separatedfields.
// (2) Do any necessary conversions from string to othertypes.
// (3) Create and return a Country_data object.
}
std::vector<Country_data> read_country_data(conststd::string & filename)
{
// Fill in code to:
// (1) Create a vector<Country_data> to return.
// (2) Open the file as an ifstream.
// (3) Read and ignore the header line
// (4) Read each line and
// (4a) Parse it using parse_country_data
// (4b) Store it in the vector from step 1
// (4c) Catch any exceptions (ignore the data that caused it)
// (5) Return the vector created in step 1.
}
——————–Country_data.h————————-
#pragma once
#include <string>
#include <vector>
class Country_data
{
public:
Country_data(const std::string & n, double p1,double p2);
std::string get_name() const;
double calc_growth() const;
private:
std::string name;
double pop_1980;
double pop_2010;
};
Country_data parse_country_data(const std::string &line);
std::vector<Country_data> read_country_data(const std::string& filename);
—————-utilities.h——————————
#pragma once
#include <vector>
#include <unordered_map>
// Split a string into sub-strings based on the given
// delimiter. For example, if the input is
//
// Ron,Ginny,George,Fred,Percy,Bill,Charlie
//
// the output is a 7-element vector<string> with
// the following entries:
//
// [0] = “Ron”
// [1] = “Ginny”
// [2] = “George”
// [3] = “Fred”
// [4] = “Percy”
// [5] = “Bill”
// [6] = “Charlie”
//
std::vector<std::string> split(
const std::string & s,
char sep);
// Converts a database field string to an integer.
// If the field cannot be converted to an int,
// a runtime_error exception is thrown.
int field_to_int(const std::string & field);
// Converts a database field to a double.
// If the field cannot be converted to an double,
// a runtime_error exception is thrown.
double field_to_double(const std::string & field);
———————–utilities.cpp———————-
#include “utilities.h”
#include <algorithm>
#include <cstdlib>
std::vector<std::string> split(const std::string & s,char sep)
{
std::vector<std::string> fields;
size_t i = 0;
size_t len = s.length();
while (i < len)
{
// Skip characters until we find aseparator.
size_t j = i;
while ((i < len) &&(s[i] != sep))
i++;
// Add this field – which may beempty! – to the output.
if (j == i)
fields.emplace_back();
else
fields.emplace_back(&s[j], i – j);
// Skip past theseparator.
i++;
// If this put us at the end ofthe string,
// we need to account for the blankfield at
// the end.
if (i == len)
fields.emplace_back();
}
return fields;
}
int field_to_int(const std::string & field)
{
if (field.length() == 0)
throw std::runtime_error(“Cannotconvert 0-length string”);
if (field == “–” || (field == “NA”))
throw std::runtime_error(“No dataprovided”);
return strtol(field.c_str(), NULL, 10);
}
double field_to_double(const std::string & field)
{
if (field.length() == 0)
throw std::runtime_error(“Cannotconvert 0-length string”);
if (field == “–” || (field == “NA”))
throw std::runtime_error(“No dataprovided”);
return strtod(field.c_str(), NULL);
}
—————————————–Country_data_test.cpp————————————
#include “Country_data.h”
#include <algorithm>
#include <iomanip>
#include <iostream>
bool compare_growth(const Country_data & lhs, constCountry_data & rhs)
{
return lhs.calc_growth() < rhs.calc_growth();
}
int main()
{
std::vector<Country_data> data =read_country_data(“population_by_country.csv”);
if (data.size() == 0)
{
std::cout << “No dataread!n”;
return 1;
}
auto iters = minmax_element(std::begin(data),std::end(data), compare_growth);
auto min_iter = iters.first;
auto max_iter = iters.second;
std::cout << max_iter->get_name()
<< ” had the highest growthat “
<<max_iter->calc_growth()
<< ” million.n”;
std::cout << min_iter->get_name()
<< ” had the lowest growth at”
<<min_iter->calc_growth()
<< ” million.n”;
std::string country;
while (std::getline(std::cin, country))
{
auto iter =std::find_if(std::begin(data), std::end(data),
[&country](const Country_data & c)
{
returnc.get_name() == country;
});
if (iter ==std::end(data))
std::cout<< “There is no data for ” << country <<‘n’;
else
std::cout<< “The population of ” << country << ” increasedby “
<< std::fixed <<std::setprecision(2)
<< iter->calc_growth() << “million from 1980 to 2010.n”;
}
}
You can fix only Country_data.cpp code
Expert Answer
Answer to 11.2 Line-oriented file input In this lab, you will implement a very simple class called Country_data that stores some p… . . .
OR

