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

[C++] Lekcja 17 zabezpieczenie przed źle wprowadzonymi danymi.

Ostatnio zmodyfikowano 2014-08-17 13:25
Autor Wiadomość
carlosmay
Temat założony przez niniejszego użytkownika
[C++] Lekcja 17 zabezpieczenie przed źle wprowadzonymi danymi.
» 2014-08-13 21:41:22
C/C++
/*  1. Napisz funkcje, ktora bedzie wczytywala ze standardowego wejscia
        i zwracala wczytana wartosc (zalozenie od 1 do 1000)
    2. Funkcja ma zagwarantowac, ze zwracana liczba jest poprawna.
    3. Jesli nie to pytaj uzytkownika do skutku.*/

#include <iostream>
using namespace std;

int wczytajLiczbe()
{
    int wczytLicz;
    if( 1 < wczytLicz < 1000 );
   
    do {
        cin.good();
        cin.fail();
        cin >> wczytLicz;
       
        if( cin.fail() > 0 || wczytLicz < 1 || wczytLicz > 1000 )
             cout << "Podales zle dane: sproboj ponownie." << endl;
       
        cin.clear();
        cin.sync();
    } while( cin.fail() == 1 || wczytLicz < 1 || wczytLicz > 1000 );
   
    return wczytLicz;
}

int main()
{
    cout << "Podaj liczbe: ";
    int liczba = wczytajLiczbe();
   
    cout << "Podales liczbe: " << liczba << endl;
   
    return 0;
}


Problem jest gdy podaję do wczytania np. 123fg.
Pozostałe przypadki ogarnąłem, czyli wpisywanie samych liter oraz liczby
spoza założonego przedziału.
P-115424
Mateus.
» 2014-08-13 21:57:34
if( 1 < wczytLicz < 1000 );
 - To nic nie robi.
C/C++
do {
    cin.good(); //To i
    cin.fail(); //To jest niepotrzebne
    cin >> wczytLicz;
   
    if( cin.fail() > 0 || wczytLicz < 1 || wczytLicz > 1000 )
         cout << "Podales zle dane: sproboj ponownie." << endl;
   
    cin.clear(); // To i
    cin.sync(); // To powinno być na początku petli
} while( cin.fail() == 1 || wczytLicz < 1 || wczytLicz > 1000 );

Popraw też te warunki. One są bardzo przekombinowane i dlatego sam się w nich pogubiłeś.
P-115425
carlosmay
Temat założony przez niniejszego użytkownika
» 2014-08-16 21:28:02
C/C++
int wczytajLiczbe()
{
    int wczytLicz;
    do {
        cin.clear();
        cin.sync();
        cin >> wczytLicz;
       
        if( wczytLicz < 1 || wczytLicz > 1000 )
             cout << "Podales zle dane: sproboj ponownie." << endl;
       
       
    } while( wczytLicz < 1 || wczytLicz > 1000 );
   
    return wczytLicz;
}

Poprawiłem funkcję. Faktycznie było tego za dużo. Trochę przekombinowałem.
Nadal nie wiem jak zabezpieczyc sie przed wpisaniem takiej danej "123fg".
Wyświetla, że podałem liczbę 123 i kończy pętlę.
Jestem "świeży" w C++ i ten temat jest ostatnim jaki robiłem.

Dzięki za wskazówki.
P-115591
kubek3898
» 2014-08-16 22:13:53
Powinieneś czyścić strumień po pobraniu zmiennej, nie przed.
P-115594
carlosmay
Temat założony przez niniejszego użytkownika
» 2014-08-17 01:17:00
W pierwszej zagmatwanej od kombinowania odslonie kodu mialem czyszczenie po przyjęciu zmiennej.
Poczysciłem kod ze zbędnych warunków i instrukcji.
Zostało tylko co ważne, ale nie rozwiązuje niewykrywania błędnej danej tj.
123fg
.
P-115597
Mateus.
» 2014-08-17 08:05:22
Zrób tak, aby warunek pętli był spełniony, tylko wtedy gdy udało się wczytać i liczba jest z określonego przedziału.
P-115599
carlosmay
Temat założony przez niniejszego użytkownika
» 2014-08-17 10:42:34
C/C++
int main()
{
    int liczba;
    bool poprawnie;
    do
    {
        cout << "Podaj liczbe: " << endl;
        cin >> liczba; //wczytuje liczbe
        poprawnie = cin.good();
        cin.clear(); //czyszczenie wejscia
        cin.sync();
       
        if( liczba < 1 || liczba > 1000 ) //warunek dla wyswietlenia tekstu
             cout << "Podales nieprawidlowa liczbe. Sprobuj ponownie. " << endl;
       
    } while( !poprawnie &&( liczba < 1 || liczba > 1000 ) ); //warunek wyjscia z petli
   
    cout << "Podales: " << liczba << endl << "Koniec" << endl << endl; //wypisuje poprawnie wpisana liczbe
   
    system( "pause" );
    return 0;
}


Podaj liczbe:
123fg
Podales: 123
Koniec

Press any key to continue .  .  .

Efekt jest ciągle ten sam. Googlowałem troche temat i chyba nie da rady tego
naprawic w tym podstawowym zakresie.
Jest tak samo jak wpisanie

3.33.333.3
program wczyta tylko 3.33 i pójdzie dalej.
Dzięki za zainteresowanie.
P-115601
kubek3898
» 2014-08-17 11:11:37
http://cpp0x.pl/forum/temat/​?id=2147&p=2

Alueril stworzył dokładnie to, czego oczekujesz:

C/C++
#include <iostream>
#include <windows.h>

using namespace std;

template < typename T, typename CharT, typename Traits >
bool read( std::basic_istream < CharT, Traits >& istr, T & result )
{
    using namespace std;
   
    istr >> result;
    if( istr.good() )
    { // stream has still goodbit set, check whether next character is white.
        const ctype < CharT >& ctype_facet = use_facet < ctype < CharT > >( istr.getloc() );
        if( ctype_facet.is( ctype < CharT >::space, Traits::to_char_type( istr.peek() ) ) )
        { // it is, so everything is okay.
            return true;
        }
    }
    else if( istr.eof() )
    { // we reached end of file, don't clear state nor buffer.
        return false;
    }
    // reading failed or next character isn't white, clear stream state and buffer
    istr.clear();
    istr.sync();
    return false;
}

int main()
{
    int liczba;
   
    while( cin.good() )
    {
        cout << "Podaj liczbe: " << endl;
       
        if( read( cin, liczba ) && liczba > 1 && liczba < 1000 ) {
            cout << "Liczba prawidlowa: " << liczba << endl;
            break;
        } else {
            cout << "Podales nieprawidlowa liczbe. Sprobuj ponownie." << endl;
        }
    }
   
    cout << "Podales: " << liczba << endl << "Koniec" << endl << endl; //wypisuje poprawnie wpisana liczbe
   
    system( "pause" );
    return 0;
}
P-115602
« 1 » 2
  Strona 1 z 2 Następna strona