Subjekat-predikat-objekat

Autor zadatka: Rade Radišić <radisic.rade@uns.ac.rs>

Napisati program koji od zadatih reči sastavlja rečenice. Podaci su zadati u ulaznoj datoteci u sledećem formatu:

  • rec (jedna reč, do 20 karaktera)

  • vrsta (jedna reč, do 8 karaktera)

Učitati reči u jednostruko spregnutu listu, gde se novi čvorovi dodaju na kraj liste.

Od zadatih reči, formirati sve moguće rečenice u obliku subjekat-predikat-objekat. Obratiti pažnju da predikat i objekat moraju biti ispisani malim slovom, kao i da na kraju rečenice treba da stoji tačka. Prebrojati sve subjekte, predikate i objekte i na standardni izlaz ispisati koliko je ukupno moguće formirati rečenica u formatu:

Od <broj-subjekata> subjekta, <broj-predikata> predikata i <broj-objekata> objekta moguce je sastaviti <ukupan-broj-recenica> recenica.

Program se poziva sa imenom ulazne i izlazne datoteke kao vrednostima argumenata komandne linije.

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 1 (EXIT_FAILURE)

  • U slučaju nemogućnosti dinamičkog zauzimanja memorije, 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 poziva programa:

./a.out reci.txt recenice.txt

Primer ulazne datoteke reci.txt:

Covek    subjekat
Tamburu  objekat
Svira    predikat
Krava    subjekat
Muze     predikat
Mesecinu objekat
Mleko    objekat

Primer rada programa:

Od 2 subjekta, 2 predikata i 3 objekta moguce je sastaviti 12 recenica.

Primer izlazne datoteke recenice.txt:

Covek svira tamburu.
Covek svira mesecinu.
Covek svira mleko.
Covek muze tamburu.
Covek muze mesecinu.
Covek muze mleko.
Krava svira tamburu.
Krava svira mesecinu.
Krava svira mleko.
Krava muze tamburu.
Krava muze mesecinu.
Krava muze mleko.

Primer rešenja

  1#include <stdio.h>
  2#include <string.h>
  3#include <ctype.h>
  4#include <stdlib.h>
  5
  6#define MAX_REC 21
  7#define MAX_VRSTA 9
  8
  9#define MAX_NAZIV_IZLAZNE 11
 10
 11typedef struct rec_st
 12{
 13    char rec[MAX_REC];
 14    char vrsta[MAX_VRSTA];
 15    struct rec_st *sledeci;
 16} REC;
 17
 18FILE *safe_fopen(char *, char *, int);
 19void ucitaj_reci(FILE *, REC **);
 20void ispisi_recenice(FILE *, REC *);
 21
 22void inicijalizacija(REC **);
 23REC *napravi_cvor(char *, char *);
 24void dodaj_na_kraj(REC **, REC *);
 25int prebroj_vrstu(REC *, char *);
 26void obrisi_listu(REC **);
 27
 28int main(int argc, char **argv)
 29{
 30    REC *glava;
 31
 32    if(argc != 3)
 33    {
 34        printf("Primer poziva programa: %s reci.txt recenice.txt\n", argv[0]);
 35        exit(EXIT_FAILURE);
 36    }
 37
 38    inicijalizacija(&glava);
 39
 40    FILE *ulazna = safe_fopen(argv[1], "r", 3);
 41    ucitaj_reci(ulazna, &glava);
 42    fclose(ulazna);
 43
 44    FILE *izlazna = safe_fopen(argv[2], "w", 4);
 45    ispisi_recenice(izlazna, glava);
 46    fclose(izlazna);
 47
 48    int broj_subjekata = prebroj_vrstu(glava, "subjekat");
 49    int broj_predikata = prebroj_vrstu(glava, "predikat");
 50    int broj_objekata = prebroj_vrstu(glava, "objekat");
 51
 52    printf("Od %d subjekta, %d predikata i %d objekta moguce je sastaviti %d recenica.\n",
 53        broj_subjekata, broj_predikata, broj_objekata, broj_subjekata * broj_predikata * broj_objekata);
 54
 55    obrisi_listu(&glava);
 56
 57    return EXIT_SUCCESS;
 58}
 59
 60FILE *safe_fopen(char *naziv, char *rezim, int kod_greske)
 61{
 62    FILE *fp = fopen(naziv, rezim);
 63
 64    if(fp == NULL)
 65    {
 66        printf("Datoteka %s nije uspesno otvorena!\n", naziv);
 67        exit(kod_greske);
 68    }
 69
 70    return fp;
 71}
 72
 73void ucitaj_reci(FILE *ulazna, REC **pglava)
 74{
 75    char tmp_rec[MAX_REC];
 76    char tmp_vrsta[MAX_VRSTA];
 77    REC *novi;
 78
 79    while(fscanf(ulazna, "%s %s", tmp_rec, tmp_vrsta) != EOF)
 80    {
 81        novi = napravi_cvor(tmp_rec, tmp_vrsta);
 82        dodaj_na_kraj(pglava, novi);
 83    }
 84}
 85
 86void ispisi_recenice(FILE *izlazna, REC *glava)
 87{
 88    REC *tekuci_subjekat = glava;
 89    REC *tekuci_predikat;
 90    REC *tekuci_objekat;
 91    char subjekat[MAX_REC];
 92    char predikat[MAX_REC];
 93    char objekat[MAX_REC];
 94
 95    while(tekuci_subjekat != NULL)
 96    {
 97        if(strcmp(tekuci_subjekat->vrsta, "subjekat") == 0)
 98        {
 99            tekuci_predikat = glava;
100            
101            while(tekuci_predikat != NULL)
102            {
103                if(strcmp(tekuci_predikat->vrsta, "predikat") == 0)
104                {
105                    tekuci_objekat = glava;
106                    
107                    while(tekuci_objekat != NULL)
108                    {
109                        if(strcmp(tekuci_objekat->vrsta, "objekat") == 0)
110                        {
111                            strcpy(subjekat, tekuci_subjekat->rec);
112                            strcpy(predikat, tekuci_predikat->rec);
113                            strcpy(objekat, tekuci_objekat->rec);
114                            predikat[0] += 32;
115                            objekat[0] += 32;
116                            fprintf(izlazna, "%s %s %s.\n", subjekat, predikat, objekat);
117                        }
118                        
119                        tekuci_objekat = tekuci_objekat->sledeci;
120                    }
121                }
122
123                tekuci_predikat = tekuci_predikat->sledeci;
124            }
125        }
126
127        tekuci_subjekat = tekuci_subjekat->sledeci;
128    }
129}
130
131void inicijalizacija(REC **pglava)
132{
133    *pglava = NULL;
134}
135
136REC *napravi_cvor(char *rec, char *vrsta)
137{
138    REC *novi = (REC *)malloc(sizeof(REC));
139
140    if(novi == NULL)
141    {
142        printf("Greska prilikom zauzimanja memorije!\n");
143        exit(2);
144    }
145
146    strcpy(novi->rec, rec);
147    strcpy(novi->vrsta, vrsta);
148    novi->sledeci = NULL;
149
150    return novi;
151}
152
153void dodaj_na_kraj(REC **pglava, REC *novi)
154{
155    if(*pglava == NULL)
156    {
157        *pglava = novi;
158    }
159    else
160    {
161        REC *tekuci = *pglava;
162
163        while(tekuci->sledeci != NULL)
164        {
165            tekuci = tekuci->sledeci;
166        }
167
168        tekuci->sledeci = novi;
169    }
170}
171
172int prebroj_vrstu(REC *glava, char *vrsta)
173{
174    REC *tekuci = glava;
175    int broj = 0;
176
177    while(tekuci != NULL)
178    {
179        if(strcmp(tekuci->vrsta, vrsta) == 0)
180        {
181            broj++;
182        }
183
184        tekuci = tekuci->sledeci;
185    }
186
187    return broj;
188}
189
190void obrisi_listu(REC **pglava)
191{
192    REC *tmp;
193
194    while(*pglava != NULL)
195    {
196        tmp = *pglava;
197        *pglava = (*pglava)->sledeci;
198        tmp->sledeci = NULL;
199        free(tmp);
200    }
201}