NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: zacykleny scanf()

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
emedla
Člen
Avatar
emedla:10.8.2015 14:02

Cau, nechapu proc mi nefunguje tento kod. Delam kontrolu, jestli je hodnota nactena do promenne pohyb cislo, pokud neni probehne hlaska a pozadavek na opetovne zadani hodnoty do promenne pohyb. Jenze program probehne tak, ze bezi do nekonecna a vypisuje ty hlasky.
Za 1. - nevim proc me nenecha zadat jinou hodnotu, pokud zadam pismena, tak se zacykli.
Za 2. - jak jinak to lze udelat?
Diky

Ukazka:

scanf(" %d", &pohyb);


    while((isalnum(pohyb) == 0)||(pohyb < 0))
    {
        printf("Pohyb na ucte lze vyjadrit pouze cislem vetsim jak 0\n");
        printf("Prosim zadejte znovu pohyb na uctu-> ");
        pohyb=0;
        scanf("%d", &pohyb);

    }
 
Odpovědět
10.8.2015 14:02
Avatar
Luboš Běhounek Satik:10.8.2015 14:21

jakeho typu je promenna pohyb?

Nahoru Odpovědět
10.8.2015 14:21
https://www.facebook.com/peasantsandcastles/
Avatar
emedla
Člen
Avatar
Odpovídá na Luboš Běhounek Satik
emedla:10.8.2015 14:25

pohyb je typu int.
jinak jsem to jeste troche opravil:

while(((cislo=isalnum(pohyb)) == 0)||(pohyb < 0))

Ale nezabira -> scanf stale preskakuje a bezi dokola
cislo je taky typu int.
Zkousel jsem I misto isalnum() funcki isdigit(). Ale vysledek je stejny

 
Nahoru Odpovědět
10.8.2015 14:25
Avatar
kxmx
Tvůrce
Avatar
kxmx:10.8.2015 15:26

tohle je teda solidní oprava

(cislo=isalnum(pohyb)) == 0)

nepotřebuješ náhodou testovat jestli není pohyb větší než 0?

 
Nahoru Odpovědět
10.8.2015 15:26
Avatar
emedla
Člen
Avatar
Odpovídá na kxmx
emedla:10.8.2015 15:37
while(((cislo=isdigit(pohyb)) == 0)||(pohyb < 0))
    {
        printf("Pohyb na ucte lze vyjadrit pouze cislem vetsim jak 0\n");
        printf("Prosim zadejte znovu pohyb na uctu-> ");
        pohyb=0;
        scanf("%d", &pohyb);

    }

Jo, je to blbost. Zapomnel jsem to upravit. Takto by to melo byt spravne. Nicmene mi jde hlavne o to proc to v tom cyklu while ten scanf() preskakuje.
Zajimalo by me, co presne se do te pameti nacte, kdyz pri prikazu

scanf("%d", &pohyb)

napisu do teto adresy pismena. Kdybych tam nemel tu kotrolu a napsal pismena, tak to vetsinou potom vyhodi cislici v radu 5 cislic. Nechapu to, dovede mi na tohle odpovedet?
Dokonce, I kdyz tam necham prikaz

pohyb=0;

tak se to chova furt stejne. Je to ujety.

 
Nahoru Odpovědět
10.8.2015 15:37
Avatar
Jozef
Člen
Avatar
Odpovídá na emedla
Jozef:10.8.2015 23:17

Myslím,že najlepšie pre teba bude načítať vstup do stringu a tak skontrolovať,či je zadané číslo a ak hej, skontrolovať hodnotu. Pri použití scanf, ktoré očakáva argument typu int, nemôžeš zadať nič iné ako typ int, inak to zblbne,čo si už zistil.

Nahoru Odpovědět
10.8.2015 23:17
I'm not afraid to die on a treadmill
Avatar
Odpovídá na Jozef
Libor Šimo (libcosenior):11.8.2015 8:09
#include<stdio.h>

int main(void)
{
    int pohyb;

    printf("Zadajte sumu: ");
    scanf(" %d", &pohyb);
    while((pohyb == 0)||(pohyb < 0))
    {
        printf("Pohyb na ucte lze vyjadrit pouze cislem vetsim jak 0\n");
        printf("Prosim zadejte znovu pohyb na uctu: ");
        pohyb=0;
        scanf("%d", &pohyb);
    }

    return 0;
}
Nahoru Odpovědět
11.8.2015 8:09
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Libor Šimo (libcosenior):11.8.2015 8:44

Teraz som si všimol, toto stačí.
while(pohyb <= 0)

Nahoru Odpovědět
11.8.2015 8:44
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):11.8.2015 8:46

Ináč makrá z knižnice ctype.h sa týkajú jednotlivých znakov, nie viacciferných čísiel alebo stringov!

Nahoru Odpovědět
11.8.2015 8:46
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):11.8.2015 9:02

Napísal si:
"Pri použití scanf, ktoré očakáva argument typu int, nemôžeš zadať nič iné ako typ int, inak to zblbne,čo si už zistil."

Nesúhlasím, vyskúšaj si tento programík:

#include <stdio.h>

int main(void)
{
    int i, pohyb;

    for (i = 0; i < 5; i++) {
        printf("Zadajte slovo: ");
        scanf(" %d", &pohyb);
        printf("%d\n", pohyb);
        fflush(stdin); /* odstráni enter */
    }

    return 0;
}
Nahoru Odpovědět
11.8.2015 9:02
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
emedla
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
emedla:11.8.2015 9:14

Bohuzel nestacilo. Opet to porad bezelo dokola.

 
Nahoru Odpovědět
11.8.2015 9:14
Avatar
emedla
Člen
Avatar
emedla:11.8.2015 9:20

Spravnym resenim je jak rikal Jozef toto:
Alespon teda pro me :).

scanf("%s", r_pohyb);

    while(((pohyb=atoi(r_pohyb))<=0))
    {
        printf("Pohyb na ucte lze vyjadrit pouze cislem vetsim jak 0\n");
        printf("Prosim zadejte znovu pohyb na uctu-> ");
        //pohyb=0;
        scanf("%s", r_pohyb);

    }

Vse funguje jak ma.
Funkce atoi() vraci nulu, pokud se nejedna o retezec slozeny z cisel

 
Nahoru Odpovědět
11.8.2015 9:20
Avatar
emedla
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
emedla:11.8.2015 9:29

Aha jo.
Tak tohle je co mi tam chybelo:

fflush(stdin);

Kdyz to zakomentuju, tak to bezi 5x dokola zase samo. Je to tim, ze ten enter tam furt visi?
Jak to tam presne funguje?
Diky

 
Nahoru Odpovědět
11.8.2015 9:29
Avatar
Odpovídá na emedla
Patrik Valkovič:11.8.2015 9:39

Tyto knihovny čtou zpravidla do konce řádku (tedy do znaku '\n'). Jestliže ti visí enter na konci řádku, tak to pro funkci vypadá, jako by jsi nic nezadal (jako kdyby jsi hned odentroval). Protože ale ve frontě nějaký znak je, tak by program neměl čekat na vstup od uživatele ale pokračovat s tím, co přečetl (v tomto případě nic - "\0"). Snad to stačí takhle.

Nahoru Odpovědět
11.8.2015 9:39
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
emedla
Člen
Avatar
Odpovídá na Patrik Valkovič
emedla:11.8.2015 9:56

Jo, zhruba jo. Diky

 
Nahoru Odpovědět
11.8.2015 9:56
Avatar
Odpovídá na emedla
Libor Šimo (libcosenior):11.8.2015 10:04

"Spravnym resenim je jak rikal Jozef toto:
Alespon teda pro me."

Skús zadať

1235k

a uvidíš, že to nie je dobre!

Nahoru Odpovědět
11.8.2015 10:04
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Jozef
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Jozef:11.8.2015 10:13

Pri neočakávanom vstupe scanf() síce nevyhodí chybu, ale dôjde k neočakávanému správaniu. Funkcia fflush(stdin) iba vyčistí buffer od zostávajúceho znaku, ale to neznamená, že scanf() funguje. Vyskúšaj túto úpravu tvojho programu, zadaj si tam číslo alebo slovo a uvidíš rozdiel:

#include<stdio.h>

int main(void)
{
    int i, pohyb;

    for (i = 0; i < 5; i++) {
        printf("Zadajte slovo: ");
        int ret = scanf(" %d", &pohyb);
        printf("%d\n",ret);  // vypíše počet správne prevedených a zapísaných znakov
        printf("%d\n", pohyb);
        fflush(stdin); /* odstráni enter */
    }

    return 0;
}
Nahoru Odpovědět
11.8.2015 10:13
I'm not afraid to die on a treadmill
Avatar
Jozef
Člen
Avatar
Odpovídá na emedla
Jozef:11.8.2015 10:28

Vyskúšaj toto:

#include<stdio.h>
#include <stdlib.h>
#include<string.h>

int main(void)
{
    char s_pohyb[100];
    char *chybne;
    scanf("%s", s_pohyb);
    int pohyb;
    while((pohyb = strtol(s_pohyb, &chybne, 10) <= 0)||(strlen(chybne)))
    {
        printf("Pohyb na ucte lze vyjadrit pouze cislem vetsim jak 0\n");
        printf("Prosim zadejte znovu pohyb na uctu-> ");
        scanf("%s", &s_pohyb);

    }
    return 0;
}

Ak zadáš číslo a je menšie ako 0 alebo zadáš niečo iné ako číslo, alebo zadáš číslo nasledované znakom(napr. spomínané "1235k") tak to vyhodí do while cyklu. Ak ale chceš, aby ti po zadaní "1235k" prečítalo vstup iba ako číslo 1235, tak vyhoď z podmienky

||(strlen(chybne))

Potom ti prečíta všetky číslice pred chybou, teda iným znakom- napr. po zadaní 12a5 bude v premennej pohyb uložené číslo 12; ale po zadaní a55 sa dostaneš do while cyklu.

Nahoru Odpovědět
11.8.2015 10:28
I'm not afraid to die on a treadmill
Avatar
Odpovídá na Jozef
Libor Šimo (libcosenior):11.8.2015 11:04

Máš pravdu, ale platí to iba na celé čísla a ak som správne pochopil prvý príspevok, majú sa zadávať finančné čiastky (pohyb na účte).
Neviem, či na to existuje funkcia, ja by som to riešil asi takto:

#include <stdio.h>
#include <stdlib.h>

/** Funkcia skontroluje ci je retazec cislo
* @param pointer na retazec
* @return 1 alebo 0 (pravda 1, nepravda 0)
*/
int je_cislo(char *cislo)
{
    int i = 0, bodka = 0, je = 1;

    while (cislo[i]) {
        if ((cislo[i] < '0' || cislo[i] > '9') && cislo[i] != '.') { /* znaky su ine ako cislice a bodka, cislo je neplatne */
            je = 0;
        }
        if (cislo[i] == '.') /* spocitanie bodiek */
            bodka++;
        i++;
    }
    if (bodka > 1) /* ak je viac bodiek ako jedna, cislo je neplatne */
        je = 0;

    return je;
}

int main(void)
{
    char r_pohyb[50];

    scanf("%s", r_pohyb);
    while (!(je_cislo(r_pohyb)) || atof(r_pohyb) <= 0.0)
    {
        printf("Pohyb na ucte lze vyjadrit pouze cislem vetsim jak 0\n");
        printf("Prosim zadejte znovu pohyb na uctu-> ");
        scanf("%s", r_pohyb);
    }

    return 0;
}
Nahoru Odpovědět
11.8.2015 11:04
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Jozef
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Jozef:11.8.2015 11:20

Riešil som to pre jeho zadanie a v ňom bola premenná pohyb typu int. Ak by išlo o premennú typu float, existuje funkcia strtof (http://www.cplusplus.com/…dlib/strtof/) a ak by chcel použiť double tak funkcia strtod (http://www.cplusplus.com/…dlib/strtod/).

Nahoru Odpovědět
11.8.2015 11:20
I'm not afraid to die on a treadmill
Avatar
Jozef
Člen
Avatar
Odpovídá na Jozef
Jozef:11.8.2015 11:24

Teda jedine by bola treba veľmi drobná úprava kódu, ktorý som ukázal:

float pohyb;                //double pohyb
while((pohyb = strtof(s_pohyb, &chybne) <= 0.0)||(strlen(chybne)))   //pohyb = strtod(..ostatné nezmenené
Nahoru Odpovědět
11.8.2015 11:24
I'm not afraid to die on a treadmill
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 21 zpráv z 21.