Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Väärien vastauksien tarkistaminen

Sivun loppuun

MIB [31.08.2009 18:05:49]

#

Moro taas.

Jos on $string, jonka arvo on "Pekalla on huomenna poutasää". Sitten käyn sen sanan merkit yksi kerrallaan läpi (for). Sitten on tuo strpos() funktio:

<?php
$string = "Pekalla on huomenna poutasää";
$haettava = $_GET["hae"];

for($i = 0; $i < strlen($string); $i++) {
   $strpos = strpos($haettava, $string[$i];
   //...
}
?>

Nyt tuolla for käydä läpi, että montako arvausta on väärin (Eli jos on arvattu p, e, k, a, l, o, x esimerkiksi), niin pitäisi laskea että miten monta on arvauksissa väärin. Jos laitan vaan, että $vaarin = 0; if($strpos == false) $vaarin++;, niin se ei toimi. Ainakaan ei minulla.

Elikkä, jos merkkiä ei löydy $string muuttujasta, niin lisätään $vaarin muuttujan arvoa yhdeltä. Eli oikeastaan näin:

<?php
$sana = "Pekalla on uusi auto.";
$arvaukset = $_GET["arvaukset"];

$vaarin = 0;

for($i = 0; $i < strlen($sana); $i++) {
	$strpos = strpos($arvaukset, $sana[$i]);

	if($strpos == false) $vaarin++;
	else continue;
}

echo $vaarin;
?>

Tuossa vaan on ongelma: Tuo laskee tyhjänkin merkinnän vääräksi, eli jos $_GET["hae"] taulukko on tyhjä, niin on tuon mukaan 21 väärää vastausta.
Toivottavasti hoksaatte mitä haen.

trilog [31.08.2009 18:14:38]

#

<?php
$sana = "Pekalla on uusi auto.";
$arvaukset = (isset($_GET["arvaukset"]) ? $_GET["arvaukset"] : NULL);

$vaarin = 0;

if ($arvaukset) {
    for ($i = 0; $i < strlen($sana); $i++) {
        $strpos = strpos($arvaukset, $sana[$i]);

        if ($strpos === false) $vaarin++;
    }

    echo $vaarin;
}
?>

MIB [31.08.2009 18:17:37]

#

Ei toimi noin. Jos laittaa "?arvaukset=p", niin tulos on heti 21.

trilog [31.08.2009 18:20:24]

#

MIB kirjoitti:

Ei toimi noin. Jos laittaa "?arvaukset=p", niin tulos on heti 21.

Niin, eikö tässä juuri siitä ollut kyse? Eihän tuosta kyseisestä merkkijonosta p:tä löydy, P löytyy kylläkin.

Metabolix [31.08.2009 18:23:00]

#

Oma logiikkasi on nyt virheellinen. Yrität tarkistaa, mitä merkkejä puuttuu, vaikka pitäisi tarkistaa, mitkä ovat ylimääräisiä. Lisäksi 0 == false, joten et tunnista ensimmäistä merkkiä oikein, koska strpos palauttaa arvon 0. Oikea vertailu on ===. Myös isot ja pienet kirjaimet menevät nyt väärin, joten käytä strtolower-funktiota (tai strtoupper) sekä arvauksiin että arvattavaan.

MIB [31.08.2009 18:24:34]

#

No, tämä ei silti tee kokonaan haluttua.
Koitas itse. Se ei saisi palauttaa getillä ?arvaukset=P yhtään mitään. Eli, se laskisi väärät vastaukset vain niistä jotka on tuolla get muuttujassa.

?arvaukset=P, tulos 0
?arvaukset=p, tulos 1
?arvaukset=xyz, tulos 3

Edit. Juuri niin Metabolix, tuota tarkoitin. Ei tullut vaan tuota ylimääräinen sanaa mieleen. Kerrotko miten pitäisi muakata tota?

Metabolix [31.08.2009 18:59:58]

#

Vaihda $string ja $haettava toisin päin ja tee muut mainitsemani muutokset (vertailuoperaattori ja strtolower). Ja käytä PHP:n manuaalia, ennen kuin kysyt uudestaan, nimittäin siellä selitetään nämäkin kaksi asiaa.

MIB [31.08.2009 19:04:43]

#

Missä kohdin vaihdan $stringin ja $haettavan toisin päin?

Metabolix [31.08.2009 19:38:28]

#

No siinä tarkistuksessa. Nythän katsot, mitkä $stringin ovat $haettavassa, kun pitäisi katsoa, mitkä $haettavan merkit ovat $stringissä.

MIB [31.08.2009 21:03:13]

#

En ymmärtänyt oikein, voitko näyttää?

Chiman [31.08.2009 23:05:55]

#

Nyt käyt merkki kerrallaan läpi merkkijonoa "Pekalla on uusi auto." ja tutkit löytyykö sen merkkejä arvauksestasi.

Tarkoituksenasi kaiketi oli käydä läpi arvausta merkki kerrallaan ja tutkia löytyykö niitä merkkijonosta.

MIB [01.09.2009 08:26:14]

#

En vieläkään ymmärtänyt, että mitä pitäisi muuttaa. Siis, ainoa kohta mihin voisin kuvitella sen saavani, on tuo strpos(), mutta sitten siinä taas ei ole mitään järkeä jos P kirjaimesta etsitään "Pekalla on uusi auto." -tekstiä.

Chiman [01.09.2009 08:45:15]

#

Käy for-silmukassa läpi arvauksen merkkejä, älä arvattavan merkkijonon?

MIB [01.09.2009 16:31:04]

#

Voisitko antaa esimerkin? :/

Chiman [01.09.2009 16:49:54]

#

Valmista koodia en anna, koska et näytä yhtään halukkuutta miettiäksesi asiaa itse, vaikka virhekohtaa on sinulle selitetty.

Aloitusviestissäsi selität omaa tai jonkun muun sinulle tekemää koodia väärin. Sanot "jos merkkiä ei löydy $string muuttujasta", vaikka koodi ei etsi merkkiä $string-muuttujasta, vaan $haettavasta. Käyt for-silmukassa läpi väärää merkkijonoa ja etsit sen merkkejä väärästä merkkijonosta.

Metabolix [01.09.2009 18:45:02]

#

Tässä yksi "korjaus", tosin enemmänkin tässä rikotaan koodia vielä toisestakin kohti niin, että se näyttää lopulta toimivan oikein:

<?php
$sana = $_GET["hae"];
$haettava = "Pekalla on huomenna poutasää";

Mieti sitä sitten. Olen asiasta aivan samaa mieltä kuin Chiman: tässä on jo selityksiä varmaan kymmenen vastaavan ongelman tarpeiksi, ja silti et tunnu millään tajuavan. Oletko edes yrittänyt korjata asiaa mitenkään? Miten? Mikä oli lopputulos? Mikä tässä esitetyissä neuvoissa ("vaihda kaksi muuttujaa silmukasta") on hankala ymmärtää?

MIB [02.09.2009 15:59:47]

#

No, sain sen sitten toimimaan.

<?php
$sana = $_GET["sana"];
$lause = "Pekalla on uusi auto.";
$vaarat = 0;
$merkit = "";

echo "V&auml;&auml;r&auml;t ennen for-silmukkaa: " . $vaarat . "<br>";
for($i = 0; $i < strlen($sana); $i++) {
	$pos = strpos($lause, $sana[$i]);

	if($pos === false) {
		$vaarat++;
		$merkit .= $sana[$i];
	}
}

echo "V&auml;&auml;r&auml; merkkien summa: " . $vaarat . "<br>";
echo "V&auml;&auml;r&auml;t merkit: $merkit";
?>

Ehkä sen voisi tehdä vähän helpomminkin (?), mutta noin nyt aluksi. Kiitos teille avusta.

Metabolix [02.09.2009 17:42:36]

#

Toivottavasti nyt jälkikäteen käsität, että olet tehnyt tuossa juuri sen muutoksen, jota tässä on pitkän aikaa yritetty selittää, eli olet vaihtanut for-silmukan käymään läpi eri muuttujaa, ja olet vaihtanut strpos-funktion parametrit vastaavasti oikein. Aluksihan hait sanasta lauseen merkkejä, nyt haet lauseesta sanan merkkejä.

MIB [02.09.2009 18:25:58]

#

Kyllä ymmärsin.

Huomasin tässä, että tuo ei nähtävästi osaa ääkkösiä käyttää oikein.

<?php
for($a = 0; $a < strlen($aakkoset); $a++) {
		$strpos2 = strpos($arvaukset, $aakkoset[$a]);

		if($strpos2 === false) {
			//Tulostetaan arvauslinkit
			echo "<a href=\"hirsipuu.php?a=" . $_GET["a"] . $aakkoset[$a] . "\">" . $aakkoset[$a] . "</a>&nbsp;";
		} else echo "<strike>" . $aakkoset[$a] . "</strike>&nbsp;";
	]
?>

Tuon pitäisi siis yliviivata kaikki merkit, jotka on arvattu. Tämä ei vain yliviivaa ääkkösiä. Eli, tuo strpos() ei nähtävästi osaa käsitellä ääkkösiä?

Esimerkki: ?kirjaimet=abcäöå
Tulostus: <strike>a</strike> <strike>b</strike> <strike>c</strike> ä ö å
Vaikka tulostuksen kuuluisi olla: <strike>a</strike> <strike>b</strike> <strike>c</strike> <strike>ä</strike> <strike>ö</strike> <strike>å</strike>

Metabolix [02.09.2009 18:32:10]

#

Jos käytät UTF-8-merkistöä, ääkköset vievät kaksi tavua. PHP on tyhmästi suunniteltu yksitavuisille merkistöille, ja UTF-8:n käyttö edes jossain määrin oikein vaatii mbstring-laajennoksen, ja merkkien hakuun pitää hakasulkujen sijaan käyttää substr-funktiota. Voit myös muuttaa merkit tarkistuksen ajaksi toiseen merkistöön iconv-funktiolla (vaatii iconv-laajennoksen), tai voit vaihtaa ääkköset str_replacella muiksi merkeiksi (%, $, @ jne; valitse tavallisia ASCII-merkkejä, joita tekstissä ei muuten esiinny).

MIB [03.09.2009 08:46:13]

#

Kyllä käytän UTF-8 merkistöä. Minulla pitäisi olla kyllä käytössä mbstring ja iconv laajennukset.

Metabolix kirjoitti:

merkkien hakuun pitää hakasulkujen sijaan käyttää substr-funktiota.

Anteeksi miten? En oikein hoksannut, että mitkä hakasulkeet pitää poistaa ja laittaa substr-funktio.

Koitin korvata ääkköset erikoismerkeiksi ja palauttaa takaisin, mutta ei toiminut. Jos ette ole vielä keksineet, että mitä tästä voisi tulla, niin sanon että hirsipuu-peli.

MIB [03.09.2009 09:47:37]

#

Muuten, miten saisin tuon kelpuuttamaan kaikenkokoiset kirjaimet? IF-lauseella varmaankin, mutta nyt ei raksuta. Täytyy koulupäivän aikana miettiä lisää.

Grez [03.09.2009 10:01:15]

#

Usein kirjainkoosta riippumattomuus toteutetaan muuttamalla käyttäjän syöte esimerkiksi isoiksi kirjaimiksi (esim. strtoupper) ja koodaamalla tarkistukset pelkille isoille kirjaimille. Tällöin homma toimii, antoi käyttäjä sitten pieniä tai isoja kirjaimia.

MIB [03.09.2009 10:04:42]

#

Nojuu, kyllähän se sillain on järkevintä. No, nyt muutin kaikki isoiksi kirjaimiksi. Vielä kun saan ääkköset kuntoon :D

Metabolix [03.09.2009 10:19:29]

#

Mene sivulle hirsipuu.php?a=ä ja tulosta seuraavat:

<?php
$q = explode("=", $_SERVER['QUERY_STRING']);
echo "<p>", end($q), "</p>";
echo "<p>", urlencode($_GET['a']), "</p>";
echo "<p>", urlencode('ä'), "</p>";

Ensimmäisestä pitäisi selvitä varmasti, missä merkistössä selain lähettää tekstin. Toisen pitäisi olla sama, ellei PHP tee jotain mystistä muunnosta välissä. Kolmas kertoo, missä merkistössä varsinainen PHP-koodisi on, ja jos tämä poikkeaa edellisestä, olet mokannut sivujesi merkistöjen kanssa pahan kerran.

Tuota strtoupper-muunnosta ehdotin jo kauan sitten. Lisäksi kannattaa pitää mielessä, että se ei välttämättä osaa muuttaa ääkkösiä.

MIB [03.09.2009 14:27:12]

#

ä

%E4

%C3%A4

En usko että tuo on se mitä kuuluu, vai olenko väärässä?

Metabolix [03.09.2009 14:46:12]

#

Kuten näet, GET-muuttuja on ISO-8859-1-enkoodattu mutta PHP:n 'ä' on UTF-8-enkoodattu. (Ensimmäisessä kohdassa selain ei toiminutkaan aivan odotetusti, mutta tällä ei nyt ole merkitystä, koska vika selvisi kahdesta jälkimmäisestä.)

Lähetätkö sivujesi mukana tiedon oikeasta merkistöstä? Jos katsot esimerkiksi Firefoxin Live HTTP Headers -lisäosalla HTTP-otsikoita, mitä Content-Type-otsikossa lukee?

Voit lähettää oikean sisältötyypin header-funktiolla:

<?php
// "text/html" tarkoittaa HTML:ää tai XHTML 1.0:aa.
header("Content-Type: text/html; charset=UTF-8");

Sama tieto on hyvä lisätä (X)HTML-koodin head-osioon:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

Lisäksi voit asettaa php.ini-tiedostoon merkistön:

default_charset = "UTF-8"

MIB [03.09.2009 19:41:31]

#

Minulla ei ole noista mitään käytöss tuolla. Mitä enemmän laitan noita, sitä enemmän sotkee.
Voisin alkaa tästä lähdin tallentamaan sivut joksikin muuksi, vaikka ISO-8859-1 koodatuiksi. Kai PHP tätä tukee paremmin?

Ärsyttää, kun aina kaikki jää jumiin tuohon ääkkös-juttuun. Toivottavasti PHP:n 6 versiossa olisi kunnon tuki ääkkösille.

~MIB

Metabolix [03.09.2009 20:06:04]

#

Älä viitsi poistella ja lähettää uudestaan viestejäsi, annat vain huonon kuvan itsestäsi. :(

Kyllä, PHP tukee yksitavuisia merkistöjä paremmin, eikö se jo käynyt keskustelusta ilmi? Se, että sait UTF-8-jutuilla koodisi entistä pahemmin rikki, tarkoittaa, ettet oikeastaan ymmärrä, mikä se UTF-8 on, miksi se vaatii erilaista käsittelyä ja miksi koodisi ei silloin toimi. Ei ole mikään ongelma saada kaikkea toimimaan UTF-8:n kanssa, mutta luultavasti säästät kaikkien hermoja, kun vaihdat ISO-8859-1:een. Tuskin kuitenkaan tarvitset vieraita merkistöjä (kuten kyrillisiä tai muita itämaisia), ja ainahan voit käyttää HTML-merkintöjä (&euro; jne.).

MIB [04.09.2009 07:55:50]

#

Kyllähän voin laittaa ääkköset näiksi &auml, &ouml, jne merkeiksi, mutta sitten pitää taas säätää lisää: Koska koodini käsitelee merkin kerrallaan, niin sitä täytyy muokata.

MIB [04.09.2009 13:39:45]

#

No, laitampas vielä pari kysymystä:
1. Jos muuttaisin kaikki sivut tuoksi ISO-8859-1 merkistöön, niin missä muodossa editorini ne pitäisi tallentaa?
2. Tämä ISO-8859-1 siis osaa käsitellä ääkköset yhtenä merkkinä, ja PHP:n kanssa tälläinen ~keskitason koodaaja osaa sitä käyttää helpommin?

Metabolix [04.09.2009 13:52:18]

#

MIB kirjoitti:

1. Jos muuttaisin kaikki sivut tuoksi ISO-8859-1 merkistöön, niin missä muodossa editorini ne pitäisi tallentaa?

ISO-8859-1-muodossa. Windowsissa cp1252 (suomenkielisen Windowsin oletusmerkistö) on suunnilleen vastaava.

MIB kirjoitti:

2. Tämä ISO-8859-1 siis osaa käsitellä ääkköset yhtenä merkkinä, ja PHP:n kanssa tälläinen ~keskitason koodaaja osaa sitä käyttää helpommin?

Merkistö ei käsittele yhtään mitään, vaan merkistö on sopimus siitä, mitä asiat tarkoittavat. ISO-8859-1:ssä on sovittu, että tavu %E4 tarkoittaa ä-kirjainta, ja UTF-8:ssa on sovittu, että tavupari %C3%A4 tarkoittaa ä-kirjainta. PHP:n suunnittelijat ovat ajatelleet, että yksi tavu vastaa yhtä merkkiä, joten ISO-8859-1 toimii helposti oikein, koska siinä tosiaan yksi tavu on aina yksi merkki. Sen sijaan UTF-8:ssa merkki voi olla monen tavun mittainen, jolloin PHP käsittelee tekstiä väärin. Tällaisia merkistöjä varten on vasta jälkikäteen kehitelty PHP:hen paikkauksia ja purkkavirityksiä, ja siksi niiden käyttö vaatii jonkin verran tietämystä siitä, mistä kohti PHP:tä on paikattu ja mistä ei ja milloin asialla on merkitystä. (Sama tilanne on monessa muussakin vanhassa ohjelmointikielessä. Monia ei ole edes yritetty paikata, jolloin ongelmia ei ole, kun kaikki pitää tietää itse. ;] Jotkin taas on paikattu niin hyvin, että UTF-8 toimii jo hienosti.)

Mutta kyllä, sadannen kerran, ISO-8859-1:tä on helpompi käyttää.

MIB [04.09.2009 13:57:59]

#

Editorissani, Notepad++, ei ole tuollaista suoraan. Vaihtoehdot ovat: ANSI, UTF8 Without BOM, UTF8, UCS-2 Big Endian ja UCS-2 Little Endian.

Metabolix [04.09.2009 13:59:50]

#

Testaapa, toimisiko ANSI.

MIB [04.09.2009 14:07:00]

#

Kiitos! Nyt sain toimimaan :)

Edit. Katos, Grez otti vastauksen pois, kun oli samallainen kuin Metabolixella :D

MIB [04.09.2009 15:37:37]

#

Kysyisin vielä, että miksi tämä ei toimi?

<?php
...
for($a = 0; $a < strlen($aakkoset); $a++) {
		$strpos2 = strpos($arvaukset, $aakkoset[$a]);

		if($strpos2 === false) {
			echo "<a href=\"$sivu?a=" . $_GET["a"] . $aakkoset[$a] . "\">" . $aakkoset[$a] . "</a>&nbsp;";
		} else {
			echo "<u><strike>" . $aakkoset[$a] . "</strike></u>&nbsp;";
		}
	}
...
?>

Se ei ikinä anna tulosta, että olisi jo arvattu ko. kirjain. Eli, jos on jo arvattu kirjain, niin sen pitäisi olla listassa yliviivattuna. Muuten linkkinä.

Metabolix [04.09.2009 15:44:35]

#

Miksi käytät sekaisin $_GET["a"]:ta ja $arvaukset-muuttujaa? Onko $arvaukset-muuttujan sisältö oikea? Oletko muistanut strtoupper-kutsun?

Chiman [04.09.2009 15:47:42]

#

Tuollaisissa tapauksissa tulosta $aakkoset- ja $arvaukset-muuttujien sisällöt, niin pystyt päättelemään vian.

MIB [04.09.2009 15:49:07]

#

Metabolix keksikin sen jo... En ollut muistanut tuota strtoupper funktiota laittaa oikeaan kohtaan.


Sivun alkuun

Vastaus

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

Tietoa sivustosta