Zadatak „Prosečna cena goriva”

Section author: Petar Marić <petarmaric@uns.ac.rs>

Iz zadate ulazne datoteke učitati podatke u jednostruko spregnutu listu, gde struktura gorivo_st sadrži sledeća polja:

  • skraćena oznaka grada (jedna reč, tačno 2 karaktera)
  • tip goriva (jedna reč, do 10 karaktera)
  • cena goriva (pozitivan realan broj)

Naravno, struktura gorivo_st sadrži i polja potrebna za pravilno formiranje jednostruko spregnute liste.

Na osnovu zadatog tipa goriva tip_goriva (gas, benzin ili dizel) iz formirane liste upisati podatke u zadatu izlaznu datoteku, u sledećem rasporedu polja strukture gorivo_st:

  • cena (zaokružena na 2 decimale, koristiti "%6.2f" format specifikator)
  • skraćena oznaka grada
  • tip goriva

i potom u istu izlaznu datoteku upisati informaciju koja je prosečna cena zadatog tipa goriva (zaokružena na 2 decimale, koristiti "%6.2f" format specifikator).

Primer poziva:

./gorivo benzin cene.txt izvestaj.txt

sa tip_goriva=benzin i zadatim ulazom u datoteci cene.txt:

NS gas     71.90
NS benzin 155.20
NS dizel  165.15
NI gas     69.30
NI benzin 155.30
NI dizel  165.20
BG gas     70.20
BG benzin 155.50
BG dizel  165.40

i očekivanim izlazom u datoteci izvestaj.txt:

 71.90 NS gas
155.20 NS benzin
165.15 NS dizel
 69.30 NI gas
155.30 NI benzin
165.20 NI dizel
 70.20 BG gas
155.50 BG benzin
165.40 BG dizel

AVG = 155.33

Primer poziva kada gorivo sa zadatim kriterijumima ne postoji:

./gorivo gas mala_pumpa.txt izvestaj.txt

sa tip_goriva=gas i zadatim ulazom u datoteci mala_pumpa.txt:

SA benzin 196.90
PE dizel  191.60

i očekivanim izlazom u datoteci izvestaj.txt:

196.90 SA benzin
191.60 PE dizel

NOT FOUND!

Primer rešenja

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_GRAD 2+1
#define MAX_TIP_GORIVA 10+1

#define ERROR_MAGIC_NUM -666.999

typedef struct gorivo_st {
    char grad[MAX_GRAD];
    char tip_goriva[MAX_TIP_GORIVA];
    double cena;

    struct gorivo_st *next;
} GORIVO;

void init_list(GORIVO **head) {
    *head = NULL;
}

void add_to_list(GORIVO *new, GORIVO **head) {
    if(*head == NULL) { // list is empty
        *head = new;
        return;
    }

    add_to_list(new, &((*head)->next));
}

GORIVO *create_new_item(char grad[], char tip_goriva[], double cena) {
    GORIVO *new = (GORIVO *)malloc(sizeof(GORIVO));
    if (new == NULL) {
        printf("Not enough RAM!\n");
        exit(21);
    }

    strcpy(new->grad, grad);
    strcpy(new->tip_goriva, tip_goriva);
    new->cena = cena;

    new->next = NULL;

    return new;
}

void read_list_from(FILE *in, GORIVO **head) {
    char grad[MAX_GRAD];
    char tip_goriva[MAX_TIP_GORIVA];
    double cena;

    while(fscanf(in, "%s %s %lf", grad, tip_goriva, &cena) != EOF) {
        GORIVO *new = create_new_item(grad, tip_goriva, cena);
        add_to_list(new, head);
    }
}

void save_item_to(FILE *out, GORIVO *x) {
    fprintf(
        out, "%6.2f %s %s\n",
        x->cena, x->grad, x->tip_goriva
    );
}

void save_list_to(FILE *out, GORIVO *head) {
    if(head != NULL) {
        save_item_to(out, head);
        save_list_to(out, head->next);
    }
}

void destroy_list(GORIVO **head) {
    if(*head != NULL) {
        destroy_list(&((*head)->next));
        free(*head);
        *head = NULL;
    }
}

FILE *safe_fopen(char *filename, char *mode, int error_code) {
    FILE *fp = fopen(filename, mode);
    if (fp == NULL) {
        printf("Can't open '%s'!\n", filename);
        exit(error_code);
    }
    return fp;
}

int count_gorivo(GORIVO *head, char tip_goriva[]) {
    int count = 0;

    while(head != NULL) {
        if (strcmp(head->tip_goriva, tip_goriva) == 0) {
            count++;
        }

        head = head->next;
    }

    return count;
}

double sum_gorivo(GORIVO *head, char tip_goriva[]) {
    double sum = 0;

    while(head != NULL) {
        if (strcmp(head->tip_goriva, tip_goriva) == 0) {
            sum += head->cena;
        }

        head = head->next;
    }

    return sum;
}

double avg_gorivo(GORIVO *head, char tip_goriva[]) {
    int count = count_gorivo(head, tip_goriva);
    if (count == 0) {
        return ERROR_MAGIC_NUM;
    } else {
        return sum_gorivo(head, tip_goriva) / count;
    }
}

int main(int arg_num, char *args[]) {
    if (arg_num != 4) {
        printf("USAGE: %s TIP_GORIVA IN_FILENAME OUT_FILENAME\n", args[0]);
        exit(11);
    }

    char *tip_goriva = args[1];
    char *in_filename = args[2];
    char *out_filename = args[3];

    FILE *in  = safe_fopen(in_filename,  "r", 1);
    FILE *out = safe_fopen(out_filename, "w", 2);

    GORIVO *head;
    init_list(&head);

    read_list_from(in, &head);
    save_list_to(out, head);

    double avg = avg_gorivo(head, tip_goriva);
    if (avg == ERROR_MAGIC_NUM) {
        fprintf(out, "\nNOT FOUND!\n");
    } else {
        fprintf(out, "\nAVG = %6.2lf\n", avg);
    }

    destroy_list(&head);

    fclose(in);
    fclose(out);

    return 0;
}