Zabezpieczenie przed wpisywaniem liter

Bardzo często na forum pojawia się pytanie: jak zabezpieczyć program przed wpisaniem liter, gdy program oczekuje na liczby.
Najprostsze rozwiązanie w języku C++ wygląda tak:

int zmienna;
while(!(cin>>zmienna)) //dopóki strumień jest w stanie błędu -> dopóki podawane są błędne dane
{
  //ew komunikat błędu
  cin.sync(); //kasowanie zbędnych znaków z bufora
  cin.clear(); //kasowanie flagi błędu strumienia
}
//tutaj na pewno wczytano poprawne dane do zmienna
 


W języku C nie istnieje równie proste rozwiązanie tego problemu. Można spróbować użyć:

int zmienna;
while(scanf("%d", &zmienna) != 1) //dopóki nie uda się wczytać
{
  //ew. komunikat błędu
  fflush(stdin);
}


Ale nie jest to dobre rozwiązanie, ponieważ jest zależne od implementacji. fflush() nie zawsze powoduje wyczyszczenie bufora!
Rozwiązanie działające w każdej sytuacji (i implementacji) polega na żmudnym wyciągnięciu z stdin zalegających tam, zbędnych znaków (dodatkowa pętla w miejscu fflush())

int zmienna;
while(scanf("%d", &zmienna) != 1) //dopóki nie uda się wczytać
  {
    //ew. komunikat błędu
    while(char c=getchar() != '\n' && c!=EOF); //pętla wyciągająca znaki z bufora
  }
Informacje
Ostatnia modyfikacja 02-04-2010 22:25 Ostatni autor Shalom
Ilość wyświetleń 1980 Wersja 3
Komentarz
Olivia dnia 23-08-2010 21:10
Hm. A niedawno czytałam, że to błąd. Dzięki za wyprostowanie.
Shalom dnia 23-08-2010 21:08
"In the C Standard Library, character read functions such as getchar return a value equal to the symbolic value (macro) EOF to indicate that an end-of-file condition has occurred"
Parafrazując: EOF w powyższym kodzie to nie jest wartość zmiennej char, a pewne makro, które ma "specjalną wartość". Funkcja getchar() sprytnie nie zwraca nam "znaku eof" (bo takowego w ascii nie ma) a jedynie ową "specjalną wartość" kiedy natrafi na prawdziwego eof'a. Stąd też kod jest poprawny ;)
Olivia dnia 23-08-2010 20:07
Rozwiązanie c chyba nie jest zbyt dobre.  char nie przechowa EOF.

Copyright © 2000-2006 by Coyote Group 0.9.3-pre3
Czas generowania strony: 0.0247 sek. (zapytań SQL: 9)