/****************************************************************************/ /* ** K E R H O T A L . C ** ** Kerhon tietojen levylt„ lukeminen ja levylle tallettaminen. ** ** Aliohjelmat: ** luo_kerho - kysyy kerhon t„ydellisen nimen ja alustaa ** ja luo tarvittavat rakenteet. ** lisaa_jasen_rivi - lis„„ uuden j„sen joka annettu muodossa ** Ankka Aku|12234-34|... ** lue_kerho - kysyy kerhon nimen ja lukee tiedot levylt„ ** mik„li kerhoa ei l”ydy, annetaan mahdollisuus ** uuden luomiseen ** jasen_riviksi - muuttuu j„sentietueen tiedot muotoon ** Ankka Aku|12234-34|... ** talleta_kerho - tallettaa kerhon tiedot levylle ** ja muuttaa vanhan tiedoston nimelle .BAK ** talleta_poistettu - tallettaa poistetun jasenen ** kopioi_kommentit - kopioi toisen tiedoston kommentit toiseen ** ** ** Aliohjelmat olettavat tiedoston olevan seuraavaa muotoa: ** **Kelmien kerho ry **50 **;#kerho.rak **; Kenttien j„rjestys tiedostossa on seuraava: **; sukunimi etunimet|sotu |katuosoite |postinumero|postiosoite|kotipuh... **;---------------------------------------------------------------------------... **Ankka Aku |010245-123U|Ankkakuja 6 |12345 |ANKKALINNA |12-1232... **Susi Sepe |020347-123T| |12555 |Per„mets„ | ... **Ponteva Veli |030455-3333| |12555 |Per„mets„ | ... ** ** ** ;# -kommentit tarkoittavat rakennetiedostojen nimi„. ** Tiedoston alussa olevat kommenttirivit kirjoitetaan talletuksessa ** per„kk„in nimi ja koko -rivin j„lkeen. ** Se kommenttirivi, jolla on erotinmerkki, toimii talletuksen ** yhteydess„ mallirivin„, joka m„„r„„ sarakkeiden leveydet. ** ** ** Tekij„t: Vesa Lappalainen ** Ohjelmointikurssi 1991 ** Tehty: 20.12.1991 ** Muutettu: 25.12.1991 ** Mit„ muutettu: Riippuvuus kenttien nimist„ poistettu. ** K„sitell„„n lippua kerho->muutettu ** eli ei esim. talleteta jollei muutoksia. ** Mallirivin k„sittely. ** Kommenttien kopiointi ** Muutettu: 28.12.1991 ** Mit„ muutettu: K„ytt„„ yleist„ rakennetta. ** Muutettu: 1.2.1994 ** Mit„ muutettu: Poistetun tallettaminen ** ** */ #include #include #include #include "mjonot.h" #include "kerho.h" /****************************************************************************/ int /* 1 = ep„onnistui */ tulosta_mallirivi( /* 0 = onnitui */ FILE *f ,/* s Tiedosto, jonne tulostetaan. */ Rakenne_tyyppi *rakenne,/* s Rakenne, jonka mallirivi tulostetaan. */ int myos_rivi /* s 0 = ei, 1 = juu, 2 = my”s lis„teksti */ ) /* ** Funktiolla tulostetaan tiedostoon mallirivi ja viiva. ** Mik„li myos_rivi==0, niin vain 1. rivi tehd„„n. ** Jos myos_rivi==2, niin tulostetaan my”s teksti "Kenttien j„rjetys..." ** ** ;#kerho.rak ** ; nimi | sotu | ... ** ;------------------------------ ** ** Tulostus: tiedostoon ----------------------------------------------------------------------------*/ { int i; if ( fprintf(f,";#%s\n",rakenne->tiedoston_nimi)==EOF ) return 1; if ( myos_rivi == 2 ) if ( fprintf(f,"; Kenttien j„rjestys tiedostossa on seuraava:\n")==EOF ) return 1; if (!rakenne->mallirivi) return 0; if (!myos_rivi) return 0; if ( fprintf(f,"%s\n",rakenne->mallirivi)==EOF ) return 1; /* Talletetaan viiva */ if ( fprintf(f,";")==EOF ) return 1; for (i=1; imallirivi); i++) if ( fprintf(f,"-")==EOF ) return 1; if ( fprintf(f,"\n")==EOF ) return 1; return 0; } /****************************************************************************/ int /* */ kopioi_kommentit( /* 0 = onnistui, 1 = ei onnistunut */ FILE *f ,/* s Tiedosto jonne kopioidaan */ char *mista ,/* s Tiedoston nimi joka kopioidaan */ Kerho_tyyppi *kerho ,/* s Kerho, josta otetaan tarvittaessa mallirivi*/ int *nyky_rak /* t = viimeisen kopioidun rakenteen nro. */ ) /* ** Funktiolla kopioidaan toisessa tiedostossa olevat kommentit tiedostoon f. ** My”s tyhj„t rivit tulkitaan kommenteiksi. ** ;# rivi kyll„ kopioidaan, muttei sit„ lasketa kommentiksi jotta voidaan ** lis„t„ automaattiset kommentit jollei ole muita kommentteja kuin ;# ** ** Algoritmi: Luetaan tiedostoa kunnes kommentit alkavat ja lopetetaan ** lukeminen kun ne loppuvat. ----------------------------------------------------------------------------*/ { static char rivi[MAX_JASEN]; FILE *fm; int paluu = 1, kommentteja=0; *nyky_rak = 0; if ( !(fm=fopen(mista,"rt")) ) goto sulje; while ( !feof(fm) ) { rivi[1]=' '; rivi[2]=0; if ( f_lue_jono(fm,N_S(rivi)) < OLETUS ) continue; if ( (!rivi[0]) || (rivi[0]==';') ) { if ( rivi[1] !='#' ) kommentteja++; else *nyky_rak = rakenteen_nro(rivi+2); if ( fprintf(f,"%s\n",rivi)==EOF ) goto sulje; } else if (kommentteja) break; } if (kommentteja) paluu=0; sulje: fclose(fm); if (!paluu) return 0; /* Jollei saatu kommentteja toisesta tiedostosta, tehd„„n ne itse */ *nyky_rak = kerho->rakenne->rak_nro; return tulosta_mallirivi(f,kerho->rakenne,2); } /****************************************************************************/ char /* NULL = onnistui */ *luo_kerho( /* muut = virheilmoitus merkkijonona */ Kerho_tyyppi *kerho /* s Luotava kerho */ ) /* ** Funktiolla tehd„„n uuden kerhon luomisessa tarvittavat toimenpiteet. ** Aluksi yritet„„n lukea rakennetiedostoa oletus.rak. Mik„li t„m„ ** ep„onnistuu, kysyt„„n rakennetiedoston nime„. Tyhj„ vastaus ** k„ytt„„ kerhorak.c:ss„ asetettuja oletuksia. ** ** Sy”tt”: P„„tteelt„ ** Tulostus: N„ytt””n ** Kutsuu: lue_rakennetiedosto ** lue_jono_oletus ** lue_kokluku_oletus ** luo_jasentaulukko ----------------------------------------------------------------------------*/ { char *viesti, nimi[80]=""; printf("\n"); viesti=lue_rakennetiedosto(kerho,"oletus.rak"); if (viesti) { lue_jono_oletus("Anna rakennetiedoston nimi ",0,0,nimi,N_S(nimi)); viesti=lue_rakennetiedosto(kerho,nimi); if( viesti ) return viesti; } lue_jono_oletus("Anna aineiston koko nimi ",0,0, kerho->tiedoston_nimi,N_S(kerho->kerhon_nimi)); printf("Anna aineiston maksimim„„r„>"); lue_kokluku_oletus(MAX_JASENIA,&(kerho->max_jasenia)); kerho->jasenia=0; kerho->rakenne->mallirivi=mallirivi(kerho->rakenne); kerho->muutettu = 1; return luo_jasentaulukko(kerho,kerho->max_jasenia); } /****************************************************************************/ int /* */ lisaa_jasen_rivi( /* 0 = lis„ys onnistui, 1 = lis„ys ep„onnistui */ Kerho_tyyppi *kerho ,/* s,t Kerho johon rivi lis„t„„n */ char *rivi /* s Rivi joka sis„lt„„ lis„tt„v„n tiedot */ ) /* ** Funktiolla lis„t„„n j„senist””n merkkijonossa rivi oleva j„sen. ** J„senen tiedot t„ytyy olla eroteltuina erotinmerkeill„. ** ** Globaalit: KENTTIA ** Muuttuu: *rivi ** Kutsuu: poista_tyhjat ** palanen ** jono_kentaksi ** lisaa_jasen ** Esimerkki: rivi = Ankka Aku |010245-123U|Ankkakuja 6 |12345|... ** jasen = Ankka Aku,010245-123U,Ankkakuja 6,12345... ----------------------------------------------------------------------------*/ { char *m; int j; int k; Jasen_tyyppi jasen; jasen.rakenne = kerho->rakenne; m = rivi; for (k=0; kkenttia; k++) { jono_kentaksi(k,&jasen,poista_tyhjat(palanen(m,EROTTIMET,&j))); m = NULL; } return lisaa_jasen(kerho,&jasen); } static char *TIEDOSTO_VAARIN = "Tiedosto on v„„r„„ muotoa!"; static char *NIMEA_EI_ANNETTU = "Kerhon nime„ ei annettu!"; /****************************************************************************/ char /* NULL = onnistui */ *lue_kerho( /* muut = virheilmoitus merkkijonona */ Kerho_tyyppi *kerho /* s,t Kerho johon luetaan. */ ) /* ** Funktiolla luetaan kerhon nimi. Mik„li tiedosto l”ytyy, luetaan ** tiedosto. Mik„li tiedostoa ei l”ydy ja se halutaan luoda, kysyt„„n ** kerhon lis„tietoja ja alustetaan tarpeelliset asiat. ** ** Tiedoston muoto oletetaan seuraavaksi: **Kerhon koko nimi **max_jasenia **;#rakennetiedoston nimi **; Kommenttirivi 1 **; Kommenttirivi ... **; Kommenttirivi n **; nimi |sotu | |... **;-----------------------------------.... **Ankka Aku|010245-123U|Ankkakuja 6 |12345 ... **... ** ** ** Se kommenttirivi (tai ensimm„inen niist„), joilla esiintyy ** erotinmerkki (esim. |) otetaan tallettamista varten malliriviksi. ** Muuten kommenttirivit unohdetaan. ** Tulostetaan ne rivit, joita ei jostakin syyst„ saada lis„tty„ ** j„senluetteloon. ** ** Globaalit: TARKENNIN (vakio jono) ** EROTTIMET (vakio jono) ** Sy”tt”: P„„teelt„, ** tiedostosta ** Tulostus: N„yt”lle ** Kutsuu: f_lue_jono ** N_S (makro) ** lue_jono ** luo_jasentaulukko ** lisaa_jasen_rivi ** Muuta: Mallirivien lukum„„r„„ lasketaan, jottei tiedostoon ** talletettaessa kopioida mallirivej„, jollei niit„ ole ** aluperink„„n. ----------------------------------------------------------------------------*/ { #define PALAUTA(sanoma) {paluu_viesti = sanoma; goto sulje;} FILE *f; static char jono[MAX_JASEN],apu[50]; char *viesti, *paluu_viesti = NULL; int vikoja=0; lue_rakennetiedosto(kerho,""); kerho->nykyjasen = 0; kerho->max_jasenia = MAX_JASENIA; kerho->jasenia = 0; kerho->muutettu = 0; kerho->malliriveja = 0; do { /* Kysell„„n kunnes tiedosto l”ytyy! */ if ( kerho->tiedoston_nimi[0] == 0 ) { printf("Anna tiedoston nimi>"); if ( lue_jono(N_S(kerho->tiedoston_nimi)) <= OLETUS ) return NIMEA_EI_ANNETTU; } kopioi_jono(N_S(jono),kerho->tiedoston_nimi); if ( strstr(jono,TARKENNIN) == NULL ) liita_jono (N_S(jono),TARKENNIN); if ( !(f=fopen(jono,"rt")) ) { /* Avaus ei onnistu! Luodaanko? */ printf("Tiedostoa %s ei ole!\n",kerho->tiedoston_nimi); printf("Luodaanko tiedot (K/e):"); if ( kylla_vastaus() ) return luo_kerho(kerho); kerho->tiedoston_nimi[0] = 0; } /* Avaus ei onnistu! Luodaanko? */ } while (!f); /* Kunnes tiedosto l”ytyy! */ /* Luetaan tiedostosta kerhon nimi ja max_koko sek„ luodaan j„senist” */ if ( f_lue_jono(f,N_S(kerho->kerhon_nimi))max_jasenia); if ( (viesti=luo_jasentaulukko(kerho,kerho->max_jasenia))!=NULL ) PALAUTA(viesti); /* Luetaan j„senist”: */ while ( !feof(f) ) { if ( f_lue_jono(f,N_S(jono))<=OLETUS ) continue; if ( jono[0]==';' ) { /* Jos kommenttirivi */ if ( jono[1]=='#' ) { /* Rakennetiedosto */ viesti=lue_rakennetiedosto(kerho,jono+2); if( viesti ) PALAUTA(viesti); continue; } if ( strpbrk(jono,EROTTIMET) ) { /* Mallirivi */ if ( !kerho->rakenne->mallirivi ) kerho->rakenne->mallirivi = tee_jono(jono); kerho->malliriveja++; } continue; /* Muuten kommenttirivit unohdetaan. */ } kopioi_jono(N_S(apu),jono); /* Jemmataan p„tk„ rivi„ viestiksi! */ if ( lisaa_jasen_rivi(kerho,jono) ) { printf("*** Ei saada lis„tty„: %s ***\n",apu); vikoja++; } } if (!kerho->rakenne->mallirivi) kerho->rakenne->mallirivi = mallirivi(kerho->rakenne); sulje: fclose(f); if (vikoja) { printf("%d nime„ j„i lis„„m„tt„!\n",vikoja); odota_jotakin(); } return paluu_viesti; #undef PALAUTA } /****************************************************************************/ int /* */ jasen_riviksi( /* 0 = onnistuu 1 = ei onnistu */ Jasen_tyyppi *jasen ,/* s J„sen joka muutetaan */ char *rivi ,/* t Rivi jonne j„sen muutetaan */ int max_pit /* s Rivin maksimipituus */ ) /* ** Funktiolla muutetaan j„sen yhdeksi riviksi, jossa kent„t on erotettu ** toisistaan mallirivist„ l”ytyvill„ erotinmerkeill„. Mik„li malliriviss„ ** on v„hemm„n tilaa, kuin tarvitaan, k„ytet„„n tarvittava m„„r„ tilaa. ** Mik„li mallirivi on tyhj„, pakataan tiedot niin ahtaalle kuin mahdollista. ** ** Globaalit: EROTTIMET ** Algoritmi: Mallirivist„ etsit„„n erotinmerkkej„. Aina kun erotinmerkki ** l”ytyy, laitetaan tulosriviin kentt„listan mukaisesti seuraava ** kentt„ ja riitt„v„sti tyhji„, jotta erotin merkki saadaan ** samalle paikalle. Sitten laitetaan erotinmerkki. Mik„li ** mallirivin erotinmerkit loppuu ennen kentt„listaa, k„ytet„„n ** edellist„ erotinmerkki„ jotta koko kentt„lista saadaan ** muutetuksi. ** Esimerkki: malli = "nimi |sotu |Katuosoite | ..." ** jasen = Ankka Aku,010245-123U,Ankkakuja 6,12345... ** rivi = Ankka Aku |010245-123U|Ankkakuja 6 |12345 ----------------------------------------------------------------------------*/ { char erotin; char *malli; int mi=0,ri=0; /* Indeksi mallissa ja riviss„ */ int lm; int k; if (!jasen->rakenne->mallirivi) jasen->rakenne->mallirivi=mallirivi(jasen->rakenne); malli = jasen->rakenne->mallirivi; lm=strlen(malli); rivi[0] = 0; /* Tyhjennet„„n tulosjono. */ erotin = EROTTIMET[0]; for (k=0; krakenne->kenttia; k++) { mi += strcspn(&malli[mi],EROTTIMET); /* Etsit„„n mallin seuraava erotin.*/ if (mi= max_pit-1 ) return 1; /* Jos rivist„ tuli liian pitk„ -> */ for (;(rijasenet[i]->rakenne FILE *f; static char jono[MAX_JASEN],bak_nimi[20]; char *paluu=NULL; int vanhat_tallessa,i; int nyky_rak; logo(); /* Jollei mit„„n muutettu, ei kannata tallettaa! */ talleta_kaikki_rakenne_optiot(); if ( !kerho->muutettu ) return NULL; kopioi_jono(N_S(bak_nimi),kerho->tiedoston_nimi); liita_jono (N_S(bak_nimi),VANHATARK); kopioi_jono(N_S(jono) ,kerho->tiedoston_nimi); liita_jono (N_S(jono) ,TARKENNIN); remove(bak_nimi); /* Vanha .BAK t„ytyy poistaa jotta rename toimii */ vanhat_tallessa = !rename(jono,bak_nimi); if ( !(f = fopen(jono,"wt") ) ) return EI_AUKEA_K; if ( fprintf(f,"%s\n",kerho->kerhon_nimi)==EOF ) PALAUTA(EI_TALLETU); if ( fprintf(f,"%d\n",kerho->max_jasenia)==EOF ) PALAUTA(EI_TALLETU); if ( kopioi_kommentit(f,bak_nimi,kerho,&nyky_rak) ) PALAUTA(EI_TALLETU); for (i=0; ijasenia; i++) { jasen_riviksi(kerho->jasenet[i],N_S(jono)); if ( nyky_rak != RAKENNE->rak_nro ) { if ( tulosta_mallirivi(f,RAKENNE,kerho->malliriveja>1) ) PALAUTA(EI_TALLETU); } nyky_rak = RAKENNE->rak_nro; if ( fprintf(f,"%s\n",jono)==EOF ) PALAUTA(EI_TALLETU); } if ( nyky_rak != kerho->rakenne->rak_nro ) if ( tulosta_mallirivi(f,kerho->rakenne,0) ) PALAUTA(EI_TALLETU); sulje: fclose(f); printf("\n"); printf("Tiedot talletettu tiedostoon %s%s\n",kerho->tiedoston_nimi,TARKENNIN); if (vanhat_tallessa) printf("Vanhat tiedot tiedostossa %s%s\n",kerho->tiedoston_nimi,VANHATARK); return paluu; #undef RAKENNE #undef PALAUTA } /****************************************************************************/ char /* NULL = onnistui */ *talleta_poistettu( /* muut = virheilmoitus merkkijonona */ Jasen_tyyppi *jasen /* s Talletetava kerho */ ) /* ** Funktiolla talletetaan poistettu jasen. ** ** Globaalit: ** ** Tulostus: Tiedostoon ** Kutsuu: kopioi_jono ** liita_jono ** kopioi_kommentit ** tulosta_mallirivi ** jasen_riviksi ----------------------------------------------------------------------------*/ { #define PALAUTA(sanoma) {paluu = sanoma; goto sulje;} FILE *f; static char jono[MAX_JASEN]; char *paluu=NULL; if ( !(f = fopen(POIS_NIMI,"at") ) ) return EI_AUKEA_K; jasen_riviksi(jasen,N_S(jono)); if ( fprintf(f,"%s\n",jono)==EOF ) PALAUTA(EI_TALLETU); sulje: fclose(f); return paluu; #undef PALAUTA }