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.