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

Извор: SI Wiki
< Програмирање 2
Датум измене: 28. јул 2020. у 17:29; аутор: Ivan Pešić (разговор | доприноси) (Dodato resenje zadatka)
(разл) ← Старија измена | Тренутна верзија (разл) | Новија измена → (разл)
Пређи на навигацију Пређи на претрагу

Задатак

Написати програм на програмском језику C који разврстава ђаке основних школа у жељене средње школе. У сваком реду датотеке сколе.тxт се налазе информације о средњој школи у следећем формату:

бројМеста називСколе

  • бројМеста - број слободних уписних места у школи (цео број)
  • називСколе - низ знакова, који може садржати бланко знаке, од највише 30 карактера.

Свакој школи се додељује редни број који одговара редном броју линије текста у којем се школа налази. Редни бројеви школа почињу од 0. У датотеци има података о највише 400 школа. У бинарној датотеци зеље.под сваки запис садржи:

  • пријавни број ђака (цео број)
  • име и презиме ђака (дужине тачно 30 карактера)
  • просечну оцену (реалан број)
  • редни број средње школе коју ђак жели да упише (цео број)

Пријавни бројеви ђака су јединствени. Информације о школама и ученицима се чувају помоћу следећих структура:

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

Декларације ових типове се налазе у датотеци тyпе.х и њу је потребно укључити свугде где се користе ови типови.

Прва функција

Реализовати функцију воид реадСцхоолс(Сцхоол сцхоолс[МАX_НУМБЕР_ОФ_СЦХООЛС]); која учитава податке о школама тако што сваки ред из датотеке сколе.тxт смешта у један елемент низа сцхоолс.

#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);
}

Друга функција

Реализовати функцију Ноде* реадПупилс(); која учитава податке о ђацима из датотеке зеље.под тако што сваки ред из датотеке смешта у један елемент листе. Функција као повратну вредност враћа показивач на први елемент листе.

#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;
}

Трећа функција

Реализовати функцију воид сортПупилс(Ноде*); која сортира листу ђака опадајуће по просечној оцени. Уколико су просечне оцене једнаке, онда по пријавном броју растуће. Показивач хеад показује на први елемент листе.

#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;
            }
        }
    }
}

Четврта функција

Реализовати функцију воид матцхWрите (Ноде* хеад, Сцхоол сцхоолс[МАX_НУМБЕР_ОФ_СЦХООЛС]); која формира текстуалну датотеку уписи.тxт која ће за сваког ђака садржати податке о додељеној средњој школи. Један ред датотеке треба да има следећи формат:

пријавниБр имеПрезиме просОцена називСколе

Ако нема места у школи коју је ђак навео као жељу, уместо уписане школе уписати НЕУПИСАН. Ђаци са вишом просечном оценом имају већи приоритет при распоређивању. Предност приликом уписа ђака са истим просеком имају они са нижим пријавним бројем. Информације о ђацима се чувају у листи на чији први елемент показује показивач хеад. Информације о школама се чувају у низу сцхоолс.

#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);
}

Пета функција

Реализовати функцију воид деаллоцате(Ноде* хеад); која деалоцира листу ђака.

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

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

Главна функција

Коришћењем претходно реализованих функција написати главни програм који најпре из датотеке сколе.тxт учита информације о школама у низ и из датотеке зеље.под учита податке о ђацима у листу. Програм потом треба да сортира ђаке по просеку и да формира датотеку уписи.тxт.

#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;
}