/****************************************************************************/ /* ** K E R H O T A R . C ** ** Tiedosto sis„lt„„ kerhon sy”t”n tarkistuksessa tarvittavat aliohjelmat. ** ** T„ss„ tiedostossa esiteltyjen funktioiden tulee olla tyyppi„ ** Tarkistus_tulos_tyyppi (int) ja niill„ t„ytyy olla kaksi parametri„: ** ** 1. Tarkistus_tyyppi *tark - jossa kent„t: ** *kerho - kerho jota tutkitaan (jotta samat l”ydet„„n) ** *jasen - j„sen, jonka tietoja tarkistetaan ** jotta haluttaessa voidaan muuttaa seuraavien ** kenttien arvoja sy”t”ss„ ** kentta - kent„n numero, jota muutetaan ** *seuraava_kentta - kentt„ jota seuraavaksi muutetaan. T„m„ ** pit„„ kutsussa alustaa -1:ksi, jolloin ** jos sit„ ei muuteta, niin se tarkoittaa ** ett„ kutsuva ohjelma saa itse p„„tt„„ ** seuraavan kent„n ** syotto_tyyppi - onko kyseess„ LISAYS vai PAIVITYS ** ** ** 2. char *jono - jono jonka oikeellisuus pit„„ tutkia. ** ** ** Aliohjelmien pit„„ palauttaa ** 0 Jono on oikein (tai on korjattu oikeaksi) ** 1 Jono pit„„ kysy„ uudelleen, jono on muutettu haluttuun muotoon ** (korjattu tai tyhjennetty) ** 2 Jonon alkuper„inen arvo pit„„ palauttaa takaisin ja jono pit„„ ** kysy„ uudelleen ** -1 mik„li halutaan poistua kokonaan kyselyist„. ** ** Em. virheille on nimet: ** TARK_OK, TARK_TOISTA, TARK_PAL_OLET, TARK_LOPETUS ** ** Aliohjelmat: ** tarkistus_nimi - palauttaa funktion nimen (avustusten tek.) ** tarkistus_fun - palauttaa funktion nimen perusteella ** ** Tarkistusfunktiot: ** t_ok - palauttaa aina 0 ** t_nimi - tarkistetaan l”ytyyk” nime„ ennest„„n ** t_sotu - hyv„ksyt„„n muodot ** tyhj„ ** ppkkvv (jos oikein) ** ppkkvv-nnnT (jos oikein) ** ppkkvv+nnnT (jos oikein) ** ennest„„n l”ytyv„„ sotua EI hyv„ksyt„! ** t_katu - pit„isi hoitaa c/o-toiminto ja ** saman osoitteen etsiminen ja t„ydent„minen ** muttei toistaiseksi tee muuta kuin ** muuttaa alkuisoiksi ** t_isoksi - muutaa jonon isoksi ** t_alku_isoksi - muuttaa jonon muotoon Aaaa Bbbb ** t_numeerinen - tarkistaa, ett„ jokainen jonon merkki on numero ** t_vuosi_1900 - tarkistaa sy”t”n olevan muotoa ** xx -xx 19xx ja muuttaa muotoon 19xx ** t_puh - sallii kaikki puhelinnumeroon sallitut merkit ** t_arvo - sallii sy”t”t 5 5.25 5+ 5.5 5« 5.75 6- ** ** Tekij„t: Vesa Lappalainen ** Ohjelmointikurssi 1991 ** Tehty: 22.11.1991 ** Muutettu: 18.12.1993/vl ** t_arvo lis„tty ** joukossa funktio lis„tty ** Mit„ muutettu: ** */ #include #include #include #include #include "kerho.h" #include "mjonot.h" #include "pvm.h" /****************************************************************************/ /* ** Tunnetut tarkistusfunktiot: */ typedef struct { char *nimi; Tarkistus_funktio tark_fun; } Tarkistus_fun_tyyppi; static Tarkistus_fun_tyyppi FUNKTIOT[] = { {"NULL" ,NULL }, {"t_ok" ,t_ok }, {"t_nimi" ,t_nimi }, {"t_sotu" ,t_sotu }, {"t_katu" ,t_katu }, {"t_isoksi" ,t_isoksi }, {"t_alku_isoksi",t_alku_isoksi}, {"t_numeerinen" ,t_numeerinen }, {"t_vuosi_1900" ,t_vuosi_1900 }, {"t_puh" ,t_puh }, {"t_arvo" ,t_arvo }, {NULL,NULL} }; /****************************************************************************/ char * /* "NULL" = funktiolle ei ole nime„ */ tarkistus_nimi( /* muut = tarkistusfunktiota vastaava nimi */ Tarkistus_funktio f /* s Funktio, jonka nime„ etsit„„n */ ) /* Funktiolla palautetaan tarkistusfunktion osoitetta vastaava nimi ** Esim. t_ok -> "t_ok" ----------------------------------------------------------------------------*/ { int i; for (i=0; FUNKTIOT[i].nimi; i++) if ( FUNKTIOT[i].tark_fun == f ) return FUNKTIOT[i].nimi; return "NULL"; } /****************************************************************************/ Tarkistus_funktio /* NULL = nime„ vastaavaa funktiota ei ole */ tarkistus_fun( /* muut = nime„ vastaavan funktion osoite */ const char *nimi /* s Funktion nimi, jota etsit„„n. */ ) /* Funktiolla palautetaan tarkistusfunktion nime„ vastaava funktio ** Esim. "t_ok" -> t_ok ** "t_o*" -> t_ok - jokerit kelpaavat ** "T_OK" -> t_ok - isoilla ja pienill„ ei v„li„ ----------------------------------------------------------------------------*/ { int i; for (i=0; FUNKTIOT[i].nimi; i++) if ( onko_samat(FUNKTIOT[i].nimi,nimi) == 0 ) return FUNKTIOT[i].tark_fun; return NULL; } #define TARK_OK (!jono && !tark) /* Aina 0, mutta viit. jono ja tark jottei */ /* k„„nt„j„ valita niiden k„ytt„m„tt”myydes*/ /****************************************************************************/ static int joukossa(Tarkistus_tyyppi *tark, char *jono, const char *sallitut) /* Tarkistetaan onko kaikki mekrit sallituissa ja jos jokin ei ole, ** tulostetaan virheilmoitus ja ensimm„isen virheellisen merkin paikka. */ { int n = sallituissa(jono,sallitut); if ( n >= 0 ) { printf("Jonon kaikki merkit eiv„t ole joukossa \"%s\"!\n",sallitut); printf(" %s\n",jono); printf(" %*c\n",n+1,'^'); return TARK_PAL_OLET; } return TARK_OK; } /****************************************************************************/ Tarkistus_tulos_tyyppi t_ok(Tarkistus_tyyppi *tark, char *jono) /* ** Funktiolla palautetaan aina 0 ** T„m„ on vain apufunktio tarkistuksiin sellaisissa tapauksissa, kun ** jonon sis„lt”„ ei tarvitse tarkistaa. ** ----------------------------------------------------------------------------*/ { return TARK_OK; } /****************************************************************************/ Tarkistus_tulos_tyyppi t_nimi(Tarkistus_tyyppi *tark, char *jono) /* ** Funktiolla palautetaan 0, mik„li nimi ok. Mik„li nimi on ennest„„n ja ** uutta ei haluta lis„t„, palautetaan 1. Mik„li jono on tyhj„, palautetaan ** -1. ** Jono muutetaan isoilla alkavaksi. ** Lasketaan onko kerhossa muita samannimisi„. Mik„li on, varoitetaan ** paitsi korjailussa, jos nimi on jo kerran sinne hyv„ksytty. ** ----------------------------------------------------------------------------*/ { int muita,viimeinen,oliko_tama,kohdalla=-1; jono_alku_isoksi(jono); if ( !jono[0] ) return TARK_LOPETUS; if ( tark->syotto_tyyppi != LISAYS ) kohdalla = tark->kerho->nykyjasen; if ( !(muita=laske_montako_muuta(tark->kerho, tark->kentta,jono,kohdalla,&viimeinen,&oliko_tama) ) ) return TARK_OK; /* Oli muita samannimisi„. Ei haittaa jos korjailu ja t„m„ nimi oli */ /* jo ennest„„n. Lis„ys ja muutos samannimiseksi varmistetaan! */ if ( oliko_tama ) return TARK_OK; printf("\n%s esiintyy ennest„„n",jono); if ( muita > 1 ) printf(" %d kertaa!\nEsimerkiksi:\n",muita); printf("\n"); tulosta_jasen(stdout,tark->kerho->jasenet[viimeinen]); printf("\nLis„„t„„nk” nimi t„st„ huolimatta? (K/e):"); if ( kylla_vastaus() ) return TARK_OK; return TARK_PAL_OLET; } /* 0 1 2 3 */ /* 0123456789012345678901234567890 */ static char SOTUTARK[] = "0123456789ABCDEFHJKLMNPRSTUVWXY"; /****************************************************************************/ Tarkistus_tulos_tyyppi t_sotu(Tarkistus_tyyppi *tark, char *jono) /* ** Tyhj„ sotu hyv„ksyt„„n erikoistapauksena. ** Jono muutetaan isoiksi. ** Tarkistetaan muodon oikeellisuus. Hyv„ksyt„„n muodot: ** tyhj„ ** ppkkvv (jos oikein) ** ppkkvv-nnnT (jos oikein, jos tarkitusmerkki v„„rin, muutetaan ** ppkkvv+nnnT se oikeaksi ) ** ** Tarkistusmerkki saadaan, kun kaikki sotun numerot otetaan yhdeksi ** luvuksi ja jaetaan 31:ll„. Saadun jakoj„„nn”ksen mukaan otetaan ** taulukosta (numerot 0-9, kirjaimet A-Y paitsi G,I,O) vastaavassa ** paikassa oleva merkki. ** ** Lasketaan onko kerhossa muita samansotuisia. ** Mik„li on, hyl„t„„n! ** ----------------------------------------------------------------------------*/ { int viimeinen,oliko_tama,kohdalla=-1; char tm; long alku; int loppu; jono_isoksi(jono); if (!jono[0]) return TARK_OK; /* Tyhj„ sotu hyv„ksyt„„n! */ if ( tarkista_sotu_pvm(jono) ) { /* Jo p„iv„m„„r„ v„„rin, hyl„t„„n. */ printf("Sotussa p„iv„m„„r„ v„„rin!\n"); return TARK_PAL_OLET; } if ( strlen(jono)==6 ) return TARK_OK;/* Pelkk„ syntym„aika hyv„ksyt„„n! */ if ( strlen(jono)!=11 ) { /* En„„ kelpaa muoto ppkkvv+/-nnnT */ printf("Sotussa pit„„ olla 11 merkki„!\n"); return TARK_PAL_OLET; } if ( !strchr("+-",jono[6]) ) { /* Pit„„ olla + tai - */ printf("Sotussa pit„„ syntym„ajan ja tunnuksen v„lill„ olla + tai - !\n"); return TARK_PAL_OLET; } if (!(isdigit(jono[7])&&isdigit(jono[8])&&isdigit(jono[9]))) { /*Lop ei num*/ printf("Tunnusosan kaikki merkit eiv„t ole numeroita!\n"); return TARK_PAL_OLET; } sscanf(jono,"%6ld",&alku); sscanf(jono+7,"%3d",&loppu); tm = SOTUTARK[(int)((alku*1000+loppu) % 31)]; if ( jono[10] != tm ) { printf("TARKISTA SOTU (tarkistusmerkiksi tulisi %c)!\n",tm); jono[10] = tm; return TARK_TOISTA; } if ( tark->syotto_tyyppi != LISAYS ) kohdalla = tark->kerho->nykyjasen; if ( !laske_montako_muuta(tark->kerho, tark->kentta,jono,kohdalla,&viimeinen,&oliko_tama) ) return TARK_OK; /* Oli muita samansotuisia. */ printf("\n%s esiintyy ennest„„n:\n",jono); tulosta_jasen(stdout,tark->kerho->jasenet[viimeinen]); printf("\n"); if ( tark->syotto_tyyppi == PAIVITYS ) return TARK_PAL_OLET; jono[0] = 0; return TARK_TOISTA; } /****************************************************************************/ Tarkistus_tulos_tyyppi t_katu(Tarkistus_tyyppi *tark, char *jono) /* ** Toistaiseksi ilmoitetaan, ettei c/o toimi ja palautetaan 2 ** Muuten muutetaan merkit alkuisoiksi ja palautetaan 0. ----------------------------------------------------------------------------*/ { if ( strstr(jono,"c/o") ) { printf("c/o toimintoa ei ole toteutettu! Anna osoite kokonaan!\n"); return TARK_PAL_OLET; } jono_alku_isoksi(jono); return TARK_OK; } /****************************************************************************/ Tarkistus_tulos_tyyppi t_isoksi(Tarkistus_tyyppi *tark, char *jono) /* ** Funktiolla palautetaan aina 0 ** Jono muutetaan isoksi kirjaimiksi ** ----------------------------------------------------------------------------*/ { jono_isoksi(jono); return TARK_OK; } /****************************************************************************/ Tarkistus_tulos_tyyppi t_alku_isoksi(Tarkistus_tyyppi *tark, char *jono) /* ** Funktiolla palautetaan aina 0 ** Jono muutetaan sanojen alkukirjaimista isoksi kirjaimiksi ** ----------------------------------------------------------------------------*/ { jono_alku_isoksi(jono); return TARK_OK; } /****************************************************************************/ Tarkistus_tulos_tyyppi t_numeerinen(Tarkistus_tyyppi *tark, char *jono) /* ** Palautetaan 0, mik„li jonon jokainen kirjain on numero ** muuten 2 ----------------------------------------------------------------------------*/ { return joukossa(tark,jono,"0123456789."); } /****************************************************************************/ Tarkistus_tulos_tyyppi t_vuosi_1900(Tarkistus_tyyppi *tark, char *jono) /* ** Tarkistetaan onko sy”tt” muotoa 91 -91 tai 1991. ** jollei, palautetaan 2. ** Muuten muutetaan muotoon 1991 ja palautetaan 0. ----------------------------------------------------------------------------*/ { int v; if ( jono[0] == 0 ) return TARK_OK; /* Tyhj„ sy”tt” hyv„ksyt„„n */ if ( jono[0] == '-' ) jono[0]='0'; v = t_numeerinen(tark,jono); if (v) return v; if ( strlen(jono) > 4 ) { printf("Vuosiluku liian pitk„!\n"); return TARK_PAL_OLET; } sscanf(jono,"%d",&v); if ( 100