/*
4. zadatak Ispit jul 2017 v1
U ovoj verziji pojednostavili smo zadatak tako sto smatramo
da svi studenti imaju po 3 polozena ispita.
Verzija 2 je sa promenljivim brojem polozenih ispita po svakom studentu.
U svakoj liniji tekstualne ulazne datoteke studenti.txt.
nalaze se podaci o studentima i podaci o polozenim ispitima.
Svaka linija u ovoj ulaznoj datoteci se sastoji od vise kolona
koje su medjusobno odvojene znakom tackazarez (;).
U prvoj koloni se nalazi ime i prezime studenta (maksimalan broj karaktera je 50).
U drugoj koloni se nalazi broj indeksa studenta (maksimalan broj karaktera je 9).
Potom slede podaci o polozenim ispitima.
Za svaki ispit cuvaju se podaci o sifri ispita (maksimalan broj karaktera je 6)
i oceni sa tog ispita (ocene su u intervalu od 6 do 10).
Prebaciti podatke iz tekstualne datoteke studenti.txt u jednostruko spregnutu listu.
(20 poena)
Sortirati ovu listu (u opadajucem redosledu prema prosecnoj oceni)
i prikazati njen sadrzaj. (15 poena)
Prikaz jedne linije ulazne datoteke:
Marko Markovic;0001/2016;P1;8;OIKT;9;UIS;6;
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_SIZE 100
#define SIZE_IME 51 // veci za 1 zbog karaktera '\0' na kraju stringa
#define SIZE_INDEKS 10 // veci za 1 zbog karaktera '\0' na kraju stringa
#define SIZE_SIFRA 7 // veci za 1 zbog karaktera '\0' na kraju stringa
/*
NAPOMENA: Listu treba sortirati prema prosecnoj oceni sa polozenih ispita studenta,
i zato u listi treba odmah predvideti
int BrojPolozenihIspita i
float ProsecnaOcena
za svakog studenta.
*/
struct cvor{ // struktura cvor, to je jedan element liste
char imeiprezime[SIZE_IME]; // sadrzaj cvora
char BrojIndeksa[SIZE_INDEKS];
char SifraIspita1[SIZE_SIFRA];
int ocena1;
char SifraIspita2[SIZE_SIFRA];
int ocena2;
char SifraIspita3[SIZE_SIFRA];
int ocena3;
int BrojPolozenihIspita;
float ProsecnaOcena;
struct cvor *sledeci; // i pointer na sledeceg clana
};
typedef struct cvor CVOR; // jedan cvor liste CVOR
typedef CVOR* PCVOR; // pointer na listu CVOR
// Prikazuje sadrzaj cvorova liste glava
void prikazi_listu(char *tekst, PCVOR glava)
{
printf("\n%s\n",tekst);
if(glava == NULL) {
printf(" prazna. \n");
} else {
while(glava) {
printf("\n | %-16s %-10s %6s %2d %6s %2d %6s %2d %2d %5.2f | \n",
glava->imeiprezime,
glava->BrojIndeksa,
glava->SifraIspita1,
glava->ocena1,
glava->SifraIspita2,
glava->ocena2,
glava->SifraIspita3,
glava->ocena3,
glava->BrojPolozenihIspita,
glava->ProsecnaOcena );
glava = glava->sledeci;
}
}
printf("\n");
}
// Prikazuje sadrzaj jednog cvora tekuci
void prikazi_jedan_cvor_liste(char *tekst, PCVOR tekuci)
{
printf("\n%s\n",tekst);
if(tekuci == NULL) {
printf(" prazan. \n");
} else {
printf("\n | %-16s %-10s %6s %2d %6s %2d %6s %2d %2d %5.2f | \n",
tekuci->imeiprezime,
tekuci->BrojIndeksa,
tekuci->SifraIspita1,
tekuci->ocena1,
tekuci->SifraIspita2,
tekuci->ocena2,
tekuci->SifraIspita3,
tekuci->ocena3,
tekuci->BrojPolozenihIspita,
tekuci->ProsecnaOcena );
}
}
// Na kraj liste glava dodaje vec napravljeni novi cvor
void dodaj_na_kraj (PCVOR *glava, PCVOR *rep, PCVOR novi)
{
if(*glava == NULL) { // ako je lista prazna
*rep = novi; // i rep i glava su taj novi cvor
*glava = novi;
} else { // ako lista nije prazna
(*rep)->sledeci = novi; // sledeci od starog repa je taj novi
*rep = novi; // novi rep je taj novi
}
}
// Sortira listu glava u opadajucem redosledu po prosenoj oceni studenta
void sortiraj_listu_po_prosecno_oceni_opadajuce( PCVOR *glava, PCVOR *rep )
{
PCVOR i, j; // pomocne liste i i j
int mem_int; // memorija za pamcenje integer-a
float mem_float; // memorija za pamcenje float-a
char mem_string[SIZE_IME]; // memorija za pamcenje string-a
for ( i=*glava; i; i=i->sledeci ) // i ide od glave do repa
for ( j=*glava; j; j=j->sledeci ) // j ide od glave do repa
if ( i->ProsecnaOcena > j->ProsecnaOcena ) { // KRITERIJUM SORTIRANJA
// medjusobno zamenjujemo mesta svim podacima (sadrzajima cvorova i i j)
strcpy(mem_string, i->imeiprezime); // sa stringovima mora strcpy()
strcpy(i->imeiprezime, j->imeiprezime);
strcpy(j->imeiprezime, mem_string);
strcpy(mem_string, i->BrojIndeksa ); // sa stringovima mora strcpy()
strcpy(i->BrojIndeksa, j->BrojIndeksa);
strcpy(j->BrojIndeksa, mem_string);
strcpy(mem_string, i->SifraIspita1 ); // sa stringovima mora strcpy()
strcpy(i->SifraIspita1, j->SifraIspita1);
strcpy(j->SifraIspita1, mem_string);
mem_int = i->ocena1;
i->ocena1 = j->ocena1;
j->ocena1 = mem_int;
strcpy(mem_string, i->SifraIspita2 ); // sa stringovima mora strcpy()
strcpy(i->SifraIspita2, j->SifraIspita2);
strcpy(j->SifraIspita2, mem_string);
mem_int = i->ocena2;
i->ocena2 = j->ocena2;
j->ocena2 = mem_int;
strcpy(mem_string, i->SifraIspita3 ); // sa stringovima mora strcpy()
strcpy(i->SifraIspita3, j->SifraIspita3);
strcpy(j->SifraIspita3, mem_string);
mem_int = i->ocena3;
i->ocena3 = j->ocena3;
j->ocena3 = mem_int;
mem_int = i->BrojPolozenihIspita;
i->BrojPolozenihIspita = j->BrojPolozenihIspita;
j->BrojPolozenihIspita = mem_int;
mem_float = i->ProsecnaOcena ;
i->ProsecnaOcena = j->ProsecnaOcena;
j->ProsecnaOcena = mem_float;
}
}
int main(void)
{
FILE *p_ul_fajl; // pointer na ulazni fajl
PCVOR glava = NULL; // deklarisemo listu (OBAVEZNO =NULL)
PCVOR rep = NULL; // deklarisemo rep liste (OBAVEZNO =NULL)
PCVOR novi = NULL; // deklarisemo cvor novi;
PCVOR pom = NULL; // deklarisemo pomocni cvor pom;
char tekst[SIZE_IME]; // privremeni string
char red[MAX_SIZE]; // string u koji smestamo jedan ucitani red iz ulaznog fajla
int i,j; // indeksi
// Otvaramo ulazni txt fajl za citanje
p_ul_fajl = fopen("studenti.txt","r");
if( p_ul_fajl == NULL ) {
printf("\n Greska pri otvaranju ulaznog fajla ulaz.txt ! \n");
exit(1);
}
// Ucitavamo red po red do kraja fajla i podatke smestamo u cvor novi
while( fgets(red,MAX_SIZE,p_ul_fajl) ){ // ucitavamo red po red do kraja fajla
// fgets() ucitava i karakter '\n' na kraju reda
red[ strlen(red)-1 ] = '\0'; // karakter '\n' na kraju reda zamenjujemo sa '\0'
novi = (PCVOR)malloc(sizeof(CVOR)); // rezervisemo memoriju za cvor novi
if(novi == NULL) {
printf("\n Greska pri rezervisanju memorije! \n");
exit(1);
}
// Iz reda ucitavamo podatke koji su razdvojeni karakterom ';'
novi->BrojPolozenihIspita = 0; // resetujemo BrojPolozenihIspita
// Ucitavamo imeiprezime
i=0; // resetujemo indeks stringa red[i]
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string imeiprezime
novi->imeiprezime[j++] = red[i++];
novi->imeiprezime[j] = '\0'; // zavrsavamo string koji ucitavamo
// Ucitavamo BrojIndeksa
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string BrojIndeksa
novi->BrojIndeksa[j++] = red[i++];
novi->BrojIndeksa[j] = '\0'; // zavrsavamo string koji ucitavamo
// Ucitavamo sifre ispita i ocene
// Ucitavamo sifru 1. ispita
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string SifraIspita1
novi->SifraIspita1[j++] = red[i++];
novi->SifraIspita1[j] = '\0'; // zavrsavamo string koji ucitavamo
// Ucitavamo ocenu 1. ispita
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string tekst
tekst[j++] = red[i++];
tekst[j] = '\0'; // zavrsavamo string koji ucitavamo
novi->ocena1 = atoi(tekst); // ucitani string tekst pretvaramo u integer ocena1
novi->BrojPolozenihIspita++; // uvecavamo BrojPolozenihIspita
// Ucitavamo sifru 2. ispita
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string SifraIspita2
novi->SifraIspita2[j++] = red[i++];
novi->SifraIspita2[j] = '\0'; // zavrsavamo string koji ucitavamo
// Ucitavamo ocenu 2. ispita
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string tekst
tekst[j++] = red[i++];
tekst[j] = '\0'; // zavrsavamo string koji ucitavamo
novi->ocena2 = atoi(tekst); // ucitani string tekst pretvaramo u integer ocena2
novi->BrojPolozenihIspita++; // uvecavamo BrojPolozenihIspita
// Ucitavamo sifru 3. ispita
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string SifraIspita3
novi->SifraIspita3[j++] = red[i++];
novi->SifraIspita3[j] = '\0'; // zavrsavamo string koji ucitavamo
// Ucitavamo ocenu 3. ispita
i++; // preskacemo karakter ';'
j=0; // resetujemo indeks stringa koji ucitavamo
// Dok ne naidjemo na ';' ili na kraj reda
while( red[i] != ';' && red[i] != '\0' ) // ucitavamo string tekst
tekst[j++] = red[i++];
tekst[j] = '\0'; // zavrsavamo string koji ucitavamo
novi->ocena3 = atoi(tekst); // ucitani string tekst pretvaramo u integer ocena3
novi->BrojPolozenihIspita++; // uvecavamo BrojPolozenihIspita
// Racunamo prosecnu ocenu
novi->ProsecnaOcena =
(float)(novi->ocena1 + novi->ocena2 + novi->ocena3) / novi->BrojPolozenihIspita;
// OBAVEZNO =NULL inace prikaz poslednjeg cvora liste ne radi dobro
novi->sledeci = NULL;
// cvor novi smestamo na kraj liste glava da bi zadrzali isti redosled kao u fajlu
dodaj_na_kraj(&glava,&rep,novi);
}
prikazi_listu(" Lista je: ",glava);
sortiraj_listu_po_prosecno_oceni_opadajuce(&glava,&rep);
prikazi_listu(" Lista sortirana po prosecnoj oceni opadajuce je: ",glava);
// Zatvaramo ulazni i izlazni txt fajl
fclose(p_ul_fajl);
return 0;
}