Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: PHP: strpos ja ö-kirjain

Sivun loppuun

NuMiNi [03.07.2012 14:20:44]

#

	$yolauseke = '/^([0-9];Y)/';
	//;;;;;;;;6,99;Yö;;;;;;;

		// Tavoitteena etsiä muuaikariviltä joko "aina", "yö" tai "muu aika". Jos joku näistä löytyy kaikki on ok, jos ei löydy kyseessä poikkeama ja silloin mennään else-rakenteeseen
		if(strpos($nelikko['muuaikarivi'], $ainatunniste) || preg_match($yolauseke, $nelikko['muuaikarivi'], $osumat) || strpos($nelikko['muuaikarivi'], $muuaikatunniste))
		{
			$poikkeama4loytyi = false;
			echo "<font color='green'>PITAA YLEENSA TULLA</font><br>";
		}

		else
		{
			echo "<font color='red'>EI SAA TULLA KUIN HARVOIN</font><br>";
			$poikkeama4loytyi = true;
            // Tarvittavat toiminnot
		}

Eli tavoitteena on löytää preg_match ja strpos funktioilla tietyiltä riveiltä tietty hakusana. Vaihtoehtoja on kolme kappaletta tässä tapauksessa. Ongelma on se, että strpos ei käy jokaiseen, koska se ei toimi ö:n kanssa. Yritin ratkaista ongelman preg_matchilla mutta ei onnistu. Mikä mättää...

Tukki [03.07.2012 16:03:47]

#

NuMiNi kirjoitti:

Eli tavoitteena on löytää preg_match ja strpos funktioilla tietyiltä riveiltä tietty hakusana. Vaihtoehtoja on kolme kappaletta tässä tapauksessa. Ongelma on se, että strpos ei käy jokaiseen, koska se ei toimi ö:n kanssa. Yritin ratkaista ongelman preg_matchilla mutta ei onnistu. Mikä mättää...

Ö ei sinänsä ole ongelma strpos-funktiolle vaan merkistökoodaukset joissa yksi merkki esitetään useammalla kuin yhdellä tavulla eli esim. utf8:n kanssa se ei toimi mutta latin1:n kanssa toimii. Valitse siis stringinkäsittelyfunktiosi käyttämäsi merkistön mukaan, mb_strpos ja muut mb_* funktiot tukevat multibyte-merkistöjä.

Ja muista vertailla (mb_) strpos-funktion paluuarvoa tyypin kanssa jos olet kiinnostunut siitä löytyikö haettu sana vai ei. Osuma hakustringin alussa palauttaa 0 joka castautuu falseksi ilman tyyppiä vertailtaessa.

Metabolix [03.07.2012 17:21:26]

#

Tukki kirjoitti:

Ö ei sinänsä ole ongelma strpos-funktiolle vaan merkistökoodaukset joissa yksi merkki esitetään useammalla kuin yhdellä tavulla eli esim. utf8:n kanssa se ei toimi mutta latin1:n kanssa toimii.

Tämä on väärin, nimittäin strpos toimii aivan erinomaisesti merkistöstä riippumatta. Toki merkin paikka voi ihmisen näkökulmasta mennä pieleen, koska strpos laskee tavuja eikä merkkejä, mutta tämä ei estä funktion käyttöä merkkien etsimiseen.

Ainoa järkevä selitys sille, miksi funktio tällä kertaa "ei toimi", on väärän merkistön käyttö. Tarkista, että PHP-koodin merkistö on sama kuin käsiteltävän datan merkistö. Voit tutkia asiaa näin:

function merkisto($str) {
	if (!preg_match("`[\\x80-\\xff]`s", $str)) {
		return "ASCII";
	}
	if (!preg_match("`(?<=[\\x00-\\x7f]|^)(?=[\\x80-\\xbf])|(?<=[\\xc0-\\xff])(?![\\x80-\\xbf])`s", $str)) {
		return "UTF-8";
	}
	return "muu";
}

if (merkisto($data) != "ASCII" && merkisto($data) != merkisto("yö")) {
	printf("Merkistöt eivät täsmää! Data: %s, PHP: %s.", merkisto($data), merkisto("yö"));
}

Toinen vika koodissa on, että strpos-funktion paluuarvoa käytetään suoraan. Jos haettu sana on tekstin alussa, strpos palauttaa arvon 0 ja ehto onkin virheellisesti epätosi. Kun strpos-funktiolla tarkistetaan, onko teksti olemassa, kannattaa kirjoittaa strpos(...) !== false.

Säännöllisessä lausekkeessa on taas enemmänkin vikaa: alussa on ^, joka takia lauseke hyväksyy vain tekstin alussa olevan osuman, ja siitä puuttuu kokonaan puheena ollut ö-kirjain.

Yksi mahdollinen ratkaisu koko ongelmaan (tämän tiedon valossa) näyttäisi tältä:

if (count(array_intersect(explode(";", $rivi), array("aina", "yö", "muu aika")))) /* ... */;

Säännöllisellä lausekkeella taas voisi tehdä näin:

if (preg_match("/(^|;)(aina|yö|muu aika)(;|$)/", $rivi)) /* ... */;

NuMiNi [03.07.2012 18:52:51]

#

Kiitoksia neuvoista. Tuo merkistötarkistusfunktio ei anna mitään tulosta, mutta kyllä tässä mun systeemissä on noiden merkistöjen kanssa ongelma. Tekstitiedosto josta tiedot luetaan, on ASCII-muodossa. Mutta minun php:ssa ei ole mitään merkkimuunnoksia kun en oikein niistä ymmärrä mitään. Tai no oli siinä aiemmin näin:

header('Content-Type: text/html; charset=ISO-8859-1');

Tuon kanssa tiedostosta luetut tiedot näkyvät ääkkösten kanssa, mutta esim. php:n echolla ääkköset eivät puolestaan näy oikein. Mitähän tässä nyt kannattaisi kokeilla.

Tuo ;;;;;;;;6,99;Yö;;;;;;; kuvastaa yhtä riviä txt-tiedostossa josta tiedot luetaan. Ja Yön tilalla voi olla "Aina" jne.

Metabolix [03.07.2012 23:29:48]

#

NuMiNi kirjoitti:

Tuo merkistötarkistusfunktio ei anna mitään tulosta,

Miten niin "ei anna mitään tulosta"? Tietenkin se antaa jonkin tuloksen. Veikkaan, että teit antamallani koodilla jotain ihan hölmöä.

NuMiNi kirjoitti:

Tekstitiedosto josta tiedot luetaan, on ASCII-muodossa.

Jos tiedostossa on ö-kirjain, tiedosto ei voi olla ASCII-muodossa, koska ASCII ei sisällä ö-kirjainta.

NuMiNi kirjoitti:

Mutta minun php:ssa ei ole mitään merkkimuunnoksia kun en oikein niistä ymmärrä mitään.

Ei pidäkään olla.

NuMiNi kirjoitti:

Tai no oli siinä aiemmin näin: – – charset=ISO-8859-1 – – Tuon kanssa tiedostosta luetut tiedot näkyvät ääkkösten kanssa, mutta esim. php:n echolla ääkköset eivät puolestaan näy oikein. Mitähän tässä nyt kannattaisi kokeilla.

Olet siis tallentanut tekstitiedoston ISO-8859-1-koodauksella (tai vastaavalla, ehkä Windows-1252) mutta PHP-koodin jollain muulla (varmaan UTF-8). Sinun pitää tallentaa kummatkin tiedostot samalla merkistökoodauksella ja lähettää myös vastaava Content-Type-otsikko.

NuMiNi [04.07.2012 10:28:04]

#

Metabolix kirjoitti:

Miten niin "ei anna mitään tulosta"? Tietenkin se antaa jonkin tuloksen. Veikkaan, että teit antamallani koodilla jotain ihan hölmöä.

Käyttöohjetta ei tullut mukana, joten ilmestyi vain tyhjä sivu kun pikaisesti kokeilin.

Metabolix kirjoitti:

Jos tiedostossa on ö-kirjain, tiedosto ei voi olla ASCII-muodossa, koska ASCII ei sisällä ö-kirjainta.

Juu pitäs vissii perehtyä vähä ensin itsekin ennen kuin kysyy. Alkuperäinen tiedosto on ANSI-muodossa. Muutin utf-8 muotoon ja sillä ne ongelmat sitten ratkesi.

Joten kiitoksia kaikille avusta!

Tukki [04.07.2012 11:50:23]

#

Yleisestiottaen kannattaa muistaa että nettisivuja tehdessä merkistöt ovat olennainen asia ja että niihin tulisi kiinnittää huomiota aina kun merkkijonoja käsitellään tai tallennetaan. Ohjelmat eivät pääsääntöisesti itse yritä mitenkään automaattisesti tunnistaa merkistöä, vaan käsittelevät tekstejä sellaisina kuin niille on kerrottu merkistöjen olevan. Lähes jokaiselle mukana olevalle ohjelmalle (editori, tietokanta, selain,...) löytyy omat tapansa kertoa missä merkistössä käsiteltävä teksti on ja ohjelmoijan tehtävä on kertoa se.

Metabolix [04.07.2012 16:53:13]

#

NuMiNi kirjoitti:

Käyttöohjetta ei tullut mukana, joten ilmestyi vain tyhjä sivu kun pikaisesti kokeilin.

"Vastausohjetta ei tullut mukana, joten palautin tyhjän tenttipaperin." Luitko edes koodia? Huomasitko siinä yhtään kohtaa, jota pitäisi jotenkin täydentää – esimerkiksi jotain muuttujaa, josta mainittaisiin jo koodia edeltävässä selostuksessa ja johon vain sinä pystyisit asettamaan oikean arvon?

NuMiNi kirjoitti:

Alkuperäinen tiedosto on ANSI-muodossa.

Oikeasti ei ole olemassa mitään yhtä ja ainoaa ANSI-merkistöä, joten ei kannata puhuakaan sellaisesta. "ANSI-muoto" on Microsoftin hämäys ja voi tarkoittaa mitä tahansa Windowsin natiivia merkistöä – Suomessa yleensä Windows-1252-merkistöä, joka itse asiassa ei edes ole ANSI-merkistö.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta