diff --git a/cv7/program.c b/cv7/program.c index 8054d0a..3b3edc6 100644 --- a/cv7/program.c +++ b/cv7/program.c @@ -2,144 +2,121 @@ #include #include -#define MAX_TEXT 256 +#define SIZE 256 // Структура вузла дерева -typedef struct Node { - char text[MAX_TEXT]; - struct Node *yes; - struct Node *no; -} Node; +struct TreeNode { + char *value; // текст питання або відповіді + struct TreeNode *left; // "так" гілка + struct TreeNode *right; // "ні" гілка +}; -// Функція для створення нового вузла -Node* createNode(const char* text) { - Node* node = (Node*)malloc(sizeof(Node)); - if (node) { - strncpy(node->text, text, MAX_TEXT); - node->yes = NULL; - node->no = NULL; - } +// Функція для створення вузла дерева з текстом +struct TreeNode* createNode(const char *text) { + struct TreeNode *node = (struct TreeNode*) malloc(sizeof(struct TreeNode)); + node->value = strdup(text); + node->left = NULL; + node->right = NULL; return node; } -// Завантаження дерева з файлу -Node* loadTree(FILE *file) { - char line[MAX_TEXT]; - if (!fgets(line, sizeof(line), file)) { +// Функція для завантаження бази знань у форматі pre-order +struct TreeNode* loadTree(FILE *file) { + char buffer[SIZE]; + if (!fgets(buffer, SIZE, file) || buffer[0] == '\n') { return NULL; } - line[strcspn(line, "\n")] = 0; // Видаляємо новий рядок - // Визначаємо, чи це листовий вузол - if (line[0] == '*') { - return createNode(line + 1); // Видаляємо символ '*' на початку + // Створюємо вузол для поточного рядка + struct TreeNode *node = createNode(buffer); + + // Якщо це відповідь (починається з '*'), то повертаємо листовий вузол + if (buffer[0] == '*') { + return node; } - // Створюємо внутрішній вузол з двома піддеревами - Node *node = createNode(line); - node->yes = loadTree(file); - node->no = loadTree(file); + // Інакше рекурсивно завантажуємо лівий і правий нащадки + node->left = loadTree(file); + node->right = loadTree(file); return node; } -// Функція для підрахунку вузлів (листових та внутрішніх) -void countNodes(Node* root, int* leafCount, int* internalCount) { - if (root == NULL) { +// Рекурсивна функція для підрахунку товарів у базі знань +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"); return; } - if (root->yes == NULL && root->no == NULL) { - (*leafCount)++; + + // Отримуємо відповідь користувача + char answer; + scanf(" %c", &answer); + + // Переходимо до відповідного нащадка + if (answer == 'a') { + runExpertSystem(node->left); + } else if (answer == 'n') { + runExpertSystem(node->right); } else { - (*internalCount)++; - countNodes(root->yes, leafCount, internalCount); - countNodes(root->no, leafCount, internalCount); + printf("Nerozumiem\n"); } } -// Функція для проведення діалогу з користувачем -void interact(Node* root) { - Node* current = root; - while (current->yes != NULL && current->no != NULL) { - printf("Odpovedajte 'a' pre prvu moznost alebo 'n' pre druhu moznost.\n"); - printf("%s (a/n): ", current->text); - - char answer; - - // Читання одного символа для відповіді - int res = fgetc(stdin); // Використовуємо fgetc для точного контролю вводу - // Пропускаємо всі зайві символи нового рядка або пробіли - while (res == '\n' || res == ' ' || res == '\t') { - res = fgetc(stdin); - } - - if (res == EOF) { - printf("Некоректна відповідь! Завершення програми.\n"); - return; - } - - answer = (char)res; // Зберігаємо введений символ - - if (answer == 'a') { - current = current->yes; - } else if (answer == 'n') { - current = current->no; - } else { - printf("Некоректна відповідь! Завершення програми.\n"); - return; - } - } - - // Коли досягнуто листового вузла (товар) - printf("%s\n", current->text); +// Функція для очищення пам'яті +void freeTree(struct TreeNode *node) { + if (node == NULL) return; + freeTree(node->left); + freeTree(node->right); + free(node->value); + free(node); } -// Функція для очищення пам'яті дерева -void freeTree(Node* root) { +int main() { + // Відкриваємо файл з базою знань + // FILE *file = fopen("baza.txt", "r"); + // if (file == NULL) { + // printf("Nepodarilo sa otvoriť súbor databázy znalostí.\n"); + // return 0; + // } + + // Завантажуємо базу знань в дерево + struct TreeNode *root = loadTree(stdin); + // fclose(file); + + // Перевірка наявності порожнього рядка після бази знань if (root == NULL) { - return; - } - freeTree(root->yes); - freeTree(root->no); - free(root); -} - -int main(int argc, char *argv[]) { - // Відкриваємо файл або використовуємо стандартний вхід - FILE *file; - if (argc > 1) { - file = fopen(argv[1], "r"); - if (!file) { - printf("Помилка: не вдалося відкрити файл %s.\n", argv[1]); - return 1; - } - } else { - file = stdin; // Використовуємо стандартний вхід, якщо файл не заданий + printf("Помилка: База знань некоректна або пуста.\n"); + return 0; } - // Завантажуємо дерево з файлу - Node* root = loadTree(file); - if (file != stdin) fclose(file); + // Рахуємо кількість товарів і виводимо повідомлення + 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"); - // Перевірка на успішне завантаження дерева - if (!root) { - printf("Помилка: дерево не було завантажене.\n"); - return 1; - } + // Запуск експертної системи + runExpertSystem(root); - // Підрахунок вузлів - int leafCount = 0, internalCount = 0; - countNodes(root, &leafCount, &internalCount); - printf("Zasadny vykon\n"); - printf("Zagolna kilkist tovariv (listovykh vuzliv): %d\n", leafCount); - printf("Kilkist pytan (vnutrishnikh vuzliv): %d\n", internalCount); - - // Інтерактивна взаємодія з користувачем - printf("Pochynayemo dialoh...\n"); - interact(root); - - // Очищення пам'яті + // Звільняємо пам'ять freeTree(root); - printf("Program zaversheno uspishno.\n"); return 0; }