From 9748e394627f1221f3bcc73be2ded186dfaf2107 Mon Sep 17 00:00:00 2001 From: Yurii Chechur Date: Wed, 13 Nov 2024 14:18:36 +0000 Subject: [PATCH] Update cv7/program.c --- cv7/program.c | 189 +++++++++++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 79 deletions(-) diff --git a/cv7/program.c b/cv7/program.c index 2fadd7b..2149e60 100644 --- a/cv7/program.c +++ b/cv7/program.c @@ -6,113 +6,144 @@ // Структура вузла дерева struct TreeNode { - char *value; // текст питання або відповіді + char value[SIZE]; // текст питання або відповіді struct TreeNode *left; // "так" гілка struct TreeNode *right; // "ні" гілка }; -// Функція для створення вузла дерева з текстом -struct TreeNode* createNode(const char *text) { - struct TreeNode *node = (struct TreeNode*) malloc(sizeof(struct TreeNode)); - node->value = strdup(text); + +struct TreeNode *read_tree(FILE *file) { + char buffer[SIZE]; + + // Зчитуємо рядок тексту для поточного вузла + if (fgets(buffer, SIZE, file) == NULL) { + return NULL; // Кінець файлу або помилка читання + } + + // Виділяємо пам'ять для нового вузла + struct TreeNode *node = (struct TreeNode *)malloc(sizeof(struct TreeNode)); + if (node == NULL) { + perror("Не вдалося виділити пам'ять"); + exit(EXIT_FAILURE); + } + + // Копіюємо значення в новий вузол + strncpy(node->value, buffer, SIZE); + node->value[strcspn(node->value, "\n")] = '\0'; // Видаляємо символ нового рядка node->left = NULL; node->right = NULL; + + // Перевіряємо, чи є вузол питанням (якщо починається з '#') + if (node->value[0] == '#') { + // Якщо це питання, рекурсивно зчитуємо ліве і праве піддерева + node->left = read_tree(file); // Піддерево для відповіді "так" + node->right = read_tree(file); // Піддерево для відповіді "ні" + } + + // Повертаємо створений вузол (або лист, або вузол з піддеревами) return node; } -// Функція для завантаження бази знань у форматі pre-order -struct TreeNode* loadTree(FILE *file) { - char buffer[SIZE]; - if (!fgets(buffer, SIZE, file) || buffer[0] == '\n') { - return NULL; - } - // Створюємо вузол для поточного рядка - struct TreeNode *node = createNode(buffer); +void read_code(char *code, int size, FILE *file) { + // Очищаємо буфер перед використанням + memset(code, 0, size); - // Якщо це відповідь (починається з '*'), то повертаємо листовий вузол - if (buffer[0] == '*') { - return node; - } - - // Інакше рекурсивно завантажуємо лівий і правий нащадки - node->left = loadTree(file); - node->right = loadTree(file); - return node; -} - -// Рекурсивна функція для підрахунку товарів у базі знань -int countItems(struct TreeNode *node) { - if (node == NULL) { - return 0; - } - if (node->left == NULL && node->right == NULL) { - return 1; // Листовий вузол є товаром - } - return countItems(node->left) + countItems(node->right); -} - -// Функція для запуску експертної системи з питаннями і відповідями -void runExpertSystem(struct TreeNode *node) { - if (node == NULL) return; - - // Виводимо поточне питання або відповідь - printf("%s", node->value); - - // Якщо це листовий вузол, то закінчуємо роботу - if (node->left == NULL && node->right == NULL) { - printf("Koniec\n"); + // Зчитуємо код з файлу або stdin + if (fgets(code, size, file) == NULL) { + printf("Помилка: не вдалося зчитати код\n"); return; } - // Отримуємо відповідь користувача - char answer; - scanf(" %c", &answer); // пробіл перед %c для пропуску зайвих пробілів + // Видаляємо символ нового рядка, якщо він є + code[strcspn(code, "\n")] = '\0'; +} - // Переходимо до відповідного нащадка - if (answer == 'a') { - runExpertSystem(node->left); - } else if (answer == 'n') { - runExpertSystem(node->right); + +void traverse_tree(struct TreeNode *root, const char *code) { + struct TreeNode *current = root; // Починаємо з кореня дерева + + for (int i = 0; i < strlen(code); i++) { + // Перевірка на символ "0" або "1" + if (code[i] == '0') { + current = current->left; // Переходимо вліво + } else if (code[i] == '1') { + current = current->right; // Переходимо вправо + } else { + printf("Помилка: код містить некоректний символ '%c'\n", code[i]); + return; + } + + // Перевіряємо, чи не вийшли за межі дерева + if (current == NULL) { + printf("Помилка: шлях у коді виходить за межі дерева\n"); + return; + } + } + + // Виводимо результат, якщо досягли листа + if (current->left == NULL && current->right == NULL) { + printf("Відповідь: %s\n", current->value); } else { - printf("Nerozumiem\n"); // Неправильна відповідь + printf("Помилка: код не веде до кінцевої відповіді\n"); } } -// Функція для очищення пам'яті -void freeTree(struct TreeNode *node) { - if (node == NULL) return; - freeTree(node->left); - freeTree(node->right); - free(node->value); + + +void destroy_tree(struct TreeNode *node) { + if (node == NULL) { + return; // Якщо вузол порожній, просто повертаємося + } + + // Рекурсивно очищаємо ліве і праве піддерева + destroy_tree(node->left); + destroy_tree(node->right); + + // Звільняємо пам'ять для поточного вузла free(node); } -int main() { - // Відкриваємо файл з базою знань - // В даному випадку, ми використовуємо stdin (вхід з консолі) - struct TreeNode *root = loadTree(stdin); - - // Перевірка наявності порожнього рядка після бази знань - if (root == NULL) { - printf("Помилка: База знань некоректна або пуста.\n"); +int validate_code(const char *code) { + // Перевірка на довжину рядка + if (strlen(code) >= SIZE) { + printf("Помилка: код перевищує допустиму довжину\n"); return 0; } - // Рахуємо кількість товарів і виводимо повідомлення - int itemCount = countItems(root); - printf("Expert z bufetu to vie.\n"); - printf("Pozna %d druhov ovocia a zeleniny.\n", itemCount); - printf("Odpovedajte 'a' pre prvu moznost alebo 'n' pre druhu moznost.\n"); + // Перевірка кожного символу + for (int i = 0; i < strlen(code); i++) { + if (code[i] != '0' && code[i] != '1') { + printf("Помилка: код містить некоректний символ '%c'\n", code[i]); + return 0; + } + } - // Запуск експертної системи - runExpertSystem(root); + return 1; // Код коректний +} - // Виведення повідомлення про завершення вводу - printf("Koniec vstupu\n"); - // Звільняємо пам'ять - freeTree(root); +int main() { + // Зчитуємо дерево + struct TreeNode *root = read_tree(stdin); + + // Зчитуємо код для навігації + char code[SIZE]; + printf("Введіть код для навігації деревом: "); + read_code(code, SIZE, stdin); + + // Перевірка коректності коду + if (!validate_code(code)) { + destroy_tree(root); // Очищення дерева перед завершенням програми + return 1; // Завершення програми через некоректний код + } + + // Навігація деревом за допомогою коду та виведення результату + traverse_tree(root, code); + printf("\n"); + + // Очищення пам'яті, зайнятої деревом + destroy_tree(root); return 0; }