Anim Temat założony przez niniejszego użytkownika |
Sprawdzanie poprawności typu (cin, cin.good) » 2016-11-27 23:42:15 Cześć :) Potrzebowałbym Waszej porady. Potrzebuję stabilnej kontroli wprowadzanego typu. Poniższy kod nie jest odpowiedni :) a więc kod: #include<iostream>
using namespace std;
int main() { int liczba; cin >> liczba; if( !( cin.good() ) ) { cout << "error\n"; cin.clear(); cin.sync(); } else cout << "Ok\n"; return 0; }
Kontrola typu za pomocą cin.good() nie wchodzi w rachubę, ponieważ w przypadku, gdy ktoś wprowadzi np. "4f" wyskoczy "Ok" - rozumiem, że cin.good/cin.fail sprawdza tylko pierwszy znak(?). Jak pominąć coś takiego? czy w grę wchodzą tylko tablice i sprawdzanie znak po znaku? czy jest jakaś funkcja, która lepiej obsłuży mój problem ;> |
|
karambaHZP |
» 2016-11-28 00:44:51 #include <iostream> #include <numeric>
int main() { int a; while( true ) { std::cin >> a; if( !std::cin ) { std::cin.clear(); std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); } else if( std::cin.get() != '\n' ) { std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); continue; } else { std::cout << a << '\n'; break; } } } Można jeszcze napisać to jako szablon i będzie uniwersalna funkcja wczytująca liczby. |
|
Gibas11 |
» 2016-11-28 01:28:43 @UP Ja tam użyłbym czegoś takiego: #include <iostream>
size_t ignoreNonDigits( std::istream & input ) { char character; auto count = 0u; while( !std::isdigit( character = input.get(), std::locale( "" ) ) ) count++; input.putback( character ); return count; }
int main() { int a; while( true ) { auto ignored = ignoreNonDigits( std::cin ); std::cin >> a; std::cout << "number: " << a << ", trash: " << ignored << " bytes" << std::endl; } }
Pobiera co ma i mówi ile śmieci było po drodze. |
|
Anim Temat założony przez niniejszego użytkownika |
» 2016-11-28 09:42:41 Super :) Dziękować :)
Powinien być taki kliczek na forum: Dziękuję ^^
Jeszcze tylko dla jasności: co dokładnie dzieje się w cin.get() ? Bo ja to interpretuję, że ten (if(cin.get!='\n')) ignoruje wszystko co nie jest enterem... ale chyba nie do końca, bo przecież w taki sposób ignorowałby również liczby. Hm... Mógłbym prosić o szybkie wyjaśnienie?
//Sam sobie odpowiem (może ktoś mnie poprawić): cin.get() sprawdza do momentu wpisania do bufora zmiennej określoego typu ( w moim przypadku int), jak napotka inny znak, to go ignoruje i traktuje jako błąd, czyli w moim przypadku, jak wpiszę 1234g, to cin.get() sprawdza w buforze strumienia, do momentu napotkania literki 'g', a to zdecydowanie jest różne od '\n' :) dobrze wykoncypowałem? ^^
|
|
karambaHZP |
» 2016-11-28 14:59:01 Mógłbym prosić o szybkie wyjaśnienie? |
std::cin.get() pobiera jeden znak z bufora strumienia i go zwaraca. W warunku sprawdzamy czy zwrócony znak jest znakiem końca linii, ponieważ operator >> pozostawia znaki nowej linii po wczytaniu danych. Jeśli nie jest '\n' oznacza, że oprócz poprawnie wczytanej wartości coś jeszcze zostało. W tej sytuacji czyścimy bufor std::cin.ignore i kontynuujemy do początku pętli. std::istream::get() |
|
Anim Temat założony przez niniejszego użytkownika |
» 2016-11-30 15:37:12 W związku z faktem, że kontrola podana przez kolegów powyżej ponownie nie odpowiadała moim oczekiwaniom, rozwiązałem mój problem poprzez konwersję stringa na inta. Dodatkowo potrzebowałem konsekwencji w przyjmowaniu spacji. Przy wprowadzaniu " 5" kod od Karamby przyjmował liczbę 5, natomiast przy wprowadzeniu "5 " już liczba 5 była traktowana jako błędna. Zapewne kod od Karamby można zmienić, aby bardziej odpowiadał moim oczekiwaniom, ale niestety nie umiałem tego zrobić (ogólnie, nie lubię posługiwać się strumieniami ;/) może komuś się przyda mój kod (kod jest zaprojektowany dla liczb od 0-99, ale łatwo go uogólnić do liczb większych, dodatkowym jego atutem - według mnie - jest wiekszą możliwość manipulowania warunkami): #include<iostream> #include<string>
using namespace std;
int main() { string a; int b; for(;; ) { getline( cin, a ); if( a.size() == 1 &&( a[ 0 ] > 48 && a[ 0 ] < 58 ) ) { break; } else if( a.size() == 2 &&( a[ 0 ] > 48 && a[ 0 ] < 58 ) &&( a[ 1 ] > 47 && a[ 1 ] < 58 ) ) { break; } else continue; } if( a.size() == 1 ) { b =( int )( a[ 0 ] - 48 ); cout << b << endl; } else { b =( int )( a[ 0 ] - 48 ) * 10 +( int )( a[ 1 ] - 48 ); cout << " " << b << endl; } }
|
|
« 1 » |