usaa24/cv7/program.c
2024-11-08 13:41:41 +01:00

120 lines
3.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>
#define MAX_LINE_LENGTH 100
typedef struct Node {
char text[MAX_LINE_LENGTH];
struct Node *yes;
struct Node *no;
} Node;
// Создает узел с текстом
Node* create_node(const char* text) {
Node *node = (Node*)malloc(sizeof(Node));
if (!node) {
fprintf(stderr, "Ошибка выделения памяти.\n");
exit(1);
}
strncpy(node->text, text, MAX_LINE_LENGTH);
node->yes = NULL;
node->no = NULL;
return node;
}
// Рекурсивно создает дерево из базы знаний, хранящейся в массиве строк
Node* parse_knowledge_base(char lines[][MAX_LINE_LENGTH], int *index, int line_count) {
if (*index >= line_count || lines[*index][0] == '\0') {
return NULL;
}
char *line = lines[*index];
(*index)++; // Переход к следующей строке
Node *node = NULL;
if (line[0] == '*') {
node = create_node(line + 1); // Узел с ответом
} else {
node = create_node(line); // Узел с вопросом
node->yes = parse_knowledge_base(lines, index, line_count); // Ветка "да"
node->no = parse_knowledge_base(lines, index, line_count); // Ветка "нет"
}
return node;
}
// Подсчитывает количество конечных узлов (продуктов) в дереве
int count_products(Node *node) {
if (!node) return 0;
if (!node->yes && !node->no) return 1; // Листовой узел - это продукт
return count_products(node->yes) + count_products(node->no);
}
// Запускает систему, задавая вопросы и ожидая ответы
void run_expert_system(Node *node) {
while (node) {
if (!node->yes && !node->no) { // Достигнут конечный узел
printf("*%s\n", node->text);
return;
}
printf("%s\n", node->text);
char answer;
if (scanf(" %c", &answer) != 1) {
return;
}
if (answer == 'a') {
node = node->yes;
} else if (answer == 'n') {
node = node->no;
} else {
return;
}
}
}
// Освобождает выделенную память для дерева
void free_tree(Node *node) {
if (node) {
free_tree(node->yes);
free_tree(node->no);
free(node);
}
}
int main() {
char lines[100][MAX_LINE_LENGTH];
int line_count = 0;
// Считываем базу знаний построчно
while (fgets(lines[line_count], sizeof(lines[line_count]), stdin)) {
lines[line_count][strcspn(lines[line_count], "\n")] = 0; // Удаляем символ новой строки
if (lines[line_count][0] == '\0') { // Пустая строка завершает ввод базы знаний
break;
}
line_count++;
}
// Создаем дерево из базы знаний
int index = 0;
Node *root = parse_knowledge_base(lines, &index, line_count);
if (!root) {
return 1;
}
int product_count = count_products(root);
printf("Pozna %d druhov ovocia a zeleniny.\n", product_count);
// Запуск опроса пользователя
run_expert_system(root);
// Очистка памяти
free_tree(root);
return 0;
}