Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: tiedostosta lukeminen

Sivun loppuun

rosie [19.11.2013 22:09:22]

#

Mulla nyt tökkää tässä siihen, että ohjelmani toimii muuten mutta en saa tehtyä siihen looppia, joka lukisi seuraavan rivin. Millaisella loopilla tämä nyt pitäisi käydä läpi? Nyt siis koodi näyttää tältä:

tiedosto = open("merkkijonoja.txt", "r")
sisalto = tiedosto.readline()
salasana = sisalto.rstrip('\n')
ehto = salasana.isalnum()

for i in salasana:

	if ehto == False:
		print (salasana, "sisältää virheellisiä merkkejä.")

	else:
		print (salasana, "kelpaa salasanaksi.")

tiedosto.close()

ja TEHTÄVÄNANTO:
Lähdekooditiedoston kanssa samaan hakemistoon on tallennettuna tiedosto "merkkijonoja.txt". Tämä tiedosto sisältää satunnaisesti luotuja merkkijonoja, joissa esiintyy kahdenlaisia merkkijonoja: sellaisia, joissa on kirjaimia ja mahdollisesti numeroita, sekä sellaisia, joissa on kirjaimia, numeroita ja erikoismerkkejä (€,#,{, §, jne). Tehtävänäsi on tehdä ohjelma, joka lukee tiedostosta rivin, testaa onko merkkijono sellainen, joka sisältää vain kirjaimia ja numeroita, ja sen mukaan tulostaa joko "[merkkijono] kelpaa salasanaksi" jos on, tai "[merkkijono] sisältää virheellisiä merkkejä." mikäli siinä on ei-alfanumeerisia merkkejä. Toimiessaan ohjelma tulostaa seuraavaa:

5345m345ö34l kelpaa salasanaksi.
no2no123non4 kelpaa salasanaksi.
noq234n5ioqw#% sisältää virheellisiä merkkejä.
%#""SGMSGSER sisältää virheellisiä merkkejä.
(...jne...)

Metabolix [19.11.2013 23:09:19]

#

Tässä on kaksi vaihtoehtoa tiedoston lukemiseen. Ensimmäinen lukee ensin kaikki rivit ja vasta sitten aloittaa silmukan, ja jälkimmäinen taas lukee rivejä silmukan edetessä.

for salasana in tiedosto.readlines():
	# tarkista ja tulosta
for salasana in tiedosto:
	# tarkista ja tulosta

Nykyisessä koodissasi on aivan väärässä paikassa for-silmukka: nyt i käy läpi kaikki salasanan merkit, jolloin esimerkiksi salasanan ollessa "kissa2" tulostuu kuusi kertaa, että salasana kelpaa, ja salasanan ollessa "1+1" tulostuu kolme kertaa, että salasana ei kelpaa.

Ehkä olet myös ymmärtänyt myös ehto-muuttujan toiminnan väärin. Et voi tallentaa muuttujaan kokonaista ehtoa vaan ainoastaan ehdon tuloksen kyseisellä hetkellä. Muuttujan arvo ei vaihdu, vaikka ehdon tulos joskus myöhemmin olisikin erilainen:

salasana = "kissa2"
ehto = salasana.isalnum() # True
salasana = "1+1"
# ehto == True, vaikka salasana.isalnum() == False!

Ehto onkin viisainta vain kirjoittaa suoraan if-lauseeseen ilman turhia muuttujia.

uta [20.11.2013 07:54:12]

#

Onpa muuten harvinaisen idiootti tehtävänanto. Vai osaako joku kertoa hyvän syyn miksei salasana saisi sisältää erikoismerkkejä?

Metabolix [20.11.2013 10:02:52]

#

uta kirjoitti:

Vai osaako joku kertoa hyvän syyn miksei salasana saisi sisältää erikoismerkkejä?

Milloin salasanaa on rajoitettu jostain hyvästä syystä? Vieläkin on palveluita, joissa salasanan maksimipituus on 6–8 merkkiä.

Erikoismerkkien kieltäminen on sikäli perusteltavissa, että niitä ei voi (helposti) kirjoittaa kaikilla näppäimistöillä tai käyttöjärjestelmillä. Moni tulee ajatelleeksi asiaa vasta siinä vaiheessa, kun merkkejä ei löydy. Ulkomailla jo ä-kirjain voi olla mahdoton, ja merkit », ¿, ç, ø, ř ja ů eivät ehkä Suomessakaan aina onnistu.

Tästä päästäänkin siihen, että nähtävästi tehtävänannon tarkistus on epäonnistunut: se kelpuuttaa riskialttiin ö-kirjaimen muttei yksinkertaista ASCII-merkistön välilyöntiä tai viivaa. Itse asiassa isalnum-funktio hyväksyy jopa kiinaa ja japania. ”です kelpaa salasanaksi.”

Jos salasanaa oikeasti haluaa rajoittaa, hyödyllisintä olisi sallia vain ASCII-merkit tai jopa vain ASCII-aakkoset, numerot ja selvimmät erikoismerkit. Jos rajoitukselle ei ole selvää teknistä syytä (esim. koodari on tunari tai joudutaan käyttämään jotain ikivanhaa järjestelmää), ei ehkä kannata suoraan kieltää ”huonoa” salasanaa vaan vain varoittaa sen ongelmista. Käyttäjä voi sitten itse arvioida, kaipaako salasanaansa ulkomailla tai ylipäänsä kodin ulkopuolella.

Näitä näkökulmia voisi mielellään välittää tehtävän laatijalle. Lisäterveisinä mainittakoon, että virheitä ei voi oikeuttaa sillä, että tehtävän pääpaino on muissa asioissa. ”Tänään opettelemme pilkku sääntöjä, ei tarvita yhdys sanoja.”

rosie [20.11.2013 22:11:06]

#

Kiitos vinkistä!

Pitääpä tutustua tuohon ehto-juttuun vielä jostain muualta, tuo pätkä (ehto = salasana.isalnum()) jota olen koodissa käyttänyt on nimittäin suoraa kurssimateriaalista...

rosie [21.11.2013 21:50:49]

#

Alkaako tämä näyttää teistä yhtään paremmalta? Jotenkin en nyt vaan tajua, että miten tähän saa sen loopin toimimaan niin tähän mennessä tää nyt tulostais tuon ensimmäisen rivin tällä oikein, mutta siihenpä tämä taas tökkääkin...

tiedosto = open("merkkijonoja.txt", "r")
sisalto = tiedosto.readline()
salasana = sisalto.rstrip('\n')


if salasana.isalnum():
	print(salasana,"kelpaa salasanaksi.")
else:
	print(salasana,"sisältää virheellisiä merkkejä.")

tiedosto.close()

Metabolix [21.11.2013 23:05:56]

#

Ajattele loogisesti: mitkä asiat pitää tehdä yhden kerran, ja mitkä asiat pitää tehdä monta kertaa?

Silmukan aloittava for-rivi kuuluu heti tiedoston avaamisen jälkeen, ja silmukan pitää tietenkin sisältää tarkistus ja tulostus, kuten jo sanoin.

Jos asia tuntuu vaikealta, tee ensin silmukka, jossa vain tulostat kaikki salasanat, ja kun saat sen toimimaan, lisää tuo tarkistus.

rosie [22.11.2013 19:58:36]

#

Sori mulle nyt näyttää olevan tässä tehtävässä jotenkin ylivoimaista tuo silmukka, vaikka oon kaikki toistorakenteeseen liittyneet harjotuksetki tehny. Nyt siis koodi näyttää tältä:

# -*- coding: utf-8 -*-

tiedosto = open("merkkijonoja.txt", "r")

for salasana in range(11):
	sisalto = tiedosto.readline()
	poisto = sisalto.rstrip()
	ehto = poisto.isalnum()

	if ehto == False:
		print (sisalto, "sisältää virheellisiä merkkejä.")

	else:
		print (sisalto, "kelpaa salasanaksi.")

tiedosto.close()

mutta nyt ongelmana on se, että jos laitan silmukkaan

for salasana in tiedosto

niin tuo tulostaa vain joka toisen rivin, aloittaen 2. rivistä. Sitten taas tuolla in rangella se käy jokaisen rivin läpi ja on muuten ok mutta 1. tarkistuksessa on enemmän alkioita kuin toisessa, joten tehtävää ei hyväksytä koska toinen tarkistus ei onnistu (testaa kaksi salasanaa vähemmän). Ideoita?

Metabolix [22.11.2013 20:18:31]

#

Sinulla ei pidä olla erikseen readline-riviä, vaan silmukka käy automaattisesti läpi kaikki tiedoston rivit – vai mitä oikein ajattelit salasana-muuttujaan for-rivillä tulevan?

Chiman [22.11.2013 21:25:05]

#

Ehkä seuraava esimerkki selventää. Kokeile mitä tämä tulostaa:

# -*- coding: utf-8 -*-

tiedosto = open("merkkijonoja.txt", "r")

for salasana in tiedosto:
	print (salasana.rstrip())

tiedosto.close()

rosie [22.11.2013 21:47:44]

#

No niin nyt se toimii, kiitos!


Sivun alkuun

Vastaus

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

Tietoa sivustosta