usaa24/cv7/program.c

132 lines
6.1 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_SIZE 256 // Максимальный размер строки для хранения текста узла
// Структура для представления узла бинарного дерева
struct node {
char value[MAX_SIZE]; // Значение узла (вопрос или конечный ответ)
struct node *left; // Левый дочерний узел
struct node *right; // Правый дочерний узел
int id; // Уникальный идентификатор узла
};
// Функция для чтения дерева из ввода и создания бинарного дерева
struct node* read_tree(int *id_counter) {
char line[MAX_SIZE];
// Считываем строку из ввода. Если строка пуста или конец файла, возвращаем NULL.
if (fgets(line, MAX_SIZE, stdin) == NULL || line[0] == '\n') {
return NULL;
}
// Выделяем память для нового узла
struct node *new_node = (struct node*)malloc(sizeof(struct node));
if (new_node == NULL) {
return NULL; // Проверка на успешное выделение памяти
}
// Копируем строку в значение узла и устанавливаем уникальный идентификатор
strcpy(new_node->value, line);
new_node->id = (*id_counter)++;
// Если строка начинается не с '*', узел не является листом, и мы продолжаем читать дочерние узлы
if (line[0] != '*') {
new_node->left = read_tree(id_counter); // Читаем левое поддерево
new_node->right = read_tree(id_counter); // Читаем правое поддерево
}
return new_node; // Возвращаем указатель на созданный узел
}
// Функция для освобождения памяти, занятой деревом
void free_tree(struct node *root) {
if (root == NULL) return; // Если узел пуст, ничего не делаем
free_tree(root->left); // Рекурсивно освобождаем левое поддерево
free_tree(root->right); // Рекурсивно освобождаем правое поддерево
free(root); // Освобождаем текущий узел
}
// Функция для подсчета количества конечных элементов (листов) в дереве
int count_items(struct node *root) {
if (root == NULL) return 0; // Если узел пуст, возвращаем 0
if (root->left == NULL && root->right == NULL) return 1; // Если узел - лист, возвращаем 1
return count_items(root->left) + count_items(root->right); // Рекурсивно считаем листья в поддеревьях
}
// Функция для запуска системы "Эксперт из буфета"
void start_system(struct node *current_node) {
if (current_node == NULL) return; // Если дерево пустое, ничего не делаем
int blank_lines = 0; // Счетчик пустых строк для обработки окончания ввода
int is_first_prompt = 1; // Флаг для вывода инструкции только один раз
while (current_node != NULL) {
// Если узел является листом, выводим ответ и завершаем
if (current_node->left == NULL && current_node->right == NULL) {
printf("%s", current_node->value);
printf("Koniec\n");
return;
}
// Выводим инструкцию для пользователя при первом запросе
if (is_first_prompt) {
printf("Odpovedajte 'a' pre prvu moznost alebo 'n' pre druhu moznost.\n");
is_first_prompt = 0;
}
printf("%s", current_node->value); // Выводим текущий вопрос
char response; // Переменная для хранения ответа пользователя
int result = scanf(" %c", &response); // Считываем ввод
// Проверяем окончание ввода или две пустые строки подряд
if (result == EOF || (response == '\n' && ++blank_lines >= 2)) {
printf("Koniec vstupu\n");
return;
}
// Если ответ 'a', переходим в левый дочерний узел
if (response == 'a') {
blank_lines = 0;
current_node = current_node->left;
}
// Если ответ 'n', переходим в правый дочерний узел
else if (response == 'n') {
blank_lines = 0;
current_node = current_node->right;
}
// В случае некорректного ответа выводим сообщение об ошибке и завершаем
else {
printf("Nerozumiem\n");
return;
}
}
}
int main() {
int counter = 0; // Счетчик для уникальных идентификаторов узлов
struct node *root = read_tree(&counter); // Читаем дерево из ввода
printf("Expert z bufetu to vie.\n");
// Если дерево не удалось загрузить, выводим сообщение об ошибке
if (root == NULL) {
printf("Chybna databaza\n");
return 0;
}
// Подсчитываем количество конечных элементов (видов фруктов и овощей)
int item_count = count_items(root);
printf("Pozna %d druhov ovocia a zeleniny.\n", item_count);
// Запускаем систему
start_system(root);
// Освобождаем память, занятую деревом
free_tree(root);
return 0;
}