Ale.. najpierw pojawił się problem, że nawet jak wpisana liczba była złożona z samych cyfr pojawiał się komunikat "Wpisałeś wartość spoza wyznaczonego zakresu".
Nie powinno się tak dziać. Spróbuj tego przykładu:
#include <iostream>
int main()
{
int value;
std::cin >> value;
if (std::cin.fail())
{
std::cout << "Fail\n";
}
else
{
std::cout << "Good\n";
}
return 0;
}
(...) gdy próbowałam jakoś naprawić program i zrobić tak, żeby w przypadku, gdy liczba jest poprawna, program działał i pozwalał na dalsze zgadywanie, całkiem się wysypał.
Załóżmy, że próbujesz wczytać tekst do inta (czyli prosisz użytkownika o wpisanie liczby, a on wpisuje "kopytko"). Z tego przykładu powyżej wiesz już, że w takiej sytuacji std::cin będzie miał ustawioną flagę failbit. Musisz jeszcze wiedzieć, że std::cin przechowuje u siebie cały wprowadzony przez użytkownika tekst i gdy używasz operatora >>, wyciągasz z niego kolejne porcje. Przykład:
int a, b, c;
std::cin >> a;
std::cin >> b;
std::cin >> c;
std::cout << "Finished\n";
Gdy uruchomisz program i wpiszesz 1<spacja>2<spacja>3<enter> to natychmiast się zakończy. Sprawdź sobie, uruchom powyższy kod. Dobra, teraz dlaczego tak się dzieje?
W trakcie pierwszej instrukcji odczytu std::cin miał w swoim buforze "1<spacja>2<spacja>3<enter>". Każemy mu wczytać a. Ok, wyciąga z bufora liczbę do pierwszej nie-cyfry (jak będzie "123abc", to wyciągnie 123, a abc zostawi), w tym przypadku 1. Od teraz a jest równe 1, a w buforze zostało "<spacja>2<spacja>3<enter>".
Druga instrukcja odczytu: std::cin wyrzuca białe znaki z początku strumienia (bufor: "2<spacja>3<enter>") i wczytuje do pierwszej nie-cyfry. Więc b jest równe 2 i bufor ma w sobie "<spacja>3<enter>".
Z wczytywaniem c nie ma żadnych fajerwerków, ale zauważ co zostanie w buforze. Zostanie "<enter>". Zapamiętaj na przyszłość, że tak się dzieje, to nie będziesz mieć problemów z używaniem std::getline w przyszłości, ale tym się teraz nie przejmuj :)
Dobra, wracam do rozwiązania Twojego problemu, bo się trochę rozpisałem o std::cin-ie. Co się dzieje jak wczytujesz tekst do inta. Po linijce std::cin >> value; oprócz failbit-a, w buforze std::cin-a pozostaje "kopytko". Kiedy ponownie program napotka linijkę z wczytywaniem inta (jak u Ciebie w pętli?) nawet się nie zatrzyma. Poleci dalej, a failbit i bufor pozostaną w takim stanie jak były. Czyli po tym, jak wykryjesz, że std::cin się zepsuł (std::cin.fail()), musisz go naprawić i możesz z niego korzystać dalej :)
Koniec wstępu teoretycznego, praktyka:
#include <iostream>
#include <limits>
int main()
{
int guess;
std::cout << "Enter number from 1 to 1000: ";
std::cin >> guess;
while (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Incorrect value, please enter again: ";
std::cin >> guess;
}
// Correct input was entered, we can use it now :)
}
Linijka 12. -- std::cin.clear() -- czyści flagi, a więc failbit też. Kolejna linia wyciąga z bufora wszystkie znaki aż do entera. Od tego momentu std::cin jest już zdrowy i można z niego ponownie czytać :)
Trochę długa wyszła ta odpowiedź... :) A tak w ogóle to widać, że dbasz o porządek w kodzie i dobrze nazywasz zmienne. To bardzo ważne w programowaniu. Tak trzymaj, powodzenia ;)