Stonks

Napisati program koji obrađuje podatke o podacima o vrednostima akcija kompanija na berzi. Podaci su zadati u ulaznoj datoteci u sledećem formatu:

  • naziv_kompanije (jedna reč, do 11 karaktera)

  • prvi_procenat (realan broj)

  • drugi_procenat (realan broj)

  • treci_procenat (realan broj)

  • cetvrti_procenat (realan broj)

  • peti_procenat (realan broj)

Učitati podatke o rastu deonica u statički niz, na osnovu kojih će se u izlaznu datoteku ispisati nova vrednost i trend akcija za kompaniju. Ime ulazne i izlazne datoteke se zadaju kao argumenti komandne linije. Osim imena datoteka, zadate su i početne vrednosti akcija kao realne vrednosti i prag na osnovu kog se gleda stagnacija akcija, takođe kao realna vrednost.

Procenti rasta akcija predstavljaju promenu vrednosti akcije u toku jednog dana. Da bi se dobio ukupan trend za taj dan, potrebno je sumirati sve vrednosti procenata. Nakon toga, potrebno je izračunati novu vrednost akcije. Imati na umu da se akcije pojedine kompanije mogu naći više od jednog puta u ulaznoj datoteci, stoga je potrebno na određeni način sačuvati međuvrednost akcija.

Trend akcija može sadržati tri vrednosti: rast, pad i stagnacija. Stagnacija se određuje na osnovu zadatog praga stagnacije, tako što se on pomnoži sa početnom vrednošću akcije. Ukoliko se nova vrednost akcije nalazi u okolini početne vrednosti akcije označene prethodno dobijenom vrednošću, za takvu akciju se kaže da ona stagnira. U suprotnom, gleda se vrednost rasta akcije za taj dan. Ako je rast negativna vrednost, za trend ispisati pad, u suprotnom ispisati rast.

Vrednosti imena kompanija su fiksne: Kompanija_A, Kompanija_B, Kompanija_C i Kompanija_D, tim redosledom su povezane sa vrednostima argumenata komandne linije koje idu nakon imena ulazne i izlazne datoteke. Ukoliko se u ulaznoj datoteci nađu podaci sa kompanijom čije ime nije navedeno, potrebno je na standardni izlaz ispisati tekst u formatu: Ne postoji pocetna vrednost akcija za kompaniju <naziv-kompanije>!. Preskočiti obradu tog reda, ali nastaviti sa obradom preostalih podataka.

Korisne matematičke formule

Računanje rasta akcije u toku dana i nove vrednosti akcije:

class center
\[rast = \sum{procenat}\]
class center
\[vrednost_{nova} = vrednost_{trenutna} \cdot (1 + \frac{rast}{100})\]

Računanje opsega stagnacije:

class center
\[opseg = prag \cdot vrednost_{početna}\]

Potrebno je proveriti da li se nova vrednost nalazi u opsegu:

class center
\[vrednost_{nova} \leq |opseg|\]

U slučaju uspešnog izvršavanja programa, izaći sa status kodom 0 (EXIT_SUCCESS). Ukoliko program ne može da se izvrši do kraja usled sledećih nedostataka, izaći iz programa sa sledećim status kodovima:

  • U slučaju nedovoljnog ili suvišnog broj argumenata komandne linije, izaći iz programa sa status kodom 2

  • Ako program ne može da otvori ulaznu datoteku, izaći sa status kodom 3

  • Ako program ne može da otvori izlaznu datoteku, izaći sa status kodom 4

Primer ulazne datoteke deonice.txt:

Kompanija_B  1.0  -0.5  0.0  2.0  -1.0
Kompanija_A -2.0  -1.0  0.5  0.0   1.5
Kompanija_D  3.0   1.0 -4.0  0.5   0.0
Kompanija_B -1.0  -1.0 -1.0  0.0   0.0
Kompanija_C  0.05 -0.02  0.01 -0.03  0.04
Kompanija_A  2.0   1.0  0.0 -0.5   0.0

Primer poziva programa:

./a.out deonice.txt izvestaj.txt 100.0 200.0 80.0 120.0 0.002

Primer izlazne datoteke izvestaj.txt:

Kompanija_B 203.00 rast
Kompanija_A 99.00 pad
Kompanija_D 120.60 rast
Kompanija_B 196.91 pad
Kompanija_C 80.04 stagnacija
Kompanija_A 101.47 rast

Primer ulazne datoteke deonice-sa-nepostojecom-kompanijom.txt:

Kompanija_E  2.0  -0.5  1.0  -2.4  -1.0
Kompanija_B  1.0  -0.5  0.0  2.0  -1.0
Kompanija_A -2.0  -1.0  0.5  0.0   1.5
Kompanija_D  3.0   1.0 -4.0  0.5   0.0
Kompanija_B -1.0  -1.0 -1.0  0.0   0.0
Kompanija_C  0.05 -0.02  0.01 -0.03  0.04
Kompanija_A  2.0   1.0  0.0 -0.5   0.0

Primer poziva programa:

./a.out deonice-sa-nepostojecom-kompanijom.txt izvestaj.txt 100.0 200.0 80.0 120.0 0.002

Primer ispisa programa na standardni izlaz:

Ne postoji pocetna vrednost akcija za kompaniju Kompanija_E!

Primer izlazne datoteke izvestaj.txt (isti sadržaj kao i u prethodnom primeru):

Kompanija_B 203.00 rast
Kompanija_A 99.00 pad
Kompanija_D 120.60 rast
Kompanija_B 196.91 pad
Kompanija_C 80.04 stagnacija
Kompanija_A 101.47 rast

Primer rešenja

  1#include <stdio.h>
  2#include <string.h>
  3#include <stdlib.h>
  4
  5#define MAX_NAZIV_KOMPANIJE 12
  6
  7#define MAX_SIZE 30
  8
  9typedef struct rast_deonica_st
 10{
 11    char naziv_kompanije[MAX_NAZIV_KOMPANIJE];
 12    double prvi_procenat;
 13    double drugi_procenat;
 14    double treci_procenat;
 15    double cetvrti_procenat;
 16    double peti_procenat;
 17} RAST_DEONICA;
 18
 19FILE *safe_fopen(char *ime, char *rezim, int kod_greske);
 20void ucitaj_rast_deonica(FILE *ulazna, RAST_DEONICA *rd, int *pn);
 21double sumiraj_rast_na_dnevnom_nivou(double prvi_procenat, double drugi_procenat, double treci_procenat, double cetvrti_procenat, double peti_procenat);
 22double izracunaj_rast(double trenutna, double rast);
 23int stagnira(double trenutna, double pocetna, double prag);
 24void ispisi_trend(FILE *izlazna, double trenutna, double pocetna, double prag, double rast);
 25void sumiraj_informacije_o_deonicama(FILE *izlazna, RAST_DEONICA *rd, int n, double pocetna_A, double pocetna_B, double pocetna_C, double pocetna_D, double prag);
 26
 27int main(int argc, char **argv)
 28{
 29    RAST_DEONICA rast_deonica[MAX_SIZE];
 30    int n;
 31
 32    if(argc != 8)
 33    {
 34        printf("Primer poziva: %s deonice.txt izvestaj.txt 100.0 200.0 80.0 120.0 0.002\n", argv[0]);
 35        exit(2);
 36    }
 37
 38    FILE *ulazna = safe_fopen(argv[1], "r", 3);
 39    ucitaj_rast_deonica(ulazna, rast_deonica, &n);
 40    fclose(ulazna);
 41
 42    double pocetna_A = atof(argv[3]);
 43    double pocetna_B = atof(argv[4]);
 44    double pocetna_C = atof(argv[5]);
 45    double pocetna_D = atof(argv[6]);
 46    double prag = atof(argv[7]);
 47
 48    FILE *izlazna = safe_fopen(argv[2], "w", 4);
 49    sumiraj_informacije_o_deonicama(izlazna, rast_deonica, n, pocetna_A, pocetna_B, pocetna_C, pocetna_D, prag);
 50    fclose(izlazna);
 51
 52    return EXIT_SUCCESS;
 53}
 54
 55FILE *safe_fopen(char *naziv, char *rezim, int kod_greske)
 56{
 57    FILE *fp = fopen(naziv, rezim);
 58
 59    if(fp == NULL)
 60    {
 61        printf("Datoteka %s nije uspesno otvorena!\n", naziv);
 62        exit(kod_greske);
 63    }
 64
 65    return fp;
 66}
 67
 68void ucitaj_rast_deonica(FILE *ulazna, RAST_DEONICA *rd, int *pn)
 69{
 70    int i = 0;
 71
 72    while(fscanf(ulazna, "%s %lf %lf %lf %lf %lf", 
 73            rd[i].naziv_kompanije, &rd[i].prvi_procenat, &rd[i].drugi_procenat, &rd[i].treci_procenat, &rd[i].cetvrti_procenat, &rd[i].peti_procenat) != EOF)
 74    {
 75        i++;
 76    }
 77
 78    *pn = i;
 79}
 80
 81double sumiraj_rast_na_dnevnom_nivou(double prvi_procenat, double drugi_procenat, double treci_procenat, double cetvrti_procenat, double peti_procenat)
 82{
 83    return prvi_procenat + drugi_procenat + treci_procenat + cetvrti_procenat + peti_procenat;
 84}
 85
 86double izracunaj_rast(double trenutna, double rast)
 87{
 88    return trenutna *= (1 + rast / 100);
 89}
 90
 91int stagnira(double trenutna, double pocetna, double prag)
 92{
 93    double opseg = prag * pocetna;
 94    return trenutna >= (pocetna - opseg) && trenutna <= (pocetna + opseg);
 95}
 96
 97void ispisi_trend(FILE *izlazna, double trenutna, double pocetna, double prag, double rast)
 98{
 99    if(stagnira(trenutna, pocetna, prag))
100    {
101        fputs("stagnacija\n", izlazna);
102        return;
103    }
104
105    if(rast < 0)
106    {
107        fputs("pad\n", izlazna);
108    }
109    else
110    {
111        fputs("rast\n", izlazna);
112    }
113}
114
115void sumiraj_informacije_o_deonicama(FILE *izlazna, RAST_DEONICA *rd, int n, double pocetna_A, double pocetna_B, double pocetna_C, double pocetna_D, double prag)
116{
117    int i;
118    double pocetna, trenutna, trenutna_A = pocetna_A, trenutna_B = pocetna_B, trenutna_C = pocetna_C, trenutna_D = pocetna_D;
119    double rast;
120
121    for(i = 0;i < n;i++)
122    {
123        rast = sumiraj_rast_na_dnevnom_nivou(rd[i].prvi_procenat, rd[i].drugi_procenat, rd[i].treci_procenat, rd[i].cetvrti_procenat, rd[i].peti_procenat);
124
125        if(strcmp(rd[i].naziv_kompanije, "Kompanija_A") == 0)
126        {
127            pocetna = pocetna_A;
128            trenutna_A = izracunaj_rast(trenutna_A, rast);
129            trenutna = trenutna_A;
130        }
131        else if(strcmp(rd[i].naziv_kompanije, "Kompanija_B") == 0)
132        {
133            pocetna = pocetna_B;
134            trenutna_B = izracunaj_rast(trenutna_B, rast);
135            trenutna = trenutna_B;
136        }
137        else if(strcmp(rd[i].naziv_kompanije, "Kompanija_C") == 0)
138        {
139            pocetna = pocetna_C;
140            trenutna_C = izracunaj_rast(trenutna_C, rast);
141            trenutna = trenutna_C;
142        }
143        else if(strcmp(rd[i].naziv_kompanije, "Kompanija_D") == 0)
144        {
145            pocetna = pocetna_D;
146            trenutna_D = izracunaj_rast(trenutna_D, rast);
147            trenutna = trenutna_D;
148        }
149        else
150        {
151            printf("Ne postoji pocetna vrednost akcija za kompaniju %s!\n", rd[i].naziv_kompanije);
152            continue;
153        }
154
155        fprintf(izlazna, "%s %.2lf ", rd[i].naziv_kompanije, trenutna);
156        ispisi_trend(izlazna, trenutna, pocetna, prag, rast); 
157    }
158}