Пусть десятичная запись числа подается на вход программы символ за символом. Мы хотим << прочесть>> это число (поместить в переменную типа real его значение). Кроме того, надо сообщить об ошибке, если число записано неверно.
Более конкретно, представим себе такую ситуацию. Последовательность символов на входе делится на прочитанную и оставшуюся части. Мы можем пользоваться функцией Next:char, которая дает первый символ оставшейся части, а также функцией Move, которая забирает первый символ из оставшейся части, переводя его в категорию прочитанных.

Будем называть десятичной записью такую последовательность
символов:
а также такую:
Заметим, что согласно этому определению
01. 1
не являются десятичными записями. Сформулируем теперь
задачу точно:
5.2.1. Прочесть из входной строки максимальную часть, которая
может быть началом десятичной записи. Определить, является ли
эта часть десятичной записью или нет.
var state:
(Accept, Error, Initial, IntPart, DecPoint, FracPart);
state := Initial;
while (state <> Accept) or (state <>
Error) do begin
| if state = Initial then begin
| | if Next = ' ' then begin
| | | state := Initial; Move;
| | end else if Digit(Next) then begin
| | | state := IntPart; {после начала целой части}
| | | Move;
| | end else begin
| | | state := Error;
| | end;
| end else if state = IntPart then begin
| | if Digit (Next) then begin
| | | state := IntPart; Move;
| | end else if Next = '.' then begin
| | | state := DecPoint; {после десятичной точки}
| | | Move;
| | end else begin
| | | state := Accept;
| | end;
| end else if state = DecPoint then begin
| | if Digit (Next) then begin
| | | state := FracPart; Move;
| | end else begin
| | | state := Error; {должна быть хоть одна цифра}
| | end;
| end else if state = FracPart then begin
| | if Digit (Next) then begin
| | | state := FracPart; Move;
| | end else begin
| | | state := Accept;
| | end;
| end else if
| | {такого быть не может}
| end;
end;
Заметьте, что присваивания state:=Accept и state:=Error
не сопровождаются сдвигом (символ, который не может быть частью
числа, не забирается).Приведенная программа не запоминает значение прочитанного числа.
5.2.2. Решить предыдущую задачу с дополнительным требованием: если
прочитанный кусок является десятичной записью, то в переменную
val:real следует поместить ее значение.
state := Initial; val:= 0;
while (state <> Accept) or (state <> Error) do begin
| if state = Initial then begin
| | if Next = ' ' then begin
| | | state := Initial; Move;
| | end else if Digit(Next) then begin
| | | state := IntPart; {после начала целой части}
| | | val := DigitValue (Next);
| | | Move;
| | end else begin
| | | state := Error;
| | end;
| end else if state = IntPart then begin
| | if Digit (Next) then begin
| | | state := IntPart; val := 10*val + DigitVal(Next);
| | | Move;
| | end else if Next = '.' then begin
| | | state := DecPoint; {после десятичной точки}
| | | step := 0.1;
| | | Move;
| | end else begin
| | | state := Accept;
| | end;
| end else if state = DecPoint then begin
| | if Digit (Next) then begin
| | | state := FracPart;
| | | val := val + DigitVal(Next)*step; step := step/10;
| | | Move;
| | end else begin
| | | state := Error; {должна быть хоть одна цифра}
| | end;
| end else if state = FracPart then begin
| | if Digit (Next) then begin
| | | state := FracPart;
| | | val := val + DigitVal(Next)*step; step := step/10;
| | | Move;
| | end else begin
| | | state := Accept;
| | end;
| end else if
| | {такого быть не может}
| end;
end;`
5.2.3. Та же задача, если перед числом может стоять знак -
или знак + (а может ничего не стоять).![]()
Формат чисел в этой задаче обычно иллюстрируют такой картинкой:

5.2.4. Та же задача, если к тому же после числа может стоять
показатель степени десяти, как в 254E-4 (=0.0254 )
или в 0.123E+9
(
). Нарисуйте соответствующую картинку.![]()
5.2.5. Что надо изменить в приведенной выше программе, чтобы
разрешить пустые целую и дробную части (как в 1., .1 или
даже . -- последнее число считаем равным нулю)?![]()
Мы вернемся к конечным автоматам в главе 10 (Сравнение с образцом).