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: #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 #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 |
|
Savail |
» 2013-02-23 13:25:36 "CzySukces" to przecież nie jest wywołanie funkcji cin.good()... |
|
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. |
|
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? |
|
Monika90 |
» 2013-02-24 16:07:17 |
|
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ę! |
|
« 1 » |