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

Lekcja 26 - problem z zabezpieczeniem

Ostatnio zmodyfikowano 2016-03-01 20:26
Autor Wiadomość
Totalq
Temat założony przez niniejszego użytkownika
Lekcja 26 - problem z zabezpieczeniem
» 2012-12-04 21:50:25
C/C++
//Napisz prosty program, który wczyta imię, nazwisko i wiek dwóch osób. Funkcja główna programu ma mieć następującą postać:

#include <iostream>
#include <string>

void wczytajOsobe( std::string & imie, std::string & nazwisko, int & wiek )
{
    bool x;
   
    std::cout << "Podaj imie: ";
    std::cin >> imie;
    std::cout << "Podaj nazwisko: ";
    std::cin >> nazwisko;
    std::cout << "Podaj wiek: ";
    std::cin >> wiek;
    x = std::cin.fail();
   
    if( x == true )
    do
    {
        std::cin.sync();
        std::cin.clear();
        std::cout << "Blad, wpisz wiek ponownie: ";
       
        std::cin >> wiek;
        x == std::cin.fail();
    } while( x == true );
   
}

void wypiszOsobe( std::string imie, std::string nazwisko, int wiek )
{
    std::cout << "Imie: " << imie;
    std::cout << std::endl << "Nazwisko: " << nazwisko;
    std::cout << std::endl << "Wiek: " << wiek << std::endl;
}

int main()
{
    std::string imie[ 2 ];
    std::string nazwisko[ 2 ];
    int wiek[ 2 ];
    for( int i = 0; i < 2; i++ )
         wczytajOsobe( imie[ i ], nazwisko[ i ], wiek[ i ] );
   
    std::cout << std::endl;
   
    for( int i = 0; i < 2; i++ )
         wypiszOsobe( imie[ i ], nazwisko[ i ], wiek[ i ] );
   
    return 0;
}

Co bym nie wymyślił to przy próbie wpisania czegoś dziwnego w ,,wieku" program crashuje, zamiast pozwolić mi ponownie wpisać wartość. Pomożecie? ;)
P-70355
Mrovqa
» 2012-12-04 21:58:57
C/C++
x == std::cin.fail();
Nie myl operatorów przypisania i porównania.
P-70358
Totalq
Temat założony przez niniejszego użytkownika
» 2012-12-05 20:07:55
Po poprawieniu fukcji wczytajOsobe()

C/C++
void wczytajOsobe( std::string & imie, std::string & nazwisko, int & wiek )
{
    bool x;
   
    std::cin.sync();
   
    std::cout << "Podaj imie: ";
    std::cin >> imie;
   
    std::cout << "Podaj nazwisko: ";
    std::cin >> nazwisko;
   
    std::cout << "Podaj wiek: ";
    std::cin >> wiek;
   
    x = std::cin.fail();
   
    if( x == 1 )
    do
    {
        std::cin.sync();
        std::cin.clear();
        std::cout << "Blad, wpisz wiek ponownie: ";
       
        std::cin >> wiek;
        x = std::cin.fail();
    } while( x == 1 );
   

Program dalej nie działa prawidłowo przy wpisaniu np. litery do wieku.

***EDIT***

Uff, rozgryzłem, jednakże zrodziło się pewne pytanie.

Działający kod:

C/C++
void wczytajOsobe( std::string & imie, std::string & nazwisko, int & wiek )
{
    bool x;
   
    std::cin.sync();
    std::cout << "Podaj imie: ";
    std::getline( std::cin, imie );
   
    std::cout << "Podaj nazwisko: ";
    std::getline( std::cin, nazwisko );
   
    std::cout << "Podaj wiek: ";
   
    std::cin.sync();
    std::cin >> wiek;
   
    x = std::cin.fail();
   
    if( x == 1 )
    do
    {
       
        std::cout << "Blad, wpisz ponownie: ";
        std::cin.clear();
        std::cin.sync();
       
        std::cin >> wiek;
        x = std::cin.fail();
    } while( x == 1 );
   
}

Jak dotąd nie wiedziałem, że jest jakaś różnica, czy napiszemy tak:

C/C++
std::cin.clear();
std::cin.sync();

czy tak:

C/C++
std::cin.sync();
std::cin.clear();

Mógłby mi ktoś jeszcze raz dokładniej wytłumaczyć dlaczego kolejność jest ważna i co dokładnie wykonują te metody(?).
P-70397
f0g
» 2012-12-05 20:48:27
u mnie powyższy kod działa poprawnie(gdy wpisze literę jako wiek prosi o poprawny wiek)

std::cin.clear()
 czyści flagi błędu, a
std::cin.sync()
 czyści bufor strumienia.
P-70407
Totalq
Temat założony przez niniejszego użytkownika
» 2012-12-07 20:56:20
Nie wiele mi to pomogło. Dalej nie wiem dlaczego ważne jest zachowanie kolejności. Prosiłbym też o dokładniejsze objaśnienie terminu ,,czyści flagi błędu" jeśli chodzi o metodę cin.clear();
P-70496
mszumny
» 2016-03-01 17:21:52
#include <iostream>
#include <string>

using namespace std;
void wczytajOsobe(string & imie , string & nazwisko , int & wiek)
{
    bool x1, x2, x3;
    cout << "Podaj imie: ";
    cin >> imie;
    x1 = cin.good();

    cout << "Podaj nazwisko: ";
    cin >> nazwisko;
    x2 = cin.good();

    cout << "Podaj wiek: ";
    cin >> wiek;
    x3 = cin.good();
    if (x1,x2,x3 == false )
    do
    {
        cin.clear();
        cin.sync();
        cout << "Blad, wypisz  ponownie , imie, nazwisko, wiek: ";

        cin >> imie >> nazwisko >> wiek;
        x1,x2,x3 = cin.good();

    } while (x1,x2,x3 == false);



}
void wypiszOsobe (string imie , string nazwisko , int wiek)
{
   cout << imie << endl;
   cout << nazwisko << endl;
   cout << wiek<< endl;
}



int main()
{
    string imie[ 2 ];
    string nazwisko[ 2 ];
    int wiek[ 2 ];
    for( int i = 0; i < 2; i++ )
         wczytajOsobe( imie[ i ], nazwisko[ i ], wiek[ i ] );

    for( int i = 0; i < 2; i++ )
         wypiszOsobe( imie[ i ], nazwisko[ i ], wiek[ i ] );


    return 0;
}
P-145456
carlosmay
» 2016-03-01 20:26:25
Dalej nie wiem dlaczego ważne jest zachowanie kolejności.
Błąd wczytania danych ze strumienia do zmiennej powoduje ustawinie się strumienia w stan błędu.
To blokuje działanie na obiekcie
std::cin
.
Nic nie można zrobić póki nie zresetujemy flagi błędu metoda
std::cin.clear()
, czyli
std::cin.sync()
 próbuje wyczyścić zablokowany strumień.

Swoją drogą to
std::cin.ignore()
 służy do czyszczenia strumienia.
P-145465
« 1 »
  Strona 1 z 1