Int length; // длина строки
public:
// Конструктор по умолчанию
STRING() : str(nullptr), length(0) {}
// Конструктор с параметром
STRING(const char* s) {
length = strlen(s); // Установка длины
str = new char[length + 1]; // Выделение памяти под строку
strcpy(str, s); // Копирование строки
}
// Конструктор с символом
STRING(char c) {
length = 1; // длина равна 1
str = new char[2]; // выделение памяти под два символа
str[0] = c; // после первого символа идет нуль-символ
str[1] = '\0';
}
// Конструктор копирования
STRING(const STRING& other) {
length = other.length; // Копирование длины
str = new char[length + 1]; // Выделение памяти
strcpy(str, other.str); // Копирование строки
}
// Деструктор
~STRING() {
delete[] str; // Освобождение памяти
}
// Метод для получения символа на конкретной позиции
char getCharAt(int position) const {
if (position >= 0 && position < length) { // Проверка, что позиция в границах строки
return str[position];
}
// Если вне границ, возвращаем нуль-символ
return '\0';
}
// Виртуальный метод для вывода информации о строке
virtual void print() {
std::cout << "String: " << str << ", Length: " << length << std::endl;
}
// Перегрузка оператора сравнения
bool operator==(const STRING& other) {
return strcmp(str, other.str) == 0; // Вернет true, если строки равны
}
};
// Класс IDENTIFIER_STRING, производный от STRING, который используется для идентификаторов
class IDENTIFIER_STRING : public STRING {
public:
// Конструктор по умолчанию
IDENTIFIER_STRING() : STRING() {}
// Конструктор, который проверяет валидность идентификатора перед созданием
IDENTIFIER_STRING(const char* s) : STRING() {
bool isValidIdentifier = true;
for (int i = 0; i < strlen(s); i++) {
if (!isalnum(s[i])) { // Если символ не является цифрой или буквой
isValidIdentifier = false;
break;
}
}
if (isValidIdentifier) {
length = strlen(s);
str = new char[length + 1]; // выделяем память и копируем строку
strcpy(str, s);
transformToLowercase(); // преобразуем идентификатор в нижний регистр
}
}
// Конструктор копирования
IDENTIFIER_STRING(const IDENTIFIER_STRING& other) : STRING(other) {}
// Метод для преобразования идентификатора в нижний регистр
void transformToLowercase() {
for (int i = 0; i < length; i++) {
str[i] = std::tolower(str[i]); // использование функции tolower для преобразования символа в нижний регистр
}
}
// Переопределение метода print()
void print() override {
std::cout << "Identifier String: " << str << ", Length: " << length << std::endl;
}
};
// Класс COMPLEX_NUMBER, производный от STRING, который обрабатывает комплексные числа
class COMPLEX_NUMBER : public STRING {
private:
bool isValidComplexNumber; // флаг проверки дейтсвительности формата комплексного числа
public:
// Конструктор по умолчанию
COMPLEX_NUMBER() : STRING(), isValidComplexNumber(true) {}
// Конструктор, который проверяет валидность формата комплексного числа при создании
COMPLEX_NUMBER(const char* s) : STRING(), isValidComplexNumber(true) {
int separatorPosition = findSeparatorPosition(s); // Позиция разделителя 'i'
if (separatorPosition != -1) { // Если есть 'i'
if (isValidRealPart(s, separatorPosition) && isValidImaginaryPart(s, separatorPosition)) { // проверяем валидность реальной и мнимой частей
length = strlen(s);
str = new char[length + 1];// выделяем память и копируем строку
strcpy(str, s);
}
}
}
// Конструктор копирования
COMPLEX_NUMBER(const COMPLEX_NUMBER& other) : STRING(other), isValidComplexNumber(other.isValidComplexNumber) {}
// Метод, который "выполняет" деление комплексного числа на другое
void divide(const COMPLEX_NUMBER& other) {
if (isValidComplexNumber && other.isValidComplexNumber) {
std::cout << "Performing division of complex numbers" << std::endl;
} else {
std::cout << "Invalid complex numbers for division" << std::endl; // Сообщение выводится, если числа не в правильном формате
}
}
// Переопределение метода print()
void print() override {
std::cout << "Complex Number: " << str << ", Length: " << length << std::endl;
}
private:
// Утилитарные методы, используемые внутри класса
int findSeparatorPosition(const char* s) {
/* Ищет позицию 'i' в строке */
for (int i = 0; i < strlen(s); i++) {
if (s[i] == 'i') {
return i;
}
}
return -1;
}
bool isValidRealPart(const char* s, int separatorPosition) {
/* Проверяет действительность реальной части */
return separatorPosition == 0 || !isOperator(s[0]);
}
bool isValidImaginaryPart(const char* s, int separatorPosition) {
/* Проверяет действительность мнимой части */
if (separatorPosition == strlen(s) - 1) {
return isOperator(s[separatorPosition + 1]);
}
return false;
}
bool isOperator(char c) {
/* Проверяет, является ли символ оператором */
return c == '+' || c == '-';
}
};
// Функция для тестирования методов класса STRING
void testMethods(STRING* string) {
string->print();
}
int main() {
int numElements;
std::cout << "Enter the number of elements: ";
std::cin >> numElements;
std::cin.ignore();
STRING** stringArray = new STRING*[numElements]; // Создание динамического массива со ссылками на строки
for (int i = 0; i < numElements; i++) {
// Блок кода, где пользователю предлагается выбрать тип строки и ввести начальное значение
// После этого создается соответствующий экземпляр STRING и заносится в массив.
}
// Основной цикл программы, где пользователю предоставляются разные возможности для взаимодействия со строками
for (int i = 0; i < numElements; i++) {
delete stringArray[i]; // Удаление динамических данных
}
delete[] stringArray; // Очистка массива указателей
return 0;
}
Данный программный код включает в себя два главных уровня меню: "Инициализация" и "Тестирование" для тестирования методов классов. Каждый уровень меню представлен в виде своей конструкции switch.
Также в программе используются функции printMenu() и _getch(). Первая функция выводит на экран меню на основе переменной choiceMenu. Вторая обрабатывает нажатую пользователем клавишу и возвращает ее код.
При запуске программы на экране выводится главное меню, в котором необходимо выбрать начальное значение для массива указателей или начать тестирование. Если пользователь выбирает "Инициализация", программа предлагает два подпункта: задание количества элементов и задание начальных значений. Значение каждого выбранного элемента сохраняется в массиве arrString, который был динамически выделен. Если пользователь выбирает "Тестирование", программе предлагается выбрать тип строки для тестирования и соответствующий метод для каждого экземпляра.
При выборе тестирования каждого класса соответствующая функция вызывает методы этого класса, выводя на экран информацию о текущих операциях. По завершении тестирования пользователь может вернуться к главному меню, повторно выбрать настройки или завершить работу.
В конце программы освобождаются выделенные ресурсы для объектов класса, а также для массива указателей на базовый класс.
