Škola jezika

Autor zadatka: Aleksandar Vasiljević <alexva02@uns.ac.rs>

Iz zadate ulazne datoteke učitati podatke u binarno stablo, gde struktura skola_jezika_st sadrži sledeća polja:

  • naziv (jedna reč, maksimalno 30 karaktera),

  • grad (jedna reč, maksimalno 2 karaktera),

  • prvi strani jezik (jedna reč, maksimalno 15 karaktera),

  • drugi strani jezik (jedna reč, maksimalno 15 karaktera),

  • najviši nivo koji se može postići (jedna reč, maksimalno 8 karaktera),

  • osnovna cena kursa (realan broj),

  • broj polaznika po grupi (pozitivan ceo broj) i

  • cena sa popustom (realan broj).

Struktura skola_jezika dodatno sadrži i polja potrebna za pravilno formiranje binarnog stabla. Binarno stablo urediti po ključu osnovna cena kurs u opadajućem redosledu. Iz formiranog binarnog stabla upisati podatke u zadatu izlaznu datoteku, u sledećem rasporedu polja strukture skola_jezika_st:

  • naziv,

  • grad,

  • broj polaznika po grupi,

  • cena sa popustom (zaokružena na 3 decimale),

  • prvi strani jezik i

  • drugi strani jezik.

Cena sa popustom se izračunava na sledeći način:

  • ako je broj polaznika veći od 3 a manji od 7, popust iznosi 5%

  • Ukoliko ima 7 i/ili više od 7 a manje od 10 polaznika, cena se umanjuje za 10%

  • U slučaju da je broj polaznika 10 i/ili viši od 10, tada se osnovna cena kursa smanjuje za popust od 15%

U izlaznu datoteku potrebno je ispisati još i sledeće informacije:

  1. školu stranih jezika u kojoj se nemački uči kao drugi strani jezik a čija je cena sa popustom najniža i

  2. za odabranu školu stranih jezika (bira se na osnovu parametra odabranaSkola koji se prosleđuje kao argument komandne linije) ispisati koliko ima polaznika koji kao prvi strani jezik uče francuski a čija je cena kursa najviša

Primer poziva programa:

./zad Academy skole.txt izvestaj.txt

sa zadatim parametrima odabranaSkola = "Academy" i zadatim ulazom u datoteci skole.txt:

Academy NS engleski nemacki srednji 14800.0 7
Lingua BG nemacki francuski napredni 21099.0 10
Skill KG francuski engleski osnovni 8050.0 3
Berlitz NI engleski francuski napredni 19999.0 9
Lingua KG francuski nemacki osnovni 9020.0 2
Manhattan NS nemacki engleski napredni 20650.0 4
Academy NI francuski engleski srednji 13450.0 8
Skill BG engleski nemacki napredni 20199.0 6
Manhattan KG francuski nemacki osnovni 8345.0 12
Berlitz NS engleski francuski srednji 14200.0 5

očekivanim izlazom u datoteci izvestaj.txt:

Lingua BG 10 17934.150 nemacki francuski
Manhattan NS 4 19617.500 nemacki engleski
Skill BG 6 19189.051 engleski nemacki
Berlitz NI 9 17999.100 engleski francuski
Academy NS 7 13320.000 engleski nemacki
Berlitz NS 5 13490.000 engleski francuski
Academy NI 8 12105.000 francuski engleski
Lingua KG 2 9020.000 francuski nemacki
Manhattan KG 12 7093.250 francuski nemacki
Skill KG 3 8050.000 francuski engleski


Skola jezika u kojoj se nemacki uci kao drugi strani jezik a cija je cena sa popustom najniza: Manhattan KG 7093.250

Broj polaznika skole Academy koji kao prvi strani jezik uci francuski a cija je osnovna cena kursa (13450.000): 8.

U slučaju da se program pozove sa prosleđenim parametrom odabranaSkola = "Akademija", očekivani izlaz u datoteci je:

Lingua BG 10 17934.150 nemacki francuski
Manhattan NS 4 19617.500 nemacki engleski
Skill BG 6 19189.051 engleski nemacki
Berlitz NI 9 17999.100 engleski francuski
Academy NS 7 13320.000 engleski nemacki
Berlitz NS 5 13490.000 engleski francuski
Academy NI 8 12105.000 francuski engleski
Lingua KG 2 9020.000 francuski nemacki
Manhattan KG 12 7093.250 francuski nemacki
Skill KG 3 8050.000 francuski engleski

Skola jezika u kojoj se nemacki uci kao drugi strani jezik a cija je cena sa popustom najniza:
Manhattan KG 7093.250

Nema trazene skole!

Primer rešenja

  1// primer poziva programa:
  2// ./zad Academy skole.txt izvestaj.txt
  3
  4#include<stdio.h>
  5#include<stdlib.h>
  6#include<string.h>
  7#include<math.h>
  8
  9#define NAZIV 30+1
 10#define GRAD 2+1
 11#define PRVI_JEZIK 15+1
 12#define DRUGI_JEZIK 15+1
 13#define NIVO 8+1
 14
 15typedef struct skola_jezika_st {
 16	char naziv[NAZIV];
 17	char grad[GRAD];
 18	char prviStraniJezik[PRVI_JEZIK];
 19	char drugiStraniJezik[DRUGI_JEZIK];
 20	char nivo[NIVO];
 21	float osnovnaCenaKursa;
 22	unsigned brojPolaznikaPoGrupi;
 23	float cenaSaPopustom;
 24	struct skola_jezika_st* levi;
 25	struct skola_jezika_st* desni;
 26}SKOLA;
 27
 28void inicijalizacija(SKOLA **koren) {
 29	*koren = NULL;
 30}
 31
 32void dodaj(SKOLA **koren, SKOLA *novi) {
 33	if(*koren == NULL) {
 34		*koren = novi;
 35	} else if(novi->osnovnaCenaKursa >= (*koren)->osnovnaCenaKursa) {
 36		dodaj(&((*koren)->levi),novi);
 37	} else {
 38		dodaj(&((*koren)->desni),novi);
 39	}
 40}
 41
 42SKOLA *napravi_cvor(char naziv[], char grad[], char prviStraniJezik[], char drugiStraniJezik[],
 43                    char nivo[], float osnovnaCenaKursa, unsigned brojPolaznikaPoGrupi) {
 44	SKOLA *novi = (SKOLA *)malloc(sizeof(SKOLA));
 45	if (novi == NULL) {
 46		printf("\tNema dovoljno memorije!\n");
 47		exit(4);
 48	}
 49
 50	strcpy(novi->naziv, naziv);
 51	strcpy(novi->grad, grad);
 52	strcpy(novi->prviStraniJezik, prviStraniJezik);
 53	strcpy(novi->drugiStraniJezik, drugiStraniJezik);
 54	strcpy(novi->nivo, nivo);
 55	novi->osnovnaCenaKursa = osnovnaCenaKursa;
 56	novi->brojPolaznikaPoGrupi = brojPolaznikaPoGrupi;
 57
 58	//konacno
 59	if(novi->brojPolaznikaPoGrupi > 3 && novi->brojPolaznikaPoGrupi < 7) { //5%
 60		novi->cenaSaPopustom = novi->osnovnaCenaKursa * 0.95;
 61	} else if(novi->brojPolaznikaPoGrupi >= 7 && novi->brojPolaznikaPoGrupi < 10) { //10%
 62		novi->cenaSaPopustom = novi->osnovnaCenaKursa * 0.9;
 63	} else if(novi->brojPolaznikaPoGrupi >= 10) {
 64		novi->cenaSaPopustom = novi->osnovnaCenaKursa * 0.85;
 65	} else {
 66		novi->cenaSaPopustom = novi->osnovnaCenaKursa;
 67	}
 68
 69	novi->levi = NULL;
 70	novi->desni = NULL;
 71
 72	return novi;
 73}
 74
 75void ucitaj(FILE *in, SKOLA **koren) {
 76	char naziv[NAZIV];
 77	char grad[GRAD];
 78	char prviStraniJezik[PRVI_JEZIK];
 79	char drugiStraniJezik[DRUGI_JEZIK];
 80	char nivo[NIVO];
 81	float osnovnaCenaKursa;
 82	unsigned brojPolaznikaPoGrupi;
 83
 84	while(fscanf(in, "%s %s %s %s %s %f %u", naziv, grad, prviStraniJezik, drugiStraniJezik,
 85                 nivo, &osnovnaCenaKursa, &brojPolaznikaPoGrupi) != EOF) {
 86		SKOLA *novi = napravi_cvor(naziv, grad, prviStraniJezik, drugiStraniJezik,
 87                                   nivo, osnovnaCenaKursa, brojPolaznikaPoGrupi);
 88		dodaj(koren, novi);
 89	}
 90}
 91
 92void ispisi_stablo(FILE *out, SKOLA *koren) {
 93	if(koren != NULL) {
 94		ispisi_stablo(out, koren->levi);
 95		fprintf(out, "%s %s %u %.3lf %s %s\n", koren->naziv, koren->grad, koren->brojPolaznikaPoGrupi,
 96                koren->cenaSaPopustom, koren->prviStraniJezik, koren->drugiStraniJezik);
 97		ispisi_stablo(out, koren->desni);
 98	}
 99}
100
101void obrisi_stablo(SKOLA **koren) {
102	if(*koren != NULL) {
103		obrisi_stablo(&((*koren)->levi));
104		obrisi_stablo(&((*koren)->desni));
105		free(*koren);
106		*koren = NULL;
107	}
108}
109
110FILE *safe_fopen(char *imeDatoteke, char *rezim) {
111    FILE *fp = fopen(imeDatoteke, rezim);
112    
113	if (fp == NULL) {
114        printf("Problem prilikom otvaranja %s datoteke!\n", imeDatoteke);
115        exit(33);
116    }
117	
118    return fp;
119}
120
121SKOLA *nemackiKaoDrugiJezik(FILE *izlazna, SKOLA *koren) {
122	if (koren == NULL) {
123		return NULL;
124	}
125
126	//samo skole u kojima se nemacki uci kao drugi strani jezik
127	SKOLA *skola = NULL;
128	if(strcmp(koren->drugiStraniJezik, "nemacki") == 0) {
129		skola = koren;
130	}
131
132	//obilazak levog podstabla
133	SKOLA *skolaL = nemackiKaoDrugiJezik(izlazna, koren->levi);
134	if(skolaL != NULL) {
135		if(skola == NULL || skolaL->cenaSaPopustom < skola->cenaSaPopustom) {
136			skola = skolaL;
137		}
138	}
139
140	//obilazak desnog podstabla
141	SKOLA *skolaD = nemackiKaoDrugiJezik(izlazna, koren->desni);
142	if(skolaD != NULL) {
143		if(skola == NULL || skolaD->cenaSaPopustom < skola->cenaSaPopustom) {
144			skola = skolaD;
145		}
146	}
147
148	return skola;
149}
150
151SKOLA *polazniciFrancuski(FILE *out, SKOLA *koren, char *odabranaSkola) {
152	if(koren == NULL) {
153		return NULL;
154	}
155
156	//samo skole u kojima se francuski uci kao prvi strani jezik
157	SKOLA *skola = NULL;
158	if(strcmp(koren->naziv, odabranaSkola) == 0 && strcmp(koren->prviStraniJezik, "francuski") == 0) {
159		skola = koren;
160	}
161
162	//obilazak levog podstabla
163	SKOLA *skolaL = polazniciFrancuski(out, koren->levi, odabranaSkola);
164	if(skolaL != NULL) {
165		if(skola == NULL || skolaL->osnovnaCenaKursa > skola->osnovnaCenaKursa) {
166			skola = skolaL;
167		}
168	}
169
170	//obilazak desnog podstabla
171	SKOLA *skolaD = polazniciFrancuski(out, koren->desni, odabranaSkola);
172	if(skolaD != NULL) {
173		if(skola == NULL || skolaD->osnovnaCenaKursa > skola->osnovnaCenaKursa) {
174			skola = skolaD;
175		}
176	}
177
178	return skola;
179}
180
181int main(int brArg, char *args[]) {
182	if(brArg != 4) {
183		printf("Pogresan unos argumenata!\n");
184		exit(3);
185	}
186
187	FILE *in = safe_fopen(args[2], "r");
188	FILE *out = safe_fopen(args[3], "w");
189
190	SKOLA *koren;
191
192	inicijalizacija(&koren);
193	ucitaj(in, &koren);
194	ispisi_stablo(out, koren);
195
196	SKOLA *skolaNemacki = nemackiKaoDrugiJezik(out, koren);	
197	fprintf(out, "\n\nSkola jezika u kojoj se nemacki uci kao drugi strani jezik a cija je cena sa popustom najniza: %s %s %.3lf",
198            skolaNemacki->naziv, skolaNemacki->grad, skolaNemacki->cenaSaPopustom);
199
200	SKOLA *skolaPolazniciFrancuski = polazniciFrancuski(out, koren, args[1]);
201
202	if(skolaPolazniciFrancuski)
203		fprintf(out, "\n\nBroj polaznika skole %s koji kao prvi strani jezik uci francuski a cija je osnovna cena kursa (%.3lf): %d.",
204                skolaPolazniciFrancuski->naziv, skolaPolazniciFrancuski->osnovnaCenaKursa, skolaPolazniciFrancuski->brojPolaznikaPoGrupi);
205	else
206		fprintf(out,"\n\nNema trazene skole!");
207
208	obrisi_stablo(&koren);
209
210	fclose(in);
211	fclose(out);
212
213	return 0;
214}