usaa24/cv7/program.c

121 lines
4.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Структура вузла для дерева знань
typedef struct Node {
char *question_or_answer;
struct Node *yes_branch;
struct Node *no_branch;
} Node;
// Функція для створення нового вузла
Node* createNode(char *text) {
Node *newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Помилка виділення пам'яті.\n");
exit(1);
}
newNode->question_or_answer = strdup(text); // Копіюємо текст у вузол
newNode->yes_branch = NULL;
newNode->no_branch = NULL;
return newNode;
}
// Функція для побудови дерева з бази знань
Node* buildTree(FILE *file) {
char buffer[256];
if (!fgets(buffer, sizeof(buffer), file) || buffer[0] == '\n') {
return NULL; // Кінець бази знань
}
buffer[strcspn(buffer, "\n")] = '\0'; // Видаляємо символ нового рядка
Node *node = NULL;
if (buffer[0] == '*') { // Якщо рядок починається з '*', це кінцева відповідь
node = createNode(buffer + 1); // Створюємо вузол з відповіддю, без '*'
} else { // Інакше це питання
node = createNode(buffer); // Створюємо вузол з питанням
node->yes_branch = buildTree(file); // Рекурсивно будуємо гілку "так"
node->no_branch = buildTree(file); // Рекурсивно будуємо гілку "ні"
}
return node;
}
// Функція для підрахунку кількості кінцевих відповідей (листків) у дереві
int countAnswers(Node *node) {
if (node == NULL) return 0;
if (node->yes_branch == NULL && node->no_branch == NULL) return 1; // Листок
return countAnswers(node->yes_branch) + countAnswers(node->no_branch);
}
// Функція для діалогу з користувачем
void runExpertSystem(Node *node) {
while (node != NULL) {
// Якщо вузол є кінцевою відповіддю, виводимо її і завершуємо
if (node->yes_branch == NULL && node->no_branch == NULL) {
printf("Відповідь: %s\n", node->question_or_answer);
return;
}
// Виводимо питання
printf("%s (Введіть 'a' для так або 'n' для ні): ", node->question_or_answer);
// Читаємо відповідь користувача
char choice;
scanf(" %c", &choice);
// Обробка відповіді
switch (choice) {
case 'a': // Якщо "так"
node = node->yes_branch;
break;
case 'n': // Якщо "ні"
node = node->no_branch;
break;
default: // Некоректний ввід
printf("Некоректне значення. Завершення програми.\n");
return;
}
}
}
// Рекурсивна функція для звільнення пам'яті
void freeTree(Node *node) {
if (node == NULL) return;
freeTree(node->yes_branch);
freeTree(node->no_branch);
free(node->question_or_answer); // Звільняємо текст питання/відповіді
free(node); // Звільняємо сам вузол
}
int main() {
// Відкриваємо файл із базою знань
FILE *file = fopen("cv7/data.txt", "r");
if (!file) {
printf("Не вдалося відкрити файл бази знань.\n");
return 0;
}
// Будуємо дерево знань з файлу
Node *root = buildTree(file);
fclose(file);
// Перевірка, чи дерево успішно збудовано
if (root == NULL) {
printf("Помилка завантаження бази знань.\n");
return 1;
}
// Рахуємо кількість видів у базі знань
int totalAnswers = countAnswers(root);
printf("Експертна система знає %d видів.\n", totalAnswers);
// Запускаємо діалог з користувачем
runExpertSystem(root);
// Звільняємо пам'ять
freeTree(root);
return 0;
}