Програмирање 2/К3 2017

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Zadatak

Napisati program na programskom jeziku C koji razvrstava đake osnovnih škola u željene srednje škole. U svakom redu datoteke skole.txt se nalaze informacije o srednjoj školi u sledećem formatu:

brojMesta nazivSkole

  • brojMesta - broj slobodnih upisnih mesta u školi (ceo broj)
  • nazivSkole - niz znakova, koji može sadržati blanko znake, od najviše 30 karaktera.

Svakoj školi se dodeljuje redni broj koji odgovara rednom broju linije teksta u kojem se škola nalazi. Redni brojevi škola počinju od 0. U datoteci ima podataka o najviše 400 škola. U binarnoj datoteci zelje.pod svaki zapis sadrži:

  • prijavni broj đaka (ceo broj)
  • ime i prezime đaka (dužine tačno 30 karaktera)
  • prosečnu ocenu (realan broj)
  • redni broj srednje škole koju đak želi da upiše (ceo broj)

Prijavni brojevi đaka su jedinstveni. Informacije o školama i učenicima se čuvaju pomoću sledećih struktura:

typedef struct school {
    int id, places;
    char name[31];
} School;

typedef struct pupil {
    int id, school;
    char name[31];
    double averageGrade;
} Pupil;

typedef struct node {
    Pupil pupil;
    struct node *next;
} Node;

#define MAX_NUMBER_OF_SCHOOLS 400

Deklaracije ovih tipove se nalaze u datoteci type.h i nju je potrebno uključiti svugde gde se koriste ovi tipovi.

Prva funkcija

Realizovati funkciju void readSchools(School schools[MAX_NUMBER_OF_SCHOOLS]); koja učitava podatke o školama tako što svaki red iz datoteke skole.txt smešta u jedan element niza schools.

#include <stdio.h>
#include <stdlib.h>
#include "type.h"

void readSchools ( School schools[MAX_NUMBER_OF_SCHOOLS] ) {
    FILE *in = fopen("skole.txt", "r");
    
    for(int i = 0; fscanf(in, "%d %[^\n]\n", &schools[i].places, schools[i].name)==2; i++)
        schools[i].id = i;    
    fclose(in);
}

Druga funkcija

Realizovati funkciju Node* readPupils(); koja učitava podatke o đacima iz datoteke zelje.pod tako što svaki red iz datoteke smešta u jedan element liste. Funkcija kao povratnu vrednost vraća pokazivač na prvi element liste.

#include <stdio.h>
#include <stdlib.h>
#include "type.h"

Node* readPupils ( ) {
    FILE *in = fopen("zelje.pod", "rb");
    Node *head = NULL, *tail = head;
    Pupil p;
    while(fread(&p, sizeof(p), 1, in) == 1)
    {
        Node *tmp = malloc(sizeof(Node));
        tmp->pupil = p;
        tmp->next = NULL;
        if(!head)
            head = tmp;
        else
            tail->next = tmp;
        tail = tmp;
    }
    fclose(in);
    return head;
}

Treća funkcija

Realizovati funkciju void sortPupils(Node*); koja sortira listu đaka opadajuće po prosečnoj oceni. Ukoliko su prosečne ocene jednake, onda po prijavnom broju rastuće. Pokazivač head pokazuje na prvi element liste.

#include "type.h"

void sortPupils ( Node *head ) {
    for(Node* f = head; f; f = f->next)
    {
        for(Node* s = f->next; s; s = s->next)
        {
            if(f->pupil.averageGrade < s->pupil.averageGrade ||
            f->pupil.averageGrade == s->pupil.averageGrade && f->pupil.id < s->pupil.id)
            {
                Pupil tmp = f->pupil;
                f->pupil = s->pupil;
                s->pupil = tmp;
            }
        }
    }
}

Četvrta funkcija

Realizovati funkciju void matchWrite (Node* head, School schools[MAX_NUMBER_OF_SCHOOLS]); koja formira tekstualnu datoteku upisi.txt koja će za svakog đaka sadržati podatke o dodeljenoj srednjoj školi. Jedan red datoteke treba da ima sledeći format:

prijavniBr imePrezime prosOcena nazivSkole

Ako nema mesta u školi koju je đak naveo kao želju, umesto upisane škole upisati NEUPISAN. Đaci sa višom prosečnom ocenom imaju veći prioritet pri raspoređivanju. Prednost prilikom upisa đaka sa istim prosekom imaju oni sa nižim prijavnim brojem. Informacije o đacima se čuvaju u listi na čiji prvi element pokazuje pokazivač head. Informacije o školama se čuvaju u nizu schools.

#include <stdio.h>
#include <stdlib.h>
#include "type.h"

void matchAndWrite ( Node *head, School schools[MAX_NUMBER_OF_SCHOOLS] ) {
    FILE* out = fopen("upisi.txt", "w");
    
    for(Node* n = head; n; n = n->next)
    {
        int found = 0;
        fprintf(out, "%d %s %.6lf ", n->pupil.id, n->pupil.name, n->pupil.averageGrade);
        for (int s = 0; s < MAX_NUMBER_OF_SCHOOLS; s++)
        {
            if(n->pupil.school == schools[s].id)
            {
                if(schools[s].places > 0)
                {
                    found = 1;
                    schools[s].places--;
                    fprintf(out, "%s\n", schools[s].name);
                }
                break;
            }
        }
        if(!found)
            fprintf(out, "NEUPISAN\n");
    }
    fclose(out);
}

Peta funkcija

Realizovati funkciju void deallocate(Node* head); koja dealocira listu đaka.

#include <stdlib.h>
#include "type.h"

void deallocateList ( Node *head ) {
    while(head)
    {
        Node* old = head;
        head = head->next;
        free(old); 
    }
}

Glavna funkcija

Korišćenjem prethodno realizovanih funkcija napisati glavni program koji najpre iz datoteke skole.txt učita informacije o školama u niz i iz datoteke zelje.pod učita podatke o đacima u listu. Program potom treba da sortira đake po proseku i da formira datoteku upisi.txt.

#include <stdio.h>
#include <stdlib.h>
#include "type.h"

int main()
{
    School schools[MAX_NUMBER_OF_SCHOOLS];
    Node* pupils;
    
    readSchools(schools);
    pupils = readPupils();
    sortPupils(pupils);
    matchAndWrite(pupils, schools);
    deallocateList(pupils);
    return 0;
}