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

Zabezpieczenie Int"a przed String"iem

Cloud VPS
+1 głos
1,230 wizyt
pytanie zadane 27 grudnia 2016 w C i C++ przez breeg Początkujący (390 p.)
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <math.h>
#include <fstream>
#include <time.h>
#include <conio.h>
using namespace std;

float weight,height,score,score1;

float bmi_score(float score);


int main()
{
    cout << "Program do obliczania Bmi!" << endl;
    cout << "--------------------------" << endl;

    int choice;
    string choice2="1";
    while(choice2!="2")         // petla ktora wraca do poczatku
    {
    cout<<"Co chcesz zrobic?!"<<endl;
    cout<<"1)Sprawdz swoje BMI!"<<endl;       // Pocz¹tek programu
    cout<<"2)Wyjdz z programu!"<<endl;
    cout<<"Wybierz: ";
    cin>>choice;
    system("cls");


    switch(choice)                            //wybór rozpaczecia
    {

    case 1:



    cout << "Podaj swoja wage(kg)! ";
    cin>>weight;                              //zmienne do BMI
    cout << "Podaj swoj wzrost(cm)! ";
    cin>>height;

    if (weight<=0 || height <=0)
    {
        cout<<"Waga tak jak i wzrost musza byc wieksze od zera..."<<endl;      //Zabezpiecza przed podaniem liczby "0" 
    }

    else
    {
    cout<<"Twoje BMI!: ";
                                  //wynik BMI
    score=bmi_score(score);
    cout<<score<<endl;

    if (score<16)
    {
    cout<<"Wyglodzenie!"<<endl;
    }
    else if (score>=16 && score <=17)
    {
    cout<<"Wychudzenie!"<<endl;
    }                                                                                ////////warunki BMI

    else if (score>17 && score <18.5)
    {
    cout<<"Niedowaga!"<<endl;
    }

    else if (score>=18.5 && score <25)
    {
    cout<<"Waga prawidlowa!"<<endl;
    }

    else if (score>=25 && score <30)
    {
    cout<<"Nadwaga!"<<endl;
    }

    else if (score>=30 && score <35)
    {
    cout<<"I stopien otylosci!"<<endl;
    }

    else if (score>35)
    {
    cout<<"II stopien otylosci!"<<endl;
    }
    }
    cout<<endl<<"Co chcesz teraz zrobic ?"<<endl;
    cout<<"1)Licz jeszcze raz!"<<endl;
    cout<<"2)Wyjdz z programu!"<<endl;
    cout<<"Wybierz: ";
                   //wraca lub konczy program

    cin>>choice2;
    system("cls");

    if (choice2=="2")
    {
     system("cls");
     cout<<"Do zobaczenia !..."<<endl;
     Sleep(3000);                         //wyjscie z programu
     exit(0);
    }
    else if (choice2!="1" && choice2!="2")
    {
        cout<<"Wprowadziles zly znak! Program za chwile wroci do poczatku..."<<endl;
        Sleep(3000);
        system("cls");
    }


    break;


    case 2:

     system("cls");
     cout<<"Do zobaczenia !..."<<endl;
     Sleep(3000);                         //wyjscie z programu
     exit(0);

    break;



    }

    }

    return 0;
}


float bmi_score(float score)
{
    score=weight/pow(height,2)*10000 ;                //liczy bmi

    time_t czas;
    time( & czas );                           //podaje dokładny czas
    char * data = ctime( & czas );



    fstream plik;
    plik.open("bmi.txt",ios::out | ios::app);                              // zapisuje bmi i date do pliku
    plik<<"BMI: "<<score<<" /Data-";
    plik<<data;
    plik.close();
    return score;
};

Mam problem tego typu ze nie wiem jak zabezpieczyć program przed podaniem znaków zamiast cyfr ;d uprzedzam ze jest to jeden z moich pierwszych programów wiec kod moze byc słabo napisany :d prosze tez o jakies wskazówki co moge w nim poprawić :) 

komentarz 27 grudnia 2016 przez breeg Początkujący (390 p.)
 if (weight<=0 || height <=0)
    {
        cout<<"Waga tak jak i wzrost musza byc wieksze od zera..."<<endl;      //Zabezpiecza przed podaniem liczby "0" 
    }
 

w kodzie jest taki if :) i dołączam do tego pytania czy da sie dopisać jeszcze jakiś warunek przed podanie stringa do tego ifa ? :) 

1 odpowiedź

+1 głos
odpowiedź 27 grudnia 2016 przez plkpiotr Stary wyjadacz (12,420 p.)
edycja 27 grudnia 2016 przez plkpiotr
 
Najlepsza

Może po prostu pobierać dane, dopóki strumień okaże się poprawny:

int zmienna; // lub inny wbudowany typ liczbowy
cin >> zmienna;
while (!cin.good()) { // warunek niepoprawnosci strumienia
    cin.clear();
    cin.ignore(liczbaZnakow, '\n'); // bardziej profesjonalnie: std::cin.ignore(std::numeric_limits < std::streamsize >::max(), '\n' );
    cin >> zmienna;
}

Co można jeszcze zrobić? Sformatować nieco kod, aby był bardziej czytelny dla innych poprzez dodanie wcięć i usunięcie pustych linii. Jeśli działasz pod Code::Blocks to PPM -> format use AStyle. Samo usuwanie linii odbywa się przez ctrl+l. Oszczędziliśmy tym samym około pięćdziesiąt linijek...

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <math.h>
#include <fstream>
#include <time.h>
#include <conio.h>
using namespace std;

float weight, height, score, score1;
float bmi_score(float score);

int main() {
    cout << "Program do obliczania Bmi!" << endl;
    cout << "--------------------------" << endl;
    int choice;
    string choice2 = "1";
    while (choice2 != "2") {    // petla ktora wraca do poczatku
        cout << "Co chcesz zrobic?!" << endl;
        cout << "1)Sprawdz swoje BMI!" << endl;   // Pocz¹tek programu
        cout << "2)Wyjdz z programu!" << endl;
        cout << "Wybierz: ";
        cin >> choice;
        system("cls");
        switch (choice) {                         //wybór rozpaczecia
        case 1:
            cout << "Podaj swoja wage(kg)! ";
            cin >> weight;                            //zmienne do BMI
            cout << "Podaj swoj wzrost(cm)! ";
            cin >> height;
            if (weight <= 0 || height <= 0) {
                cout << "Waga tak jak i wzrost musza byc wieksze od zera..." << endl;  //Zabezpiecza przed podaniem liczby "0"
            } else {
                cout << "Twoje BMI!: ";
                //wynik BMI
                score = bmi_score(score);
                cout << score << endl;
                if (score < 16) {
                    cout << "Wyglodzenie!" << endl;
                } else if (score >= 16 && score <= 17) {
                    cout << "Wychudzenie!" << endl;
                }                                                                                ////////warunki BMI
                else if (score > 17 && score < 18.5) {
                    cout << "Niedowaga!" << endl;
                } else if (score >= 18.5 && score < 25) {
                    cout << "Waga prawidlowa!" << endl;
                } else if (score >= 25 && score < 30) {
                    cout << "Nadwaga!" << endl;
                } else if (score >= 30 && score < 35) {
                    cout << "I stopien otylosci!" << endl;
                } else if (score > 35) {
                    cout << "II stopien otylosci!" << endl;
                }
            }
            cout << endl << "Co chcesz teraz zrobic ?" << endl;
            cout << "1)Licz jeszcze raz!" << endl;
            cout << "2)Wyjdz z programu!" << endl;
            cout << "Wybierz: ";
            //wraca lub konczy program
            cin >> choice2;
            system("cls");
            if (choice2 == "2") {
                system("cls");
                cout << "Do zobaczenia !..." << endl;
                Sleep(3000);                         //wyjscie z programu
                exit(0);
            } else if (choice2 != "1" && choice2 != "2") {
                cout << "Wprowadziles zly znak! Program za chwile wroci do poczatku..." << endl;
                Sleep(3000);
                system("cls");
            }
            break;
        case 2:
            system("cls");
            cout << "Do zobaczenia !..." << endl;
            Sleep(3000);                         //wyjscie z programu
            exit(0);
            break;
        }
    }
    return 0;
}

float bmi_score(float score) {
    score = weight / pow(height, 2) * 10000 ;         //liczy bmi
    time_t czas;
    time( & czas );                           //podaje dokładny czas
    char * data = ctime( & czas );
    fstream plik;
    plik.open("bmi.txt", ios::out | ios::app);                             // zapisuje bmi i date do pliku
    plik << "BMI: " << score << " /Data-";
    plik << data;
    plik.close();
    return score;
}

Dodatkowo można pozbyć się nawiasów klamrowych w wyrażeniach if lub if else gdzie mamy do czynienia z jedną instrukcją, ponieważ gdy mamy jedną instrukcję w if'ach, czy w pętli to klamerki nie są potrzebne - ponownie skrócimy nasz kod : )

Tak na pierwszy rzut oka można byłoby pomyśleć o multiplatformowym czyszczeniu konsoli, aby nie ograniczać się wyłącznie do Windowsa... Może coś na wzór takiego rozwiązania, które można umieścić w pliku źródłowym:

#ifdef _WIN32 || _WIN64
#include <windows.h>
void clearScreen() {
    system("cls");
}
#else
#include <cstdio>
void clearScreen() {
    printf("\033[2J"); // Screen
    printf("\033[0;0f"); // Cursor
}

#endif

Wtedy aby wyczyścić konsolę wywołujemy funkcję clearScreen() - może ona nazywać się oczywiście inaczej.

komentarz 27 grudnia 2016 przez breeg Początkujący (390 p.)
cin.ignore(liczbaZnakow, '\n'); 

dzięki wielkie :) pomogłeś bardzo :) jeszcze jakbyś mógł tak dobrze wytłumaczyć o co chodzi w powyższej funkcji :) byłbym wdzięczny :)

komentarz 27 grudnia 2016 przez plkpiotr Stary wyjadacz (12,420 p.)

Nie ma sprawy ; ) Cieszę się, że mogłem pomóc : )

Wobec tego rozważmy [1] i [2] linijkę jeszcze raz:

cin.clear();
cin.ignore(1000, '\n');

Jak widać dokonujemy operacji na strumieniu wejściowym cin. To co jest po kropce to metody (funkcje wykonywane na rzecz strumienia). Język C++ w zależności od jego stanu ustawia flagi (pojedyncze bity) na stan 0 (false) lub 1 (true). Te bity to:

  • goodbit - true gdy wszystko ze strumieniem w porządku
  • badbit - true gdy np. próbujemy czytać z pliku, który został usunięty
  • failbit - true gdy podamy niewłaściwy format danych (Twój przypadek)
  • eofbit - true gdy chcemy przeczytać dane znajdujące się za znakiem końca pliku

U nas po wpisaniu liter zamiast liczb failbit został ustawiony na true, tym samym goodbit na false. Do ponownego, poprawnego działania w strumieniu musimy wyczyścić flagi błędów metodą clear() (bez argumentów), tym samym failbit zostanie ustawiony na false, a goodbit wraca do true. [1]

No dobrze flaga błędów nie informuje już nas o błędzie, ale nadal na strumieniu nie możemy działać, zatem pomińmy te znaki które były w strumieniu do znaku nowego wiersza (entera) - wszystkie te, które spowodowały błąd, dlatego ustawia tam się dużą liczbę np. 1000 znaków, aby były wyczyszczone. [2]
Od teraz możemy działać na strumieniu (np. wczytywać z klawiatury).

Bibliografia ; )
clear() - en.cppreference.com oraz flagi - tabela na końcu artykułu - en.cppreference.com

Podobne pytania

0 głosów
3 odpowiedzi 1,371 wizyt
pytanie zadane 23 listopada 2016 w C i C++ przez String Gaduła (4,520 p.)
0 głosów
1 odpowiedź 304 wizyt
0 głosów
1 odpowiedź 1,047 wizyt
pytanie zadane 16 listopada 2018 w C i C++ przez robertwe Gaduła (4,620 p.)

93,454 zapytań

142,449 odpowiedzi

322,718 komentarzy

62,833 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

Kursy INF.02 i INF.03
...