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


Zobrazeno 21 zpráv z 21.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
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.