NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Nekonečná smyčka

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

Aktivity
Avatar
Martin Kobelka:25.9.2016 21:53

Dobrý den

Omlouvám se že dnes už obtěžuji po druhé. Mám takový dotaz na jeden příklad, kterými nejde do hlavy. Tento program jednoduše převádí měnu v daném kurzu.

#include <stdio.h>

int main(void)
{
    int eur;
    while(1) {
        printf("zadejte kolik máte eur: ");

        scanf("%d", &eur);

        printf("Je to %f korun\n", eur * 26.5);
    }
    return 0;
}

V případě kdy zadám číslo, tak program funguje. V případě kdy zadám znak tak program začne do nekonečna vypisovat to samé a další vstup už po mě nepožaduje. Kde je chyba? Jak to ošetřit. Přemýšlíme nad tim ve dvou a ani jeden nevíme. Děkuji za odpověď :)

 
Odpovědět
25.9.2016 21:53
Avatar
Odpovídá na Martin Kobelka
Neaktivní uživatel:25.9.2016 22:02

scanf v tomto případě nedovede naparsovat vstup, proto nechá stdin neflushnutý, čili v dalši iteraci mu příjde ten samý vstup. Řešením by bylo testovat vrácenou hodnotu na 0 a případně flushnout stdin pomocí funkce fflush.

Editováno 25.9.2016 22:04
Nahoru Odpovědět
25.9.2016 22:02
Neaktivní uživatelský účet
Avatar
Jan Vargovský
Tvůrce
Avatar
Odpovídá na Martin Kobelka
Jan Vargovský:25.9.2016 22:04
if(scanf("%d", &eur) == 1)
{
        printf("Je to %f korun\n", eur * 26.5);
}
else
{
        printf("Neplatny znak\n");
        while((getchar())!='\n');
}

Jde o to, že máš nějaký buffer v pozadí a z něj bereš data. Jestliže máš v bufferu třeba "x123", tak se pořád snaží najít číslo, ale to tam není. Takže ti jen vrátí, že tam číslo není, ale to 'x' tam pořád zůstane.

 
Nahoru Odpovědět
25.9.2016 22:04
Avatar
Odpovídá na Martin Kobelka
Neaktivní uživatel:26.9.2016 15:05
/* Prevod EUR/CZK */

#define _CRT_SECURE_NO_WARNINGS

#include <conio.h> // _getch()
#include <ctype.h> // isdigit()
#include <stdio.h> // printf(), putchar()
#include <stdlib.h> // atof()

int main(int argc, char *argv[]){

        char eur[11] = ""; // castka v EUR
        unsigned char c; // cislice tvorici castku v EUR
        int done = 0; // status hlavni smycky programu (0 - beh, 1 - konec)
        int pos = 0; // pozice v retezci castky v EUR
        const double kurz = 26.5; // kurz EUR/CZK

        printf("Prevod EUR/CZK\n\n");
        while (!done) {
                printf("Zadejte kolik mate EUR: ");
                do {
                        c = _getch();
                        if (isdigit(c)) {
                                if (pos < 10) {
                                        putchar(c);
                                        eur[pos] = c;
                                        pos++;
                                }
                        }
                } while ((c != '\r')||(!pos));
                eur[pos] = '\0';
                printf("\n%s EUR = %.2f CZK\n\n", eur, atof(eur) * kurz);
                printf("Chcete pokracovat\? [a/n]: ");
                do {
                        c = _getch();
                } while ((c != 'a') && (c != 'n'));
                putchar(c);
                if (c == 'a') pos = 0;
                else done = 1;
                printf("\n\n");
        }
        return 0;
}

Ono použití funkce scanf() je samo o sobě dost nešťastné řešení. Programátor má velmi malou kontrolu nad tím jak ošetřit chyby na vstupu. Funkce je v knížkách uváděna zejména pro svoji jednoduchost. Každý program je ale jiný, což si vyžaduje individuální přístup k danému řešení. Problem se dá řešit mnoha způsoby. Funkce scanf() nabízí možnost určit sadu zpracovávaných znaků, dokonce umožňuje omezit maximální délku řetězce přiřazeného do jejího argumentu a pak aplikovat funkce ze standardní knihovny jazyka C. Nebo využít vhodnější funkci pro práci s řetězci funkci gets(). Ale ani ona sama bez použití dalších funkcí řešení nenabízí. Není ale nic snazšího než si načtení čísla s kontrolou ošetření chyb naprogramovat sám. viz kód.

PS: Ještě jedna věc, pozor na českou diakritiku v kódu. Bez určení znakové sady se nebudou znaky vypisovat správně.

Nahoru Odpovědět
26.9.2016 15:05
Neaktivní uživatelský účet
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 4 zpráv z 4.