diff options
feat(Week01): Add solutions
5 files changed, 202 insertions, 0 deletions
| -rw-r--r-- | Week01/Exercise03/ioHelpers.cpp | 57 | ||||
| -rw-r--r-- | Week01/Exercise03/ioHelpers.h | 17 | ||||
| -rw-r--r-- | Week01/Exercise03/main.cpp | 40 | ||||
| -rw-r--r-- | Week01/Exercise03/stringHelpers.cpp | 74 | ||||
| -rw-r--r-- | Week01/Exercise03/stringHelpers.h | 14 |
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 |
