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

Zadanie 2.15 nr 1.

Ostatnio zmodyfikowano 2016-07-14 06:03
Autor Wiadomość
CCbolt
Temat założony przez niniejszego użytkownika
Zadanie 2.15 nr 1.
» 2016-07-13 20:57:30
Mam problem z zrozumieniem pewnego zagadnienia.

Mój kod pierwotnie wyglądał tak(kod nr1), wszystko przy cyfrach działa idealnie jednak przy literach zapętla się w nieskończoność.
W sieci znalazłem kod (kod nr 2) i podciągnąłem z niego do swojej pentli do/while komendy:
cin.clear(); cin.sync();
W kodzie nr 3 na pozór wszystko gra, przy cyfrach działa poprawnie przy literach drugie zapytanie jest powtórzone dwukrotnie i dzieje się to tylko raz.

Nie rozumiem czemu to się dzieje i jak się pozbyć podwójnego zapytania i jak się okazało nie rozumiem czemu
cin.clear(); cin.sync();
 wpływa na zamknięcie pętli zwłaszcza że w poprzednich zadaniach tych komend nie potrzebowałem.

http://forum.pasja-informatyki.pl/7534/co-jest-zlego-w-tym-kodzie <<= kod nr 2

Kod nr1
C/C++
#include <iostream>
using namespace std;

int main()
{
    float liczba;
    bool sprawdzam; // wynik 0/1 jako pomocniczy
   
    cout << "Podaj liczbe: ";
    cin >> liczba;
    sprawdzam = cin.good();
   
    if( sprawdzam == false )
    {
        do
        {
            cout << "Podaj liczbe: ";
            cin >> liczba;
            sprawdzam = cin.good();
        } while( sprawdzam == false );
       
    }
    cout << "Twoja liczba to: " << liczba;
    return 0;
}

Kod nr 2
C/C++
#include <iostream>

using namespace std;

int main()
{
    int liczba;
    do
    {
        cout << "Podaj liczbe:\n";
        cin.clear();
        cin.sync();
    }
    while( !( cin >> liczba ) );
   
    cout << "Twoja liczba to: " << liczba;
   
    return 0;
}

Kod nr 3
C/C++
#include <iostream>
using namespace std;

int main()
{
    float liczba;
    bool sprawdzam; // wynik 0/1 jako pomocniczy
   
    cout << "Podaj liczbe: ";
    cin >> liczba;
    sprawdzam = cin.good();
   
    if( sprawdzam == false )
    {
        do
        {
            cout << "Podaj liczbe: ";
            cin >> liczba;
            sprawdzam = cin.good();
            cin.clear();
            cin.sync();
        } while( sprawdzam == false );
       
    }
    cout << "Twoja liczba to: " << liczba;
    return 0;
}


P-149921
carlosmay
» 2016-07-13 21:50:55
P-149928
CCbolt
Temat założony przez niniejszego użytkownika
» 2016-07-14 00:12:39
Czytałem kilka razy ten temat.
Dorzuciłem cin.clear();cin.sync(); po wczytaniu pierwszej liczby i działa wszystko jednak dalej nie rozumiem czemu bez tego program się zapętlał w nieskończoność. Program z kodem nr 1 pobiera zapytanie z pętli Do/While i wypisuje je na okrągło, program z kodem nr 3 za pierwszym razem dubluje zapytanie z tej samej pętli Do/While ale tylko za pierwszym razem później pytanie występuje tylko raz.

Rozumiem że bufor jest zapchany błędnymi danymi i trzyma je do czasu ich wyczyszczenia ale w 100% nie rozumiem logiki tego działania.
Na pierwszy rzut oka wygląda to tak jakby program wykonywał się do momentu cin >> i zamiast dać mi wpisać dane automatycznie sam sobie je podstawia (mimo że nie powinien) a później wykonuje polecenie jakie zostało napisane, powraca do punktu wyjścia i tak na okrągło.

Kod nr 3 to dla mnie kamikaze, wyświetla 2 pytania obok siebie aby później funkcjonować poprawnie.

Mogę oczywiście schematycznie stosować cin.clear();cin.sync() jednak wolałbym to w pełni zrozumieć.
P-149931
mateczek
» 2016-07-14 00:22:41
C/C++
#include<iostream>
#include<limits>
using namespace std;

int main()
{
    int liczba;
    while( !( cin >> liczba ) ) {
        cin.clear();
        cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
        cout << "to nie liczba" << endl;
    }
   
    cout << "wczytana liczba " << liczba << endl;
}
P-149932
CCbolt
Temat założony przez niniejszego użytkownika
» 2016-07-14 02:22:36
Próbowałem zacząć od do/while ale coś nie pykło zresztą ( std::numeric_limits < std::streamsize >::max() tego nie znałem.
P-149935
mateczek
» 2016-07-14 04:38:55
na linuksie "cin.sync()" nie działa. Trzeba cin.ignore() by opróżnić bufor z niechcianych danych. Zresztą to, że cin.sync() na Windowsie daje rade wyczyścić bufor to chyba jakiś efekt uboczny.

PS. Zapoznaj się z instrukcjami break; continue; strasznie ułatwiają sprawę
C/C++
#include<iostream>
#include<limits>
using namespace std;

int main()
{
    int liczba;
    while( 1 ) {
        if( cin >> liczba ) break; // poprawne czytanie koniec pętli
       
        cin.clear();
        cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
        cout << "to nie liczba" << endl;
    }
   
    cout << "wczytana liczba " << liczba << endl;
}
P-149936
carlosmay
» 2016-07-14 05:30:27
PS. Zapoznaj się z instrukcjami break; continue; strasznie ułatwiają sprawę
Nie całkiem. Lepiej formułować w warunku opuszczanie pętli.
Wtedy widać czym pętla się zajmuje. Nadużywając
continue
 i
break;
 zmuszasz się do dogłębniejszej analizy większego fragmentu kodu.
Pisz tak, żeby "każdy głupek" mógł zrozumieć.

Rozumiem że bufor jest zapchany błędnymi danymi i trzyma je do czasu ich wyczyszczenia ale w 100% nie rozumiem logiki tego działania.
Po wprowadzeniu błędnych danych strumień ustawia flagę błędu. Póki flagi nie zostaną wyzerowane
std::cin.clear();
 użycie
std::cin
 będzie zablokowane i pomijane przy każdej próbie wczytywania. Wyzerowanie flag odblokowuje strumień i ponownie możliwe jest pobieranie danych z bufora. Jeśli w bufor nie zostanie oczyszczony (
std::cin.ignore();
) strumień ponownie zablokuje się na tych samych danych.
P-149937
CCbolt
Temat założony przez niniejszego użytkownika
» 2016-07-14 05:53:49
@carlosmay Łopatologiczne tłumaczenie jest najlepsze, rozterki rozwiane.
Jedno zagadnienie które mnie nurtuje to te z kodu nr3 czyli wystąpienie podwójnego zapytania w jednej linii, dzieje się to tylko raz.
Wiem że t błąd i jak go się pozbyć ale z czystej ciekawości się zastanawiam nad tym zjawiskiem, czemu to wygląda tak a nie inaczej.
P-149940
« 1 » 2
  Strona 1 z 2 Następna strona