/****************************************************************************/ /* ** T U L K K I T A . C ** ** Tiedosto sis„lt„„ TULKKI-ohjelman sanaston lukemisessa tarvittavat ** aliohjelmat. ** ** Aliohjelmassa lue_sanasto on laiteriippuva kohta: ** Turbo-C:ss„ sanaston nimeen liitet„„n se polku, josta ohjelma on ** k„ynnistynyt, joten sanaston ei tarvitse olla oletushakemistossa. ** Muissa j„rjestelmiss„ t„ytyy toistaiseksi pit„„ sanasto ** oletushakemistossa ** ** Tietorakenteet ks. TULKKI.C ** ** Aliohjelmat: ** lue_sanasto - luetaan sanasto levylt„ ja luodaan ** samalla tietorakenne ** Apualiohjelmat: ** etsi_iso_kirjain - etsii sanasta isoa kirjainta lyhennett„ varten ** tee_sanat - muuttaa merkkijonon sanaston riviksi ** lisaa_sanat - lis„„ merkkijonon sanastoon riviksi ** tee_kielet - muuttaa merkkijonon kielien nimiksi ** ** ** ** ** Tekij„t: Vesa Lappalainen ** Ohjelmointikurssi 1991 ** Tehty: 6.12.1991 ** Muutettu: ** Mit„ muutettu: ** */ #include #include #include #include "tulkki.h" #include "mjonot.h" /* ** Makro uuden sanarivin luomista varten. Tarvittava koko on ** muuten Sanat_tyypiss„, mutta taulukkoon t„ytyy saada tilaa ** lis„alkioille, eli (kielia-KIELIA_VALMIINA) uutta alkiota */ #define S_KOKO \ (sizeof(Sanat_tyyppi) + ((sanasto->kielia - KIELIA_VALMIINA)*sizeof(char *))) /****************************************************************************/ char /* 0 = ei l”ydy */ etsi_iso_kirjain( /* 1. l”ytynyt iso kirjain. */ char *jono /* s Jono josta isoa kirjainta etsit„„n. */ ) /* ** Funktiolla etsit„„n ja palautetaan merkkijonon 1. iso kirjain. ** ** Algoritmi: Etsit„„n 1. kirjain joka on sama isoksi muutettuna ** mutta eri pieneksi muutettuna. ** Kutsuu: isoksi ** pieneksi ** Esimerkki: jono = "saVO" -> 'V' ** jono = "kissa!" -> 0 ----------------------------------------------------------------------------*/ { char *p; for (p=jono; *p; p++ ) if ( (*p==isoksi(*p)) && (*p!=pieneksi(*p)) ) return *p; return 0; } static char *EI_TILAA_SANOILLE = "Sanoille ei saada varattua tilaa!"; static char *VAARA_MAARA_SANOJA = "Rivill„ v„„r„ m„„r„ sanoja!"; /****************************************************************************/ char /* NULL = onnistui */ *tee_sanat( /* muuten virheilmoitus */ Sanasto_tyyppi *sanasto,/* s Sanasto, jonne sanoja ollaan tekem„ss„ */ Sanat_tyyppi *sanat ,/* s,t Sanat jonne jonon sanat laitetaan. */ char *jono /* s Jono josta sanat otetaan. */ ) /* ** Funktiolla tehd„„n jonoa vastaava merkkijono ja sanat-taulukon osoittimet ** laitetaan osoittamaan merkkijonossa oleviin eri sanoihin. ** Dynaamisesti tehd„„n koko rivi„ vastaava merkkijono. Voitaisiin ** tietysti tehd„ my”s kukin sana omana dynaamisena muuttujana, mutta ** usein pienet dynaamiset muuttujat viev„t suhteelliseti paljon tilaa. ** ** Muuttuu: jonon sis„lt” muuttuu! ** Kutsuu: laske_merkit ** tee_jono ** palanen ** poista_tyhjat ** Algoritmi: ** seuraava sanat[] ** 0 1 2 ** ----------------------------- ** sanat--->|o| o | o | o | ** -+----+------+--------+------ ** | | | | ** v ---- --- | ** | | | ** v v v ** sana_jono-------->Suomi Ruotsi Englanti ** ----------------------------------------------------------------------------*/ { char *sana_jono,*jono_os; int i,jaljella; poista_tyhjat(jono); sana_jono = tee_jono(jono); if (!sana_jono) return EI_TILAA_SANOILLE; jono_os = sana_jono; if ( laske_merkit(jono,"|")+1 < sanasto->kielia ) return VAARA_MAARA_SANOJA; for (i=0; ikielia; i++) { sanat->sanat[i] = poista_tyhjat(palanen(jono_os,"|",&jaljella)); jono_os = NULL; } return NULL; } static char *EI_SAA_TILAA = "Sanastolle ei saada varattua riitt„v„sti tilaa!"; /****************************************************************************/ char /* NULL = onnistui */ *lisaa_sanat( /* muuten virheilmoitus */ Sanasto_tyyppi *sanasto,/* s,t Sanasto jonne sanat lis„t„„n */ char *jono /* s Lis„tt„v„t sanat */ ) /* ** Funktiolla lis„t„„n merkkijonona tuodut sanat sanastoon. ** Mik„li kaikki menee hyvin, palaatetaan NULL. Huonossa tapauksessa ** palautetaan virheilmoitus. Mahdollisia virheit„ on rivin v„„r„ ** muoto ja muistin loppuminen. ** Oletetaan ett„ 1. listan alkio on jo lis„tty (eli kielet). ** ** Kutsuu: tee_sanat ** Algoritmi: ** Sanasto: ** ---------- ** |Kieli„ 3| 0 1 2 ** | |-------- ** |Lyhenteet |S|R|E| ** | |-------- ** | | 0 1 2 ** | | ----------------------------- ** |kielet o+->|o|Suomi |Ruotsi |Englanti| ** | | -+--------------------------- ** | | | ** | | v ** | | ----------------------------- ** |loppu o| |o|min„ |jag |i | ** --------+- -+--------------------------- ** | | ** | v ** | ----------------------------- ** |-->|o|sin„ |du |you | ** -+--------------------------- ** | ** - ** ----------------------------- ** uusi--->|o|h„n |han(mask|he(mask)| ** -+--------------------------- ** | ** v ** NULL ** ----------------------------------------------------------------------------*/ { char *virhe; Sanat_tyyppi *uusi; if ( !(uusi = malloc(S_KOKO)) ) return EI_SAA_TILAA; uusi->seuraava = NULL; sanasto->loppu->seuraava = uusi; sanasto->loppu = uusi; if ( (virhe=tee_sanat(sanasto,sanasto->loppu,jono)) != NULL ) return virhe; return NULL; } static char *LIIAN_VAHAN_KIELIA = "Tiedostossa t„ytyy olla ainakin 2 kielt„!"; static char *LIIKAA_KIELIA = "Sanastossa liian monta kielt„!"; static char *VAARAT_LYHENTEET = "Kielet lyhennetty v„„rin!"; /****************************************************************************/ char /* NULL = onnistui */ *tee_kielet( /* muuten virheilmoitus */ Sanasto_tyyppi *sanasto,/* s,t Sanasto johon kielet liitet„„n. */ char *jono /* s Jono josta kielet etsit„„n. */ ) /* ** Funktiolla alustetaan sanastoon kielet. Mik„li jokin menee pieleen, ** palautetaan virheilmoitus. ** ** ** Muuttuu: jono ** Kutsuu: tee_sanat ** etsi_iso_kirjain ** Esimerkki: jono = "Suomi | Ruotsi | Englanti" -> ** Sanasto: ** ---------- ** |Kieli„ 3| 0 1 2 ** | |-------- ** |Lyhenteet |S|R|E| ** | |-------- ** | | 0 1 2 ** | | ----------------------------- ** |kielet o+->|o| o | o | o | ** | | ^-+----+------+--------+------ ** | | | | | | | ** | | | v | --- | ** | | | NULL | | | ** |loppu o| | | v v ** --------+- | |->Suomi Ruotsi Englanti ** | | ** |--- ----------------------------------------------------------------------------*/ { int kielia,i; char *virhe,c; kielia = laske_merkit(jono,"|")+1; if ( kielia < 2 ) return LIIAN_VAHAN_KIELIA; if ( kielia > MAX_KIELIA ) return LIIKAA_KIELIA; sanasto->kielia = kielia; if ( !(sanasto->kielet = malloc(S_KOKO)) ) return EI_SAA_TILAA; sanasto->loppu = sanasto->kielet; sanasto->kielet->seuraava = NULL; if ( (virhe=tee_sanat(sanasto,sanasto->kielet,jono)) != NULL ) return virhe; for (i=0; ilyhenteet[i]=' '; sanasto->lyhenteet[kielia]=0; for (i=0; ikielet->sanat[i]); if (!c || strchr(sanasto->lyhenteet,c) ) return VAARAT_LYHENTEET; sanasto->lyhenteet[i]=c; } return NULL; } static char *EI_AUKEA = "Tiedosto "SANASTO" ei aukea lukemista varten!"; static char *MUOTOVIRHE = "Sanastotiedostossa muotovirhe!"; /****************************************************************************/ char /* NULL = onnistui */ *lue_sanasto( /* muuten virheilmoituksen osoite */ Sanasto_tyyppi *sanasto /* t Luettu sanasto */ ) /* ** Funktiolla luetaan sanasto tiedostosta. Mik„li kaikki menee hyvin, ** palautetaan NULL. Huonossa tapauksessa tulostetaan virherivi ja ** palautetaan virheilmoitus! ** ** Kutsuu: liita_jono ** kopio_jono ** f_lue_jono ** tee_kielet ** lisaa_sanat ----------------------------------------------------------------------------*/ { FILE *f; char jono[200]=";", *virhe=NULL; f = fopen(SANASTO,"rt"); if (!f) return EI_AUKEA; do { /* Luetaan kunnes tulee 1. oikea rivi, josta lasketaan kielet */ if ( f_lue_jono(f,N_S(jono)) < OLETUS ) { virhe = MUOTOVIRHE; goto sulje; } } while (jono[0]==';'); if ( (virhe = tee_kielet(sanasto,jono)) != NULL ) goto sulje; while (!feof(f)) { if ( f_lue_jono(f,N_S(jono)) <= OLETUS ) continue; /* Tyhj„t rivit unoh.*/ if ( jono[0] == ';' ) continue; /* Kommentit unohdet.*/ if ( (virhe = lisaa_sanat(sanasto,jono)) != NULL ) break; } sulje: if (virhe) printf("%s\n",jono); fclose(f); return virhe; }