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

zabezpieczenie przed blednymi danymi

Object Storage Arubacloud
0 głosów
649 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 (155,460 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 (155,460 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ź 313 wizyt
pytanie zadane 11 grudnia 2021 w PHP przez Bakkit Dyskutant (7,600 p.)
0 głosów
1 odpowiedź 538 wizyt
pytanie zadane 23 czerwca 2018 w C i C++ przez magmat Początkujący (390 p.)
0 głosów
1 odpowiedź 808 wizyt
pytanie zadane 16 stycznia 2020 w C i C++ przez PaaaV Nowicjusz (140 p.)

92,565 zapytań

141,418 odpowiedzi

319,604 komentarzy

61,952 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...