Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Roz. 15. Do .. while. Zabezpieczenie przed wczytaniem nieprawidłowej liczby.

Ostatnio zmodyfikowano 2018-09-17 20:24
Autor Wiadomość
nonamecoder
Temat założony przez niniejszego użytkownika
[C++] Roz. 15. Do .. while. Zabezpieczenie przed wczytaniem nieprawidłowej liczby.
» 2018-08-01 18:28:55
Cześć, kombinuję już godzinę jak stworzyć zabezpieczenie przed wczytaniem liter. Jak na razie wyszło mi coś takiego:
C/C++
#include <iostream>

int main()
{
    int liczba1;
   
    std::cout << "Podaj liczbe: ";
    std::cin >> liczba1;
    std::cout << "Czy podano liczbe? ";
   
    if( std::cin.good() == 1 )
         std::cout << "Tak." << std::endl;
    else
    do
    {
        std::cout << "Nie." << std::endl;
        std::cout << "Podaj liczbe: ";
        std::cin >> liczba1;
    } while( std::cin.good() != 1 );
   
    std::cout << "Twoja liczba to: " << liczba1 << std::endl;
    return 0;
}
Po wpisaniu liter/y wynik: Wypisywanie się "Podaj liczbe: Nie." w nieskończoność. Przed drobnymi zmianami wynik to wypisanie "Nie. Podaj liczbe: Twoja liczba to: (losowa liczba wielocyfrowa)" Tutaj kod przed zmianami:
C/C++
#include <iostream>

int main()
{
    int liczba1;
   
    std::cout << "Podaj liczbe: ";
    std::cin >> liczba1;
    std::cout << "Czy podano liczbe? ";
   
    if( std::cin.good() == 1 )
         std::cout << "Tak" << std::endl;
    else
         std::cout << "Nie" << std::endl;
   
    if( std::cin.good() == 0 )
    do
    {
        std::cout << "Blad. Podaj liczbe: ";
        std::cin >> liczba1;
        std::cin.clear();
        std::cin.sync();
    } while( std::cin.good() != 1 );
   
    std::cout << "Liczba: " << liczba1 << std::endl;
    return 0;
}

Nie wiem który przypadek jest bliższy właściwemu, może poszedłem w kompletnie złą stronę.
Niestety nie umiem sobie z tym poradzić i jak na razie nie przychodzi mi nic do głowy. Z góry dziękuję za wszelką pomoc.

@edit
Znalazłem różnicę w kodzie i wyszło mi, że za wypisywanie w nieskończoność odpowiada nie dopisanie
C/C++
std::cin.clear();
std::cin.sync();
 w funkcji do ... while. Nie wiem czy to ma jakiekolwiek znaczenie skoro "zabezpieczenie" nie działa w żadnym przypadku.
P-171999
pekfos
» 2018-08-01 19:00:41
good() odczytuje informację o błędzie, a clear() niszczy informację o błędzie w std::cin. Kolejność ma ogromne znaczenie.
P-172000
nonamecoder
Temat założony przez niniejszego użytkownika
» 2018-08-02 01:58:15
Okej, rozumiem, że ma to znaczenie. Zmiana, czy usunięcie tych linijek nic nie wnosi lub robię coś źle... Jeśli da radę napisać co robię źle albo może posługuję się złą funkcją przy zabezpieczeniu - prosiłbym o wyjaśnienie, chociaż nakierowanie w dobrą stronę, bo ta wiadomość dużo mi nie mówi :/
P-172001
YooSy
» 2018-08-02 09:20:33
Kolejność operacji ma ogromne znaczenie.
1. Pobierasz dane.
2. Sprawdzasz ich poprawność i dopiero gdy nie udało się wczytać poprawnie czyścisz.
3. Powtarzasz pętle, aby ponownie pobrać jeśli trzeba.

U Ciebie w pętli nie ma zachowanej odpowiedniej kolejności.
Czytasz dane, czyscisz strumień, a na koniec sprawdzasz czy strumień jest OK (a jest po użyciu clear).


Btw: zamiast sync używaj ignore.
P-172002
nonamecoder
Temat założony przez niniejszego użytkownika
» 2018-08-04 21:44:37
C/C++
#include <iostream>

int main()
{
    int liczba;
    std::cout << "Podaj liczbe: ";
    std::cin >> liczba;
    bool dobrze = std::cin.good();
    std::cout << dobrze;
    if( dobrze == 0 )
    {
        do
        {
            std::cin.clear();
            std::cin.ignore( 1000, '\n' );
            std::cout << "Blad, podaj liczbe: ";
            std::cin >> liczba;
            std::cout << dobrze << std::endl;
        } while( dobrze == 0 );
       
       
    }
    else
         std::cout << "Podales liczbe!" << std::endl;
   
    std::cout << "Twoja liczba to: " << liczba << std::endl;
    return 0;
}
Stworzyłem to coś. Działa do pewnego momentu, nie wiem dlaczego. Po wpisaniu litery pętla się wykonuje... tyle, że po wpisaniu liczby w pętli nie kończy się. (Wypisywanie cin.good() miało mi pomóc w ogarnięciu co muszę poprawić, żeby poszło dalej - kombinowałem) Pętla czyści strumień co błąd, mimo to po wpisaniu liczby dalej wypisuje 0 :x Czuję, że popełniam jakiś błąd totalnego żółtodzioba, proszę o wskazówki.
P-172018
YooSy
» 2018-08-04 22:00:22
C/C++
do
{
    std::cin.clear();
    std::cin.ignore( 1000, '\n' );
    std::cout << "Blad, podaj liczbe: ";
    std::cin >> liczba;
    // tutaj należy zapamiętać stan strumienia, a tego nie robisz i korzystasz ze stanu z początku programu
    std::cout << dobrze << std::endl; // zresztą tutaj masz kontrolną wartość i nic ci nie podpowiada?
} while( dobrze == 0 );
P-172019
rupson
» 2018-09-17 19:46:53
Mam pytanko odnośnie tego zadania, mianowicie poradziłem sobie z nim w trochę inny sposób dodając return 0 w środku kodu - czy taka operacja jest prawidłowa?
Dodam, iż kod działa zgodnie z zadaniem.

#include <iostream>
#include <limits>

using namespace std;

int main()
{
    do
    {
    float liczba;
    cout << "Podaj liczbe: "<< endl;
    cin>>liczba;
    if (cin.good()== 1)
    {
        cout <<"Podales liczbe "<<liczba<<endl;
        return 0;
    }
    else
    cin.clear();
    cin.ignore( numeric_limits < streamsize >::max(), '\n' );
    }
    while (cin.good()==1);
    return 0;
}
P-172335
pekfos
» 2018-09-17 20:24:26
Jest prawidłowa.
P-172336
« 1 »
  Strona 1 z 1