• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

zabezpieczenie przed blednymi danymi

Mały hosting, OGROMNE możliwości
0 głosów
1,142 wizyt
pytanie zadane 26 marca 2018 w C i C++ przez kracjan122 Początkujący (370 p.)

Cześć, chce zabezpieczyć swój program przed wprowadzeniem błędnych danych. Przed wprowadzeniem liter zabezpieczyłem to tak 

if (!(cin>>metal>>krysztal>>deuter))
    {
        cerr<<"Nie poprawne dane! Program zostanie zakonczony.";
        exit(0);
    }

Teraz chce zabezpieczyć to jeszcze przed liczbami ujemnymi. Deklaruje unsigned int i po wprowadzeniu ujemnej liczby program się wysypuje. Jak zrobić, żeby pokazał się ten sam komunikat co przy literach? Wiem, że jest biblioteka cctype, ale nie wiem jak mogłaby mi pomóc. Mógłbym to zrobić na if'ach ale to się mija z celem :D 

Może ktoś mi podpowie w jaki sposób to zrobić :D 

3 odpowiedzi

+1 głos
odpowiedź 26 marca 2018 przez chucksqll Stary wyjadacz (12,930 p.)

Choćby tak:

If (!(...)||(liczba<0))

 

komentarz 26 marca 2018 przez kracjan122 Początkujący (370 p.)
Dzięki, jest to jakieś rozwiązanie, ale chyba nie najbardziej optymalne ;/

W każdym razie dla tego programu na pewno wystarczające, może ktoś wpadnie na inny pomysł :D
+1 głos
odpowiedź 26 marca 2018 przez mokrowski Mędrzec (158,960 p.)

Można i tak... Jest oczywiście jeszcze kilka innych sposobów:

#include <iostream>
#include <limits>
#include <type_traits>

// Pasuje do: bool, char, char16_t, char32_t, wchar_t, short, int, long, long long...
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
readValue(const std::string& msg) {
    T value;
    for(;;) {
        std::cout << msg;
        std::cin >> value;
        if(!std::cin) {
            std::cerr << "Dane nieprawidłowe.\n"
                << "Spróbuj jeszcze raz.\n";
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        } else {
            break;
        }
    }
    return value;
}

// Pasuje do: float, double, ... 
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
readValue(const std::string& msg) {
    T value;
    for(;;) {
        std::cout << msg;
        std::cin >> value;
        if(!std::cin) {
            std::cerr << "Dane nieprawidłowe.\n"
                << "Spróbuj jeszcze raz.\n";
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        } else {
            break;
        }
    }
    return value;
}

int main() {
    auto value1 = readValue<unsigned>("Wprowadź dane bez znaku: ");
    std::cout << "Wprowadzono i przyjęto: " << value1 << '\n';
    auto value2 = readValue<int>("Wprowadź dane ze znakiem: ");
    std::cout << "Wprowadzono i przyjęto: " << value2 << '\n';
    auto value3 = readValue<float>("Wprowadź zmiennoprzecinkowe: ");
    std::cout << "Wprowadzono i przyjęto: " << value3 << '\n';
}

Testów std::is_* jest w <type_traits> wiele... 

komentarz 26 marca 2018 przez niezalogowany
in:
-20
out:
Wprowadź dane bez znaku: Wprowadzono i przyjęto: 4294967276

mokrowski kompilowałeś za pomocą clang? 

komentarz 26 marca 2018 przez mokrowski Mędrzec (158,960 p.)
clang 6.0

Jak ktoś będzie chciał, dopasuje i do gcc tylko trzeba użyć nieco innych predykatów z <type_traits>
komentarz 27 marca 2018 przez kracjan122 Początkujący (370 p.)
Dziękuje :)
0 głosów
odpowiedź 26 marca 2018 przez niezalogowany
edycja 26 marca 2018

Możesz sprawić, czy w czasie wczytywania został podany minus, jeżeli tak zostanie ustawiona flaga błędu:

#include <iostream>

std::istream& minus_not_good(std::istream& in) 
{
	if ((in >> std::ws).peek() == std::char_traits<char>::to_int_type('-')) {
		in.setstate(std::ios_base::failbit);
	}
	return in;
}

void readUnsigned(unsigned int& value) 
{
	std::cin >> minus_not_good >> value;
}

int main()
{
	unsigned int metal{}, krysztal{}, deuter{};
	readUnsigned(metal);
	readUnsigned(krysztal);
	readUnsigned(deuter);
	std::cout << metal << " " << krysztal << " " << deuter << "\n";

	if (std::cin.fail())
	{
		std::cerr << "Niepoprawne dane! Program zostanie zakonczony. \n";
		std::exit(0);
	}
}

Ewentualnie jakoś przeciążyć operator>> dla unsigned int, ale to nie wiem jak zrobić. 

komentarz 26 marca 2018 przez kracjan122 Początkujący (370 p.)
Dziękuje :)

Podobne pytania

0 głosów
1 odpowiedź 576 wizyt
pytanie zadane 11 grudnia 2021 w PHP przez Bakkit Dyskutant (7,600 p.)
0 głosów
1 odpowiedź 973 wizyt
pytanie zadane 23 czerwca 2018 w C i C++ przez magmat Początkujący (390 p.)
0 głosów
1 odpowiedź 1,366 wizyt
pytanie zadane 16 stycznia 2020 w C i C++ przez PaaaV Nowicjusz (140 p.)

93,715 zapytań

142,629 odpowiedzi

323,260 komentarzy

63,258 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...