Something went wrong. Try again.
Java--'s containers projects.intra.42.fr/projects/cpp-module-09
Something went wrong. Try again.
4.3 kB · 171 lines
C++
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172#include <BitcoinExchange.hpp>#include <cstdlib>#include <fstream>#include <iostream>#include <stdexcept>
static std::string trim(const std::string& str) { std::string result = str;
result.erase(result.find_last_not_of(" \t\n\r\f\v") + 1); result.erase(0, result.find_first_not_of(" \t\n\r\f\v"));
return result;}
static bool isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); }
static bool isValidDate(const std::string& date) { if (date.size() != 10) return false;
if (date[4] != '-' || date[7] != '-') return false;
for (size_t i = 0; i < date.size(); ++i) { if (i == 4 || i == 7) continue; if (!std::isdigit(static_cast<unsigned char>(date[i]))) return false; }
const int year = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + (date[3] - '0'); const int month = (date[5] - '0') * 10 + (date[6] - '0'); const int day = (date[8] - '0') * 10 + (date[9] - '0');
if (year <= 0) return false; if (month < 1 || month > 12) return false; if (day < 1) return false;
static const int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int maxDay = daysInMonth[month - 1]; if (month == 2 && isLeapYear(year)) maxDay = 29;
return day <= maxDay;}
static std::map<std::string, double> validateCSV(const std::string& fileName) { std::ifstream inputFile(fileName.c_str());
if (!inputFile.is_open() || !inputFile.good()) std::cerr << ("Error: could not open file.") << std::endl;
std::string line; bool firstLine = true; static bool input = false; // smelly, pefect std::map<std::string, double> data; while (std::getline(inputFile, line)) { std::size_t separator = line.find(','); if (separator == std::string::npos) { separator = line.find('|'); // That is not a CSV file...
if (separator == std::string::npos) { std::cerr << "Error: bad input => " + line << std::endl; continue; } }
std::string first = trim(line.substr(0, separator)); std::string second = trim(line.substr(separator + 1));
if (second.empty()) { std::cerr << "Error: bad input => " + line << std::endl; continue; }
if (firstLine) { firstLine = false;
if (first != "date" || (input && second != "value") || (!input && second != "exchange_rate")) { std::cerr << "Error: bad => " + line << std::endl; continue; }
continue; }
if (!isValidDate(first)) { std::cerr << "Error: bad input => " + first << std::endl; continue; }
bool badSecond = false; bool dot = false; bool dash = false; for (size_t i = 0; i < second.size(); ++i) { if (std::isdigit(static_cast<unsigned char>(second[i]))) continue;
if (!dot && second[i] == '.' && i + 1 < second.size()) { dot = true; continue; }
if (!dash && second[i] == '-' && i == 0 && i + 1 < second.size()) { dash = true; continue; }
std::cerr << "Error: bad input => " + second << std::endl; badSecond = true; break; }
if (badSecond) continue;
const double value = std::strtod(second.c_str(), NULL); if (value < 0) { std::cerr << "Error: not a positive number." << std::endl; continue; } else if (input && value > 1000) { std::cerr << "Error: too large a number." << std::endl; continue; }
const std::pair<std::string, double> pair(first, value);
if (!input && data.find(first) != data.end()) { std::cerr << "Error: bad input => " + first << std::endl; continue; }
data.insert(pair); }
input = true;
return data;}
int main(int argc, char* argv[]) { if (argc != 2) { std::cout << "Usage: " << argv[0] << " <input.csv>" << std::endl; return EXIT_FAILURE; }
try { const std::map<std::string, double> data = validateCSV("data.csv");
if (data.empty()) throw std::runtime_error("data file is empty");
const BitcoinExchange exchange(data);
const std::map<std::string, double> input = validateCSV(argv[1]);
for (std::map<std::string, double>::const_iterator it = input.begin(); it != input.end(); ++it) { const double value = exchange.getValue(it->first);
std::cout << it->first << " => " << it->second << " = " << value * it->second << std::endl; }
} catch (const std::exception& exception) { std::cerr << "Exception caught, cause: " << exception.what() << std::endl; return EXIT_FAILURE; }}