diff --git a/cv7/program.c b/cv7/program.c index 2a5c625..8c0a150 100644 --- a/cv7/program.c +++ b/cv7/program.c @@ -2,119 +2,96 @@ #include #include -// Структура вузла для дерева знань +#define MAX_LINE_LENGTH 100 + +// Структура для вузла дерева typedef struct Node { - char *question_or_answer; - struct Node *yes_branch; - struct Node *no_branch; + char *question; // Питання + char *answer; // Відповідь (товар) + struct Node *yes; // Далі по "так" + struct Node *no; // Далі по "ні" } 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); // Рекурсивно будуємо гілку "ні" - } +Node* create_node(char *question, char *answer) { + Node *node = (Node*)malloc(sizeof(Node)); + node->question = question; + node->answer = answer; + node->yes = NULL; + node->no = NULL; 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); -} +// Функція для зчитування дерева з файлу +Node* build_tree(FILE *file) { + char line[MAX_LINE_LENGTH]; + if (fgets(line, sizeof(line), file) == NULL) return NULL; -// Функція для діалогу з користувачем -void runExpertSystem(Node *node) { - while (node != NULL) { - // Якщо вузол є кінцевою відповіддю, виводимо її і завершуємо - if (node->yes_branch == NULL && node->no_branch == NULL) { - printf("Відповідь: %s\n", node->question_or_answer); - return; - } + // Видалити пробіли та символи нового рядка в кінці + line[strcspn(line, "\n")] = 0; - // Виводимо питання - 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; - } + if (line[0] == '*') { // Це відповідь + return create_node(NULL, strdup(line + 1)); // Пропускаємо зірочку + } else { // Це питання + Node *node = create_node(strdup(line), NULL); + node->yes = build_tree(file); // Рекурсія для 'так' + node->no = build_tree(file); // Рекурсія для 'ні' + return node; } } -// Рекурсивна функція для звільнення пам'яті -void freeTree(Node *node) { - if (node == NULL) return; - freeTree(node->yes_branch); - freeTree(node->no_branch); - free(node->question_or_answer); // Звільняємо текст питання/відповіді - free(node); // Звільняємо сам вузол +// Функція для підрахунку кількості товарів (листків дерева) +int count_items(Node *node) { + if (node == NULL) return 0; + if (node->answer != NULL) return 1; // Листок дерева + return count_items(node->yes) + count_items(node->no); +} + +// Функція для взаємодії з користувачем +void ask_questions(Node *node) { + while (node != NULL) { + if (node->answer != NULL) { // Якщо це відповідь + printf("Expert z bufetu to vie.\n"); + printf("Pozna %d druhov ovocia a zeleniny.\n", count_items(node)); + printf("Koniec\n"); + return; + } + printf("%s\n", node->question); + printf("Odpovedajte 'a' pre prvu moznost alebo 'n' pre druhu moznost.\n"); + + char response; + scanf(" %c", &response); // Читання відповіді + + if (response == 'a') { + node = node->yes; + } else if (response == 'n') { + node = node->no; + } else { + printf("Nespravny vstup. Koniec.\n"); + return; + } + } } 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"); + FILE *file = fopen("data.txt", "r"); + if (file == NULL) { + printf("Помилка при зчитуванні файлу.\n"); return 1; } - // Рахуємо кількість видів у базі знань - int totalAnswers = countAnswers(root); - printf("Експертна система знає %d видів.\n", totalAnswers); + Node *tree = build_tree(file); + fclose(file); - // Запускаємо діалог з користувачем - runExpertSystem(root); + if (tree == NULL) { + printf("Помилка в структурі файлу.\n"); + return 1; + } + + printf("Expert z bufetu to vie.\n"); + printf("Pozna %d druhov ovocia a zeleniny.\n", count_items(tree)); + + ask_questions(tree); - // Звільняємо пам'ять - freeTree(root); return 0; }