Przeczytałem artykuł dotyczący wyjątków na tej stronie, lecz niestety nie udało mi się go do końca ogarnąć. Mam oto taki problem. Stworzyłem przykładowo program w którym jest dajmy na to 40 poleceń readln oczekujących na podanie liczby. Oczywiście po podaniu jakiejkolwiek litery program padnie. I tu następuje moje pytanie - czy istnieje możliwość stworzenia jednego fragmentu kodu obsługującego ten wyjątek dla całego programu, a nie tworzyć dla każdego z tych 40 readln z osobna?
Jeżeli wszystkie procedury Readln mają wczytywać liczbę tego samego typu, to bez problemu możesz sobie napisać funkcję, która będzie to obsługiwała; Tylko żeby program nie został przerwany po podaniu czegoś innego niż liczby, trzeba wyłączyć obsługę błędów wejścia/wyjścia dyrektywą $IOCHECKS; A żeby sprawdzić czy pobranie liczby z klawiatury powiodło się, można wykorzystać funkcję IOResult;
Przykład takiej funkcji poniżej:
{$IOCHECKS OFF}
function GetNumber(out ANumber: Integer): Boolean;
begin
ReadLn(ANumber);
Result := IOResult() = 0;
end;
var
intNumber: Integer;
begin
Write('Podaj liczbe: ');
if GetNumber(intNumber) then
Write('podano liczbe ', intNumber)
else
Write('nie podano poprawnie liczby');
ReadLn;
end.
Dzięki temu program nie wyłaczy się (ani nie zatrzyma w trybie debug), jeśli podamy nieprawidłową liczbę;
Inny sposób to pobieranie łańcucha a nie liczby i wypróbowanie konwersji łańcucha na liczbę, np. za pomocą funkcji TryStrToInt:
uses
SysUtils;
function GetNumber(out ANumber: Integer): Boolean;
var
strInput: AnsiString;
begin
ReadLn(strInput);
Result := TryStrToInt(strInput, ANumber);
end;
var
intNumber: Integer;
begin
Write('Podaj liczbe: ');
if GetNumber(intNumber) then
Write('podano liczbe ', intNumber)
else
Write('nie podano poprawnej liczby');
ReadLn;
end.
I też będzie działać bez przerywania czy innych cudów.
Ok, a gdybym chciał powtórzyć wpisywanie liczby? I czy można to zrobić dla liczb rzeczywistych? Czyli na zasadzie: wprowadź liczbę-> wpisano litery -> powtórz wprowadzania liczby aż do skutku. Wyglądałoby to tak?
{$IOCHECKS OFF}
function GetNumber(out ANumber: real): Boolean;
begin
ReadLn(ANumber);
Result := IOResult() = 0;
end;
procedure podajliczbe(rNumber);
begin
GetNumber(rNumber);
Write('podano liczbe ', rNumber)
else
begin
Write('nie podano poprawnie liczby');
GetNumber(rNumber);
end;
end;
var
rNumber: real;
begin
Write('Podaj liczbe: ');
podajliczbe;
ReadLn;
end.
dodanie znacznika <code class="delphi">
- @furious programming
Jeśli chcesz wpisywać liczbę do skutku, to możesz to zrobić np. tak:
{$IOCHECKS OFF}
procedure GetNumber(const AMessage: AnsiString; out ANumber: Double);
begin
repeat
Write(AMessage);
ReadLn(ANumber);
until IOResult() = 0;
end;
var
dblNumber: Double;
begin
GetNumber('Podaj liczbe: ', dblNumber);
Write('Podana liczba: ', dblNumber:2:2);
ReadLn;
end.
Tylko pamiętaj, że w ten sposób wprowadzana liczba z klawiatury obsługuje znak .
jako separator dziesiętny.