Glasanje za pesmu Evrovizije¶
Autor zadatka: Rade Radišić <radisic.rade@uns.ac.rs>
Napisati program koji izračunava ukupan broj glasova koji je određena država osvojila na Evroviziji. Iz ulazne datoteke učitati podatke u jednostruko spregnutu listu, gde se struktura sastoji iz sledećih polja:
naziv_drzave
(jedna reč, do 30 karaktera)glasovi_publike
(neoznačena, celobrojna vrednost)glasovi_zirija
(neoznačena, celobrojna vrednost)ukupno_glasova
(neoznačena, celobrojna vrednost)
Struktura sadrži dodatna polja za pravilno formiranje jednostruko spregnute liste.
Program prima ime ulazne i izlazne datoteke kao argumente komandne linije. Naziv države i glasovi se učitavaju u jednostruko spregnutu listu, dok se ukupan broj glasova izračunava kao suma glasova žirija i publike:
Prilikom učitavanja u listu, podaci se sortiraju na osnovu ukupnog broja osvojenih glasova.
Ispisati podatke iz jednostruko spregnute liste u izlaznu datoteku u sledećem formatu: %2d. %-9s %3u %3u %3u
, gde %d
predstavlja redni broj države,
dok su ostale vrednosti, redom, naziv države, ukupan broj glasova, glasovi publike i glasovi žirija.
Pronaći državu čija je razlika između glasova publike i glasova žirija najmanja:
Ispisati dobijeni rezultat nakon svih država u izlazni fajl u sledećem obliku:
Drzava ucesnica sa najmanjom razlikom izmedju glasova publike(<glasovi_publike>) i zirija(<glasovi_zirija>) je <naziv_države>.
U slučaju uspešnog izvršavanja programa, izaći sa status kodom 0
(EXIT_SUCCESS
).
Ukoliko program ne može da se izvrši do kraja usled sledećih nedostataka, izaći iz programa sa sledećim status kodovima:
U slučaju nedovoljnog ili suvišnog broj argumenata komandne linije, kao i nemogućnosti dinamičkog zauzeća memorije, izaći iz programa sa status kodom
1
(EXIT_FAILURE
)Ako program ne može da otvori ulazni fajl, izaći sa status kodom
2
Ako program ne može da otvori izlazni fajl, izaći sa status kodom
3
Primer poziva programa:
./prebrojavanje glasanje.txt rezulati.txt
Primer ulazne datoteke glasanje.txt
:
Srbija 225 87
Grcka 57 158
Italija 110 158
Svedska 180 258
Britanija 183 283
Spanija 228 231
Portugal 36 171
Ukrajina 439 192
Norveska 146 36
Moldavija 239 14
Primer izlazne datoteke rezultati.txt
:
1. Ukrajina 631 439 192
2. Britanija 466 183 283
3. Spanija 459 228 231
4. Svedska 438 180 258
5. Srbija 312 225 87
6. Italija 268 110 158
7. Moldavija 253 239 14
8. Grcka 215 57 158
9. Portugal 207 36 171
10. Norveska 182 146 36
Drzava ucesnica sa najmanjom razlikom izmedju glasova publike(228) i zirija(231) je Spanija.
Primer rešenja¶
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4
5#define MAX_NIZ 30
6
7#define MAX_SIROVINA 31
8
9typedef struct glas_st {
10 char naziv_drzave[MAX_SIROVINA];
11 unsigned glasovi_publike;
12 unsigned glasovi_zirija;
13 unsigned ukupno_glasova;
14 struct glas_st *sledeci;
15} GLAS;
16
17FILE *safe_fopen(char *naziv, char *rezim, int kod_greske);
18void ucitaj_glasove(FILE *ulazna, GLAS **pglava);
19void ispisi_konacne_rezultate(FILE *izlazna, GLAS *glava);
20
21void inicijalizacija(GLAS **pglava);
22GLAS *napravi_cvor(char *naziv_drzave, unsigned glasovi_publike, unsigned glasovi_zirija);
23void dodaj_sortirano(GLAS **pglava, GLAS *novi);
24GLAS *najmanja_razlika_izmedju_glasova(GLAS *);
25void obrisi_listu(GLAS **pglava);
26
27int main(int argc, char **argv) {
28 GLAS *glava;
29
30 if(argc != 3) {
31 printf("Primer poziva programa: %s glasanje.txt rezultati.txt\n", argv[0]);
32 exit(EXIT_FAILURE);
33 }
34
35 inicijalizacija(&glava);
36
37 FILE *ulazna = safe_fopen(argv[1], "r", 2);
38 ucitaj_glasove(ulazna, &glava);
39 fclose(ulazna);
40
41 FILE *izlazna = safe_fopen(argv[2], "w", 3);
42 ispisi_konacne_rezultate(izlazna, glava);
43
44 GLAS *najmanja_razlika_cvor = najmanja_razlika_izmedju_glasova(glava);
45 fprintf(izlazna,
46 "\nDrzava ucesnica sa najmanjom razlikom izmedju glasova publike(%u) i zirija(%u) je %s.\n",
47 najmanja_razlika_cvor->glasovi_publike,
48 najmanja_razlika_cvor->glasovi_zirija,
49 najmanja_razlika_cvor->naziv_drzave
50 );
51
52 fclose(izlazna);
53
54 obrisi_listu(&glava);
55
56 return EXIT_SUCCESS;
57}
58
59FILE *safe_fopen(char *naziv, char *rezim, int kod_greske) {
60 FILE *fp = fopen(naziv, rezim);
61
62 if(fp == NULL) {
63 printf("Datoteka %s nije uspesno otvorena!\n", naziv);
64 exit(kod_greske);
65 }
66
67 return fp;
68}
69
70void ucitaj_glasove(FILE *pulazna, GLAS **pglava) {
71 char tmp_naziv_drzave[MAX_SIROVINA];
72 unsigned tmp_glasovi_publike;
73 unsigned tmp_glasovi_zirija;
74
75 while(fscanf(pulazna, "%s %u %u",
76 tmp_naziv_drzave,
77 &tmp_glasovi_publike,
78 &tmp_glasovi_zirija) != EOF) {
79 GLAS *novi = napravi_cvor(tmp_naziv_drzave, tmp_glasovi_publike, tmp_glasovi_zirija);
80 dodaj_sortirano(pglava, novi);
81 }
82}
83
84void ispisi_konacne_rezultate(FILE *izlazna, GLAS *glava) {
85 GLAS *tekuci = glava;
86 int brojac = 1;
87
88 while(tekuci != NULL) {
89 fprintf(izlazna, "%2d. %-9s %3u %3u %3u\n", brojac, tekuci->naziv_drzave,
90 tekuci->ukupno_glasova, tekuci->glasovi_publike, tekuci->glasovi_zirija);
91
92 tekuci = tekuci->sledeci;
93 brojac++;
94 }
95}
96
97void inicijalizacija(GLAS **pglava) {
98 *pglava = NULL;
99}
100
101GLAS *napravi_cvor(char *naziv_drzave, unsigned glasovi_publike, unsigned glasovi_zirija) {
102 GLAS *novi = (GLAS *)malloc(sizeof(GLAS));
103
104 if(novi == NULL) {
105 printf("Greska prilikom zauzimanja memorije!\n");
106 exit(EXIT_FAILURE);
107 }
108
109 strcpy(novi->naziv_drzave, naziv_drzave);
110 novi->glasovi_publike = glasovi_publike;
111 novi->glasovi_zirija = glasovi_zirija;
112 novi->ukupno_glasova = glasovi_publike + glasovi_zirija;
113 novi->sledeci = NULL;
114
115 return novi;
116}
117
118void dodaj_sortirano(GLAS **pglava, GLAS *novi) {
119 if(*pglava == NULL || (*pglava)->ukupno_glasova < novi->ukupno_glasova) {
120 novi->sledeci = *pglava;
121 *pglava = novi;
122 } else {
123 GLAS *tekuci = *pglava;
124
125 while(tekuci->sledeci != NULL &&
126 novi->ukupno_glasova < tekuci->sledeci->ukupno_glasova) {
127 tekuci = tekuci->sledeci;
128 }
129
130 novi->sledeci = tekuci->sledeci;
131 tekuci->sledeci = novi;
132 }
133}
134
135GLAS *najmanja_razlika_izmedju_glasova(GLAS *glava) {
136 GLAS *tekuci = glava;
137 GLAS *najmanja_razlika_cvor = glava;
138 unsigned najmanja_razlika = abs(glava->glasovi_publike - glava->glasovi_zirija);
139 unsigned tekuci_razlika;
140
141 while(tekuci != NULL) {
142 tekuci_razlika = abs(tekuci->glasovi_publike - tekuci->glasovi_zirija);
143
144 if(tekuci_razlika < najmanja_razlika) {
145 najmanja_razlika = tekuci_razlika;
146 najmanja_razlika_cvor = tekuci;
147 }
148
149 tekuci = tekuci->sledeci;
150 }
151
152 return najmanja_razlika_cvor;
153}
154
155void obrisi_listu(GLAS **pglava) {
156 GLAS *tmp;
157
158 while(*pglava != NULL) {
159 tmp = *pglava;
160 *pglava = (*pglava)->sledeci;
161 tmp->sledeci = NULL;
162 free(tmp);
163 }
164}
165