ex00: init: work but some value qre not right maybe upperbound
This commit is contained in:
commit
a4838511eb
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
*
|
||||||
|
!/**/
|
||||||
|
!*.*
|
||||||
|
!/**/Makefile
|
||||||
|
*.o
|
26
ex00/Makefile
Normal file
26
ex00/Makefile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
CXX := c++
|
||||||
|
CXXFLAGS := -std=c++98 -Wall -Wextra -Werror -g
|
||||||
|
SRCDIR := src
|
||||||
|
OBJDIR := obj
|
||||||
|
NAME := ex00
|
||||||
|
|
||||||
|
SRCS := $(wildcard $(SRCDIR)/*.cpp)
|
||||||
|
OBJS := $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRCS))
|
||||||
|
|
||||||
|
all: $(NAME)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
|
||||||
|
mkdir -p obj
|
||||||
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(NAME): $(OBJS)
|
||||||
|
$(CXX) $(CXXFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIR)
|
||||||
|
|
||||||
|
fclean: clean
|
||||||
|
rm -fr $(NAME)
|
||||||
|
|
||||||
|
re: fclean
|
||||||
|
@make --no-print-directory all
|
209
ex00/src/BitcoinExchange.cpp
Normal file
209
ex00/src/BitcoinExchange.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
#include <asm-generic/errno-base.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "BitcoinExchange.hpp"
|
||||||
|
|
||||||
|
static bool is_leap(int year)
|
||||||
|
{
|
||||||
|
return (((year % 4 == 0) &&
|
||||||
|
(year % 100 != 0)) ||
|
||||||
|
(year % 400 == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool date_is_valid(int d, int m, int y)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
if (m < 1 || m > 12)
|
||||||
|
return false;
|
||||||
|
if (d < 1 || d > 31)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m == 2)
|
||||||
|
{
|
||||||
|
if (is_leap(y))
|
||||||
|
return (d <= 29);
|
||||||
|
else
|
||||||
|
return (d <= 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m == 4 || m == 6 ||
|
||||||
|
m == 9 || m == 11)
|
||||||
|
return (d <= 30);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_date(const std::string& line, unsigned int& out)
|
||||||
|
{
|
||||||
|
unsigned int year, mounth, day;
|
||||||
|
|
||||||
|
year = std::atoi(line.c_str());
|
||||||
|
mounth = std::atoi(line.substr(5).c_str());
|
||||||
|
day = std::atoi(line.substr(8).c_str());
|
||||||
|
|
||||||
|
if (date_is_valid(day, mounth, year))
|
||||||
|
return 1;
|
||||||
|
out = year * 10000 + mounth * 100 + day;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_value(const std::string& value_str, int flag, float& out)
|
||||||
|
{
|
||||||
|
out = atof(value_str.c_str());
|
||||||
|
if (errno == ERANGE)
|
||||||
|
{
|
||||||
|
std::cout << "Error: too large a number." << std::endl;
|
||||||
|
errno = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (flag == INPUT && out > 1000)
|
||||||
|
{
|
||||||
|
std::cout << "Error: too large a number." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (out < 0)
|
||||||
|
{
|
||||||
|
std::cout << "Error: not a positive number." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_line(const std::string& line, regex_t& reegex, const std::string& delimiter, int flag, std::pair<unsigned int, float>& out)
|
||||||
|
{
|
||||||
|
if (line == "date,exchange_rate")
|
||||||
|
return 1;
|
||||||
|
if (regexec(&reegex, line.c_str(), 0, NULL, 0) == REG_NOMATCH)
|
||||||
|
{
|
||||||
|
std::cout << "bad input => " << line << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
unsigned int date;
|
||||||
|
if (check_date(line, date))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
float value;
|
||||||
|
if (check_value(line.substr(10 + delimiter.length()), flag, value))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
out.first = date;
|
||||||
|
out.second = value;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_data(std::map<unsigned int, float>& out)
|
||||||
|
{
|
||||||
|
std::ifstream file("data.csv");
|
||||||
|
|
||||||
|
if (!file.good())
|
||||||
|
{
|
||||||
|
std::cout << "error: file: " << "data.csv" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
regex_t reegex;
|
||||||
|
|
||||||
|
if (regcomp(&reegex, DATA_PATERN, REG_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << "regex compilation fail" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::pair<unsigned int, float> line_parsed;
|
||||||
|
|
||||||
|
while (std::getline(file, line))
|
||||||
|
if (!check_line(line, reegex, ",", DATABASE, line_parsed))
|
||||||
|
out[line_parsed.first] = line_parsed.second;
|
||||||
|
|
||||||
|
regfree(&reegex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string utodate(unsigned int u)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << u / 10000
|
||||||
|
<< "-"
|
||||||
|
<< std::setfill('0') << std::setw(2) << (u % 10000) / 100
|
||||||
|
<< "-"
|
||||||
|
<< std::setfill('0') << std::setw(2) << u % 100;
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_input(const std::string& file_path, const std::map<unsigned int, float>& database)
|
||||||
|
{
|
||||||
|
std::ifstream file(file_path.c_str());
|
||||||
|
|
||||||
|
if (!file.good())
|
||||||
|
{
|
||||||
|
std::cout << "error: file: " << "file_path.csv" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
regex_t reegex;
|
||||||
|
|
||||||
|
if (regcomp(&reegex, INPUT_PATERN, REG_EXTENDED))
|
||||||
|
{
|
||||||
|
std::cout << "regex compilation fail" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::pair<unsigned int, float> line_parsed;
|
||||||
|
|
||||||
|
while (std::getline(file, line))
|
||||||
|
{
|
||||||
|
if (!check_line(line, reegex, " | ", INPUT, line_parsed))
|
||||||
|
{
|
||||||
|
std::map<unsigned int, float>::const_iterator it = database.upper_bound(line_parsed.first);
|
||||||
|
if (it->first < line_parsed.first)
|
||||||
|
std::cout << "Error: bad input => " << utodate(line_parsed.first) << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << utodate(line_parsed.first)
|
||||||
|
<< " => " << line_parsed.second
|
||||||
|
<< " = " << line_parsed.second * it->second << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regfree(&reegex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int get_price(const std::string& file_path)
|
||||||
|
{
|
||||||
|
static bool db_init = 0;
|
||||||
|
static std::map<unsigned int, float> database;
|
||||||
|
|
||||||
|
if (db_init == 0)
|
||||||
|
get_data(database);
|
||||||
|
|
||||||
|
get_input(file_path, database);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int ac, char** av)
|
||||||
|
{
|
||||||
|
if (ac != 2)
|
||||||
|
{
|
||||||
|
std::cout << "error: missing file" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
get_price(std::string(av[1]));
|
||||||
|
return 0;
|
||||||
|
}
|
6
ex00/src/BitcoinExchange.hpp
Normal file
6
ex00/src/BitcoinExchange.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define INPUT_PATERN "^[0-9]{4}\\-[0-9]{2}\\-[0-9]{2} \\| [+\\-]*[0-9]*(\\.[0-9]+)?$"
|
||||||
|
#define DATA_PATERN "^[0-9]{4}\\-[0-9]{2}\\-[0-9]{2},[+\\-]*[0-9]*(\\.[0-9]+)?$"
|
||||||
|
#define INPUT 0
|
||||||
|
#define DATABASE 1
|
Loading…
Reference in New Issue
Block a user