#include "BitcoinExchange.hpp" bool is_leap_year(int year) { if (year % 100 != 0 && year % 400 == 0) return false; return (year % 4 == 0); } Date::Date(void) { } Date::Date(std::string str) { // check format (4 char & isdigit into dash into 2 char isdigit & < 1 && isdigit & < 2, and same for day except ahah funny cuz 30 and 31 and 28 and 29 agfjasfgfjahkfga) _value = 0; for (size_t i = 0; str[i]; ++i) { if (!isdigit(str[i]) && !((i == (str.length() - 6) || i == (str.length() - 3)) && str[i] == '-')) { std::cout << str.length() - 6 << i << std::endl; throw std::invalid_argument("invalid date."); } } for (std::string::iterator it = str.begin(); it < str.end(); ++it) { if (!isdigit(*it)) continue ; _value *= 10; _value += *it - '0'; } int year = _value / 10000; int month = (_value / 100) % 100; int day = _value % 100; if (month > 12 || month == 0 || day == 0) throw std::invalid_argument("invalid date."); int monthly_days[] = {0, 31, is_leap_year(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 ,31 }; if (day > monthly_days[month]) throw std::invalid_argument("invalid date."); } Date::Date(const Date &other) { this->_value = other._value; } Date &Date::operator=(const Date &other) { this->_value = other._value; return *this; } Date::~Date(void) { } bool Date::operator==(const Date &other) const { return this->_value == other._value; } bool Date::operator!=(const Date &other) const { return this->_value != other._value; } bool Date::operator<(const Date &other) const { return this->_value < other._value; } bool Date::operator>(const Date &other) const { return this->_value > other._value; } bool Date::operator<=(const Date &other) const { return this->_value <= other._value; } bool Date::operator>=(const Date &other) const { return this->_value >= other._value; } std::ostream &operator<<(std::ostream &os, const Date &date) { os << date.getValue(); return os; } // --------------------------------------------------- // void BitcoinExchange::parseData(const std::string filename) { std::ifstream input_file(filename.c_str()); if (input_file.fail()) throw std::runtime_error("Error: could not open file."); std::string line; (void) std::getline(input_file, line); // ignore first line while (std::getline(input_file, line)) { std::stringstream ss(line); std::string date_str; std::string value_str; if (!std::getline(ss, date_str, ',') || !std::getline(ss, value_str, ',')) throw std::runtime_error("parsing issue in the data.csv file."); try { this->_data.insert(std::make_pair(Date(date_str), std::strtod(value_str.c_str(), NULL))); } catch (std::invalid_argument &e) { throw std::invalid_argument(e.what()); } } /*for (std::map::iterator it = this->_data.begin(); it != this->_data.end(); it++) { std::cout << it->first // string (key) << ':' << it->second // string's value << std::endl; }*/ } std::string trim(const std::string &s) { std::string::size_type start = 0; while (start < s.size() && std::isspace(static_cast(s[start]))) ++start; std::string::size_type end = s.size(); while (end > start && std::isspace(static_cast(s[end - 1]))) --end; return s.substr(start, end - start); } void BitcoinExchange::str(std::string filename) { //std::stringstream input_ss(input); std::ifstream input_ss(filename.c_str()); if (input_ss.fail()) throw std::runtime_error("Error: could not open file."); std::string line; (void) std::getline(input_ss, line); // ignore first line while (std::getline(input_ss, line)) { std::stringstream ss(line); std::string date_str; std::string value_str; if (!std::getline(ss, date_str, '|') || !std::getline(ss, value_str, '|')) { std::cout << "Error: bad input => " << line << std::endl; continue ; } if (std::atol(value_str.c_str()) > 2147483647) { std::cout << "Error: too large a number." << std::endl; continue ; } if (std::strtod(value_str.c_str(), NULL) < 0) { std::cout << "Error: not a positive number." << std::endl; continue ; } try { Date date(trim(date_str)); if (date < _data.begin()->first) { std::cout << "Error: input date too low." << std::endl; continue ; } std::map::iterator it = _data.lower_bound(date); if (it == _data.end() || it->first > date) { if (it == _data.begin()) it = _data.end(); else --it; } std::cout << date_str << " => " << value_str << " = " << it->second * std::strtod(value_str.c_str(), NULL) << std::endl; } catch (std::invalid_argument &e) { std::cout << "Error: " << e.what() << std::endl; continue ; } } }