Pijanističko takmičenje¶
Autor zadatka: Rade Radišić <radisic.rade@uns.ac.rs>
Pijanista takmičar predstavljen je preko strukture, pomoću sledećih polja:
ime (string, do 20 karaktera)
prezime (string, do 30 karaktera)
broj osvojenih poena (neoznačena, celobrojna vrednost)
Učitati takmičare iz ulazne datoteke u binarno stablo pretrage. Koristiti broj osvojenih poena kao ključno obeležje. U izlaznu datoteku ispisati ime i prezime takmičara, zajedno sa nagradom koju je osvojio sortirano, u opadajućem redosledu. Pravila za nagrađivanje su sledeća:
Ukoliko takmičar ima od 91-100 osvojenih poena, osvojio je prvu nagradu
Ukoliko takmičar ima od 81-90 osvojenih poena, osvojio je drugu nagradu
Ukoliko takmičar ima 80 i niže poena, osvojio je pohvalu
Kako više takmičara može osvojiti prvu i drugu nagradu, one se dodatno rangiraju u odnosu na osvojeni broj poena.
Na primer, u slučaju da postoje dva takmičara, gde je jedan osvojio 99, a drugi 94 poena, prvi je osvojio prvu prvu, a drugi je osvojio prvu drugu nagradu.
U slučaju da je takmičar osvojio prvu ili drugu nagradu, koristiti format ispisa "%-10s %-12s %d. %d."
, dok u slučaju osvojene pohvale, koristiti "%-10s %-12s pohvala"
.
Pogledati primer izlazne datoteke za detaljnije objašnjenje.
U slučaju nedovoljnog ili suvišnog broja argumenata, izaći iz programa sa kodom greške
1
(EXIT_FAILURE
)U slučaju da nije moguće dinamički zauzeti memoriju, izaći iz programa sa kodom greške
2
U slučaju neuspešnog otvaranja ulazne datoteke, izaći iz programa sa kodom greške
3
U slučaju neuspešnog otvaranja izlazne datoteke, izaći iz programa sa kodom greške
4
Primer ulaznog fajla takmicari.txt
Andja Stankic 97
Aleksandra Novak 89
Ljubomir Kovacevic 99
Pedja Maric 78
Radmila Loncar 100
Miljana Jerkovic 85
Mileva Pavlovic 93
Miljana Zivkovic 95
Josif Stojanovic 86
Mihajlo Dragovic 72
Primer poziva programa:
./program takmicari.txt rezultati.txt
Primer izlazne datoteke rezultati.txt
:
Radmila Loncar 1. 1.
Ljubomir Kovacevic 1. 2.
Andja Stankic 1. 3.
Miljana Zivkovic 1. 4.
Mileva Pavlovic 1. 5.
Aleksandra Novak 2. 1.
Josif Stojanovic 2. 2.
Miljana Jerkovic 2. 3.
Pedja Maric pohvala
Mihajlo Dragovic pohvala
Primer rešenja¶
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4
5#define MAX_IME 21
6#define MAX_PREZIME 31
7
8typedef struct takmicar_st {
9 char ime[MAX_IME];
10 char prezime[MAX_PREZIME];
11 unsigned broj_ostvarenih_poena;
12 struct takmicar_st *levi;
13 struct takmicar_st *desni;
14} TAKMICAR;
15
16FILE *safe_fopen(char *, char *, int);
17void ucitaj_takmicare(FILE *, TAKMICAR **);
18int ispisi_rezultate(FILE *, TAKMICAR *, int *);
19
20void inicijalizacija(TAKMICAR **);
21TAKMICAR *napravi_cvor(char *, char *, unsigned);
22void dodaj_u_stablo(TAKMICAR **, TAKMICAR *);
23void obrisi_stablo(TAKMICAR **);
24
25int main(int argc, char **argv) {
26 TAKMICAR *koren;
27
28 if(argc != 3) {
29 printf("Primer poziva programa: %s takmicari.txt rezultati.txt\n", argv[0]);
30 return EXIT_FAILURE;
31 }
32
33 inicijalizacija(&koren);
34
35 FILE *ulazna = safe_fopen(argv[1], "r", 3);
36 ucitaj_takmicare(ulazna, &koren);
37 fclose(ulazna);
38
39 FILE *izlazna = safe_fopen(argv[2], "w", 4);
40 int redni_broj = 0; // Koristi nam da pratimo koje mesto u okviru nagrade je osvojio takmicar (prenosi se po referenci)
41
42 // Mesto nam je potrebno samo dok prolazimo kroz stablo u rekurzivnim pozivima, necemo uzimati povratnu vrednost u main funkciji
43 // Kada imamo takvu situaciju, odnosno pozivamo funkciju ciju povratnu vrednost necemo koristiti,
44 // u programskom jeziku C je dobra praksa je njen rezultat cast-ovati u void
45 (void) ispisi_rezultate(izlazna, koren, &redni_broj);
46
47 fclose(izlazna);
48
49 obrisi_stablo(&koren);
50
51 return EXIT_SUCCESS;
52}
53
54FILE *safe_fopen(char *naziv, char *rezim, int kod_greske) {
55 FILE *fp = fopen(naziv, rezim);
56
57 if(fp == NULL) {
58 printf("Datoteka %s nije uspesno otvorena!\n", naziv);
59 exit(kod_greske);
60 }
61
62 return fp;
63}
64
65void ucitaj_takmicare(FILE *ulazna, TAKMICAR **pkoren) {
66 char tmp_ime[MAX_IME];
67 char tmp_prezime[MAX_PREZIME];
68 unsigned tmp_broj_ostvarenih_poena;
69
70 while(fscanf(ulazna, "%s %s %u", tmp_ime, tmp_prezime, &tmp_broj_ostvarenih_poena) != EOF) {
71 TAKMICAR *novi = napravi_cvor(tmp_ime, tmp_prezime, tmp_broj_ostvarenih_poena);
72 dodaj_u_stablo(pkoren, novi);
73 }
74}
75
76int ispisi_rezultate(FILE *izlazna, TAKMICAR *koren, int *predni_broj) {
77 int mesto = 0;
78
79 if(koren != NULL) {
80 int mesto_levi = ispisi_rezultate(izlazna, koren->desni, predni_broj);
81 mesto = mesto_levi; // mesto je uvek 0, tako da je bitno samo sta mesto_levi ima u sebi (moze biti 0 ili neki veci broj)
82
83 if(koren->broj_ostvarenih_poena >= 91 && koren->broj_ostvarenih_poena <= 100) {
84 mesto = 1;
85 } else if(koren->broj_ostvarenih_poena >= 81 && koren->broj_ostvarenih_poena <= 90) {
86 if(mesto == 1) {
87 *predni_broj = 0; // reset rednog broja, jer smo izbrojali prve i prelazimo na druge nagrade
88 }
89 mesto = 2;
90 } else {
91 mesto = 3; // pohvala (vrednost rednog broja nebitna)
92 }
93
94 switch(mesto) {
95 case 1:
96 case 2:
97 (*predni_broj)++;
98 fprintf(izlazna, "%-10s %-12s %d. %d.\n", koren->ime, koren->prezime, mesto, *predni_broj);
99 break;
100 case 3:
101 fprintf(izlazna, "%-10s %-12s pohvala\n", koren->ime, koren->prezime);
102 break;
103 }
104
105 int mesto_desni = ispisi_rezultate(izlazna, koren->levi, predni_broj);
106 if(mesto_desni > mesto) {
107 mesto = mesto_desni;
108 }
109 }
110
111 return mesto;
112}
113
114void inicijalizacija(TAKMICAR **pkoren) {
115 *pkoren = NULL;
116}
117
118TAKMICAR *napravi_cvor(char *ime, char *prezime, unsigned broj_ostvarenih_poena) {
119 TAKMICAR *novi = (TAKMICAR *)malloc(sizeof(TAKMICAR));
120
121 if(novi == NULL) {
122 printf("Greska prilikom zauzimanja memorije!\n");
123 exit(2);
124 }
125
126 strcpy(novi->ime, ime);
127 strcpy(novi->prezime, prezime);
128 novi->broj_ostvarenih_poena = broj_ostvarenih_poena;
129 novi->levi = NULL;
130 novi->desni = NULL;
131
132 return novi;
133}
134
135void dodaj_u_stablo(TAKMICAR **pkoren, TAKMICAR *novi) {
136 if(*pkoren == NULL) {
137 *pkoren = novi;
138 } else {
139 if((*pkoren)->broj_ostvarenih_poena > novi->broj_ostvarenih_poena) {
140 dodaj_u_stablo(&(*pkoren)->levi, novi);
141 } else {
142 dodaj_u_stablo(&(*pkoren)->desni, novi);
143 }
144 }
145}
146
147void obrisi_stablo(TAKMICAR **pkoren) {
148 if(*pkoren != NULL) {
149 obrisi_stablo(&(*pkoren)->levi);
150 obrisi_stablo(&(*pkoren)->desni);
151 free(*pkoren);
152 *pkoren = NULL;
153 }
154}
155