Ubuntu Suomen keskustelualueet

Ubuntun käyttö => Ohjelmointi, palvelimet ja muu edistyneempi käyttö => Aiheen aloitti: Jere Sumell - 12.02.21 - klo:09.50

Otsikko: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: Jere Sumell - 12.02.21 - klo:09.50
Mitenkäs C-kielessä voisi tarkistaa syötteen tietotyypin? Esimerkkinä tällainen ohjelma, kun laskee kertoman komentorivin parametrista, pitäisi tarkistaa, onko syöten int-tyyppiä, eikä negatiivinen eikä muumerkkijono

Koodia: [Valitse]
#include <stdio.h>

//Declaring function(s)
int kertoma(int x);

int kertoma(int x) {
    if (x<=0) {
    return 1;
    }
    return (x*kertoma(x-1));
}
//Main Method
int main(int argc, char *argv[]) {
    if (argc <=1) {
        printf("Syötä parametrina luku, jonka kertoman tuloksen haluat selvittää!");
    }
    else
    {
        int tulos;
        int input = atoi(argv[1]);
        tulos = kertoma(input);
        printf("%d",tulos);
    }
}

Minimalistisin keino olisi vähiten koodia että tarvitsisi kirjoittaa, lyhtentäisin koodia

Koodia: [Valitse]
#include <stdio.h>

//Declaring function(s)
int kertoma(int x);

int kertoma(int x) {
    if (x<=0) {
    return 1;
    }
    return (x*kertoma(x-1));
}
//Main Method
int main(int argc, char *argv[]) {
    if (argc <=1) {
        printf("Syötä parametrina luku, jonka kertoman tuloksen haluat selvittää!");
    }
    else
    {

        printf("%d",kertoma(atoi(argv[1]));
    }
}

Eli eliminoisin tarvittavien muuttujien sijoitusoperaatiot lauseella

Koodia: [Valitse]
printf("%d",kertoma(atoi(argv[1]));
Meneekö se ihan tuossa haarautumis-ehtolausekohdassa tuolla
if (argc <=1 ), vai miten tuon syötteen tyypin voisi tarkistaa, että jos käyttäjä syöttää esimerkiksi stringin

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:10.09
Kävi mielessä, että kun C-kieli käsittelee char-taulukkona komentorivin syötteet, niin pitäisikö joka tietotyypille kirjoittaa jokin ylikuormitettu (overload) "tulosta" -metodi, jossa merkkijono muunnettaisiin yhdessä intiksi, jos liukuluku syötetään, sitten toisessa pyöristettäisiin lähimpään kokonaislukuun edellyttäen tietenkin, että ohjelma alussa sisällytettäisiin matematiikka-kirjasto käyttöön, mutta ongelma on edelleen jonkin aakkosia sisältävän käyttäjän syötteen tarkistus.

Palaa siihen kysymyseen, että pitäisi löytyä jokin keino tarkistaa tietotyyppi, että se olisi int, muuten ohjelma herjaa siitä tai ei tulosta mitään.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Ganymedes - 12.02.21 - klo:10.52
Enpä tunne kieltä tarpeeksi, mutta eikös se stringin voi vain (tyhjien poiston jälkeen) yrittää konvertoida INT:ksi? Jos ei pääty virheeseen, niin on oikein. Virheellä taas mennään virheenkäsittelyn alirutiiniin - mikä se se sitten onkaan näille tapauksille (jos on useita samanlaisia, jotka voi hoitaa vain eri parametrillä, muutoin tälle on vain oma rutiininsa).
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:11.30
Enpä tunne kieltä tarpeeksi, mutta eikös se stringin voi vain (tyhjien poiston jälkeen) yrittää konvertoida INT:ksi? Jos ei pääty virheeseen, niin on oikein. Virheellä taas mennään virheenkäsittelyn alirutiiniin - mikä se se sitten onkaan näille tapauksille (jos on useita samanlaisia, jotka voi hoitaa vain eri parametrillä, muutoin tälle on vain oma rutiininsa).

varmaan toi stringistä intiksi muunnosmetodi palauttaa intin, ja en tiedä, jos se olisi boolean tyyppinen palautusarvo, että jos muunto onnistuu, niin sitten tämä olisi ratkaistavissa sillä, mutta en tiedä mitä arvoja atoi-palauttaa, jos muunnos epäonnistuu jostain syystä. Katsoin Tutorialspointista Google-haulla "C language refence atoi" -hakutermillä, niin Tutorialspointissa metodin määrittely APIssa on seuraava

Koodia: [Valitse]
int atoi(const char *str)Kyseisessä artikkelissa ei kerrota, mikä palautusarvo sitten on, jos muunto epäonnistuu. joku intti se on, mutta mikä, tiedostonluvussa yleensä on -1 sitten kun EOF -saavutetaan, mutta -1 on validi  arvo, joka sijoittuu int-primaarimuuttujan arvo-alueeseen, joten se ei ole se tässä tilanteessa. Tietenkin voisi kokeilla, mitä se palauttaa ja käyttää tarkistuksessa sitä arvoa, jos se on jokin nullin kaltainen.

Tuo ohjelmanihan toimii vain niissä tapauksissa ongelmitta, jossa käyttäjä toimii "rehellisesti" annettujen sääntöjen ja puitteiden rajoissa, että antaa positiivisen kokonaisluvun, mutta siihen pitäisi vielä lisätä kaksi tarkistusta, eli tuo int-tyypin tarkistus, ja sen jälkeen vielä että luku on positiivinen, tai suurempi kuin 0, koska negatiivisista luvuista ei voi kertomaa laskea. Liukuluku-syötekään tuota niin paljon ongelmia, kuin aakkos- tai erikoismerkkipohjainen syöte.

Tietysti, jos tarkistaisi, että syöte on etumerkitön int, niin se poissulkisi -0 ja muut negatiiviset luvut, mutta juuri se kysymys, että onko sitä miten mahdollista varmistua siitä, että käyttäjä syöttää nimenomaan int-tyyppisen positiivisen luvun.

Tämä on juuri tätä poikkeus-ja ongelatilanteiden ohjelmointia, jolla ei itsessään ohjelmoinnin oppimisen kannalta ole juuri muuta merkitystä, muuta kuin jos teollisuuskoodaauksessa kuluu juuri tämän kaltaisiin paljon aikaa, kun pitää ajatella loppukäyttäjän näkökulmasta.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Ganymedes - 12.02.21 - klo:11.47
OK, mutta olettaisin, että tulee ERROR ja ohjelma kaatuu - tuonhan voit kokeillakin.

Löytyykö joku:

On Error Goto Virhetilanne, (Palautusarvo, "INT muunnos virhe")

, jolloin Virhetilanne alirutiini voi tulostaa ruudulle miksi ohjelma päätyi virheeseen, ja tehdä lisäksi mitä hyvänsä.

Virherutiini sitten palauttaa ohjelman takaisin parametrin kanssa ja pääohjelmassa jatketaan ehtolauseella, jossa testataan käytiinkö virheenkäsittelyssä vai ei ja toimitaan sen mukaan erilailla (joko jatketaan tai pyydetään uudestaan tai annetaan vaihtoehto lopettaa ohjelma).

Jatkettaessa tehdään negatiiviselle arvolle jotakin ... mutta sehän on eri (otetaan itseisarvo tai pyydetään uutta tai annetaan mahdollisuus lopettaa). Itse asiassa tämä INPUT-toimintokin on näköjään oma alirutiininsa, koska siinä on toistuvuutta jo näissä kahdessa kuvatussa asiassa.

... jotain tällaista noin periaatteessa. Sorry, en tiedä syntakseista mitään.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: SuperOscar - 12.02.21 - klo:12.13
Heh, atoi() on tasan niin typerä miksi Unix Hater’s Handbook koko C-kieltä manaa: jollei muunnos onnistu, palautuu vain arvo 0. Mikä tahansa merkkijono on siis oletusarvoisesti kokonaisluku nolla.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: _Pete_ - 12.02.21 - klo:12.17
Kävi mielessä, että kun C-kieli käsittelee char-taulukkona komentorivin syötteet, niin pitäisikö joka tietotyypille kirjoittaa jokin ylikuormitettu (overload) "tulosta" -metodi, jossa merkkijono muunnettaisiin yhdessä intiksi, jos liukuluku syötetään, sitten toisessa pyöristettäisiin lähimpään kokonaislukuun edellyttäen tietenkin, että ohjelma alussa sisällytettäisiin matematiikka-kirjasto käyttöön, mutta ongelma on edelleen jonkin aakkosia sisältävän käyttäjän syötteen tarkistus.

Palaa siihen kysymyseen, että pitäisi löytyä jokin keino tarkistaa tietotyyppi, että se olisi int, muuten ohjelma herjaa siitä tai ei tulosta mitään.

Ei pitäisi koska a) c:ssä ei ole ylikuormitusta ollenkaan b) eikä myöskään metodeita.

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: _Pete_ - 12.02.21 - klo:12.22
Itse merkkijono -> int scanf voisi toimia paremmin vs atoi.

Se pelauttaa onnistuko muunnos ja sillä voi siten ilmoittaa virheen ei numeroksi kelpaamattomasta inputista.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:12.37
Tsekkasin tuon palautusarvon "laittomilla" syötteillä, niin jos syöttää aakkosellista merkkijonotietoa  tai negatiivisen arvon, niin palautuu 1. Ratkaisin ongelman, että ensin lasken joka tapauksessa kertoman tuloksen, ja sitten ehtolause, jossa tulostetaan ohje sen jälkeen, jos kertoma- no, alirutiini tai metodi, mitä puhun metodeista myös proseduraalisessa ja funktionaalisen ohjelmoinnin kielissä, niin jos se palauttaa tuon ykösen.

Lopullinen koodini
Koodia: [Valitse]
#include <stdio.h>

//Declaring function(s)
int kertoma(int x);

int kertoma(int x) {
    if (x<=0) {
    return 1;
    }
    return (x*kertoma(x-1));
}
//Main Method
int main(int argc, char *argv[]) {

    int tulos = kertoma(atoi(argv[1]));
    if (tulos >1)
    {
        printf("%d", tulos);

    }
    else
    {
        printf("Parametri ei ole kokonaisluku, tai kertoman tulos on 1!");
    }

}

Muistan nuo "goto" -lausekkeet Ms DOS-ajoilta, joskus kun lapsena kokeilin Q-BASICilla tehdä yksinkertaisia ohjelmia, noita goto-lauseita pitäisi vältellä, koska muuttujien arvot voivat olla mitä tahansa siinä kohtaa, kun hyppää johonkin tiettyyn kohtaan koodia tuolla goto-käskyllä ja ohjelman suoritus ei välttämättä onnistu tai jokin menee siinäkin pieleen. En edes tiedä, onko C-kielessäkään go
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: nm - 12.02.21 - klo:12.39
Kannattaa käyttää strtol-funktiota, jonka avulla voi selvittää täsmälleen, mikä vika syötteessä on. Myös funktio strtoul on olemassa, mutta se tulkitsee miinus-etumerkin negaatioksi ja muuntaa luvun sitten unsignediksi, jota tässä tuskin halutaan. Liukuluvuille on strtod.

C-ohjelmoinnissa manuaalisivut ovat hyvä tietolähde standardikirjaston osalta, joskin ne vaativat jonkin verran esitietoja mm. C:n tavallisista virheenkäsittelymekanismeista.

Koodia: [Valitse]
man strtol
Pari nettilähdettä, joissa on lisää esimerkkejä:
https://www.cplusplus.com/reference/cstdlib/strtol/
https://www.techonthenet.com/c_language/standard_library_functions/stdlib_h/strtol.php
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:12.41
Heh, atoi() on tasan niin typerä miksi Unix Hater’s Handbook koko C-kieltä manaa: jollei muunnos onnistu, palautuu vain arvo 0. Mikä tahansa merkkijono on siis oletusarvoisesti kokonaisluku nolla.

Käytän Codeblock-IDEä tässä C-koodauksessa Mint-koneellani, niin gcc-kääntäjällä käännösvaiheessa tulee jokin varoitusherja tuosta atoi:n käytöstä, mutta ohjelma silti kääntyy, ja kun sen ajaa, niin toimii moitteetta.

En ole lukenut tuota Unix Hater's Handbookkia, mikä tämä tarina tässä atoin takana on, että siitä ei niin tykättäisi?
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: nm - 12.02.21 - klo:12.47
Käytän Codeblock-IDEä tässä C-koodauksessa Mint-koneellani, niin gcc-kääntäjällä käännösvaiheessa tulee jokin varoitusherja tuosta atoi:n käytöstä, mutta ohjelma silti kääntyy, ja kun sen ajaa, niin toimii moitteetta.

Liittyisikö siihen, että atoi() sijaitsee stdlib.h:ssa, jolle koodissasi ei ole include-riviä?


mikä tämä tarina tässä atoin takana on, että siitä ei niin tykättäisi?

Eipä siinä muuta tarinaa ole kuin itsekin havaitsemasi virheenkäsittelyn puuttuminen. Ohjelmointikielet ja kirjastot ovat kuitenkin ehtineet kehittyä 50 vuodessa, eikä C-kielikään ole täysin toivoton tapaus, vaikka sen turvallinen käyttö edellyttää melko paljon asiantuntemusta.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Ganymedes - 12.02.21 - klo:12.58
...
Muistan nuo "goto" -lausekkeet Ms DOS-ajoilta, joskus kun lapsena kokeilin Q-BASICilla tehdä yksinkertaisia ohjelmia, noita goto-lauseita pitäisi vältellä, koska muuttujien arvot voivat olla mitä tahansa siinä kohtaa, kun hyppää johonkin tiettyyn kohtaan koodia tuolla goto-käskyllä ja ohjelman suoritus ei välttämättä onnistu tai jokin menee siinäkin pieleen. En edes tiedä, onko C-kielessäkään go

Muistan hyvin tuon keskustelun. Se oli jo 70-luvun lopussa pateettista, koska esim. HP:n työasemissa oli jo silloin ohjelmointikielessä oikeat aliohjelmat eikä näitä ehdottomia GOTO-lauseita tarvittu koskaan.

Tarkoitin tuossa aliohjelmakutsua, joka voi olla muotoa ON ERROR GOTO ALIOHJELMA -virheenkäsittelyssä (esim. Microsoft VB:ssä on jotakin tuollaista). Se mistä aiemmin keskusteltiin oli GOTO hypäten johonkin kohtaa ohjelmaa pysyvästi, ei ehdollisesti. Täysin eri asioita.

Olen huomannut että kunnollista virheenkäsittelyä ei usein toteuteta ja ohjelma kaatuilevat milloin sattuu, varsinkin tällaiset näppärät pikkuohjelmat. Tuollaisilla On Error Goto -rakenteille saa lähes täydellisen virheenkäsittelyn (suht. yksinkertaisessa ohjelmassa), joka ei kaadu koskaan. Se voi kuitenkin jäädä vielä jumiin, siis pelkällä tuolla, muttei kaadu. Koodia tulee tästä käsittelystä paljon lisää, mutta ei lyhyt koodi todellisuudessa ole mikään itseisarvo vaan looginen ja selvälukuinen koodi paremminkin on.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: Ganymedes - 12.02.21 - klo:13.16
Tarkoitin siis tämän linkin takaa löytyvää petoa, taitaa HP 9845 olla varsinainen nimi. Tässä oli jo Basic, missä oli jo kunnolliset aliohjelmat, joista voi palata takaisin ja välittää parametrejä.

https://www.hpmuseum.net/display_item.php?hw=149
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: _Pete_ - 12.02.21 - klo:13.19
Tarkoitin siis tämän linkin takaa löytyvää petoa, taitaa HP 9845 olla varsinainen nimi. Tässä oli jo Basic, missä oli jo kunnolliset aliohjelmat, joista voi palata takaisin ja välittää parametrejä.

https://www.hpmuseum.net/display_item.php?hw=149

Cool! Muistatko mikä basic versio oli käytössä missä oli tuollaiset ominaisuudet?

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: Ganymedes - 12.02.21 - klo:13.47
Tarkoitin siis tämän linkin takaa löytyvää petoa, taitaa HP 9845 olla varsinainen nimi. Tässä oli jo Basic, missä oli jo kunnolliset aliohjelmat, joista voi palata takaisin ja välittää parametrejä.

https://www.hpmuseum.net/display_item.php?hw=149

Cool! Muistatko mikä basic versio oli käytössä missä oli tuollaiset ominaisuudet?

Varmaan joku HP-Basic ... en muista muuta nimeä. Tuon jälkeen kesti hetken ymmärtää tavanomaisten tietokoneiden toimintaperiaatteita :)  Tarkoitan tällä sitä, että ohjelmointi, käyttö ja rauta olivat integroituja. Esimerkiksi ohjelmien ajo, stepit ja pysäytykset toimivat sitä varten tehdyiltä näppäimiltä - eli rauta oli suoraan tehty ohjelma ajoon. Mitään erityistä ohjelmointikielen latausta ei ollut olemassa vaan se kuului kokonaisuuteen.

Sinänsä ominaisuudet olivat aika vakuuttavat tuohon aikaan:

- integroitu grafiikka. Eli siis pystyi suoraan ohjelmoimaan grafiikkaa ruudulle
- nauhurit massamuisteina ja muiden ohjelmien lataukseen. Muistaakseni erityiset matematiikkafunktiot sai käyttöönsä tämän kautta.
- lämpökirjoitin integroituna joka osasi tulostaa grafiikkaa (matriisikirjoittimet jylläsivät noihin aikoihin muualla)
- floppy-asema, erillinen. Ihmettelin pitkään, että miksi floppyjä pidettiin yleisesti epäluotettavina, koska eiväthän ne vikaantuneet koskaan. No, tämä floppyasema oli ISO ja flopyt ISOja.

Hintakin oli ihan kiva - käsittääkseni luokkaa 35 000 euroa (n. 200 000 markkaa), joka oli paljon siihen aikaan. Myöhemmin näin, että näitä koneita käytettiin mm. USAn satelliittiohjauskeskuksissa - varmaan vieläkin jos kyseiset satelliitit eivät ole jo pudonneet alas. Keravan aurinkokylän ohjaus toteutettiin tällaisella.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: _Pete_ - 12.02.21 - klo:13.54

Varmaan joku HP-Basic ... en muista muuta nimeä. Tuon jälkeen kesti hetken ymmärtää tavanomaisten tietokoneiden toimintaperiaatteita :)  Tarkoitan tällä sitä, että ohjelmointi, käyttö ja rauta olivat integroituja. Esimerkiksi ohjelmien ajo, stepit ja pysäytykset toimivat sitä varten tehdyiltä näppäimiltä - eli rauta oli suoraan tehty ohjelma ajoon. Mitään erityistä ohjelmointikielen latausta ei ollut olemassa vaan se kuului kokonaisuuteen.


Tästä muistuu mielee kun 80-luvulla pääsin viikoksi työharjoitteluun ylä-asteella Turun atk-keskukseen. Siellä oli vastaavia keskuskonevekottimia mihi piti vaihdella nauhoja nauhaasemaan + syöttää 8" lerppuja aina kun ajettavaa ohjelmaa vaihdettiin.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:15.03
Kannattaa käyttää strtol-funktiota, jonka avulla voi selvittää täsmälleen, mikä vika syötteessä on. Myös funktio strtoul on olemassa, mutta se tulkitsee miinus-etumerkin negaatioksi ja muuntaa luvun sitten unsignediksi, jota tässä tuskin halutaan. Liukuluvuille on strtod.

C-ohjelmoinnissa manuaalisivut ovat hyvä tietolähde standardikirjaston osalta, joskin ne vaativat jonkin verran esitietoja mm. C:n tavallisista virheenkäsittelymekanismeista.

Koodia: [Valitse]
man strtol
Pari nettilähdettä, joissa on lisää esimerkkejä:
https://www.cplusplus.com/reference/cstdlib/strtol/
https://www.techonthenet.com/c_language/standard_library_functions/stdlib_h/strtol.php

Voisitko arvon "nm" kirjoittaa auki lähdekoodin ja pistää jakoon tuon strtol -ratkaisumallin? Mitä pari kesää sitten kesällä 2019 käytin aikaa tähän C-kieleen perehtymiseen, niin jäi vähän vähälle huomiolle nuo pointterit ja osoittimet, vaikka ne ovat ehdottoman tärkeitä hallita, jos meinaa C:llä ohjelmoida, tai C++:lla. En oikein käsitä niitä vieläkään, pitäisi varmaan jokin tehopreppaus olla paikallaan, ja ottaa ne haltuun. Tuolla antamaassasi referenssilähteessä annetaan tuolle strtol-funktion määrittelystä päätellen syöteparametriksi viittausmuuttuja, vai pointterimuuttuja, jos sellaista on & -aloitusmerkistä päätellen, niin en handlaa, miten tuo toimisi tässä alkuperäisessä kertoma käyttäjän komentokehoite parametrisyötteestä ohjelmassa.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:15.27
Käytän Codeblock-IDEä tässä C-koodauksessa Mint-koneellani, niin gcc-kääntäjällä käännösvaiheessa tulee jokin varoitusherja tuosta atoi:n käytöstä, mutta ohjelma silti kääntyy, ja kun sen ajaa, niin toimii moitteetta.

Liittyisikö siihen, että atoi() sijaitsee stdlib.h:ssa, jolle koodissasi ei ole include-riviä?

Tuohonhan se näköjään liittyikin. Oli jostain syystä unohtunut sieltä. Kääntäjä kuitenkin olli sen verran "älykäs" näköjään, että osasi toimivan ohjelman silti kääntää.

Määrittelin kirjastoa käytettäväksi importaten tai sisällyttäen ohjelmassa käytetäväksi koodin alkuun lisäten
Koodia: [Valitse]
#include <stdlib.h>
Nyt se kääntyy ilman mitään ilmoitusta oikein, ja suoriutuu haluamastani tehtäåvästä oikein. Vielä kun saisi esimerkin tuosta "nm":n kertomasta strtol -funktion käytöstä, niin saisi ohjelmasta ehkä lopulta "oikein" toimivan. Tällä hetkellä kertoma-laskuri-ohjelmassani onko se sitten looginen vai semanttinen virhe, kun nyt joka syötteelle lasketaan kertoma, ja resursseja säästyisi, jos laskettaisiin vain syötteille, jotka ovat sen kokoisia positiivisia kokonaislukuja, että tulos mahtuisi primaarimuuttujan arvoalueeseen.

etumerkiuttömässä longissahan jos se muuntaa luvun yksi yhteen intiksi, niin on paljon laajempi arvoalue, ja onko tarvittava muistimääräkin, mikä muistista varataan, pienempi, kun pelkästään positiiviset arvot noteerataan.

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: _Pete_ - 12.02.21 - klo:15.37

Voisitko arvon "nm" kirjoittaa auki lähdekoodin ja pistää jakoon tuon strtol -ratkaisumallin? Mitä pari kesää sitten kesällä 2019 käytin aikaa tähän C-kieleen perehtymiseen, niin jäi vähän vähälle huomiolle nuo pointterit ja osoittimet, vaikka ne ovat ehdottoman tärkeitä hallita, jos meinaa C:llä ohjelmoida, tai C++:lla. En oikein käsitä niitä vieläkään, pitäisi varmaan jokin tehopreppaus olla paikallaan, ja ottaa ne haltuun. Tuolla antamaassasi referenssilähteessä annetaan tuolle strtol-funktion määrittelystä päätellen syöteparametriksi viittausmuuttuja, vai pointterimuuttuja, jos sellaista on & -aloitusmerkistä päätellen, niin en handlaa, miten tuo toimisi tässä alkuperäisessä kertoma käyttäjän komentokehoite parametrisyötteestä ohjelmassa.

Minusta tähän C pointteri juttuun on hyvä lähestymistapa se että miettii miten tietokoneen muisti oikeasti muodostuu tavu tavulta. pseudokoodauskielellä muisti on taulukko joka alkaa 0 ja päättyy siihen mihin asti on muistia (= käytännössä cpu bittisyys).


Sen jälkeen mikä ero on sillä että muistiosoitteeseen 100 pistetään luku ja sillä että on osoitin muistiosotteeseen 100.

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:16.14
Minusta tähän C pointteri juttuun on hyvä lähestymistapa se että miettii miten tietokoneen muisti oikeasti muodostuu tavu tavulta. pseudokoodauskielellä muisti on taulukko joka alkaa 0 ja päättyy siihen mihin asti on muistia (= käytännössä cpu bittisyys).

Sen jälkeen mikä ero on sillä että muistiosoitteeseen 100 pistetään luku ja sillä että on osoitin muistiosotteeseen 100.

Konekielessähän on ne suora viittaus, epäsuoraviittaus, indeksoitu viittaus jne, ja tajuan sen, jos muistipaikassa 66 tai sinne tallennetaan muuttujan lukuarvo 7, ja muistipaikassa 7 sijaitsee suoralla osoiteviittaus-tavalla luku 66, saadaan tulosteeksi 7, joka sijaitsee muistipaikassa 66. Toimiiko tämä apuna yhtään noiden pointtereiden osalta?

Eli onko tuossa sinun esityksessäsi pointterien ajattelutavan lähestymisen helpommin tajuamiseen se, että on eroa, onko tietokoneen muistipaikassa fyysisesti sijaitseva tieto, vai viittaus muistipaikkaan, jossa tieto sijaitsee, kun lopulta se fyysiesti jossain muistipaikassa sijaitsee, mutta auttaako pointterien ymmärtämisessä tämän kaltainen ajattelu? Sitten on pointterien pointtereita,, niin jos tämä näin yksinkertaisella ajattelulla menee, niin sitten nuo pointterin pointteritkin on helppoja tajuta.

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: _Pete_ - 12.02.21 - klo:16.21
Minusta tähän C pointteri juttuun on hyvä lähestymistapa se että miettii miten tietokoneen muisti oikeasti muodostuu tavu tavulta. pseudokoodauskielellä muisti on taulukko joka alkaa 0 ja päättyy siihen mihin asti on muistia (= käytännössä cpu bittisyys).

Sen jälkeen mikä ero on sillä että muistiosoitteeseen 100 pistetään luku ja sillä että on osoitin muistiosotteeseen 100.

Konekielessähän on ne suora viittaus, epäsuoraviittaus, indeksoitu viittaus jne, ja tajuan sen, jos muistipaikassa 66 tai sinne tallennetaan muuttujan lukuarvo 7, ja muistipaikassa 7 sijaitsee suoralla osoiteviittaus-tavalla luku 66, saadaan tulosteeksi 7, joka sijaitsee muistipaikassa 66. Toimiiko tämä apuna yhtään noiden pointtereiden osalta?

Eli onko tuossa sinun esityksessäsi pointterien ajattelutavan lähestymisen helpommin tajuamiseen se, että on eroa, onko tietokoneen muistipaikassa fyysisesti sijaitseva tieto, vai viittaus muistipaikkaan, jossa tieto sijaitsee, kun lopulta se fyysiesti jossain muistipaikassa sijaitsee, mutta auttaako pointterien ymmärtämisessä tämän kaltainen ajattelu? Sitten on pointterien pointtereita,, niin jos tämä näin yksinkertaisella ajattelulla menee, niin sitten nuo pointterin pointteritkin on helppoja tajuta.

Joo kyllä vaan. Juuri tuota samaa asiaa tarkoittaa C:ssä pointter, eli osoitin on viittaus indeksinumeroon (muistiosoite) josta varsinainen tieto (muistiosoitteen arvo) löytyy.

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: nm - 12.02.21 - klo:16.38
Voisitko arvon "nm" kirjoittaa auki lähdekoodin ja pistää jakoon tuon strtol -ratkaisumallin?

man-sivulla on selkeä esimerkki, mutta tässä sovellettuna ohjelmaasi:

Koodia: [Valitse]
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

long kertoma(long x);

long kertoma(long x) {
    if (x <= 0) {
    return(1);
    }
    return(x * kertoma(x - 1));
}

int main(int argc, char *argv[]) {
    long luku, tulos;
    char *loppu, *syote;

    if (argc < 2) {
        fprintf(stderr, "Virhe: Ei argumentteja\n");
        exit(EXIT_FAILURE);
    }

    syote = argv[1];
    errno = 0;
    luku = strtol(syote, &loppu, 10);

    if ((errno == ERANGE && (luku == LONG_MAX || luku == LONG_MIN))
            || (errno != 0 && luku == 0)) {
        fprintf(stderr, "Virhe: Syöte on liian pieni tai liian suuri luku\n");
        exit(EXIT_FAILURE);
    }
    if (loppu < syote + strlen(syote)) {
        fprintf(stderr, "Virhe: Syöte ei ole kokonaisluku\n");
        exit(EXIT_FAILURE);
    }
    if (loppu == syote) {
        fprintf(stderr, "Virhe: Syöte on tyhjä\n");
        exit(EXIT_FAILURE);
    }
    if (luku < 0) {
        fprintf(stderr, "Virhe: Syöte on negatiivinen luku\n");
        exit(EXIT_FAILURE);
    }
     
    tulos = kertoma(luku);
    printf("%ld\n", tulos);
}

Kannattaa myös opetella käyttämään kääntäjää komentoriviltä. IDE voi olla kiva, mutta hämärtää aika paljon taustalla tapahtuvia asioita ja sitoo käyttäjän kyseiseen ympäristöön. C-kehityksessä (erityisesti Linuxissa/Unixissa) ei ole mitään yleisesti vakiintunutta kehitysympäristöä, vaan kaikilla on omat suosikkinsa. Useamman kuin yhden henkilön projektissa vältytään ongelmilta parhaiten, kun projektin buildaus ja riippuvuuksien hallinta hoidetaan geneerisemmillä työkaluilla.

Mielestäni kannattaa siis ainakin aluksi koodata pelkällä tekstieditorilla ja kääntäjällä. Make tai CMake auttaa sitten, kun projektissa alkaa olla useita tiedostoja ja alihakemistoja tai riippuvuuksia ulkoisiin kirjastoihin.

Koodia: [Valitse]
gcc -Wall -Werror -std=c11 -pedantic -o kertoma kertoma.c
Koodia: [Valitse]
./kertoma 12
479001600

./kertoma 0
1

./kertoma -12
Virhe: Syöte on negatiivinen luku

./kertoma -12132312312312123123
Virhe: Syöte on liian pieni tai liian suuri luku

./kertoma +12132312312312123123
Virhe: Syöte on liian pieni tai liian suuri luku

./kertoma ""
Virhe: Syöte on tyhjä

./kertoma asdas
Virhe: Syöte ei ole kokonaisluku

./kertoma "  12  "
Virhe: Syöte ei ole kokonaisluku

Tuo viimeinen tapaus "  12  " menee periaatteessa läpi strtol:stä ilman varsinaisia virheitä, samoin kuin vaikka "3asdf", joka tulkittaisiin 3:ksi. Lisäsin koodiin kuitenkin tarkistuksen, että strtol:n palauttama loppuosoite on sama kuin merkkijonon loppu, eli syötteessä kokonaisluvun jälkeen tulevat merkit eivät ole sallittuja. Tyhjät merkit ennen kokonaislukua sen sijaan hyväksytään.

Tällaisissa vapaan syötteen tulkitsemistapauksissa olisi erityisen tärkeää koodata ja ylläpitää yksikkötestejä, jotka sisällytetään sovelluksen buildaus- tai release-prosessiin.


Mitä pari kesää sitten kesällä 2019 käytin aikaa tähän C-kieleen perehtymiseen, niin jäi vähän vähälle huomiolle nuo pointterit ja osoittimet, vaikka ne ovat ehdottoman tärkeitä hallita, jos meinaa C:llä ohjelmoida, tai C++:lla. En oikein käsitä niitä vieläkään, pitäisi varmaan jokin tehopreppaus olla paikallaan, ja ottaa ne haltuun.

Joo, kannattaa selvittää itselleen osoittimet ja viittaukset tarkasti. Tässä eräs suomenkielinen opas: https://fi.wikibooks.org/wiki/C/Osoittimet
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: Jere Sumell - 12.02.21 - klo:17.51
Kiitos "nm", todella paljon!

a.) miksi vertaat, jos syötteiden lukumäärä on pienempi, kuin 2? Numerointi varmaan alkaa ykkösestä, mutta onko ensimmäinen parametrialkio aina tyhjä vakiona vai mistä tuo 2:een vertaus tulee?

b) Tässä tulee juuri ongelmaksi ymmärtäminen noiden loppu ja syote pointterialustusten kanssa, että missä kohtaa ne liitetään juuri tuohon main-funktiossa syöteparametrina annettaviin char[] -taulukkoon, joka sisältää käyttäjän syötteet? Ehkä en ymmärrä juuri siitä syystä, kun en handlaa vielä noita pointtereita.

Tämän päivän aikana tullut tehtyä havaintoja, ja opittua monta asiaa, ehkä tietämättäänkin alunperin ongelmasta, joka tuli itselläni vastaan tuossa kertoma-ohjelmassa. Tuokin kirjareferenssi "Unix Hater’s Handbook", jonka SuperOscar esitti, niin oli uusi kirjanimike itselleni, ei ole koskaan tullut missään kirjastossa vastaan, ja oman oppimisprosessin kautta olin tehnyt saman havainnon tuosta atoi-funktion käytöstä. Varmaan kirjaa voisi selata, jos jostain yrittäisi löytää, jos tulisi eteen muita vastaavia ongelmia C-kieleen liittyen, että ei tarvitsisi kaikkea learn-by-doing -menetelmällä päätellä itse nollasta.

Tuossakin strrol -metodin esimerkki-esityksessäsi "nm" on aika paljon koodirivejä tuohon syötteen virhetarkistukseen käytetty, vähemmällä koodauksella selvisi, jos kirjoittaisi metodin, jossa hyödyntää ctype.h -kirjaston isdigit() -funktiota, ja vaikka ohjelmoisi sen omaan kirjastoonsa, jonka sitten sisällyttäisi ohjelmaan, jos olisi jokin käytännön tarve todella vaikka kertoman laskemiselle käyttäjän syötteestä parametrilla. Tässä minun ohjelmatapauksessani en näe mitään käytännön sovellutusta tälle, niin siinäkin mielessä tuo virheiden tarkistus vain on tällainen nyanssi valmiimman tai teollisuuskäyttöisemmän koodin aikaansaamiseksi, ja siitä ponnahti tai pulpahti esiin tuo tietotyypin tarkistusongelma mielessäni.

Varmaan noita parametrisyötteitä ja merkkijono-syötteitä käsitteleviä kirjastoja on tässä 1970-luvulta lähtien maailmalle aika paljonkin julkaistu, ja tuo strrol on ja yksi, jossa on otettu kantaa tuohon syötteen oikeellisuuden tarkistukseen, mutta ajankuluksi jos haluaa merkkijono-kirjastoa alkaa ohjelmoimaan, niin sen voisi aloittaa vaikka tällä metodilla, mikä tarkistaa syötteen olevan positiivinen kokonaisluku, mutta juuri tuo nm:n esitys lienee ihan järkevä, jolla ohjelmasta saa "täydellisen". Kuten "nm" -totesit, kehittynyt taatusti 50 vuoden ajanjakson kuluessa nuo C-kirjastot paljonkin, en epäile sitä yhtään.

En noista GOTO -lausekeskusteluista muuta tiedä, että mielestäni suoria hyppylauseita tulisi välttää, jos kieli niitä tarjoaisi, nykyaikaisissa kielissä ei taida juuri niitä enää ollakaan, ehkä jäänteenä voi josain Visual Basicissa ollakin, ja sitäkin vielä käytetään ja ohjelmistokehitäjiä on, jotka ylläpitävät vielä kielillä ohjelmia, joissa niitä käytetään.

Oma hyppylause mielipiteeni perustui tosiaan siihen, että kun hyppylauseen seuraava suoritettava koodilause, tai lauseke on edessä, hyppylauseen suorituksen jälkeen muuttujien arvot eivät siirry mukana, vaan tosiaan muuttujien arvot voivat olla mitä tahansa, joka mahdollisesti aiheuttaa koko ohjelman kaatumisen jossain vaiheessa pahimmillaan, tai sen suoritus muuttuu epämääräiseksi tai vaikeaksi hallinnoida ja riskit kasvavat sitä mukaa, mitä laajemmasta ohjelmistosta on kyse. Kuten "Ganymedes" totesit, puhutaan varmaan eri tavalla käsittäen nuo hyppylauseet, uskon sinua, että jossain voi muuttujienkin arvot siirtyä joissain kielissä.





Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:18.04

Joo kyllä vaan. Juuri tuota samaa asiaa tarkoittaa C:ssä pointter, eli osoitin on viittaus indeksinumeroon (muistiosoite) josta varsinainen tieto (muistiosoitteen arvo) löytyy.

Onko pointterin pointteri ikäänkuin sitten muistipaikan osoite, jossa on viittaus muistipaikkaan, jossa sijaitsee aiempi viittaus alkuperäisen tiedon sisältämään muistipaikkaan? Ehkä näiden pointtereiden takia monet ohjelmoijat voivat valvoa unettomia öitä, etenkin jos on laajat ohjelmistot hallittavana, erityisesti jos sitä viittausmuistipaikan osoitteen kautta voi muuttaa sitä alkuperäistä tietoa.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä
Kirjoitti: Jere Sumell - 12.02.21 - klo:18.06


Kannattaa myös opetella käyttämään kääntäjää komentoriviltä. IDE voi olla kiva, mutta hämärtää aika paljon taustalla tapahtuvia asioita ja sitoo käyttäjän kyseiseen ympäristöön. C-kehityksessä (erityisesti Linuxissa/Unixissa) ei ole mitään yleisesti vakiintunutta kehitysympäristöä, vaan kaikilla on omat suosikkinsa. Useamman kuin yhden henkilön projektissa vältytään ongelmilta parhaiten, kun projektin buildaus ja riippuvuuksien hallinta hoidetaan geneerisemmillä työkaluilla.

Mielestäni kannattaa siis ainakin aluksi koodata pelkällä tekstieditorilla ja kääntäjällä. Make tai CMake auttaa sitten, kun projektissa alkaa olla useita tiedostoja ja alihakemistoja tai riippuvuuksia ulkoisiin kirjastoihin.

Koodia: [Valitse]
gcc -Wall -Werror -std=c11 -pedantic -o kertoma kertoma.c
Joo, kannattaa selvittää itselleen osoittimet ja viittaukset tarkasti. Tässä eräs suomenkielinen opas: https://fi.wikibooks.org/wiki/C/Osoittimet

Kiitos linkkivinkistä ja neuvosta! Käännän siis bash-konteopäätteeltä ohjelmaa, mutta kirjoitan sitä mielelläni CodeBlocksilla, joskin olen joskus kysellyt tässäkin yhteisöissä noien C-IDEjen perään, ja kuten totesit, ne on makuasioita, ei niistä sen enempää.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: Jere Sumell - 14.02.21 - klo:08.55
Palaan vielä yhden postauksen ajaksi tähän viestisäikeeseen.

Mitä mainitsin tuon oman C-kirjaston laadinnasta, voisi olla ideaa ajan kuluksi laatia kirjasto, jossa on hyötykäyttöisiä metodeita kombinatoorikan, permutaatioiden laskentaan yms. matematiikan helpottamiseksi, vaikka varmaan jotkin biotietokoneinsinöörit varmaan julkaisseetkin C-kieleen sellaisen.

Tuollainenkin funktio tuli mieleen tuosta chtype.h -kirjastosta löytyvän isdigit-funktion hyödyntämiseen, jota voidaan ehkä tarvita jossain todennäköisyyslaskennassa syötteen tarkistuksessa vaihtoehtona tuolle nm:n esittämälle strtollille.

Koodia: [Valitse]
int checkInput(char *str[]) {
 for (int x = 0; x < strlen(*str); ++x)
    {
        if (!isdigit(*str[x])) return 1;
    }
    return 0;
}

En ole mitenkään tilastotieteen tai matematiikan syväosaaja, mutta esimerkiksi evoluutioalgoritmiä kehitellessä nuo permutaatioiden laskennat ja joissain muissa bioteknologia-sovelluksissa ihan asiallisia mutta myös kryptografian ongelma-asetteluissa. Evoluutiomatematiikkaa en ole koskaan tutustunut siihen, mutta jonkin verran perehtynyt evoluutioalgoritmiin, ja lukenut pääpiirteittäin Darwinin evoluutio-oppiteoksen että ymmärrän perusteiltaan sen toimintaperiaatteen. Bioteknologiaan en varmaan koskaan lähde syvemmin, kun kemian opinnoista lukiovuosilta viimeksi sitä lukeneena niin paljon jo aikaa ja jonkin Kemian lukionkertauskurssin suorittanut korkeakoulussa.
Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: _Pete_ - 14.02.21 - klo:10.53
Koodia: [Valitse]
int checkInput(char *str[]) {
 for (int x = 0; x < strlen(*str); ++x)
    {
        if (!isdigit(*str[x])) return 1;
    }
    return 0;
}


Et näköjään edelleenkään näitä uraa-uurtavia koodejasi ikinä itse edes käännä ja kokeile?




En ole mitenkään tilastotieteen tai matematiikan syväosaaja, mutta esimerkiksi evoluutioalgoritmiä kehitellessä nuo permutaatioiden laskennat ja joissain muissa bioteknologia-sovelluksissa ihan asiallisia mutta myös kryptografian ongelma-asetteluissa. Evoluutiomatematiikkaa en ole koskaan tutustunut siihen, mutta jonkin verran perehtynyt evoluutioalgoritmiin, ja lukenut pääpiirteittäin Darwinin evoluutio-oppiteoksen että ymmärrän perusteiltaan sen toimintaperiaatteen. Bioteknologiaan en varmaan koskaan lähde syvemmin, kun kemian opinnoista lukiovuosilta viimeksi sitä lukeneena niin paljon jo aikaa ja jonkin Kemian lukionkertauskurssin suorittanut korkeakoulussa.

Mikähän mahtaa olla evoluutioalgoritmi?

Otsikko: Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
Kirjoitti: Jere Sumell - 14.02.21 - klo:16.50

Mikähän mahtaa olla evoluutioalgoritmi?

Suora lainaus Wikipediasta:
Lainaus
Evoluutioalgoritmi on tietokoneohjelman tekotapa, joka jäljittelee evoluutioteorian mukaista mekanismia, jossa luonnonvalinta valitsee sopivimmat mutaatiot jatkoon.

No tuossa on nuo viittausmuuttujat, jos sen poistaa ja käyttää tavallista muuttujaa, toimii mutta ei todella mitään uraa uurtavaa. Ehkä tämäkin ketju on taputeltu?