ex00: init: work but some value qre not right maybe upperbound

This commit is contained in:
Camille Chauvet 2023-10-03 15:09:24 +00:00
commit a4838511eb
4 changed files with 246 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*
!/**/
!*.*
!/**/Makefile
*.o

26
ex00/Makefile Normal file
View 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

View 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;
}

View 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