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

Sprawdzanie poprawności typu (cin, cin.good)

Ostatnio zmodyfikowano 2016-11-30 15:37
Autor Wiadomość
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:

C/C++
#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 ;>

P-154199
karambaHZP
» 2016-11-28 00:44:51
C/C++
#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.
P-154201
Gibas11
» 2016-11-28 01:28:43
@UP Ja tam użyłbym czegoś takiego:
C/C++
#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.
P-154202
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? ^^
P-154203
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()

P-154214
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):

C/C++
#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;
    }
}

P-154344
« 1 »
  Strona 1 z 1