Diskuze: zacykleny scanf()
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 21 zpráv z 21.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
jakeho typu je promenna pohyb?
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
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.
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.
#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;
}
Teraz som si všimol, toto stačí.
while(pohyb <= 0)
Ináč makrá z knižnice ctype.h sa týkajú jednotlivých znakov, nie viacciferných čísiel alebo stringov!
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;
}
Bohuzel nestacilo. Opet to porad bezelo dokola.
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
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
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.
"Spravnym resenim je jak rikal Jozef toto:
Alespon teda pro me."
Skús zadať
1235k
a uvidíš, že to nie je dobre!
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;
}
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.
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;
}
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/).
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é
Zobrazeno 21 zpráv z 21.