SOS

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

Napisati program koji dekodira poruke napisane pomoću Morzeove abecede. Podaci su zadati u ulaznoj datoteci u sledećem formatu:

  • slovo (jedan karakter)

  • kod (jedna reč, do 5 karaktera)

Učitati Morzeove kodove u statički niz, na osnovu kojih će se u izlaznu datoteku ispisati dekodirane reči. Ime ulazne i izlazne datoteke se zadaju kao argument komandne linije, dok se reči napisane u Morzeovoj azbuci zadaju preko standardnog ulaza. Korisnik programa unosi reči čija su pojedinačni kodovi slova razdvojeni jednim razmakom dokle god ne unese string kraj, što označava kraj korisničkog unosa (pogledati primer rada programa). Ukoliko je unet Morzeov kod koji nije definisan u ulaznoj datoteci, umesto slova napisati upitnik ?. Pretpostaviti da će korisnik isključivo unositi karaktere -, . i string kraj, stoga nije potrebno raditi dodatnu validaciju unosa. Izlazna datoteka sadrži originalnu reč napisanu pomoću Morzeove azbuke, strelicu -> i prevedenu reč. Format je %s -> %s.

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

Napomene

  • Zbog učitavanja jednog karaktera, format string u fscanf naredbi mora sadržati znak za novi red "%c %s\n"

  • Beskonačna petlja u programskom jeziku C se može napisati kao while(1), dok se iz nje se može izaći sa break naredbom

Primer poziva programa:

./a.out kodovi.txt poruka.txt

Primer ulazne datoteke kodovi.txt:

A .-
E .
I ..
O ---
U ..-
P .--.
S ...
T -

Primer rada programa:

Uneti kodirane reci (za prestanak, ukucati rec kraj):
... --- ...
- .- ...
.--. .- ...
-- --- ...
kraj

Primer izlazne datoteke poruka.txt:

... --- ... -> SOS
- .- ... -> TAS
.--. .- ... -> PAS
-- --- ... -> ?OS

Primer rešenja

  1#include <stdio.h>
  2#include <string.h>
  3#include <stdlib.h>
  4
  5#define MAX_KOD 5
  6
  7#define MAX_SIZE 30
  8
  9#define MAX_KODNA_REC 51
 10#define MAX_REC 51
 11
 12typedef struct morzeov_kod_st
 13{
 14    char slovo;
 15    char kod[MAX_KOD];
 16} MORZEOV_KOD;
 17
 18FILE *safe_fopen(char *ime, char *rezim, int kod_greske);
 19void ucitaj_kodove(FILE *ulazna, MORZEOV_KOD *MORZEOV_KODovi, int *pn);
 20void dekodiraj_rec(MORZEOV_KOD *MORZEOV_KODovi, int n, char *MORZEOV_KODna_rec, int duzina_MORZEOV_KODne_reci, char *rec);
 21
 22int main(int argc, char **argv)
 23{
 24    MORZEOV_KOD kodovi[MAX_SIZE];
 25    int n;
 26
 27    if(argc != 3)
 28    {
 29        printf("Primer poziva: %s kodovi.txt poruka.txt\n", argv[0]);
 30        exit(2);
 31    }
 32
 33    FILE *ulazna = safe_fopen(argv[1], "r", 3);
 34    ucitaj_kodove(ulazna, kodovi, &n);
 35    fclose(ulazna);
 36
 37    char kodna_rec[MAX_KODNA_REC] = "";
 38    char rec[MAX_REC];
 39
 40    // ... --- ... SOS
 41    // - .- ...    TAS 
 42    // .--. .- ... PAS
 43    // -- --- ...  MAS
 44
 45    FILE *izlazna = safe_fopen(argv[2], "w", 4);
 46    printf("Uneti kodirane reci (za prestanak, ukucati rec kraj):\n");
 47    while(1)
 48    {
 49        fgets(kodna_rec, MAX_KODNA_REC, stdin);
 50        int duzina = strlen(kodna_rec);
 51        if(kodna_rec[duzina - 1] == '\n')
 52        {
 53            kodna_rec[--duzina] = '\0';
 54        }
 55
 56        if(strcmp(kodna_rec, "kraj") == 0)
 57        {
 58            break;
 59        }
 60
 61        dekodiraj_rec(kodovi, n, kodna_rec, duzina, rec);
 62        fprintf(izlazna, "%s -> %s\n", kodna_rec, rec);
 63    }
 64    fclose(izlazna);
 65
 66    return 0;
 67}
 68
 69FILE *safe_fopen(char *naziv, char *rezim, int kod_greske)
 70{
 71    FILE *fp = fopen(naziv, rezim);
 72
 73    if(fp == NULL)
 74    {
 75        printf("Datoteka %s nije uspesno otvorena!\n", naziv);
 76        exit(kod_greske);
 77    }
 78
 79    return fp;
 80}
 81
 82void ucitaj_kodove(FILE *ulazna, MORZEOV_KOD *kodovi, int *pn)
 83{
 84    int i = 0;
 85
 86    while(fscanf(ulazna, "%c %s\n", 
 87            &kodovi[i].slovo, kodovi[i].kod) != EOF)
 88    {
 89        i++;
 90    }
 91
 92    *pn = i;
 93}
 94
 95void dekodiraj_rec(MORZEOV_KOD *kodovi, int n, char *kodna_rec, int duzina_kodne_reci, char *rec)
 96{
 97    int i, j, duzina_reci = 0, duzina_kodiranog_slova = 0, nadjen_kod = 0;
 98    char kodirano_slovo[MAX_KOD] = "";
 99
100    for(i = 0;i < duzina_kodne_reci;i++)
101    {
102        if(kodna_rec[i] == ' ' || i == duzina_kodne_reci - 1)
103        {
104            if(i == duzina_kodne_reci - 1)
105            {
106                kodirano_slovo[duzina_kodiranog_slova++] = kodna_rec[i];
107            }
108
109            kodirano_slovo[duzina_kodiranog_slova++] = '\0';
110            for(j = 0;j < n;j++)
111            {
112                if(strcmp(kodirano_slovo, kodovi[j].kod) == 0)
113                {
114                    rec[duzina_reci++] = kodovi[j].slovo;
115                    nadjen_kod = 1;
116                    break;
117                }
118            }
119
120            if(!nadjen_kod)
121            {
122                rec[duzina_reci++] = '?';
123            }
124
125            duzina_kodiranog_slova = 0;
126        }
127        else
128        {
129            kodirano_slovo[duzina_kodiranog_slova++] = kodna_rec[i];
130        }
131    }
132
133    rec[duzina_reci++] = '\0';
134}