Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Kurssien ja opiskelijoiden käsittely

Sivun loppuun

kapi [04.02.2015 12:24:22]

#

class Kurssi:

    def __init__(self, kurssiNimi):
        self.kurssinimi = kurssiNimi
        self.opiskelijat = []

    def asetaOpiskelijakurssille(self, uusiOpiskelija):
        self.opiskelijat.append(Opiskelija(uusiOpiskelija))
    #Luodaan uusi Opiskelija-luokan olio ja lisätään se opiskelijat listaan

class Opiskelija:

    def __init__(self, opiskelijaNimi):
        self.oppilasnimi = opiskelijaNimi
        self.suoritus = 9

    def palautaNimi(self, nimi):
        return self.oppilasnimi

    def asetaSuoritus(self, kurssiNimi):
        self.suoritus = (kurssiNimi)

    def tulosta(self):
        return self.oppilasnimi, self.suoritus
#aliohjelmat
def etsiOpiskelija(k):
    opiskelijaNimi = str(input("Anna OPISKELIJAN nimi: "))
    for oppilas in k.opiskelijat:
        if oppilas.oppilasnimi == opiskelijaNimi:
            return (oppilas)
    print("Ei löydy opiskelijaa nimellä", opiskelijaNimi)
    print("Palataan valikkoon.")
    return(None)

def etsiKurssi(kl):
    kurssiNimi = str(input("Anna KURSSIN nimi: "))
    for kurssi in kl:
        if kurssi.kurssinimi == kurssiNimi:
            return (kurssi)
    print("Ei löydy kurssia nimeltä", kurssiNimi)
    print("Palataan valikkoon.")
    return(None)

def lisaaKurssi(kl, tied):
    print ("---Kurssin lisäys---")
    uusiKurssi = str(input("Anna lisättävän KURSSIN nimi: "))
    for kurssi in kl:
        if kurssi.nimi == uusiKurssi:
            print ("Kurssi nimeltä", uusiKurssi, "on jo lisätty. Et voi lisätä samannimistä kurssia kahdesti.")
            valikko (kl)
    uusiKurssi = Kurssi(uusiKurssi)
    kl.append(uusiKurssi)
    print ("Kurssi lisätty onnistuneesti!")
    toimintasilmukka(kl, tied)

def lisaaOpiskelijakurssille(kl, tied):
    print ("---Opiskelijan lisäys kurssille---")
    kurssi = etsiKurssi(kl)
    if kurssi != None:
        uusiopiskelija = str(input("Anna lisättävän OPISKELIJAN nimi: "))
        kurssi.asetaOpiskelijakurssille(uusiopiskelija)
        uusiopiskelija = Opiskelija(uusiopiskelija)
        #kl.append(uusiopiskelija)
        print ("Opiskelija lisätty kurssille onnistuneesti!")
        toimintasilmukka(kl, tied)

def lisaaKurssisuoritus(kl, tied):
    print ("---Kurssisuorituksen lisäys opiskelijalle---")
    kurssi = etsiKurssi(kl)
    if kurssi != None:
        opiskelija = etsiOpiskelija(kurssi)
        if opiskelija != None:
            arvosana = int(input("Anna opiskelijan ARVOSANA (0-5): "))
            opiskelija.asetaSuoritus(arvosana)
            print ("Kurssiarvosana lisätty onnistuneesti!")
            toimintasilmukka(kl, tied)

def tulostaKurssisuoritus(kl, tied):
    print ("---Opiskelijan kurssisuoritusten tulostus---")
    oppilas = (input("Anna opiskelijan nimi: "))
    for i in kl[0].opiskelijat:
        print ("ei toimi")
    #opiskelija.tulostakurssiSuoritus()


def kirjoitaTiedostoon(kl, tied):
    print ("---Tietojen kirjoittaminen tekstitiedostoon---")
    tiedosto = open(tied, "a", encoding="UTF-8")
    for i in range(len(kl)):
        for j in range(3):
            tiedosto.write(kl[i][j]+"\n")
    tiedosto.close()
    print ("Tiedot kirjoitettu tekstitiedostoon kurssikirjanpito.txt")

def valikko(kl, tied):
    print ("********")
    print ("1. Lisää kurssi")
    print ("2. Lisää opiskelija kurssille")
    print ("3. Lisää opiskelijan kurssisuoritus")
    print ("4. Tulosta opiskelijan kurssisuoritukset")
    print ("5. Tietojen kirjoittaminen tekstitiedostoon")
    print ("0. Lopeta")
    print ("********")


def toimintasilmukka(kl, tied):
    valikko(kl, tied)
    while True:
        valinta = input("Anna valinta: ")
        if (valinta == "1"):
            lisaaKurssi(kl, tied)
        elif (valinta == "2"):
            lisaaOpiskelijakurssille(kl, tied)
        elif (valinta == "3"):
            lisaaKurssisuoritus(kl, tied)
        elif (valinta == "4"):
            tulostaKurssisuoritus(kl, tied)
        elif (valinta == "5"):
            kirjoitaTiedostoon(kl, tied)
        elif (valinta == "0"):
            print ("Kiitos ohjelman käytöstä!")
            break
        else:
            ("Annoit vääränlaisen valinnan. Anna valinta uudestaan.")
            toimintasilmukka(kl, tied)
#pääohjelma
tiedosto = "kurssikirjanpito.txt"
kurssilista = []
toimintasilmukka(kurssilista, tiedosto)

Teen tällä hetkellä ohjelmaa perusopintojen harjoitustyötä varten, ja olen nyt tapellut (todennäköisesti) erittäin yksinkertaisen ongelman kanssa jo 2 viikkoa. Haluaisin saada tulostettua Kurssi-luokan opiskelijat listan olion ja hänen suorituksen. Aliohjelmassa tulostaKurssisuoritus kysytään ensin halutun opiskelijan nimeä, jonka jälkeen ohjelman tulisi tulostaa kaikki kurssit ja niiden arvosanat joissa opiskelija on mukana.

Olen kokeillut monia eri keinoja, mutta edistystä ei ole tapahtunut tippaakaan. Kysyin apua myös opettajalta, mutta ilman esimerkkejä en pysty ymmärtämään kuinka kyseinen toimenpide saadaan aikaan..

Niin ja tiedän että tiedostoon kirjoittaminenkin on vielä väärin, mutta siihen en ole vielä edes perehtynyt. Todennäköisesti se tulee olemaan toinen 2 viikon ongelmakohta.

Kiitokset avusta jo ennakkoon.

Chiman [04.02.2015 14:41:37]

#

Tässä yksi esimerkki:

def tulostaKurssisuoritus(kl, tied):
    print("---Opiskelijan kurssisuoritusten tulostus---")
    oppilasnimi = input("Anna opiskelijan nimi: ")
    for kurssi in kl:
        for op in kurssi.opiskelijat:
            if op.oppilasnimi == oppilasnimi:
                print("Kurssi: %s - %d" % (kurssi.kurssinimi, op.suoritus))

Edit: muokkasin

kapi [04.02.2015 20:09:04]

#

No huhhuh. Sehän toimii kun junan vessa. Ei se kauhean kummoinen ongelma nähtävästi ollutkaan. Vaati tosiaan vaan sen esimerkin että oivaltaa miten se toimii.

Kiitokset avusta. Pääsee lopultakin eteenpäin tässä tehtävässä.

kapi [08.02.2015 21:45:47]

#

Pahoittelen että kysyn omassa topicissani uudestaan mutta en ollut varma onko järkevää laittaa miltei samanlaista koodinpätkää uudestaan uudella topicilla tällaisen (pikku)jutun takia.

Nyt tämä työ on edistynyt melko huimaa vauhtia, mutta eräs ongelma tähän vielä liittyy. Tällä hetkellä (ja jopa tuossa yllä olevassa koodissa) valinta 0 toimintasilmukassa ei lopeta ohjelmaa jos käyttäjä on tehnyt joitain muita toimintoja (eli valinnut valikosta 1,2,3,4 ta 5).

Ongelma johtuu vissiinkin siitä että muut aliohjelmat aina lopussa kutsuu toimintasilmukka aliohjelmaa, joka jollain tavalla sekoittaa tuon breakin. Tällä hetkellä break komento siis vain tulostaa tuon: Kiitos ohjelman käytöstä! lauseen ja kysyy uutta valintaa.

Onko tähän ongelmaan mitään järkevää ratkaisua? Eli sellaista ettei tarvitsisi poistaa noita toimintasilmukka-kutsuja muista aliohjelmista.

Teen työtä Notepad++:lla ja kaikki 4 pääosaa on omassa moduulissaan. Tämän vuoksi testasin ohjelmaa myös IDLE:llä, ja siellä oli sama tulos.

Oskuz [09.02.2015 09:24:13]

#

Älä kutsu toimintasilmukkaa esim. lisääKurssisuorituksen lopussa, vaan palaa silmukkaan return lauseella. Lisäksi kutsut turhaan toimintasilmukkaa elsessä.
Nyt kun syötät 0 se lopettaa kyllä silmukan, mutta palaat viimeisimpänä kutsuttuun toimintasilmukkaan, ja siut on syötettävä niille kaikille nolla ennen kuin ohjelma loppuu.
Esim:
nyt:

ts1 -> lks -> ts2 (0) ->lks ->ts1(0)

Kun sen pitäisi olla:

ts1 -> lks -> ts1 (0)

kapi [09.02.2015 16:11:51]

#

Kiitokset avusta. Tuo keino olisi muuten toiminut hyvin, mutta pelkän return-komennon avulla se ei tulosta käyttäjälle valikkoa. Tosin kiitos tuon sinun neuvon, oivalsin että nehän voisi yhdistää (valikko + toimintasilmukka) ja käyttää sitten tuota return-komentoa. Nyt siis toimii niinkuin pitääkin.

Kiitos avusta.

kapi [05.03.2015 15:43:13]

#

class Kurssi:

    def __init__(self, kurssiNimi):

        self.kurssinimi = kurssiNimi
        self.opiskelijat = []

    def asetaOpiskelijakurssille(self, uusiOpiskelija):

        self.opiskelijat.append(Opiskelija(uusiOpiskelija))

class Opiskelija:

    def __init__(self, opiskelijaNimi):
        self.oppilasnimi = opiskelijaNimi
        self.suoritus = 99

    def asetaSuoritus(self, arvoSana):
        self.suoritus = (arvoSana)

#Aliohjelmat
def etsiOpiskelija(k):

    opiskelijaNimi = str(input("Anna OPISKELIJAN nimi: "))
    for oppilas in k.opiskelijat:
        if oppilas.oppilasnimi == opiskelijaNimi:
            return (oppilas)
    print("Ei löydy opiskelijaa nimellä", opiskelijaNimi)
    print("Palataan valikkoon.")
    return(None)

def etsiKurssi(kl):

    kurssiNimi = str(input("Anna KURSSIN nimi: "))
    for kurssi in kl:
        if kurssi.kurssinimi == kurssiNimi:
            return (kurssi)
    print("Ei löydy kurssia nimeltä", kurssiNimi)
    print("Palataan valikkoon.")
    return(None)

def lisaaKurssi(kl):

    print ("---Kurssin lisäys---")
    uusiKurssi = str(input("Anna lisättävän KURSSIN nimi: "))
    for kurssi in kl:
        if kurssi.kurssinimi == uusiKurssi:
            print ("Kurssi nimeltä", uusiKurssi, "on jo lisätty. Et voi lisätä samannimistä kurssia kahdesti.")
            return
    uusiKurssi = Kurssi(uusiKurssi)
    kl.append(uusiKurssi)
    print ("Kurssi lisätty onnistuneesti!")
    return

def lisaaOpiskelijakurssille(kl):

    print ("---Opiskelijan lisäys kurssille---")
    kurssi = etsiKurssi(kl)
    if kurssi != None:
        uusiopiskelija = str(input("Anna lisättävän OPISKELIJAN nimi: "))
        for oppilas in kurssi.opiskelijat:
            if oppilas.oppilasnimi == uusiopiskelija:
                print("Opiskelija löytyy jo kurssilta", kurssi.kurssinimi,"\npalataan valikkoon.")
                return
        kurssi.asetaOpiskelijakurssille(uusiopiskelija)
        uusiopiskelija = Opiskelija(uusiopiskelija)
        print ("Opiskelija lisätty kurssille onnistuneesti!")
        return
    return

def lisaaKurssisuoritus(kl):

    print ("---Kurssisuorituksen lisäys opiskelijalle---")
    kurssi = etsiKurssi(kl)
    if kurssi != None:
        opiskelija = etsiOpiskelija(kurssi)
        if opiskelija != None:
            try:                 # Yritetään kysyä arvosanaa. Mikäli arvosana ei ole int-tyyppinen, siirrytään except kohtaan.
                arvosana = int(input("Anna opiskelijan ARVOSANA (0-5): "))
                if (arvosana > 5) or (arvosana < 0):   # Jos arvosana on pienempi kuin 0 tai suurempi kuin 5, arvosanaa ei lisätä.
                    print ("Annoit vääränlaisen syötteen. Ainoastaan numerot 0-5 kelpaavat.")
                    return
                else:
                    opiskelija.asetaSuoritus(arvosana)
                    print ("Kurssiarvosana lisätty onnistuneesti!")
            except (ValueError): # Suoritetaan tämä kohta vain jos annettu arvosana syöte ei ollut int-tyyppinen.
                print("Annoit vääränlaisen syötteen. Ainoastaan numeerinen arvosana kelpaa.")
    return

def tulostaKurssisuoritus(kl, tied):

    print ("---Opiskelijan kurssisuoritusten tulostus---")
    oppilas = (input("Anna OPISKELIJAN nimi: "))
    print("Opiskelijan", oppilas ,"kurssisuoritukset")
    for kurssi in kl:
        for op in kurssi.opiskelijat:
            if op.oppilasnimi == oppilas:
                print("Kurssi: %s -- Arvosana: %d" % (kurssi.kurssinimi, op.suoritus))
    tiedosto = open(tied, "r", encoding="UTF-8")
    print("\nTekstitiedostoon tallennetut kurssisuoritukset:\n")
    while True:
        suoritus = tiedosto.readline()
        if len(suoritus) == 0:
            break
        print (suoritus)
    tiedosto.close()
    return

def kirjoitaTiedostoon(kl, tied):

    print ("---Tietojen kirjoittaminen tekstitiedostoon---")
    now = datetime.datetime.now()
    tiedosto = open(tied, "a", encoding="UTF-8")
    tiedosto.write(now.strftime("Päivämäärä %Y-%m-%d %H:%M\n"))
    for kurssi in kl:
        for op in kurssi.opiskelijat:
            tiedosto.write("%s\t%s\t %d \n" % (op.oppilasnimi, kurssi.kurssinimi, op.suoritus))
    tiedosto.close()
    print ("Tiedot kirjoitettu tekstitiedostoon kurssikirjanpito.txt")
    return

def varmistus(varmistetaan):

    if varmistetaan:
        print("Et ole tallentanut tekemisiäsi toimintoja (Valinta 5).")
        vastaus = input("Haluatko palata takaisin valikkoon? (k/e): ")
        if vastaus == "k" or vastaus =="K":
            print("Palataan takaisin valikkoon.")
            return(True)
    return(False)

def toimintasilmukka(kl):

    varmennus = False
    tiedosto = "kurssikirjanpito.txt"
    while True:
        print ("********")
        print ("1. Lisää kurssi")
        print ("2. Lisää opiskelija kurssille")
        print ("3. Lisää opiskelijalle kurssisuoritus")
        print ("4. Tulosta opiskelijan kurssisuoritukset")
        print ("5. Tietojen kirjoittaminen tekstitiedostoon")
        print ("0. Lopeta")
        print ("********")
        valinta = input("Anna valinta: ")
        if (valinta == "1"):
            lisaaKurssi(kl)
            varmennus = True
        elif (valinta == "2"):
            lisaaOpiskelijakurssille(kl)
            varmennus = True
        elif (valinta == "3"):
            lisaaKurssisuoritus(kl)
            varmennus = True
        elif (valinta == "4"):
            tulostaKurssisuoritus(kl, tiedosto)
        elif (valinta == "5"):
            kirjoitaTiedostoon(kl, tiedosto)
            varmennus = False
        elif (valinta == "0"):
            if varmistus(varmennus):
                continue
            print ("Kiitos ohjelman käytöstä!")
            break
        else:
            print ("Annoit vääränlaisen valinnan. Anna valinta uudestaan.")

#Pääohjelma
kurssilista = []                    # Alustetaan kurssilista
toimintasilmukka(kurssilista)       # Kaikki toiminta toimintasilmukassa

Terve taas. Kuten kuvasta näkyy, ohjelmaan on tehty muutoksia. Tosin nyt olen yrittänyt saada ohjelman tulostaKurssisuoritus aliohjelman toimimaan niin, että se osaisi ottaa huomioon myös tekstitiedostoon tallennetut tiedot. Esimerkiksi jos Matille on eilen tallennettu kurssitieto: matikka 5, niin seuraavana päivänä jos käytän ohjelmaa ja tulostan Matin tiedot, niin ohjelma tulostaa myös tekstitiedostossa olevat tiedot ohjelman tämänhetkisten tietojen lisäksi.

Tällä hetkellä sain lisättyä vain toiminnon että ohjelma tulostaa koko tekstitiedoston sisällön tulostuksen yhteydessä, mutta tämä käy melko raskaaksi erityisesti jos tekstitiedostossa on paljon eri tietoja.

Onko ideoita kuinka saisi siis otettua tekstitiedostosta pelkästään halutun opiskelijan tiedot ja tulostettua ne näytölle?

Grez [05.03.2015 16:59:49]

#

kapi kirjoitti:

Onko ideoita kuinka saisi siis otettua tekstitiedostosta pelkästään halutun opiskelijan tiedot ja tulostettua ne näytölle?

Tuossa kun olet lukenut suoritusrivin, niin tarkistat että onko se valitun opiskelijan ja tulostat sen vain mikäli se koskee valittua opiskelijaa.

#...
    tiedosto = open(tied, "r", encoding="UTF-8")
    print("\nTekstitiedostoon tallennetut kurssisuoritukset:\n")
    while True:
        suoritus = tiedosto.readline()
        if len(suoritus) == 0:
            break
        #Lisää if lause että seuraava rivi suoritetaan vain, jos suoritus koskee valittua opiskelija
        print (suoritus)
    tiedosto.close()
    return
#...

Käytännössä siis rivin pitäisi alkaa opiskelijan nimi + tabulaattorilla.

kapi [05.03.2015 17:14:38]

#

Kannattaisiko minun siis ottaa tuo päivämäärän lisäys toiminto kokonaan pois jotta helpottuu tämä tulostushomma?

Lisäys:

Ohoh..Sainpas tehtyä sen hiukan eri tavalla.
Jos nyt muut tappelee joskus saman ongelman kanssa, niin tässä ainakin yksi vaihtoehto jonka keksin, parempiakin keinoja voi kertoa. :)

#...
    tiedosto = open(tied, "r", encoding="UTF-8")
    print("\nTekstitiedostoon tallennetut kurssisuoritukset:\n")
    rivit = tiedosto.readlines()
    for rivi in rivit:
        if rivi.startswith (oppilas):
            print (rivi)
    tiedosto.close()
    return
#...

Kiitokset Grezzille avusta. Pisti aivot enemmän miettimään niin helpotti ratkaisun keksimisessä.

Metabolix [05.03.2015 17:45:42]

#

Nykyinen koodisi luultavasti toimii väärin, jos tiedostossa esiintyvät esimerkiksi Jani ja Janipetteri: haku nimellä Jani tulostaa molempien tulokset. Sinun pitää startswith-kohdassa lisätä oppilaan nimen perään se erotinmerkki, joka tiedostossa merkitsee nimen päättymistä.

kapi [05.03.2015 17:56:59]

#

Juu, itse huomasin että ei se toimi ihan niinkuin pitäisi. Tarkoitatko erotinmerkillä tabia? Tiedostossa nimi loppuu aina tabiin, jonka jälkeen tulee kurssi ja arvosana.

Metabolix [05.03.2015 18:17:54]

#

Sitten tarkoitan tabia.

kapi [05.03.2015 18:24:42]

#

Noniin. Se oli nopea korjaus. Nyt näyttäisi toimivan niinkuin pitääkin. Kiitos Metabolix avusta. :)


Sivun alkuun

Vastaus

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

Tietoa sivustosta