Kirjaimien ja numeroiden erottelu

Eli pitäis tehdä sellanen pätkä mikä tarkistaa ettei ole syöttänyt kirjaimia. Ihan if-lause eli jos kirjaimia syötetään tulee virhe-ilmotus. Olen yrittänyt etsiä et mikä se käsky on mikä erottelee nämä, mut en ole löytäny.
Tää voi olla kyllä aika alottelijan kysymys, mut aloittelija minä olenkin.

Kiitos jo etukäteen.
171414
Äänestä

Muut lukivat myös

Vastaukset 17

Vanhimmat

int c;

while (( c = getchar()) != EOF) {
   if ( !(c >= 0 && c

Äänestä
  • Joo tossa ekassa tulikin virhe,
    korjaat ton
    if ( !(c >= 0 && c = '0' && c

    Äänestä

Kannattaa myös tarkistaa, jos käyttäjä syöttää muitakin kuin kirjaimia tai numeroita, esim. jotenkin näin:

..
#include
char c;

c = luemerkkijotenkin..
/* tähän väliin syötteen loppumisen tarkistus vaikka if (c == EOF) */

if (isdigit(c)) {
numero
} elseif (isalpha(c)) {
kirjain
} else {
virheellinen syöte
}

Äänestä
  • Toi systeemi on sulla muuten oikein, mutta toi
    char c, on väärin.

    char on signed arvo ja se voi saada arvoja väliltä
    (-127,...,128)

    toi char c, pitää muuttaa
    int c,
    koska int saa arvoja n.2*10^9, nyt on käytössä suurempi määrä arvoja (mahdolliset virhe arvot, jotka ylittävät char:in arvovälin, toimivat nyt suuremmalla arvovölillä)

    Äänestä

  • Aalto kirjoitti:

    Toi systeemi on sulla muuten oikein, mutta toi
    char c, on väärin.

    char on signed arvo ja se voi saada arvoja väliltä
    (-127,...,128)

    toi char c, pitää muuttaa
    int c,
    koska int saa arvoja n.2*10^9, nyt on käytössä suurempi määrä arvoja (mahdolliset virhe arvot, jotka ylittävät char:in arvovälin, toimivat nyt suuremmalla arvovölillä)

    Siis int saa noin 4 miljardia arvoa,
    max pos. arvo on jotain 2 miljardia ja risat, ja vastaavasti negatiivinen arvo.

    Äänestä

  • Aalto kirjoitti:

    Siis int saa noin 4 miljardia arvoa,
    max pos. arvo on jotain 2 miljardia ja risat, ja vastaavasti negatiivinen arvo.

    Esimerkkejä merkin luvusta, jotka tukee int c:n käyttöä!!!!

    /* puskuroimaton getchar(), lukee stdin:ista */
    int getchar()
    {
      char c;
      return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
    }

    Kuten tosta huomaa, toi char c, castataan
    unsigned chariks.

    yks vielä.
    #define getc(fp) (--(fp)->cnt >= 0 \
         ? (unsigned char) *(fp)->ptr : _filbuff(fp))


    toikin getc on yleensä toteutettu makrona, ja
    täten getchar():kin voidaan toiteuttaa näin

    #define getchar()  getc(stdin)

    Äänestä

  • Aalto kirjoitti:

    Toi systeemi on sulla muuten oikein, mutta toi
    char c, on väärin.

    char on signed arvo ja se voi saada arvoja väliltä
    (-127,...,128)

    toi char c, pitää muuttaa
    int c,
    koska int saa arvoja n.2*10^9, nyt on käytössä suurempi määrä arvoja (mahdolliset virhe arvot, jotka ylittävät char:in arvovälin, toimivat nyt suuremmalla arvovölillä)

    On se charin käyttö esimerkin tapauksessa aivan oikein. intin käyttäminen on ehkä vähän turhaa, sillä annetut funktiot (isalpha jne.) ottavat käytännössä vastaan charin, kuten kyseisten funktoiden manuaalisivut kertovat: "These functions check whether c, which must have the value of an unsigned char or EOF". Kääntäjä konvertoi sen charin intiksi muutenkin. Kokeilin äsken molemmilla tavoilla, eikä kääntäjä valittanut mitään edes tiukimmilla optioilla (gcc -Werror -pedantic -ansi).

    Lisäksi signed char voi saada arvot -128 .. 127.

    Äänestä

  • Aalto kirjoitti:

    Siis int saa noin 4 miljardia arvoa,
    max pos. arvo on jotain 2 miljardia ja risat, ja vastaavasti negatiivinen arvo.

    Jos olisimme pedantteja, niin ollakseemme täsmällisiä kyseiset arvot ovat signed intille -2147483648 .. 2147483647 (huom. siis tyypin maksimi- ja minimiarvoja ei saa helposti vain kääntämällä etumerkkiä). unsignedin vastaava luku on 4294967295. Tämä tietysti sillä oletuksella, että käytettävän alustan kääntäjässä int on 32-bittinen.

    Myös #include ja INT_MIN/INT_MAX ovat ystäviä.

    Äänestä

  • Aalto kirjoitti:

    Esimerkkejä merkin luvusta, jotka tukee int c:n käyttöä!!!!

    /* puskuroimaton getchar(), lukee stdin:ista */
    int getchar()
    {
      char c;
      return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
    }

    Kuten tosta huomaa, toi char c, castataan
    unsigned chariks.

    yks vielä.
    #define getc(fp) (--(fp)->cnt >= 0 \
         ? (unsigned char) *(fp)->ptr : _filbuff(fp))


    toikin getc on yleensä toteutettu makrona, ja
    täten getchar():kin voidaan toiteuttaa näin

    #define getchar()  getc(stdin)

    Miksi tehdä taas oma getchar, jos se löytyy valmiinakin (#include , int getchar(void);) ? Sama juttu getc:n kanssakin (#include , int getc(FILE *stream);).

    Sitten vielä annetusta koodinpätkästä:

    >>int getchar()
    >>{

    Oman getcharin uudelleenmäärittely rikkoo koodin, jos se sisällyttää stdio.h:n.

    >> char c;

    Mikset käytä suoraan unsigned char c, niin välttyisit tuolta myöhemmältä castilta ?

    >> return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
    >>}

    Tuossa näkyy heti joitakin potentiaalisia bugeja:

    read jäänee odottamaan rivinvaihtoa, koska näppikseltä luku terminaalissa on pääsääntöisesti puskuroitua. Terminaali pitäisi saada siis puskuroimattomaksi ensin (lienee alustakohtaista miten sen saa tehtyä).

    Oletat aina readin onnistuvan. read voi palauttaa nollankin, vaikka virheitä ei ole. man 2 read sopinee iltalukemistoksi (jos siis käytät jotain UNIXia/Linuxia): "On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal."

    Äänestä

  • Mik kirjoitti:

    Miksi tehdä taas oma getchar, jos se löytyy valmiinakin (#include , int getchar(void);) ? Sama juttu getc:n kanssakin (#include , int getc(FILE *stream);).

    Sitten vielä annetusta koodinpätkästä:

    >>int getchar()
    >>{

    Oman getcharin uudelleenmäärittely rikkoo koodin, jos se sisällyttää stdio.h:n.

    >> char c;

    Mikset käytä suoraan unsigned char c, niin välttyisit tuolta myöhemmältä castilta ?

    >> return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
    >>}

    Tuossa näkyy heti joitakin potentiaalisia bugeja:

    read jäänee odottamaan rivinvaihtoa, koska näppikseltä luku terminaalissa on pääsääntöisesti puskuroitua. Terminaali pitäisi saada siis puskuroimattomaksi ensin (lienee alustakohtaista miten sen saa tehtyä).

    Oletat aina readin onnistuvan. read voi palauttaa nollankin, vaikka virheitä ei ole. man 2 read sopinee iltalukemistoksi (jos siis käytät jotain UNIXia/Linuxia): "On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal."

    ei tossa ollut tarkoitus tehdä mitään omia getchareja, tarkoitus oli näyttää että muuttujan johon merkki luetaan on oltava tyyppiä 'int'.

    Sä olet taas näitä idiootteja jotka hyväksyy kaiken vain 'black box':na ja toteaa, et katos toikin on jo toteutettu, miks mä yrittäisinkään edes vähäsen ymmärtää et miten sellainen on implementoitu.

    Äänestä

  • Mik kirjoitti:

    Miksi tehdä taas oma getchar, jos se löytyy valmiinakin (#include , int getchar(void);) ? Sama juttu getc:n kanssakin (#include , int getc(FILE *stream);).

    Sitten vielä annetusta koodinpätkästä:

    >>int getchar()
    >>{

    Oman getcharin uudelleenmäärittely rikkoo koodin, jos se sisällyttää stdio.h:n.

    >> char c;

    Mikset käytä suoraan unsigned char c, niin välttyisit tuolta myöhemmältä castilta ?

    >> return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
    >>}

    Tuossa näkyy heti joitakin potentiaalisia bugeja:

    read jäänee odottamaan rivinvaihtoa, koska näppikseltä luku terminaalissa on pääsääntöisesti puskuroitua. Terminaali pitäisi saada siis puskuroimattomaksi ensin (lienee alustakohtaista miten sen saa tehtyä).

    Oletat aina readin onnistuvan. read voi palauttaa nollankin, vaikka virheitä ei ole. man 2 read sopinee iltalukemistoksi (jos siis käytät jotain UNIXia/Linuxia): "On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal."

    Tossa mitä kirjoitat :

    >Oletat aina readin onnistuvan. read voi palauttaa >nollankin, vaikka virheitä ei ole.

    et näköjään ymmärrä mitä ehdollinen lauseke tarkoittaa. Tuo koodinpätkä
    >return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;

    palauttaa luetun merkin jos homma on toiminut, muuten palautetaan EOF, yleensä sen arvo on -1
    ( #define EOF (-1) )
    .

    Ja vielä tosta:
    >Oman getcharin uudelleenmäärittely rikkoo koodin, >jos se sisällyttää stdio.h:n.

    Luuletko tosiaan etten ole tietoinen tosta asiasta, tuo oli vain yksinkertainen huono luonnos getcharista, jos haluat käyttää tota ilman konflikteja niin nimeä se vaikka
    int getchar2(), int getcharOma(), etc...

    Äänestä

  • Aalto kirjoitti:

    Tossa mitä kirjoitat :

    >Oletat aina readin onnistuvan. read voi palauttaa >nollankin, vaikka virheitä ei ole.

    et näköjään ymmärrä mitä ehdollinen lauseke tarkoittaa. Tuo koodinpätkä
    >return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;

    palauttaa luetun merkin jos homma on toiminut, muuten palautetaan EOF, yleensä sen arvo on -1
    ( #define EOF (-1) )
    .

    Ja vielä tosta:
    >Oman getcharin uudelleenmäärittely rikkoo koodin, >jos se sisällyttää stdio.h:n.

    Luuletko tosiaan etten ole tietoinen tosta asiasta, tuo oli vain yksinkertainen huono luonnos getcharista, jos haluat käyttää tota ilman konflikteja niin nimeä se vaikka
    int getchar2(), int getcharOma(), etc...

    Kiitos ystävällisestä kommentistasi.

    Annettu koodi (read(0, &c, 1) == 1) ? (unsigned char)c : EOF; on muuten ok, paitsi jos read palauttaa virheen:

    -read palauttaa 1, return palauttaa c:n, ok tilanne

    -read palauttaa 0, return palauttaa EOF:n, myös ok

    -read palauttaa -1 (virhetilanne), return palauttaa EOF. Nyt käyttäjä voi helposti olettaa väärin, että syöte loppui, vaikka mitään ei oikeasti saatukaan luettua. Virheen erottelu EOFista käy siis vaikeaksi.

    Lisäksi read voi palauttaa nollan vaikkei oltaisikaan EOFissa, kuten manuaalisivu kertoo.

    Yksi korjaus olisi poistaa koko ehtolause, ja katso kutsuvassa funktiossa mitä kutsuttu funktio palautti. Lisäksi tapauksessa -1 voisi vielä katsoa errno:n arvon.

    Noh, eipä näillä nyt niin väliä ole Hello worldin tasoisissa ohjelmissa (oletetaan ideaalinen maailma, jossa mitään virheitä ei tapahdu). Ehkä kokemus opettaa huomioimaan kaikki tällaiset seikat, jos pääsee/joutuu tekemään jotain oikeastikin kriittistä.

    Äänestä

  • Mik kirjoitti:

    Kiitos ystävällisestä kommentistasi.

    Annettu koodi (read(0, &c, 1) == 1) ? (unsigned char)c : EOF; on muuten ok, paitsi jos read palauttaa virheen:

    -read palauttaa 1, return palauttaa c:n, ok tilanne

    -read palauttaa 0, return palauttaa EOF:n, myös ok

    -read palauttaa -1 (virhetilanne), return palauttaa EOF. Nyt käyttäjä voi helposti olettaa väärin, että syöte loppui, vaikka mitään ei oikeasti saatukaan luettua. Virheen erottelu EOFista käy siis vaikeaksi.

    Lisäksi read voi palauttaa nollan vaikkei oltaisikaan EOFissa, kuten manuaalisivu kertoo.

    Yksi korjaus olisi poistaa koko ehtolause, ja katso kutsuvassa funktiossa mitä kutsuttu funktio palautti. Lisäksi tapauksessa -1 voisi vielä katsoa errno:n arvon.

    Noh, eipä näillä nyt niin väliä ole Hello worldin tasoisissa ohjelmissa (oletetaan ideaalinen maailma, jossa mitään virheitä ei tapahdu). Ehkä kokemus opettaa huomioimaan kaikki tällaiset seikat, jos pääsee/joutuu tekemään jotain oikeastikin kriittistä.

    Niin ton readin pointti tossa on VAIN se että jos se saa luettua ton yhden merkin niin se palauttaa luettujen merkkien määrän, eli tässä tapauksessa yhden!!! Ja sitä kautta me annetaan käyttäjälle se luettu merkki. Ja jos on tapahtunut joku virhe, ei saada merkkiä luettua tai ihan mitä vain, se palauttaa EOF, koska meille on ihan vitun sama että mikä se virhe on ollut. Tossa esimerkin getcharissa meitä ei voisi vähempää kiinnostaa kuin että onko saatu yksi merkki luettua vai ei. Sä olet kyllä äärimmäisen tyhmä kaveri. Suosittelen sinulle
    Stevensin "Advanced Programming in the UNIX Environment" kirjaa.

    Äänestä

  • Aalto kirjoitti:

    Niin ton readin pointti tossa on VAIN se että jos se saa luettua ton yhden merkin niin se palauttaa luettujen merkkien määrän, eli tässä tapauksessa yhden!!! Ja sitä kautta me annetaan käyttäjälle se luettu merkki. Ja jos on tapahtunut joku virhe, ei saada merkkiä luettua tai ihan mitä vain, se palauttaa EOF, koska meille on ihan vitun sama että mikä se virhe on ollut. Tossa esimerkin getcharissa meitä ei voisi vähempää kiinnostaa kuin että onko saatu yksi merkki luettua vai ei. Sä olet kyllä äärimmäisen tyhmä kaveri. Suosittelen sinulle
    Stevensin "Advanced Programming in the UNIX Environment" kirjaa.

    Ystävällinen linja sen kun jatkuu vaan..

    No voi voi jos ei kiinnosta, eipä ole minun ongelmani. Jos homma voidaan helposti tehdä kunnolla, niin miksei sitten tehdä sitä virhetarkistuksineen päivineen. Tosin tuolla hälläväliä-asenteella homma edistyy nopeammin.

    Hyllyssäni on Stevensiä ainakin 15 cm paksuudelta, mutta nyt on vähän muutakin tekemistä kuin lukea niitä.

    Äänestä

  • Mik kirjoitti:

    Ystävällinen linja sen kun jatkuu vaan..

    No voi voi jos ei kiinnosta, eipä ole minun ongelmani. Jos homma voidaan helposti tehdä kunnolla, niin miksei sitten tehdä sitä virhetarkistuksineen päivineen. Tosin tuolla hälläväliä-asenteella homma edistyy nopeammin.

    Hyllyssäni on Stevensiä ainakin 15 cm paksuudelta, mutta nyt on vähän muutakin tekemistä kuin lukea niitä.

    No joo ehkä toi mun linja oli perseestä. Mut tarkoitin vain demota tota hommaa yksinkertaisilla ja helpolla tavalla.

    Äänestä

Tämä on ihan OT mutta laitetaan tännekin mielenpalautukseksi. Ainakin M$ ympäristössä on mahdollista käyttää tätä:

#include
TCHAR merkki;
merkki = 'a';
_istalpha(merkki);

eli käännösaikana valitaan automaattisesti sopivat metodit ja tietotyypit eri tekstityypeille (single-byte, multi-byte, Unicode).

Eli koodi voidaan siis kääntää myös unicode käännöksenä, jossa yksi chracter onkin 8 bitin sijaan 16 bittiä.

ja tietysti kaikki hardcodatut merkkojonot pitääkin esitellä:
TCHAR* tervehdys = _T("Merkkojono");
eikä suinkaan:
char* tervehdys = "Merkkojono";

mutta juu, hauskaahan tuota poikien kinastelua on seurata :-o

Äänestä

Kommentoi aloitusta


Ajoittelija kirjoitti:

Eli pitäis tehdä sellanen pätkä mikä tarkistaa ettei ole syöttänyt kirjaimia. Ihan if-lause eli jos kirjaimia syötetään tulee virhe-ilmotus. Olen yrittänyt etsiä et mikä se käsky on mikä erottelee nämä, mut en ole löytäny.
Tää voi olla kyllä aika alottelijan kysymys, mut aloittelija minä olenkin.

Kiitos jo etukäteen.

Anonyymi
5000

Ilmoita asiaton sisältö

  • Sisältää materiaalia, joka on loukkaavaa, herjaavaa, rasistista, uhkailevaa tai ahdistelevaa.

  • Materiaali sisältää nimiä, yhteystietoja tai muita henkilökohtaisia tietoja. Julkisuuden henkilöistä, julkisissa viroissa toimivista ihmisistä sekä yritysten vastuuhenkilöistä saa keskustella työhön liittyen. Myös yksityiselämään liittyvistä asioista voi keskustella siltä osin, kuin niistä on julkisesti kerrottu.

  • Sisältää lapsille haitallista tai heiltä kiellettyä materiaalia. Seksuaalinen sisältö on sallittua aiheeseen tarkoitetuilla palstoilla, joiden ikäraja on 18 vuotta.

  • Lainvastaista sisältöä voi olla mm. yksityiselämää loukkaavan tiedon levitys, kiihottaminen kansanryhmää vastaan, laiton uhkaaminen, alaikäisiin liittyvä seksuaalinen sisältö/grooming, petokset, identiteettivarkaudet, kunnianloukkaukset ja tekijänoikeusrikkomukset.

  • Sisältö ei liity palstan tai keskusteluketjun aiheeseen.

  • Viesti ei ole suomea tai ruotsia (pl. International Forums), se sisältää mainontaa, se sisältää tekijänoikeuksin suojattua materiaalia, se on massapostitus tai jokin muu syy.

Jaa keskustelu