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

Problem z cin.good/cin.fail a float.

Ostatnio zmodyfikowano 2025-06-04 00:36
Autor Wiadomość
Unknown22
Temat założony przez niniejszego użytkownika
Problem z cin.good/cin.fail a float.
» 2013-02-23 12:49:11
Kiedy wpisałem program podany w rozdziale 9 czyli:
C/C++
#include "stdafx.h"
#include "iostream"
int main()
{
    int a;
    float b;
    std::cout << "Podaj liczbe calkowita: ";
    std::cin >> a;
    std::cout << "Czy udalo sie wczytac? " << std::cin.good() << std::endl;
    std::cout << "Czy cos nawalilo? " << std::cin.fail() << std::endl;
    std::cin.clear();
    std::cin.sync();
   
    std::cout << "Podaj liczbe rzeczywista: ";
    std::cin >> b;
    std::cout << "Czy udalo sie wczytac? " << std::cin.good() << std::endl;
    std::cout << "Czy cos nawalilo? " << std::cin.fail() << std::endl;
    std::cin.clear();
    std::cin.sync();
   
    std::cout << "Liczba a = " << a << std::endl;
    std::cout << "Liczba b = " << b << std::endl;
    return 0;
}

Wszystko mi wyświetla poprawnie czyli wynikiem tego jest:
Podaj liczbe calkowita: 2
Czy udalo sie wczytac? 1
Czy cos nawalilo? 0
Podaj liczbe rzeczywista: tak
Czy udalo sie wczytac? 0
Czy cos nawalilo? 1
Liczba a = 2
Liczba b = -1,07374e+008

Czyli poprawnie wykrywa, że została wpisana niepoprawna dana.
Napisałem później taki o to program i nie działa mi ta funkcja poprawnie gdyż nawet po wpisaniu liter stwierdza, że zostały podane poprawne dane :/ Ma ktoś wytłumaczenie co jest nie tak? Używam Microsoft Visual Studio 2012 Professional
C/C++
#include "stdafx.h"
#include "iostream"

using namespace std;

int main()
{
    float a;
    float b;
    float c;
    bool CzySukces1 = cin.good();
    bool CzySukces2 = cin.good();
    bool CzySukces3 = cin.good();
   
    cout << "Podaj pierwsza liczbe: ";
    cin >> a; CzySukces1;
    cout << endl;
    cin.clear();
    cin.sync();
    cout << "Podaj druga liczbe: ";
    cin >> b; CzySukces2;
    cout << endl;
    cin.clear();
    cin.sync();
    cout << "Podaj trzecia liczbe: ";
    cin >> c; CzySukces3;
    cout << endl;
    cin.clear();
    cin.sync();
   
    cout << "Pierwsza liczba to: " << a << " Wczytano? " << CzySukces1 << endl;
    cout << "Druga liczba to: " << b << " Wczytano? " << CzySukces2 << endl;
    cout << "Trzecia liczba to: " << c << " Wczytano? " << CzySukces3 << endl;
   
    getchar();
    return 0;
}

Np. Dla danych wejściowych:

13.3
tak 123
33.22nie

Wyświetla
13.3 1
-1.07374e+008 1
33.22 1
P-76776
Savail
» 2013-02-23 13:25:36
"CzySukces" to przecież nie jest wywołanie funkcji cin.good()...
P-76782
Monika90
» 2013-02-23 13:26:05
Zmienne CzySukces1,2,3 miały nadaną wartośc zanim jakiekolwiek dane zostały wczytane, stan tych zmiennych nie zmieni się magicznie sam.

#include "iostream" to jest źle, powinno być <iostream>

Używanie cin.sync() nie ma sensu.
P-76783
Unknown22
Temat założony przez niniejszego użytkownika
» 2013-02-23 17:02:05
Używam cin.sync(); bo tak pisze w tym kursie na tej stronie.
Dlaczego nie używa się tego? Przecież z tego co zrozumiałem to czyści to ten bufor z danymi co wpisaliśmy, bo jeśli ktoś złośliwie wpisze np. 123nie, 452 to gdy wczytam to do zmiennej float to odczyta chyba tylko do przecinka a do float samą cyfrę 123 wczyta. A , 452 dalej został i byłby wczytany do następnej zmiennej i byłby problem? Źle to rozumiem?
P-76803
Monika90
» 2013-02-24 16:07:17
To co robi cin.sync() zależy od konkretnej implementacji i jest nieprzenośne, standard nie daje żdanych gwarancji, że sync() wyczyści bufor.
Lepiej używaj
cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );

http://en.cppreference.com/w/cpp/io/basic_istream/ignore
a jeszcze lepiej zamiast
cin >> x;
 wczytujesz całą linię tekstu
std::getline( cin, line )
 i ją analizujesz.
http://en.cppreference.com/w/cpp/string/basic_string/getline
P-76894
termistor
» 2025-06-04 00:36:26
Witaj, Unknown22. Twoje pytanie dotyczy problemu z niepoprawnym sprawdzaniem stanu strumienia wejścia w C++. Analizując Twój kod, mogę wskazać kilka kluczowych błędów i wskazać, jak je naprawić.

---

### 1. Błąd w ustawianiu zmiennych CzySukces1, CzySukces2, CzySukces3
W Twoim kodzie zmienna `CzySukces1` (i pozostałe) jest inicjalizowana **przed** jakimkolwiek wprowadzeniem danych:
```cpp
bool CzySukces1 = cin.good();
```
Tutaj `cin.good()` zwraca stan strumienia **w momencie inicjalizacji zmiennej**, czyli na samym początku programu. Natomiast wprowadzanie danych (`cin >> a;`) może spowodować zmianę stanu strumienia (np. błąd wczytania). Jeśli jednak **nie przypiszesz ponownie** wyniku `cin.good()` do `CzySukces1`, zmienna ta pozostanie z wartością z inicjalizacji (czyli `true`), mimo że wczytanie danych mogło się nie powieść.

**Poprawna wersja:**
```cpp
cout << "Podaj pierwsza liczbe: ";
cin >> a;
CzySukces1 = cin.good();  // <---- tutaj! sprawdzenie *po* wczytaniu
```

---

### 2. Niepoprawne użycie `cin.sync()`
Funkcja `cin.sync()` jest **nieprzenośna** i **niezalecana** w standardowym kodzie C++. Jej działanie zależy od implementacji biblioteki C++ i może różnić się między kompilatorami. W Twoim przypadku, po wprowadzeniu danych (np. `123nie`), strumień wychodzi w stan błędu, ale bufor wejściowy pozostaje z nieprzetworzoną częścią danych (np. `nie`). Użycie `cin.sync()` nie gwarantuje, że bufor zostanie wyczyszczony.

**Zamiast `cin.sync()`, zalecam:**
```cpp
cin.clear();                  // reset stanu błędnego
cin.ignore(numeric_limits<streamsize>::max(), '\n');  // wyczyszczenie bufora do znaku nowej linii
```
Wymaga to dołączenia nagłówka `<limits>` i użycia `std::numeric_limits`.

---

### 3. Niepoprawne przetwarzanie niepoprawnych danych
Po wprowadzeniu danych typu `tak 123` lub `33.22nie`, strumień `cin` przechodzi w stan błędu (`failbit`). Pomimo użycia `cin.clear()`, **nieprawidłowe dane pozostają w buforze** i są próbowane ponownie przy kolejnym `cin >> c;`. To powoduje, że program "próbuje" wczytać niepoprawne dane ponownie, co prowadzi do niespodziewanych wyników.

---

### 4. Poprawny sposób sprawdzania wczytania danych
Zamiast zapisywać wynik `cin.good()` do zmiennej na starcie, sprawdzaj go **po każdym wczytaniu**. Przykład poprawnej implementacji:
```cpp
#include <iostream>
#include <limits>
using namespace std;

int main() {
    float a, b, c;
    bool CzySukces1, CzySukces2, CzySukces3;

    cout << "Podaj pierwsza liczbe: ";
    cin >> a;
    CzySukces1 = cin.good();

    if (!CzySukces1) {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    cout << "Podaj druga liczbe: ";
    cin >> b;
    CzySukces2 = cin.good();

    if (!CzySukces2) {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    cout << "Podaj trzecia liczbe: ";
    cin >> c;
    CzySukces3 = cin.good();

    cout << "Pierwsza: " << a << " (" << (CzySukces1 ? "OK" : "Błąd") << ")\n";
    cout << "Druga: " << b << " (" << (CzySukces2 ? "OK" : "Błąd") << ")\n";
    cout << "Trzecia: " << c << " (" << (CzySukces3 ? "OK" : "Błąd") << ")\n";

    return 0;
}
```

---

### 5. Dodatkowe porady
- **Unikaj `using namespace std;`** w większych projektach — prowadzi to do konfliktów nazw.
- Zawsze **sprawdzaj poprawność wczytania danych** po każdym `cin >> ...`.
- Używaj `cin.ignore(...)` po `cin.clear()` w przypadku błędnego wprowadzenia danych.
- Jeśli chcesz obsłużyć bardziej skomplikowane dane (np. tekst z liczbą), rozważ użycie `std::getline` i konwersji (np. `std::istringstream`).

---

Dzięki tym zmianom Twój program będzie poprawnie reagował na błędy wprowadzania danych i wypisywał właściwe informacje o sukcesie czy niepowodzeniu wczytania. Jeśli masz więcej pytań — chętnie pomogę!
P-182482
« 1 »
  Strona 1 z 1