Spaßeshalber:
#include <limits>
#include <cstdlib>
#include <cctype>
#include <iterator>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
// Following functions trim string str up to and including one of the characters in delims.
// If delims is a zero length string, they trim up to the first none whitespace character:
void trim_left(std::string &str, std::string const &delims = "")
{
str.erase(str.begin(), std::find_if_not(str.cbegin(), str.cend(), [](int ch) { return std::isspace(ch); }));
if (str.length() && delims.length() && delims.find(str.front()) != delims.npos)
str.erase(0, 1);
}
void trim_right(std::string &str, std::string const &delims = "")
{
str.erase(std::find_if_not(str.crbegin(), str.crend(), [](int ch) { return std::isspace(ch); }).base(), str.end());
if (str.length() && delims.length() && delims.find(str.back()) != delims.npos)
str.pop_back();
}
void trim(std::string &str, std::string const &delims = "")
{
trim_left(str, delims);
trim_right(str, delims);
}
// Encloses a string in quotation marks
std::string quote(std::string str, bool quoted = true, char quotation_mark = '"')
{
if (!quoted)
return str;
return std::string{ quotation_mark } + str + quotation_mark;
}
class airport_t
{
static char constexpr delim = ',';
static char constexpr quotation_mark = '"';
static int quoted_flag_index;
enum quoted_t { unquoted_output, quoted_output };
std::string iata;
std::string name;
std::string city;
std::string state;
std::string country;
double latitude = std::numeric_limits<double>::quiet_NaN();
double longitude = std::numeric_limits<double>::quiet_NaN();
public:
airport_t() = default;
airport_t(std::string iata, std::string name, std::string city, std::string state, std::string country, double latitude, double longitude)
: iata { iata },
name { name },
city { city },
state { state },
country { country },
latitude { latitude },
longitude { longitude }
{}
// Stream extraction and insertion:
friend
std::istream& operator>>(std::istream &is, airport_t &airport)
{
airport_t temp;
std::string latitude;
std::string longitude;
if (!(std::getline(is, temp.iata, delim) && std::getline(is, temp.name, delim) && std::getline(is, temp.city, delim) &&
std::getline(is, temp.state, delim) && std::getline(is, temp.country, delim) && std::getline(is, latitude, delim) &&
std::getline(is, longitude)))
{
return is;
}
try {
temp.latitude = std::stod(latitude);
temp.longitude = std::stod(longitude);
}
catch (...) {
is.setf(std::ios::failbit);
return is;
}
std::string const quotation_mark_str { quotation_mark };
trim(temp.iata, quotation_mark_str);
trim(temp.name, quotation_mark_str);
trim(temp.city, quotation_mark_str);
trim(temp.state, quotation_mark_str);
trim(temp.country, quotation_mark_str);
airport = temp;
return is;
}
friend
std::ostream &operator<<(std::ostream &os, airport_t const &airport)
{
bool const quoted { os.iword(quoted_flag_index) == quoted_output };
return os << quote(airport.iata, quoted, quotation_mark) << ", " << quote(airport.name, quoted, quotation_mark) << ", "
<< quote(airport.city, quoted, quotation_mark) << ", " << quote(airport.state, quoted, quotation_mark) << ", "
<< quote(airport.country, quoted, quotation_mark) << ", " << airport.latitude << ", " << airport.longitude;
}
// Stream manipulators:
friend std::ios_base "ed(std::ios_base&);
friend std::ios_base &unquoted(std::ios_base&);
};
int airport_t::quoted_flag_index = std::ios_base::xalloc();
// Stream manipulators:
std::ios_base "ed(std::ios_base &os)
{
os.iword(airport_t::quoted_flag_index) = airport_t::quoted_output;
return os;
}
std::ios_base &unquoted(std::ios_base &os)
{
os.iword(airport_t::quoted_flag_index) = airport_t::unquoted_output;
return os;
}
int main()
{
char const *input_filename{ "airports.txt" };
std::ifstream input_file{ input_filename };
if (!input_file.is_open()) {
std::cerr << "Couldn't open \"" << input_filename << "\" for reading :(\n\n";
return EXIT_FAILURE;
}
// discard first line:
input_file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// read:
std::vector<airport_t> airports{ std::istream_iterator<airport_t>{ input_file }, std::istream_iterator<airport_t>{} };
// write:
std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
std::cout.put('\n');
// write with quotes:
std::cout << quoted;
std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
std::cout.put('\n');
// write without quotes again:
std::cout << unquoted;
std::copy(airports.begin(), airports.end(), std::ostream_iterator<airport_t>{ std::cout, "\n" });
std::cout.put('\n');
}
airports.txt:
"iata","airport","city","stateAbbreviation","country","lat","long"
"00M", "Thigpen","Bay Springs","MS","USA" ,31.95376472,-89.23450472
"35CA","Los Angeles County/USC Medical Center Heliport" ,"Los Angeles","CA","USA",-118.208056,34.0575
"FRA","San Francisco Airport" , "San Francisco","CA","USA",-62.1336, -31.4142
Output:
00M, Thigpen, Bay Springs, MS, USA, 31.9538, -89.2345
35CA, Los Angeles County/USC Medical Center Heliport, Los Angeles, CA, USA, -118.208, 34.0575
FRA, San Francisco Airport, San Francisco, CA, USA, -62.1336, -31.4142
"00M", "Thigpen", "Bay Springs", "MS", "USA", 31.9538, -89.2345
"35CA", "Los Angeles County/USC Medical Center Heliport", "Los Angeles", "CA", "USA", -118.208, 34.0575
"FRA", "San Francisco Airport", "San Francisco", "CA", "USA", -62.1336, -31.4142
00M, Thigpen, Bay Springs, MS, USA, 31.9538, -89.2345
35CA, Los Angeles County/USC Medical Center Heliport, Los Angeles, CA, USA, -118.208, 34.0575
FRA, San Francisco Airport, San Francisco, CA, USA, -62.1336, -31.4142