uni

University stuff
git clone git://git.margiolis.net/uni.git
Log | Files | Refs | README | LICENSE

classes.cpp (11014B)


      1 #include <algorithm>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <iomanip>
      5 #include <memory>
      6 #include <string>
      7 
      8 class Student
      9 {
     10     private:
     11         char *id;
     12         std::string name;
     13         unsigned int semester;
     14         unsigned int pcourses;
     15         float *grades;
     16 
     17     public:
     18         Student(const char *id, const std::string& name);
     19         Student(const char *id, const std::string& name,
     20                 const unsigned int semester);
     21         Student(const char *id, const std::string& name,
     22                 const unsigned int semester,
     23                 const unsigned int pcourses,
     24                 const float *grades);
     25         Student(const Student& s);
     26         ~Student();
     27 
     28         const std::string& get_name() const;
     29         constexpr const char *get_id() const;
     30         constexpr const unsigned int get_semester() const;
     31         constexpr const unsigned int get_pcourses() const;
     32         constexpr float *get_grades() const;
     33 
     34         void set_id      (const char *id);
     35         void set_name    (const std::string& name);
     36         void set_semester(const unsigned int semester);
     37         void set_pcourses(const unsigned int pcourses);
     38         void set_grades  (const float *grades);
     39 
     40         void add_grade(const float grade);
     41         void detailed_print() const;
     42 
     43     private:
     44         template<typename T> T *conv(const T *arr, std::size_t len) const;
     45         template<typename T> T *resize(const T *arr, std::size_t len);
     46         constexpr std::size_t len(const char *s) const;
     47         float avg() const;
     48 };
     49 
     50 Student::Student(const char *id, const std::string& name)
     51     :id(conv<char>(id, len(id))), name(name), semester(1), pcourses(0),
     52     grades(nullptr) {}
     53 
     54 Student::Student(const char *id, const std::string& name,
     55         const unsigned int semester)
     56     :id(conv<char>(id, len(id))), name(name), semester(semester), pcourses(0),
     57     grades(nullptr) {}
     58 
     59 Student::Student(const char *id, const std::string& name,
     60         const unsigned int semester,
     61         const unsigned int pcourses, const float *grades)
     62     :id(conv<char>(id, len(id))), name(name), semester(semester), pcourses(pcourses),
     63     grades(conv<float>(grades, pcourses)) {}
     64 
     65 Student::Student(const Student& s)
     66     :name(s.name), semester(s.semester), pcourses(s.pcourses)
     67 {
     68     this->id = conv<char>(s.id, len(s.id));
     69     this->grades = conv<float>(s.grades, s.pcourses);
     70 }
     71 
     72 Student::~Student()
     73 {
     74     if (this->id != nullptr) delete[] this->id;
     75     if (this->id != nullptr) delete[] this->grades;
     76 }
     77 
     78 const std::string&
     79 Student::get_name() const
     80 {
     81     return this->name;
     82 }
     83 
     84 /* 
     85  * The functions below are marked as constexpr just so they 
     86  * can be computed at compile time since everything is hardcoded.
     87  */
     88 constexpr const char *
     89 Student::get_id() const
     90 {
     91     return this->id;
     92 }
     93 
     94 constexpr const unsigned int
     95 Student::get_semester() const
     96 {
     97     return this->semester;
     98 }
     99 
    100 constexpr const unsigned int
    101 Student::get_pcourses() const
    102 {
    103     return this->pcourses;
    104 }
    105 
    106 constexpr float *
    107 Student::get_grades() const
    108 {
    109     return this->grades;
    110 }
    111 
    112 void
    113 Student::set_id(const char *id)
    114 {
    115     if (this->id != nullptr) delete[] this->id;
    116     this->id = conv<char>(id, len(id));
    117 }
    118 
    119 void
    120 Student::set_name(const std::string& name)
    121 {
    122     this->name = name;
    123 }
    124 
    125 void
    126 Student::set_semester(const unsigned int semester)
    127 {
    128     this->semester = semester;
    129 }
    130 
    131 void
    132 Student::set_pcourses(const unsigned int pcourses)
    133 {
    134     this->pcourses = pcourses;
    135 }
    136 
    137 void
    138 Student::set_grades(const float *grades)
    139 {
    140     this->grades = conv<float>(grades, pcourses);
    141 }
    142 
    143 void
    144 Student::add_grade(const float grade)
    145 {
    146     float *tmp = resize<float>(grades, pcourses);
    147     tmp[pcourses] = grade;
    148     grades = tmp;
    149     pcourses++;
    150 }
    151 
    152 void
    153 Student::detailed_print() const
    154 {
    155     if (grades != nullptr)
    156     {
    157         for (unsigned int i = 0; i < pcourses; i++)
    158         {
    159             std::cout << "Subject " << i+1 << ": ";
    160             std::cout << grades[i] << std::endl;        
    161         }
    162         std::cout << "Average grade: " << std::setprecision(2) << avg() << std::endl;
    163     }
    164 }
    165 
    166 constexpr std::size_t
    167 Student::len(const char *s) const
    168 {
    169     return std::strlen(s) + 1;
    170 }
    171 
    172 float
    173 Student::avg() const
    174 {
    175     if (grades != nullptr)
    176     {
    177         float sum = 0;
    178         for (unsigned int i = 0; i < pcourses; i++)
    179             sum += grades[i];
    180         float average = sum / pcourses;
    181         return average;
    182     }
    183     else return 0.0f;
    184 }
    185 
    186 /* 
    187  * Makes a copy of a given array of type T and returns a temporary array
    188  * which is meant to be stored in a member variable.
    189  * If the array is empty it returns nullptr.
    190  */
    191 template<typename T> T *
    192 Student::conv(const T *arr, std::size_t len) const
    193 {
    194     if (arr != nullptr)
    195     {
    196         T *tmp = new T[len];
    197         std::memcpy(tmp, arr, sizeof(T) * len);
    198         return tmp;
    199     }
    200     else return nullptr;
    201 }
    202 
    203 template<typename T> T *
    204 Student::resize(const T *arr, std::size_t len)
    205 {
    206     T *tmp = new T[len+1];
    207     if (arr != nullptr)
    208     {
    209         std::memcpy(tmp, arr, sizeof(T) * len);
    210         delete[] arr;
    211     }
    212     return tmp;
    213 }
    214 
    215 static std::ostream& operator<< (std::ostream& stream, const Student& s);
    216 static void cont();
    217 static void constructor1(const Student& s1);
    218 static void ostream_overload(const Student& s1);
    219 static void constructor2(const Student& s2);
    220 static void copy_constructor(const Student& copystud);
    221 static void constructor3(const Student& s3);
    222 static void detprint (const Student& s3);
    223 static void setters(Student& s3);
    224 static void addgrd(Student& s3);
    225 
    226 /*
    227  * main uses smart pointers since there are quite a few dynamically
    228  * allocated objects and so it looks cleaner to let them handle the
    229  * deletions.
    230  */
    231 int
    232 main(int argc, char **argv)
    233 {
    234     std::unique_ptr<Student> s1 =
    235         std::make_unique<Student>("12345678", std::string("Name Surname"));
    236     system("clear || cls");
    237     constructor1(*s1); cont();
    238     ostream_overload(*s1); cont();
    239     
    240     std::unique_ptr<Student> s2 =
    241         std::make_unique<Student>("92345678", std::string("Name Surnamington"), 2);
    242     constructor2(*s2); cont();
    243 
    244     std::unique_ptr<Student> copystud = std::make_unique<Student>(*s2);
    245     copy_constructor(*copystud); cont();
    246 
    247     std::unique_ptr<float[]> grd(new float[4]{9.4f, 8.4f, 5.5f, 6.3f});
    248     std::unique_ptr<Student> s3 = 
    249         std::make_unique<Student>("72345678", std::string("Name Surnaming"), 2, 4, grd.get());
    250     constructor3(*s3); cont();
    251     detprint(*s3); cont();
    252     setters(*s3);
    253     addgrd(*s3); cont();
    254 
    255     return 0;
    256 }
    257 
    258 std::ostream&
    259 operator<< (std::ostream& stream, const Student& s)
    260 {
    261     return stream <<
    262         "ID: " << s.get_id() << std::endl <<
    263         "Name: " << s.get_name() << std::endl <<
    264         "Semester: " << s.get_semester() << std::endl;
    265 }
    266 
    267 void
    268 cont()
    269 {
    270     std::cout << std::endl;
    271     std::cout << "Press <ENTER> to continue. . .";
    272     if (std::cin.get()) system("clear || cls");
    273 }
    274 
    275 void
    276 constructor1(const Student& s1)
    277 {
    278     std::cout << "Constructor for s1 (ID, Name)" << std::endl;
    279     std::cout << "----------------------------" << std::endl;
    280     std::cout << "ID: " << s1.get_id() << std::endl;
    281     std::cout << "Name: " << s1.get_name() << std::endl;
    282     std::cout << "Semester (default value): " << s1.get_semester() << std::endl;
    283     std::cout << "Courses passed (default value): " << s1.get_pcourses() << std::endl;
    284 }
    285 
    286 void
    287 ostream_overload(const Student& s1)
    288 {
    289     std::cout << "std::ostream overload" << std::endl;
    290     std::cout << "----------------------------" << std::endl;
    291     std::cout << s1 << std::endl;
    292 }
    293 
    294 void
    295 constructor2(const Student& s2)
    296 {
    297     std::cout << "Constructor for s2 (ID, Name, Semester)" << std::endl;
    298     std::cout << "----------------------------" << std::endl;
    299     std::cout << "ID: " << s2.get_id() << std::endl;
    300     std::cout << "Name: " << s2.get_name() << std::endl;
    301     std::cout << "Semester: " << s2.get_semester() << std::endl;
    302     std::cout << "Courses passed (default value): " << s2.get_pcourses() << std::endl;
    303 }
    304 
    305 void
    306 copy_constructor(const Student& copystud)
    307 {
    308     std::cout << "Copy Constructor using copystud object as a copy of s2" << std::endl;
    309     std::cout << "----------------------------" << std::endl;
    310     std::cout << "ID: " << copystud.get_id() << std::endl;
    311     std::cout << "Name: " << copystud.get_name() << std::endl;
    312     std::cout << "Semester: " << copystud.get_semester() << std::endl;
    313     std::cout << "Courses passed (default value): " << copystud.get_pcourses() << std::endl;
    314 }
    315 
    316 void
    317 constructor3(const Student& s3)
    318 {
    319     std::cout << "Constructor for s3 (ID, Name, Semester, Courses passed, Grades)" << std::endl;
    320     std::cout << "----------------------------" << std::endl;
    321     std::cout << "ID: " << s3.get_id() << std::endl;
    322     std::cout << "Name: " << s3.get_name() << std::endl;
    323     std::cout << "Semester: " << s3.get_semester() << std::endl;
    324     std::cout << "Courses passed: " << s3.get_pcourses() << std::endl;
    325 
    326     float *gr = s3.get_grades();
    327     if (gr != nullptr)
    328     {
    329         std::cout << "Grades: ";
    330         for (unsigned int i = 0; i < s3.get_pcourses(); i++)
    331         {
    332             if (i != s3.get_pcourses()-1) std::cout << gr[i] << ", ";
    333             else std::cout << gr[i] << std::endl;
    334         }
    335     }
    336 }
    337 
    338 void
    339 detprint (const Student& s3)
    340 {
    341     std::cout << "Detailed print of s3's grades" << std::endl;
    342     std::cout << "----------------------------" << std::endl;
    343     s3.detailed_print();
    344 }
    345 
    346 void
    347 setters(Student& s3)
    348 {
    349     s3.set_id("010101");
    350     s3.set_name("AAAA");
    351     s3.set_semester(100);
    352     s3.set_pcourses(2);
    353     std::unique_ptr<float> gg(new float[2]{0.1f, 2.2f});
    354     s3.set_grades(gg.get());
    355 
    356     std::cout << "Setters example using s3" << std::endl;
    357     std::cout << "----------------------------" << std::endl;
    358     std::cout << "Input: 010101" << std::endl;;
    359     std::cout << "New ID: " << s3.get_id() << std::endl;
    360     std::cout << std::endl;
    361     std::cout << "Input: AAAA" << std::endl;
    362     std::cout << "New name: " << s3.get_name() << std::endl;
    363     std::cout << std::endl;
    364     std::cout << "Input: 100" << std::endl;
    365     std::cout << "New semester: " << s3.get_semester() << std::endl;
    366     std::cout << std::endl;
    367     std::cout << "Input: 2" << std::endl;
    368     std::cout << "New courses passed: " << s3.get_pcourses() << std::endl;
    369     std::cout << std::endl;
    370     std::cout << "Input: 0.1, 2.2" << std::endl;
    371     std::cout << "New grades: ";
    372 
    373     float *gr = s3.get_grades();
    374     if (gr != nullptr)
    375     {
    376         for (unsigned int i = 0; i < s3.get_pcourses(); i++)
    377         {
    378             if (i != s3.get_pcourses()-1)   std::cout << gr[i] << ", ";
    379             else std::cout << gr[i] << std::endl << std::endl;
    380         }
    381     }
    382 }
    383 
    384 void
    385 addgrd(Student& s3)
    386 {
    387     s3.add_grade(7.5f);
    388     float *gr = s3.get_grades();
    389     if (gr != nullptr)
    390     {
    391         std::cout << "Input: 7.5" << std::endl;
    392         std::cout << "Updated grades: ";
    393         for (unsigned int i = 0; i < s3.get_pcourses(); i++)
    394         {
    395             if (i != s3.get_pcourses()-1) std::cout << gr[i] << ", ";
    396             else std::cout << gr[i] << std::endl;
    397         }
    398     }
    399 }