Prodavnica

Autor zadatka: Aleksandar Vasiljević <alexva02@uns.ac.rs>

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

  • serijski_broj (ceo broj),

  • naziv (jedna reč, maksimalno 13 karaktera),

  • kolicina (pozitivan ceo broj),

  • jedinicna_cena (realan broj) i

  • ukupna_cena (realan broj).

Struktura artikal_st, takođe sadrži i polja potrebna za pravilno formiranje jednostruko spregnute liste. Prilikom formiranja jednostruko spregnute liste voditi računa o tome da je potrebno elemente sortirati u rastućem redosledu serijskog broja. Polje strukture ukupna_cena izračunati na sledeći način: ukupna_cena = kolicina * jedinicna_cena.

Potrebno je kupiti sve one artikle iz ponude prodavnice čiji zbir ukupnih cena ne premašuje vrednost zadatog budžeta budzet . Nakon uspešne kupovine, ispisati sve informacije o svim kupljenim artiklima. Uz to, ispisati još i iznos preostalog budžeta i informaciju o broju kupljenih artikala. Ako se ispostavi da je budžet nedovoljan za kupovinu bilo kog artikla iz ponude, ispisati odgovarajuću poruku i izaći iz programa sa izlaznim kodom 333.

Ako se za vrednost argumenta komandne linije budzet unese negativna vrednost ispisati poruku o grešci i iz programa izaći sa izlaznim kodom 22.

Primer poziva:

./a.out 22800 artikli.txt

sa zadatim argumentom budzet = 22800 i zadatim ulazom u datoteci artikli.txt:

123.19 3 limun 2396
4399.99 25 trenerka 1179
109.11 8 tecni_sapun 7421
45.01 5 luk 7965
999.99 3 duks 4598
89.99 22 banane 8942
145.11 78 pasta_za_zube 1124
189.22 23 arf 3211
5899.39 7 pantalone 1698
215.49 13 ananas 1147
386.29 49 regenerator 3352
2354.99 15 farmerke 4452

i očekivanim ispisom na standardnom izlazu:

1124 pasta_za_zube 11318.58
1147 ananas 2801.37
2396 limun 369.57
3211 arf 4352.06
4598 duks 2999.97
7421 tecni_sapun 872.88

Uspesno ste kupili 6 proizvoda.
Na racunu vam je ostalo 85.57 din.

Ako se program pozove sa vrednošću budzet = -250 ispis treba da bude sledeći:

Budzet mora biti pozitivan broj!

Ako se program pozove sa vrednošću budzet = 100 ispis treba da bude sledeći:

Nemate dovoljno novca za kupovinu nijednog od proizvoda iz ponude!

Primer rešenja

  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4
  5#define MAX_NAZIV 13+1
  6
  7typedef struct artikal_st {
  8    int serijski_broj;    
  9    char naziv[MAX_NAZIV];
 10    unsigned kolicina;
 11    double jedinicna_cena;
 12    double ukupna_cena;
 13    struct artikal_st *sledeci;
 14} ARTIKAL;
 15
 16void init_list(ARTIKAL **head) {
 17    *head = NULL;
 18}
 19
 20void add_to_list(ARTIKAL *new, ARTIKAL **head) {
 21    ARTIKAL *tek,*pret1;
 22    int nakraj=1;
 23    if(*head == NULL) {
 24        *head = new;
 25        return;
 26    }
 27    pret1=*head;
 28    tek=*head;
 29
 30    if(new->serijski_broj < tek->serijski_broj) {
 31        new->sledeci=*head;
 32        *head=new;
 33        return;
 34    }
 35
 36    while(tek != NULL) {
 37        if(new->serijski_broj < tek->serijski_broj) {
 38            nakraj=0;
 39            break;
 40        }
 41        pret1=tek;
 42        tek = tek->sledeci;
 43    }
 44
 45    if(nakraj == 1) {
 46        pret1 -> sledeci = new;
 47    } else {
 48        new->sledeci = pret1->sledeci;
 49        pret1->sledeci = new;
 50    }
 51}
 52
 53ARTIKAL *create_new_item(int ser_br, char naz[], unsigned kol, double jed_c) {
 54    ARTIKAL *new = (ARTIKAL *)malloc(sizeof(ARTIKAL));
 55    if (new == NULL) {
 56        printf("Not enough RAM!\n");
 57        exit(21);
 58    }
 59    new->serijski_broj = ser_br;
 60    strcpy(new->naziv, naz);
 61    new->kolicina = kol;
 62    new->jedinicna_cena = jed_c;
 63    new->ukupna_cena = kol * jed_c;
 64
 65    new->sledeci = NULL;
 66
 67    return new;
 68}
 69
 70void read_list_from(FILE *in, ARTIKAL **head) {
 71    int tmpSerBr;
 72    char tmpNaz[MAX_NAZIV];
 73    unsigned tmpKol;
 74    double tmpJedC;
 75
 76    while(fscanf(in,"%lf %u %s %d",&tmpJedC,&tmpKol,tmpNaz,&tmpSerBr) != EOF) {
 77        ARTIKAL *new = create_new_item(tmpSerBr, tmpNaz, tmpKol, tmpJedC);
 78        add_to_list(new, head);
 79    }
 80}
 81
 82void save_item_to(ARTIKAL *x) {
 83    printf("\t%d %s %.2lf\n", x->serijski_broj, x->naziv, x->ukupna_cena);
 84}
 85
 86void save_list_to(ARTIKAL *head) {
 87    if(head != NULL) {
 88        save_item_to(head);
 89        save_list_to(head->sledeci);
 90    }
 91}
 92
 93void destroy_list(ARTIKAL **head) {
 94    if(*head != NULL) {
 95        destroy_list(&((*head)->sledeci));
 96        free(*head);
 97        *head = NULL;
 98    }
 99}
100
101void korpa(ARTIKAL * head,double budzet) {
102
103    int kupljeno=0;
104
105    if (head==NULL) {
106        return;
107    }
108
109    while(head != NULL) {
110        if(budzet-head->ukupna_cena >= 0) {
111            kupljeno++;
112            budzet-=head->ukupna_cena;
113            save_item_to(head);
114        }
115        head = head->sledeci;
116    }
117
118    if(kupljeno == 0) {
119        printf("Nemate dovoljno novca za kupovinu");
120        printf(" nijednog od proizvoda iz ponude!\n");
121        exit(333);
122    } else {
123        printf("\n\tUspesno ste kupili %d proizvoda.\n\t",kupljeno);
124        printf("Na racunu vam je ostalo %.2lf din.\n",budzet);
125    }
126}
127
128FILE *safe_fopen(char *filename, char *mode, int error_code) {
129    FILE *fp = fopen(filename, mode);
130    if (fp == NULL) {
131        printf("Can't open '%s'!\n", filename);
132        exit(error_code);
133    }
134    return fp;
135}
136
137
138//primer poziva ./a.out 22800 artikli.txt
139int main(int arg_num, char *args[]) {
140    if (arg_num != 3) {
141        printf("Pogresan unos argumenata\n");
142        exit(11);
143    }
144
145    if(atof(args[1]) < 0) {
146        printf("Budzet mora biti pozitivan broj!\n");
147        exit(22);
148    }
149
150    FILE *in  = safe_fopen(args[2],"r", 1);
151
152    ARTIKAL *head;
153    init_list(&head);
154
155    read_list_from(in, &head);
156
157    korpa(head,atof(args[1]));
158
159    destroy_list(&head);
160
161    fclose(in);
162
163    return 0;
164}