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 }