Finished commenting

This commit is contained in:
Anton Dolozin 2025-11-11 13:25:04 +01:00
parent ecdf8f38f8
commit b9974c6fc8

View File

@ -5,54 +5,80 @@
#include <stdbool.h>
#define SIZE 100
// Struktura na vytvorenie bynarneho stromu. Ma ulozenu hodnotu, pole charov, a referencii na l'aveho a praveho syna.
// V danom pripade je to plny bynarny strom, cize kazdy uzol bude mat dva alebo nullu synov
struct tree{
char value[SIZE];
/// Referencii v pamati
struct tree* left;
struct tree* right;
};
// Funkcia na uvolnenie bynarneho stromu. Je to recursivna implementacia, znamena, ze danu funkciu budeme volat vo vnuri seba na iny argument.
// Tato funkcia a vsetky ine recursivne funkcii v kontexte binarneho stromu operuju na baze postorder, cize budeme navstevat' na zaciatku podstromy a potom sam uzol
// Pre-order operuje tak, ze na zaciatku ide sam uzol a potom podstormy, a inorder - jeden podstrom, uzol iny podstrom
void destroy_tree(struct tree* tree){
/// V danom pripade, uvolnime l'avy podstrom, potom pravy podstrom a koren
if(tree->left){
// dojde do uzla bez synov, ho uvolnime a uvolnime vsetky ine uzly v podstrome
destroy_tree(tree->left);
}
if(tree->right){
// Tak tiez, prechadzame do uzla bez potomkov pravom podstrome
destroy_tree(tree->right);
}
//Vlasne uvolnime v pamati uzol
free(tree);
}
// Funkcia pre nacitanie stromu
struct tree* read_tree(){
///Buffer pre nacitanie
char buffer[SIZE];
/// Inticializacia vsetkych bytov na 0
memset(buffer,0,SIZE);
/// vlasne nacitanie jedneho riadku. Ako argumenty mame kam, pocet bytov a odkial'
char* r = fgets(buffer,SIZE,stdin);
// Vratime NULL ak nepodarilo nacitat'
if(!r) {
return NULL;
}
/// Odmietnime newline a premenime ho na null terminator - koniec riadku
buffer[strcspn(buffer, "\n")] = '\0';
/// Allokujeme v pamati jeden uzol. Calloc inticializuje vsetky byty na 0.
struct tree* node = calloc(1,sizeof(struct tree));
///Prekopirujeme naticany riadok v pamati do hodnoty uzla
memcpy(node->value,buffer,SIZE);
// Ak ma riadok *, tak to znamena ze to odpoved - listovy uzol a nebude mat' synov
if(buffer[0] == '*'){
// Syny su NULL
node->left = NULL;
node->right = NULL;
// vratime uzol
return node;
}
// Pokracujeme v nacitani, ak nie je to odpoved
node->left = read_tree();
node->right = read_tree();
/// Ak sconcime nacitanie, tak vratime koren
return node;
}
/// Pomocna funkcia na vyhl'adovanie nepravidelneho vstupu
bool find_the_incorrect(struct tree* tree) {
if (tree == NULL)
return false;
if
if /// Ak strcspn, funkcia ze najdi kde prvy krat tento pattern, vrati index, tak to znamena, ze tieto chary su v slove
// Ak symboly nie su v ret'azce, tak to vratilo by dlzku retazca
// Overenie pre nekoretne otazky: nemozu mat' * na zacatku
((strcspn(tree->value, "*") != strlen(tree->value) &&
strcspn(tree->value, "?") != strlen(tree->value)) ) {
// vratime true ak to je nekorektna otakzka
return true;
}
// prechadzame po vsetkemu stromu a vyhladavame recursivne prvky
// || - logicky operator OR - alebo
// Na zacatku pozrieme do l'aveho podstromu a potom do praveho
return find_the_incorrect(tree->left) || find_the_incorrect(tree->right);
}
void print_tree(struct tree* tree,int offset){
@ -65,44 +91,70 @@ void print_tree(struct tree* tree,int offset){
print_tree(tree->right,offset +3);
}
}
// Funkcia pre pocitanie listov binarneho stromu. Recursivna implementacia.
// List - je to uzol bez synov. Musi ich byt na 1 viac ako vnutornych uzlov, tych, co maju potomkov.
int count_leaves(struct tree* tree){
// Na zacatku pocet je null
int count = 0;
if(tree == NULL){
// Ak koren je NULL, tak to znamena ze strom je NULL a vratime pocet, cize 0
return count;
}
// Inak, ak je len jeden koren - vratime 1
if(tree->left == NULL && tree->right == NULL && tree){
return count +1;
}
// Inak prechadzame strom, na zaciatku volame funkciu na l'avy podstom a potom a pravy
else{
return count + count_leaves(tree->left) + count_leaves(tree->right);
}
}
/// Tak tiez, recursivna funkcia na pocet ne lisov
int count_non_leaves(struct tree* tree){
// Ak je uzol NULL alebo ne ma synov, tak vratime 0
if(tree == NULL || ( tree->left== NULL && tree->right ==NULL)){
return 0;
}
// Inak, vratime 1(sam uzol) + pocet ne uzlov v oboch podstromoch
return 1 + count_non_leaves(tree->left) +count_non_leaves(tree->right);
}
int main(void){
bool whitespace = false;
/// Main pre systemem
int main(void){
/// Overenie na medzeru po databaze
bool whitespace = false;
/// Vytvorime strom
struct tree* tree = read_tree();
/// Buffer pre prazdny riadok
char line[SIZE];
/// Spocitame listy a vnutorny uzly
int numOfLeaves = count_leaves(tree);
int numOfNonLeaves = count_non_leaves(tree);
/// Pole pre odpoved' od pouzivatel'a
char answer[SIZE];
// Hl'adame prazdny riadok pomcou while
while (fgets(line, sizeof(line), stdin)) {
// Pokial' mame co nacitovat' po databazu pre strom
/// Musime odmietnut newline aby spravne porovnat'
line[strcspn(line, "\n")] = '\0';
/// Ak prvy prvok bufferu bude null terminator, tak to bude prazdny riadok
if (line[0] == '\0') {
// Check je splneny
whitespace = true;
// Vyjdeme z cyklusu
break;
}
}
/// Prechadzame podstromy a hl'adame nespravne vstupy
bool found = find_the_incorrect(tree);
printf("Expert z bufetu to vie.\n");
/// Ak nepodarilo nacitst alebo nie je tam medzera alebo nasli sme nespravny vstup, vypiseme hlasku a sconcime program.
// To plati ak zaciatok bazy nie je spravny
/// Ak stringy su rovnake, atak strcmp vrati 0
if(!tree || !whitespace || found || strcmp(tree->value, "Rastie to nad zemou alebo pod zemou ?") == 0){
printf("Chybna databaza\n");
return 0;
@ -110,17 +162,23 @@ int main(void){
printf("Pozna %d druhov ovocia a zeleniny.\n", numOfLeaves);
printf("Odpovedajte 'a' pre prvu moznost alebo 'n' pre druhu moznost.");
/// Pokial uzol nie je null, pokracuejme v systeme
while(tree){
/// Vypis otazky
printf("\n%s", tree->value);
/// Nacitame vstup od pouzivatel'a
fgets(answer, sizeof(answer), stdin);
// Odmietnime newline pre porovnanie
answer[strcspn(answer, "\n")] = '\0';
// Ak je to prazdny ridok, tak to znamena ze vstup uz ne mame
if(answer[0] == '\0'){
printf("\nKoniec vstupu\n");
return 0;
}
/// Ak je to nie, tak prejdeme na pravy podstrom
if(strcmp(answer, "n") == 0){
tree = tree->right;
/// Ak hodnotra daneho uzla je odpoved, ju vypiseme a skoncime prgram
if(tree->value[0] == '*'){
printf("\n%s\n", tree->value);
printf("Koniec\n");
@ -128,6 +186,7 @@ int main(void){
}
}
// Analogicky pre ano
else if(strcmp(answer, "a") == 0){
tree = tree->left;
if(tree->value[0] == '*'){
@ -138,10 +197,12 @@ int main(void){
}
}
/// Inak, fakticke skoncime program
else{
printf("\nNerozumiem\n");
return 0;
}
}
/// Uvolnime v pamati strom'""
destroy_tree(tree);
return 0;}