commit 8284b73c34c68d2ae3b795b44818d611ae2331c2 parent 7f9f269f2148b12b4158cb39dc361150855e4ee8 Author: Christos Margiolis <christos@margiolis.net> Date: Sat, 2 May 2020 18:12:32 +0300 added excpetion handling and proper file read/write Diffstat:
25 files changed, 242 insertions(+), 51 deletions(-)
diff --git a/assignment-2.4-inheritance/bin/inheritance b/assignment-2.4-inheritance/bin/inheritance Binary files differ. diff --git a/assignment-2.4-inheritance/obj/app.o b/assignment-2.4-inheritance/obj/app.o Binary files differ. diff --git a/assignment-2.4-inheritance/obj/appsystem.o b/assignment-2.4-inheritance/obj/appsystem.o Binary files differ. diff --git a/assignment-2.4-inheritance/obj/main.o b/assignment-2.4-inheritance/obj/main.o Binary files differ. diff --git a/assignment-2.4-inheritance/obj/manufacturer.o b/assignment-2.4-inheritance/obj/manufacturer.o Binary files differ. diff --git a/assignment-2.4-inheritance/obj/review.o b/assignment-2.4-inheritance/obj/review.o Binary files differ. diff --git a/assignment-2.4-inheritance/res/appdata.csv b/assignment-2.4-inheritance/res/appdata.csv @@ -0,0 +1,5 @@ +Type,SN,Name,OS,Manf,Price,Genre,Online +Game,123,LoL,Windows,Riot,0,MOBA,Yes +Game,345,CS:GO,Cross,Valve,14,FPS,Yes +Office,567,Libre,Linux,GNU,0,N/A,N/A +Office,789,Vim,Linux,GNU,0,N/A,N/A diff --git a/assignment-2.4-inheritance/res/appout.csv b/assignment-2.4-inheritance/res/appout.csv @@ -0,0 +1,6 @@ +Type,SN,Name,OS,Manf,Price,Genre,Online +Game,123,LoL,Windows,Riot,0,MOBA,Yes +Game,345,CS:GO,Cross,Valve,14,FPS,Yes +Office,567,Libre,Linux,GNU,0,N/A,N/A +Office,789,Vim,Linux,GNU,0,N/A,N/A +Office,459,LibreOffice,Linux 2.2,GNU,0,N/A,N/A diff --git a/assignment-2.4-inheritance/res/data.csv b/assignment-2.4-inheritance/res/data.csv @@ -1,11 +0,0 @@ -SerialNum,Name,Email -0001,GNU,gnu@gnu.com -0002,Chris,chris@chris.com -0003,John,john@john.com -0004,Ok,ok@ok.com -0005,Aa,aa@aa.com -0006,Lol,lol@lol.com -0007,XD,xd@xd.com -0008,Bruh,bruh@bruh.com -0009,Retard,ret@ret.com -0010,Nice,nice@nice.com diff --git a/assignment-2.4-inheritance/res/manfdata.csv b/assignment-2.4-inheritance/res/manfdata.csv @@ -0,0 +1,4 @@ +SN,Name,Email +741,Riot,riot@riot.com +987,Valve,valve@valve.com +456,GNU,gnu@gnu.com diff --git a/assignment-2.4-inheritance/res/manfout.csv b/assignment-2.4-inheritance/res/manfout.csv @@ -0,0 +1,6 @@ +SN,Name,Email +1234,GNU,gnu@gnu.com +5678,Chris,chris@cm.com +741,Riot,riot@riot.com +987,Valve,valve@valve.com +456,GNU,gnu@gnu.com diff --git a/assignment-2.4-inheritance/res/output.csv b/assignment-2.4-inheritance/res/output.csv diff --git a/assignment-2.4-inheritance/src/app.cpp b/assignment-2.4-inheritance/src/app.cpp @@ -6,7 +6,10 @@ App::App() App::App(const char *serialnum, const std::string& name, const std::string& os, Manufacturer *manf, int price) :serialnum(convsn(serialnum)), name(name), os(os), manf(manf), price(price) -{} +{ + try {if (price < 0) throw price;} + catch (int price) {throw std::runtime_error("Price can't have negative value.");} +} App::~App() { diff --git a/assignment-2.4-inheritance/src/appsystem.cpp b/assignment-2.4-inheritance/src/appsystem.cpp @@ -29,11 +29,37 @@ AppSystem& AppSystem::operator+= (Manufacturer *man) return *this; } -bool AppSystem::read_data(const char *fpath) +template<> +bool AppSystem::read_data<Manufacturer>(const char *fpath) { std::ifstream f; - // bug??? - //f.exceptions(std::ifstream::failbit | std::ifstream::badbit); + f.exceptions(std::ifstream::badbit); + try + { + f.open(fpath); + if (f.is_open()) + { + std::string skip; + std::getline(f, skip); + while (f.good()) + if (!read_manf(f)) break; + } + f.close(); + } + catch (const std::ifstream::failure& e) + { + std::cerr << "Error reading file \'" << fpath << "\'." << std::endl << + e.what() << std::endl; + return false; + } + return true; +} + +template<> +bool AppSystem::read_data<App>(const char *fpath) +{ + std::ifstream f; + f.exceptions(std::ifstream::badbit); try { f.open(fpath); @@ -43,13 +69,12 @@ bool AppSystem::read_data(const char *fpath) std::getline(f, skip); while (f.good()) { - std::string sn, name, email; - std::getline(f, sn, ','); - std::getline(f, name, ','); - std::getline(f, email); - if (f.eof()) break; - std::cout << sn << " " << name << " " << email << std::endl; - manfs.push_back(new Manufacturer(sn.c_str(), name.c_str(), email)); + std::string type; + std::getline(f, type, ','); + if (type == "Game") + if (!read_game(f)) break; + if (type == "Office") + if (!read_office(f)) break; } } f.close(); @@ -63,17 +88,143 @@ bool AppSystem::read_data(const char *fpath) return true; } -bool AppSystem::export_data(const char *fpath) +bool AppSystem::read_manf(std::ifstream& f) +{ + try + { + std::string sn, name, email; + std::getline(f, sn, ','); + std::getline(f, name, ','); + std::getline(f, email); + if (f.eof()) return true; + manfs.push_back(new Manufacturer(sn.c_str(), name.c_str(), email)); + } + catch (const std::ifstream::failure& e) + { + std::cerr << "Error reading manufacturer data." << std::endl << + e.what() << std::endl; + return false; + } + return true; +} + +bool AppSystem::read_game(std::ifstream& f) +{ + try + { + std::string sn, name, os, manf, price, genre, online; + std::getline(f, sn, ','); + std::getline(f, name, ','); + std::getline(f, os, ','); + std::getline(f, manf, ','); + std::getline(f, price, ','); + std::getline(f, genre, ','); + std::getline(f, online); + bool onl = online == "Yes"; + + if (!manfs.empty()) + { + for (auto& man : manfs) + { + if (man->get_name() == manf) + { + apps.push_back(new Game(sn.c_str(), name, os, + man, std::stoi(price), genre, onl)); + break; + } + } + } + } + catch (const std::ifstream::failure& e) + { + std::cerr << "Error reading game data." << std::endl << + e.what() << std::endl; + return false; + } + return true; +} + +bool AppSystem::read_office(std::ifstream& f) +{ + try + { + std::string sn, name, os, manf, price, skip1, skip2; + std::getline(f, sn, ','); + std::getline(f, name, ','); + std::getline(f, os, ','); + std::getline(f, manf, ','); + std::getline(f, price, ','); + std::getline(f, skip1, ','); + std::getline(f, skip2); + + if (!manfs.empty()) + { + for (auto& man : manfs) + { + if (man->get_name() == manf) + { + apps.push_back(new Office(sn.c_str(), name, os, + man, std::stoi(price), {})); + break; + } + } + } + } + catch (const std::ifstream::failure& e) + { + std::cerr << "Error reading office data." << std::endl << + e.what() << std::endl; + return false; + } + return true; +} + +template<> +bool AppSystem::export_data<Manufacturer>(const char *fpath) { std::ofstream f; f.exceptions(std::ofstream::failbit | std::ofstream::badbit); try { f.open(fpath); - //while (f.good()) - //{ + f << "SN,Name,Email\n"; + for (auto& manf : manfs) + f << manf->get_serialnum() << ',' << + manf->get_name() << ',' << + manf->get_email() << std::endl; + f.close(); + } + catch (const std::ofstream::failure& e) + { + std::cerr << "Error writing to file \'" << fpath << "\'." << std::endl << + e.what() << std::endl; + return false; + } + return true; +} - //} +template<> +bool AppSystem::export_data<App>(const char *fpath) +{ + std::ofstream f; + f.exceptions(std::ofstream::failbit | std::ofstream::badbit); + try + { + f.open(fpath); + f << "Type,SN,Name,OS,Manf,Price,Genre,Online\n"; + for (auto& app : apps) + { + Manufacturer manf = app->get_manf(); + Game *o = dynamic_cast<Game *>(app); + f << (o ? "Game" : "Office") << ','; + f << app->get_serialnum() << ',' << + app->get_name() << ',' << + app->get_os() << ',' << + manf.get_name() << ',' << + app->get_price() << ',' << + (o ? o->get_genre() :"N/A") << ',' << + (o ? (o->get_online() ? "Yes" : "No") : "N/A") << std::endl; + } f.close(); } catch (const std::ofstream::failure& e) @@ -191,13 +342,17 @@ const std::vector<Game *> AppSystem::get_goodgames() const if (Game *o = dynamic_cast<Game *>(app)) { std::vector<Review *> revs = o->get_revs(); - int sum = 0, count = 0; - for (auto& rev : revs) + if (!revs.empty()) { - sum += rev->get_stars(); - count++; + int sum = 0, count = 0; + for (auto& rev : revs) + { + sum += rev->get_stars(); + count++; + } + if (sum / count > 4) ggames.push_back(o); + } - if (sum / count > 4) ggames.push_back(o); } } return ggames; diff --git a/assignment-2.4-inheritance/src/appsystem.h b/assignment-2.4-inheritance/src/appsystem.h @@ -20,8 +20,8 @@ class AppSystem AppSystem& operator+= (App *app); AppSystem& operator+= (Manufacturer *manf); - bool read_data (const char *fpath); - bool export_data(const char *fpath); + template<typename T> bool read_data(const char *fpath); + template<typename T> bool export_data(const char *fpath); void newrev (const std::string& appname, Review *rev); void chserialnum(const std::string& appname, const char *serialnum); void chname (const std::string& appname, const std::string& name); @@ -38,6 +38,11 @@ class AppSystem const std::vector<Game *> get_goodgames() const; const std::vector<App *>& get_apps() const; const std::vector<Manufacturer *>& get_manfs() const; + + private: + bool read_manf(std::ifstream& f); + bool read_game(std::ifstream& f); + bool read_office(std::ifstream& f); }; #endif /* APPSYSTEM_H */ diff --git a/assignment-2.4-inheritance/src/main.cpp b/assignment-2.4-inheritance/src/main.cpp @@ -15,24 +15,22 @@ std::ostream& operator<< (std::ostream& stream, const AppSystem& sys) if (Office *o = dynamic_cast<Office *>(app)) { std::vector<std::string> exts = o->get_exts(); - if (!exts.empty()) - for (auto& ext : exts) - stream << ext << " "; + for (auto& ext : exts) + stream << ext << " "; } else if (Game *o = dynamic_cast<Game *>(app)) { stream << o->get_genre() << " " << - o->get_online() << " "; + (o->get_online() ? "Yes" : "No") << " "; } std::vector<Review *> revs = app->get_revs(); - if (!revs.empty()) - for (auto& rev : revs) - stream << - rev->get_stars() << " " << - rev->get_username() << " " << - rev->get_comment() << " "; + for (auto& rev : revs) + stream << + rev->get_stars() << " " << + rev->get_username() << " " << + rev->get_comment() << " "; stream << m.get_serialnum() << " " << @@ -51,12 +49,13 @@ int main(int argc, char **argv) Manufacturer *cm = new Manufacturer("5678", "Chris", "chris@cm.com"); sys += gnu; sys += cm; - if (!sys.read_data("res/data.csv")) return -1; + if (!sys.read_data<Manufacturer>("res/manfdata.csv")) return -1; + if (!sys.read_data<App>("res/appdata.csv")) return -1; std::vector<std::string> ext = {".doc", ".xls", ".ppt"}; - sys += new Office("132456", "LibreOffice", "Linux 2.2", gnu, 0, ext); - sys += new Game("731234", "minecurses", "Linux 4.5", cm, 0, "Puzzle", false); + sys += new Office("459", "LibreOffice", "Linux 2.2", gnu, 0, ext); + sys += new Game("731", "minecurses", "Linux 4.5", cm, 0, "Puzzle", false); - Review rev(6, "Name Surnaming", "Good"); + Review rev(4, "Name Surnaming", "Good"); sys.newrev("minecurses", &rev); std::cout << sys << std::endl; @@ -70,7 +69,8 @@ int main(int argc, char **argv) for (auto& ggame : ggames) std::cout << ggame->get_name() << std::endl; - if (!sys.export_data("res/output.csv")) return -1; + if (!sys.export_data<Manufacturer>("res/manfout.csv")) return -1; + if (!sys.export_data<App>("res/appout.csv")) return -1; return 0; } diff --git a/assignment-2.4-inheritance/src/manufacturer.cpp b/assignment-2.4-inheritance/src/manufacturer.cpp @@ -5,7 +5,19 @@ Manufacturer::Manufacturer() Manufacturer::Manufacturer(const char *serialnum, const char *name, const std::string& email) - :serialnum(convstr(serialnum)), name(convstr(name)), email(email) {} + :serialnum(convstr(serialnum)), name(convstr(name)), email(email) +{ + try + { + if (email.find("@") == std::string::npos) + throw email; + } + catch (const std::string& email) + { + std::string err = "Invalid email format. (" + email + ")"; + throw std::runtime_error(err); + } +} Manufacturer::Manufacturer(const Manufacturer& m) :serialnum(convstr(m.serialnum)), name(convstr(m.name)), email(m.email) {} diff --git a/assignment-2.4-inheritance/src/manufacturer.h b/assignment-2.4-inheritance/src/manufacturer.h @@ -3,6 +3,7 @@ #include <string> #include <string.h> +#include <stdexcept> class Manufacturer { diff --git a/assignment-2.4-inheritance/src/review.cpp b/assignment-2.4-inheritance/src/review.cpp @@ -4,7 +4,11 @@ Review::Review() :stars(0), username(""), comment("") {} Review::Review(int stars, const std::string& username, const std::string& comment) - :stars(stars), username(username), comment(comment) {} + :stars(stars), username(username), comment(comment) +{ + try {if (stars < 0 || stars > 5) throw stars;} + catch (int stars) {throw std::runtime_error("Wrong star value.");} +} int Review::get_stars() const { diff --git a/assignment-2.4-inheritance/src/review.h b/assignment-2.4-inheritance/src/review.h @@ -2,6 +2,7 @@ #define REVIEW_H #include <string> +#include <stdexcept> class Review { diff --git a/assignment-2.5-spreadsheets/bin/spreadsheets b/assignment-2.5-spreadsheets/bin/spreadsheets Binary files differ. diff --git a/assignment-2.5-spreadsheets/obj/main.o b/assignment-2.5-spreadsheets/obj/main.o Binary files differ. diff --git a/assignment-2.5-spreadsheets/obj/xstring.o b/assignment-2.5-spreadsheets/obj/xstring.o Binary files differ. diff --git a/assignment-2.5-spreadsheets/src/xstring.cpp b/assignment-2.5-spreadsheets/src/xstring.cpp @@ -236,6 +236,7 @@ void xstring::clear() { if (!this->empty()) delete[] str; str = new char[1]; + *this = ""; len = 0; } diff --git a/assignment-2.5-spreadsheets/src/xstring.h b/assignment-2.5-spreadsheets/src/xstring.h @@ -74,7 +74,6 @@ xstring to_xstr(T val) return xstring(buf); } -// set a default T template<typename T> xstring to_xstr(const char *fs, T val) {