previous next Up Title Contents Index

15.2.2 mjonot.c


Vastaavasti itse tiedosto, jossa aliohjelmat ovat, olisi seuraavan näköinen:

ali\mjonot.c - aliohjelmia merkkijonojen käsittelyyn

	/****************************************************************************/
	/*  
	** M J O N O T . C
	**
	** Yleisiä merkkijonojen käsittelyyn liittyviä aliohjelmia.               
	**
	...
	** Aliohjelmat:
	**    tee_jono               -  luo uuden merkkijonon jonne jono kopioidaan
	**    kopioi_jono            -  kopioi kork. annetun määrän merkkejä
	...
	**                             merkkijonossa
	**    wildmat                -  vertaa onko sana == maski, missä maskissa
	**                             voi olla jokeri- merkkejä
	...
	*/       
	
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <ctype.h>
	#include "mjonot.h"
	
	char *VALIMERKIT=" .,- ;:?!";  
	
	/****************************************************************************/
	char                    /* = jonon kopion osoite                            */
	*tee_jono(              /* NULL = ei voida kopioida                         */
	  char *jono            /* s   Kopioitava merkkijono                        */
	)
	...
	... Kuten ennenkin ...
	...                                       
	
	/****************************************************************************/
	int                       /*                                                */
	wildmat(                  /* 0 = jono täsmää maskiin                        */
	                          /* 1 = jono ei täsmää maskiin                     */
	  const register char *s ,/* s   Tutkittava jono                            */
	  const register char *m  /* s   Maski, johon jonoa verrataan               */
	)
	/*
	** Funktiolla tutkitaan täsmääkö annettu jono verrattavaan maskiin.
	** Maski saa sisältää seuraavia erikoismerkkejä:
	**   * vastaa 0-n merkkiä
	**   ? vastaa mitä tahansa yhtä merkkiä
	**
	** Algoritmi: Kysymysmerkki ja tavallinen kirjain normaalisti
	**            Jos tulee vastaan tähti joka ei ole jonon lopussa,
	**            niin ongelmahan on oikeastaan
	**            (koska tähän asti kaikki on ollut oikein)
	**            "Onko loppujono sama kuin toisen jonon loppu JOSTAKIN
	**             kohdasta alkaen"?
	**            Siis kokeillaan sovittaa loppujonoa aliohjelman itsensä
	**            (rekursio) avulla kaikkiin mahdollisiin loppupaikkoihin.
	** Esimerkki: s = "Kissa" m = "*ss*" -> 0
	**                          = "*ss"  -> 1
	** Vika alkuperäisessä algoritmissa:
	**   Jos m="*a" ja s="" ja s[1]!=0 (mikä tietysti sallittua!)
	**   niin vastaus oli 0.
	**   Korjattu 29.1.1994/vl muuttamalla rekursion jälkeinen
	**             if (!*++s) return 1;
	**   muotoon
	**             if (!*s || !*++s) return 1;
	----------------------------------------------------------------------------*/
	{
	  while (*m) {                    /* Jos kokeiltavaa jonoa on jäljellä      */
	    if (*m == '?') {              /* Jos kysymysmerkki, niin kaikki kelpaa  */
	      if (!*s) return 1;          /* paitsi jos jono on loppunut!           */
	    }
	    else if (*m == '*') {         /* Jos * niin katsotaan onko viimeinen    */
	      if (*++m)                   /* Jollei * viimeinen, niin kokeillaan    */
	        while (wildmat(s, m))     /* loppujonoa jokaiseen eri paikkaan.     */
	          if (!*s || !*++s) return 1;/* Jos jono loppuu kesken ei täsmää!   */
	      return 0;                   /* Muuten samat (* viimeinen tai loppujono*/
	    }                             /* täsmäsi)                               */
	    else if (*s != *m)            /* Jos samat merkit niin tietysti OK!     */
	      return 1;
	    s++; m++;                     /* Kummassakin jonossa eteenpäin          */
	  }
	
	  return *s;                      /* Jos jono loppui yhtäaikaa, niin OK!    */
	}
	...

Olemme lisänneet kirjastoon muutamia uusia aliohjelmia, joiden tarpeellisuuden totesimme jo kerhorekisterin suunnitteluvaiheessa.

Kirjastossa on mm. wildmat- aliohjelma merkkijonojen samaistamiseksi, kun jonossa saa esiintyä jokerimerkkejä * ja ? (vrt. MS- DOS).

Tehtävä 15.148 wildmat (opettavainen)

Pöytätestaa wildmat- aliohjelma syötöllä Kissa ja *ss*. Ohje: Kirjoita normaalin pöytätestin mukainen taulukko. Koska funktio kutsuu itseään, kannattaa jokaista uutta itseään kutsumista varten kirjoittaa oma uusi sarake uuden kutsukerran muuttujista. Osoittimet s ja m kannattaa säilyttää muodossa, jossa ne näyttävät loppumerkkijonon. Esimerkiksi:
	aluksi  s = "Kissa";  *s='K'
	s++  - > s = "issa"    *s='i'
	s++  - > s = "ssa"     *s='s'


previous next Up Title Contents Index