Kirjoittaja Aihe: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]  (Luettu 5697 kertaa)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: Syötteen tietotyypin tarkistus C:ssä
« Vastaus #20 : 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.

Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

_Pete_

  • Käyttäjä
  • Viestejä: 1836
  • Fufufuuffuuu
    • Profiili
Vs: Syötteen tietotyypin tarkistus C:ssä
« Vastaus #21 : 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.

« Viimeksi muokattu: 12.02.21 - klo:16.23 kirjoittanut _Pete_ »

nm

  • Käyttäjä
  • Viestejä: 16232
    • Profiili
Vs: Syötteen tietotyypin tarkistus C:ssä
« Vastaus #22 : 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
« Viimeksi muokattu: 12.02.21 - klo:16.47 kirjoittanut nm »

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
« Vastaus #23 : 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ä.





« Viimeksi muokattu: 12.02.21 - klo:18.00 kirjoittanut Jere Sumell »
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: Syötteen tietotyypin tarkistus C:ssä
« Vastaus #24 : 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.
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: Syötteen tietotyypin tarkistus C:ssä
« Vastaus #25 : 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ää.
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
« Vastaus #26 : 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.
« Viimeksi muokattu: 14.02.21 - klo:08.58 kirjoittanut Jere Sumell »
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

_Pete_

  • Käyttäjä
  • Viestejä: 1836
  • Fufufuuffuuu
    • Profiili
Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
« Vastaus #27 : 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?


Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: Syötteen tietotyypin tarkistus C:ssä [RATKAISTU]
« Vastaus #28 : 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?
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)