Bot za tehničku podršku
Napisati program koji simulira jednostavnog bota za tehničku podršku. Bot treba da postavlja da/ne pitanja korisniku i na osnovu odgovora donosi odluke o daljim pitanjima ili rešenju problema.
Pitanja i odluke treba da budu definisane u obliku binarnog stabla, gde svaki čvor predstavlja pitanje, a grane predstavljaju odgovore da ili ne. Listovi stabla predstavljaju konačne odgovore ili rešenja problema.
Ulaz
Iz fajla stablo_odluke.txt se učitava opis binarnog stabla u prefiksnoj notaciji. Svaka linija maksimalne dužine
- Ako je čvor pitanje, linija počinje sa
Q:praćeno tekstom pitanja. - Ako je čvor rešenje, linija počinje sa
A:praćeno tekstom rešenja.
Bot postavlja pitanja i sa standardnog ulaza prima odgovore da ili ne (tekst maksimalne dužine
Izlaz
Bot treba da ispisuje pitanja na standardni izlaz i čeka odgovore korisnika. Ukoliko korisnik unese nešto drugo osim da ili ne, bot obaveštava korisnika o pravilu korišćenja tako što ispisuje Molim vas unesite 'da' ili 'ne'. i ponovo postavlja isto pitanje. Na kraju, kada dođe do rešenja, bot treba da ispiše rešenje.
Primer
stablo_odluke.txt
Q: Da li je računar uključen?
A: Uključite računar.
Q: Da li je ekran crn?
Q: Da li je računar spor?
A: Kontaktirajte tehničku podršku.
A: Restartujte računar.
A: Proverite kablove i priključke.
stdin
da
ne
da
stdout
Da li je računar uključen?
Da li je ekran crn?
Da li je računar spor?
Restartujte računar.
Objašnjenje
Pregled toka programa:
Da li je računar uključen?
da
Da li je ekran crn?
ne
Da li je računar spor?
da
Restartujte računar.
Primer
stablo_odluke.txt
Q: Da li je internet veza aktivna?
A: Proverite ruter.
Q: Da li su svi kablovi pravilno povezani?
A: Povežite kablove ispravno.
A: Restartujte ruter.
stdin
neee
ne
stdout
Da li je internet veza aktivna?
Molimo unesite 'da' ili 'ne'.
Da li je internet veza aktivna?
Proverite ruter.
Objašnjenje
Pregled toka programa:
Da li je internet veza aktivna?
neee
Molimo unesite 'da' ili 'ne'.
Da li je internet veza aktivna?
ne
Proverite ruter.
Primer
Rešenje
stablo_genericko.h
#ifndef __STABLO_GENERICKO_H__
#define __STABLO_GENERICKO_H__
#include <stdio.h>
#include <stdlib.h>
#include "stablo_podatak.h"
typedef enum
{
OK,
NEDOVOLJNO_MEMORIJE,
NEMA_ELEMENATA
} status;
typedef struct cvor_stabla
{
Data podatak;
struct cvor_stabla *levo;
struct cvor_stabla *desno;
} cvor_stabla;
typedef cvor_stabla *Stablo;
status inicijalizuj_stablo(Stablo *s);
status dodaj_u_stablo(Stablo *s, const Data *podatak,
int (*poredi)(const Data *, const Data *));
status pronadji(Stablo s, const Data *trazeno, Data **nadjeno,
int (*poredi)(const Data *, const Data *));
int broj_elemenata(Stablo s);
void ispisi_stablo(Stablo s);
void obrisi_stablo(Stablo *s);
#endifstablo_podatak.h
#ifndef __STABLO_PODATAK_H
#define __STABLO_PODATAK_H
typedef enum {
QUESTION,
ANSWER
} DataType;
typedef struct {
DataType type;
char *text;
} Data;
Data napravi_pitanje(const char* pitanje);
Data napravi_odgovor(const char* odgovor);
void dodeli(Data *dest, const Data *str);
void ispisi_podatak(const Data* data);
#endifmain.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "stablo_podatak.h"
#include "stablo_genericko.h"
#define FILENAME "stablo_odluke.txt"
#define MAX_LINE_SIZE 256
#define MAX_RESPONSE_SIZE 16
static status ucitaj_stablo(FILE *f, Stablo *bot)
{
char type;
fscanf(f, "%c%*c%*c", &type);
char line[MAX_LINE_SIZE];
if (type == 'Q') {
fgets(line, MAX_LINE_SIZE, f);
Data pitanje = napravi_pitanje(line);
status s = dodaj_u_stablo(bot, &pitanje, NULL);
if (s != OK) {
return s;
}
s = ucitaj_stablo(f, &((*bot)->levo));
if (s != OK) {
return s;
}
s = ucitaj_stablo(f, &((*bot)->desno));
if (s != OK) {
return s;
}
} else if (type == 'A') {
fgets(line, MAX_LINE_SIZE, f);
Data odgovor = napravi_odgovor(line);
status s = dodaj_u_stablo(bot, &odgovor, NULL);
if (s != OK) {
return s;
}
} else {
return NEMA_ELEMENATA;
}
return OK;
}
static void interaktivni_rezim(Stablo bot)
{
char odgovor[MAX_RESPONSE_SIZE];
Stablo trenutni = bot;
while (trenutni != NULL) {
ispisi_podatak(&(trenutni->podatak));
if (trenutni->podatak.type == ANSWER) {
break;
}
scanf("%s", odgovor);
if (strcmp(odgovor, "da") == 0) {
trenutni = trenutni->desno;
} else if (strcmp(odgovor, "ne") == 0) {
trenutni = trenutni->levo;
} else {
printf("Molimo unesite 'da' ili 'ne'.\n");
}
}
}
int main(void)
{
Stablo bot;
status s = inicijalizuj_stablo(&bot);
if (s != OK) {
exit(EXIT_FAILURE);
}
FILE* f = fopen(FILENAME, "r");
if (f == NULL) {
obrisi_stablo(&bot);
exit(EXIT_FAILURE);
}
s = ucitaj_stablo(f, &bot);
if (s != OK) {
fclose(f);
obrisi_stablo(&bot);
exit(EXIT_FAILURE);
}
interaktivni_rezim(bot);
fclose(f);
obrisi_stablo(&bot);
exit(EXIT_SUCCESS);
}stablo_genericko.c
#include "stablo_genericko.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
cvor_stabla *novi_cvor_stabla(const Data *podatak)
{
cvor_stabla *novi = malloc(sizeof(cvor_stabla));
if (novi == NULL)
return NULL;
dodeli(&(novi->podatak), podatak);
novi->levo = NULL;
novi->desno = NULL;
return novi;
}
status inicijalizuj_stablo(Stablo* s)
{
*s = NULL;
return OK;
}
status dodaj_u_stablo(Stablo* s, const Data* podatak,
int (*poredi)(const Data*, const Data*))
{
cvor_stabla* tmp;
cvor_stabla* novi = novi_cvor_stabla(podatak);
if (novi == NULL)
return NEDOVOLJNO_MEMORIJE;
novi->levo = NULL;
novi->desno = NULL;
if (*s == NULL) {
*s = novi;
return OK;
}
tmp = *s;
while (1) {
if (poredi(podatak, &(tmp->podatak)) <= 0) {
if (tmp->levo == NULL) {
tmp->levo = novi;
return OK;
}
else
tmp = tmp->levo;
}
else {
if (tmp->desno == NULL) {
tmp->desno = novi;
return OK;
}
else
tmp = tmp->desno;
}
}
return OK;
}
status pronadji(Stablo s, const Data* trazeno, Data** nadjeno,
int (*poredi)(const Data*, const Data*))
{
if (s == NULL)
return NEMA_ELEMENATA;
if (poredi(trazeno, &(s->podatak)) == 0) {
*nadjeno = &(s->podatak);
return OK;
}
if (poredi(trazeno, &(s->podatak)) < 0)
return pronadji(s->levo, trazeno, nadjeno, poredi);
return pronadji(s->desno, trazeno, nadjeno, poredi);
}
int broj_elemenata(Stablo s)
{
return s == NULL ?
0 :
broj_elemenata(s->levo)+1+broj_elemenata(s->desno);
}
void ispisi_stablo(Stablo s)
{
if (s != NULL) {
ispisi_stablo(s->levo);
ispisi_podatak(&(s->podatak));
ispisi_stablo(s->desno);
}
}
void obrisi_stablo(Stablo* s)
{
if (*s != NULL) {
obrisi_stablo(&((*s)->levo));
obrisi_stablo(&((*s)->desno));
free(*s);
*s = NULL;
}
}stablo_podatak.c
#include <stdio.h>
#include <string.h>
#include "stablo_podatak.h"
Data napravi_pitanje(const char* pitanje)
{
Data data;
data.type = QUESTION;
data.text = strdup(pitanje);
return data;
}
Data napravi_odgovor(const char* odgovor)
{
Data data;
data.type = ANSWER;
data.text = strdup(odgovor);
return data;
}
void dodeli(Data *dest, const Data *src)
{
dest->type = src->type;
dest->text = strdup(src->text);
}
void ispisi_podatak(const Data* data)
{
printf("%s", data->text);
}