* U datoteci pesme.txt nalaze se informacije o gledanosti pesama na Youtube-u u sledecem formatu: izvodjac - naslov, brojGledanja
* Napisati program koji ucitava informacije o pesmama i vrsi sortiranje pesama u zavisnosti od argumenata komandne linije:
* (a) nema opcija, sortiranje po broju gledanja.
* (b) -i, sortiranje po imenu izvodaca
* (c) -n, sortiranje po naslovu pesme
* Ne praviti nikakve pretpostavke o maksimalnoj duzini imena izvodjaca, naslova pesme, kao i ukupnom broju pesama.
Da li mi neko može dati savet kako da dinamički alociram ove niske, ime izvođača i naziv pesme? Postaviću dole kod, ali on funkcioniše samo ako se navedu ograničenja u dužini ta dva podatka :(
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// broj elemenata koje rezervisemo unapred
#define KORAK 10
// struktura Pesme
typedef struct {
char* izvodjac;
char* naslov;
int brGledanja;
} Pesme;
// pomocni karakter, globalna promenljiva u kojoj se cuva opcija koju je korisnik naveo
char kriterijum;
// samo prototip funkcije, telo se nalazi ispod glavne
int uporedi(const void*, const void*);
int main(int argc, char** argv) {
// brojaci
int i, j;
// pomocna promenljiva za iscitavanje niski iz datoteke
char s[50];
// ucitavanje podataka iz datoteke, i smestanje u niz struktura Pesme
FILE* ulaz;
if((ulaz = fopen("pesme.txt", "r")) == NULL) {
printf("Greska pri ucitavanju datoteke.\n");
exit(1);
}
// rezervisemo mesta za jednu strukturu Pesme
Pesme* pesme = (Pesme*) malloc(sizeof(Pesme));
if(pesme == NULL) {
printf("Greska pri alokaciji.\n");
exit(1);
}
// broj (unetih) elemenata u nizu struktura
int n = 0;
// broj alociranih struktura u memoriji
int alocirano = 1;
while(1) {
// ako je broj alociranih jednak broju unetih struktura, alociramo jos prostora
if(alocirano == n) {
alocirano+=KORAK;
pesme = (Pesme*)realloc(pesme, sizeof(Pesme)*alocirano);
// i naravno, obavezna provera da li je alokacija memorije uspesno izvrsena
if(pesme == NULL) {
printf("Greska pri alokaciji.\n");
exit(1);
}
}
// ako procitamo prazan red, dosli smo do kraja datoteke, i naslino izlazimo iz petlje
if(fgets(s,50,ulaz) == NULL) break;
// sada u niski s cuvamo liniju iz datoteke, a ona je formata " ime_autora ili/i_prezime_odnosno_pseudonim_autora - naziv_pesme, 123456789 "
// ime autora citamo do prve povlake, s tim sto se vratimo jedan karakter unazad, i tu nalepimo nulu (da ne bismo cuvali belinu)
// koristimo dva brojaca, i i j, sa i se krecemo po liniji iz datoteke, a sa j po odredjenom podatku strukture
for(i=0,j=0;s[i]!='-';i++,j++)
pesme[n].izvodjac[j] = s[i];
pesme[n].izvodjac[j-1] = '\0';
// naziv pesme ucitavamo od i (koje cuva karakter kod kog smo stali sa citanjem) pa jos dva karaktera desno, do zareza
for(i=i+2,j=0;s[i]!=',';i++,j++)
pesme[n].naslov[j] = s[i];
pesme[n].naslov[j-1] = '\0';
// sada smo na itoj poziciji, ali krecemo sa citanjem od i+2 da ne bismo ucitali zarez i belinu
// koristim pomocnu nisku pom, u kojoj cu cuvati broj u obliku niske
char pom[20];
pesme[n].brGledanja = 0;
for(i=i+2, j=0;s[i]!='\n';i++, j++)
pom[j] = s[i];
pom[j] = '\0';
pesme[n].brGledanja = atoi(pom);
n++;
}
// kriterijum po default vrednosti neka stoji na b; u slucaju da je unesena opcija, dolazi do izmene
kriterijum = 'b';
if(strcmp(argv[1],"-i") == 0 || strcmp(argv[1], "-n") == 0)
kriterijum = argv[1][1];
// kriterijum se cuva u globalnoj promenljivoj, tako da funkcija uporedi na osnovu njega vraca odgovarajucu vrednost
qsort(pesme, n, sizeof(Pesme), &uporedi);
// ispisujemo sortiran niz struktura
for(i=0;i<n;i++)
printf("%s - %s, %d\n", pesme[i].izvodjac, pesme[i].naslov, pesme[i].brGledanja);
// oslobadjamo alociranu memoriju
free(pesme);
// zatvaramo datoteku
fclose(ulaz);
// saljemo informaciju o uspesnom izvrsavanju programa. the end.
return 0;
}
int uporedi(const void* pPesma1, const void* pPesma2) {
Pesme Pesma1 = *(Pesme*)pPesma1;
Pesme Pesma2 = *(Pesme*)pPesma2;
if(kriterijum == 'i')
return strcmp(Pesma1.izvodjac, Pesma2.izvodjac);
if(kriterijum == 'n')
return strcmp(Pesma1.naslov, Pesma2.naslov);
return Pesma1.brGledanja - Pesma2.brGledanja;
}