Website Summary Files Commits Branches @commit @diff @stats
path: root / Week01 / Exercise03
diff options
context:
space:
mode:
Commitfcf38e62e8160f2c9901bdfd33760afed28beb8d (patch)
Author
 Syndamia <kamen@syndamia.com>
2026-02-22 19:18:46 +0200
Committer
 Syndamia <kamen@syndamia.com>
2026-02-22 19:18:46 +0200
Files838fd5897d88700491a389cdf6837e35da3347ae /Week01/Exercise03
oop-2025-solutions-fcf38e62e8160f2c9901bdfd33760afed28beb8d.tar
oop-2025-solutions-fcf38e62e8160f2c9901bdfd33760afed28beb8d.tar.gz
oop-2025-solutions-fcf38e62e8160f2c9901bdfd33760afed28beb8d.zip
Parentc365ede952f852c6e8feb92fc3a0766186f989f1 (diff)
feat(Week01): Add solutions
5 files changed, 202 insertions, 0 deletions
-rw-r--r--Week01/Exercise03/ioHelpers.cpp57
-rw-r--r--Week01/Exercise03/ioHelpers.h17
-rw-r--r--Week01/Exercise03/main.cpp40
-rw-r--r--Week01/Exercise03/stringHelpers.cpp74
-rw-r--r--Week01/Exercise03/stringHelpers.h14
diff --git a/Week01/Exercise03/ioHelpers.cpp b/Week01/Exercise03/ioHelpers.cpp
new file mode 100644
index 0000000..caf63fe
--- /dev/null
+++ b/Week01/Exercise03/ioHelpers.cpp
@@ -0,0 +1,57 @@
+#include <iostream>
+#include "ioHelpers.h"
+#include "stringHelpers.h"
+
+int readInteger(const char* prompt, int min, int max) {
+ std::cout << prompt;
+
+ int value;
+ std::cin >> value;
+
+ while (value < min || max < value) {
+ std::cout << "Value must in range [" << min << ", " << max << "]! Try again... " << std::endl;
+ std::cin >> value;
+ }
+
+ return value;
+}
+
+double readDouble(const char* prompt, double min, double max) {
+ std::cout << prompt;
+
+ double value;
+ std::cin >> value;
+
+ while (value < min || max < value) {
+ std::cout << "Value must in range [" << min << ", " << max << "]! Try again... " << std::endl;
+ std::cin >> value;
+ }
+
+ return value;
+}
+
+char* readString(const char* prompt) {
+ std::cout << prompt;
+
+ const unsigned BUFFER_SIZE = 1024;
+ char buffer[BUFFER_SIZE];
+
+ // Когато правим "std::cin >> x", std::cin чете само нужния брой знаци за x,
+ // докато std::cin.getline чете от последната позиция нататък.
+ // Тоест, ако направим например "std::cin >> integerValue" и след това
+ // "std::cin.getline(...)" и входа ни е "5 ABC", тогава първото std::cin
+ // ще прочете само 5-цата и getline ще запише " ABC".
+ // Когато обаче имаме нов ред, тоест еквивалентно на "5\nABC", тогава
+ // getline ще почне да чете от "\nABC", ще види това "\n" и ще запише
+ // празния низ "".
+ // std::cin.peek() връща текущата буква, без да премества напред четенето,
+ // std::cin.ignore() игнорира една буква (т.е. четенето продължава след нея).
+ // Общо взето, това долу игнорира знак за нов ред, ако сме срещнали такъв.
+ // Това оправя ситуацията, когато получаваме "First name: Last name: ".
+ if (std::cin.peek() == '\n')
+ std::cin.ignore();
+
+ std::cin.getline(buffer, BUFFER_SIZE);
+
+ return newString(buffer);
+}
diff --git a/Week01/Exercise03/ioHelpers.h b/Week01/Exercise03/ioHelpers.h
new file mode 100644
index 0000000..bf365dd
--- /dev/null
+++ b/Week01/Exercise03/ioHelpers.h
@@ -0,0 +1,17 @@
+#ifndef IOHELPERS
+#define IOHELPERS
+
+// Прочита от потребителския вход цяло число между min и max включително,
+// като предоставя prompt преди въведената стойност
+// При невалидна стойност, пита пак за вход
+int readInteger(const char* prompt, int min, int max);
+// Прочита от потребителския вход число с плаваща запетая между min и max включително,
+// като предоставя prompt преди въведената стойност
+// При невалидна стойност, пита пак за вход
+double readDouble(const char* prompt, double min, double max);
+// Прочита от потребителския вход един ред текст,
+// като предоставя prompt преди въведената стойност
+// При невалидна стойност, пита пак за вход
+char* readString(const char* prompt);
+
+#endif
diff --git a/Week01/Exercise03/main.cpp b/Week01/Exercise03/main.cpp
new file mode 100644
index 0000000..beea1f5
--- /dev/null
+++ b/Week01/Exercise03/main.cpp
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "ioHelpers.h"
+#include "stringHelpers.h"
+
+int main() {
+ // Нямаме ограничение на броя студенти, затова просто ще сложим максимума
+ // да е най-голямата стойност за 32-битов signed integer: 2^31 - 1
+ // По-коректно е да се ползват специални константи, които пазят максималната
+ // стойност на отделните типове данни, защото на стар компютър, int може да
+ // не е 32 бита.
+ unsigned numStudents = readInteger("Number of students: ", 0, 2147483647);
+
+ double* grades = new double[numStudents];
+ char** names = new char*[numStudents];
+
+ for (unsigned i = 0; i < numStudents; ++i) {
+ char* firstName = readString("First name: ");
+ char* lastName = readString("Last name: ");
+
+ names[i] = concatStrings(firstName, lastName, " ");
+
+ deleteString(firstName);
+ deleteString(lastName);
+
+ double grade = readDouble("Grade: ", 2.0, 6.0);
+
+ grades[i] = grade;
+ }
+
+ for (unsigned i = 0; i < numStudents; ++i) {
+ std::cout << names[i] << " has grade " << grades[i] << std::endl;
+ }
+
+ delete[] grades;
+ for (unsigned i = 0; i < numStudents; ++i)
+ deleteString(names[i]);
+ delete[] names;
+
+ return 0;
+}
diff --git a/Week01/Exercise03/stringHelpers.cpp b/Week01/Exercise03/stringHelpers.cpp
new file mode 100644
index 0000000..ee9e691
--- /dev/null
+++ b/Week01/Exercise03/stringHelpers.cpp
@@ -0,0 +1,74 @@
+#include "stringHelpers.h"
+
+char* newString(unsigned length) {
+ return new char[length + 1];
+}
+
+// Тази функция е локална: не можем да я използваме в друг файл!
+unsigned stringLength(const char* string) {
+ if (string == nullptr)
+ return 0;
+
+ unsigned length = 0;
+
+ while (*string != '\0') {
+ ++length;
+ ++string;
+ }
+
+ return length;
+}
+
+char* newString(const char* string) {
+ if (string == nullptr)
+ return nullptr;
+
+ unsigned length = stringLength(string);
+
+ char* str = newString(length);
+
+ // Правим <= length, за да пренесем и терминиращата нула
+ for (unsigned i = 0; i <= length; ++i) {
+ str[i] = string[i];
+ }
+
+ return str;
+}
+
+char* concatStrings(const char* first, const char* second, const char* separator) {
+ unsigned length = stringLength(first) + stringLength(separator) + stringLength(second);
+
+ char* str = newString(length);
+ unsigned i = 0;
+
+ if (first != nullptr) {
+ while (*first != '\0' && i < length) {
+ str[i] = *first;
+ ++first;
+ ++i;
+ }
+ }
+
+ if (separator != nullptr) {
+ while (*separator != '\0' && i < length) {
+ str[i] = *separator;
+ ++separator;
+ ++i;
+ }
+ }
+
+ if (second != nullptr) {
+ while (*second != '\0' && i < length) {
+ str[i] = *second;
+ ++second;
+ ++i;
+ }
+ }
+
+ return str;
+}
+
+void deleteString(char*& string) {
+ delete[] string;
+ string = nullptr;
+}
diff --git a/Week01/Exercise03/stringHelpers.h b/Week01/Exercise03/stringHelpers.h
new file mode 100644
index 0000000..7f86130
--- /dev/null
+++ b/Week01/Exercise03/stringHelpers.h
@@ -0,0 +1,14 @@
+#ifndef STRINGHELPERS
+#define STRINGHELPERS
+
+// Създава динамично-заделен низ по подадената дължина
+char* newString(unsigned length);
+// Създава динамично-заделен низ, копие на подадения низ
+char* newString(const char* string);
+// Слепява first и second, като поставя separator между тях (ако е валиден) и
+// връща резултатния (динамичо-заделен) низ
+char* concatStrings(const char* first, const char* second, const char* separator);
+// Освобождава паметта на динамичо-заделен низ
+void deleteString(char*& string); // Запишете nullptr в string!
+
+#endif