Текст.отд
Главная     ◄Глагол     ◄Азбука     ◄Задачи на Глаголе     Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы
 
 glagol.png Программируем по-русски
 

Основная задача Глагола — дать человеку возможность воплощать свои мысли на языке, близком к его родному языку.

Издатель Глагола
 

 
(*~\Глагол\Отделы\Числа~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                        ОТДЕЛ Текст;
(*============================================================================* 
 * НАЗНАЧЕНИЕ: преобразование Чисел в(из) Текст(а)
 *----------------------------------------------------------------------------* 
 * В задачах <ИзЧЦел> и <ИзЧВещ> входное <описание> - это цепочка знаков,
 * содержащая и обычные знаки, которые просто переписываются в <текст>
 * и описатели представлений чисел, которые имеют следующее строение:
 *
 *   %[<номарг>:,-,<ширина>,.<точность>]<вид>
 *
 *      Описатель представления начинается со знака '%'. Затем без
 *   пробелов следует ряд [необязательных] параметров:
 *
 *   [<номарг>:]   - определяет номер аргумента, к которому относится
 *                   данный описатель
 *   [-]           - признак выравнивания влево
 *   [<ширина>]    - ширина поля вывода
 *   [.<точность>] - параметр точности
 *   <вид>         - знак, определяющий вид текущего аргумента
 *
 *      Знаки, определяющие вид аргумента:
 *
 *   'd'-Десятичное целое. Значение аргумента преобразуется в цепочку
 *       десятичных цифр. Если описатель представления содержит параметр
 *       точности, то текст должен содержать количество цифр, не
 *       менее указанного значения. Если значение содержит меньше
 *       цифр, то оно дополняется слева нулями.
 *
 *   'x'-Шестнадцатеричное целое. Значение аргумента преобразуется в цепочку
 *       шестнадцатеричных цифр. Если описатель представления содержит
 *       параметр точности, то текст должен содержать количество цифр, не
 *       менее указанного значения. Если значение содержит меньше
 *       цифр, то оно дополняется слева нулями.
 *
 *   'e'-Вещественное число в научном представлении.
 *       Значение преобразуется в цепочку вида "-ц,цц...E+ццц", где ц
 *       обозначает цифру. Отрицательные числа начинаются со знака минус.
 *       Перед десятичной запятой всегда имеется одна цифра. Общее
 *       число цифр (включая цифру до запятой) задается параметром точности.
 *       По умолчанию точность равна 15.
 *       После знака порядка "E" всегда присутствует знак плюс или
 *       минус и 3 цифры порядка.
 *
 *   'f'-Вещественное число с неподвижной запятой.
 *       Значение преобразуется в цепочку вида "-ццц,ццц...".
 *       Отрицательные числа начинаются со знака минус.
 *       Параметр точности показывает, сколько цифр будет после запятой.
 *       По умолчанию точность равна 2.
 *
 *   'g'-Вещественное число в общем виде.
 *       Значение преобразуется в кратчайшее десятичное представление
 *       (научное или неподвижное). По умолчанию число цифр, которое задается
 *       параметром точности, равно 15. Лишние нули удаляются, а запятая
 *       появляется только при необходимости. Результирующая цепочка
 *       представляется с неподвижной запятой, если число цифр левее запятой
 *       меньше или равно указанной точности и если значение больше
 *       или равно 0,00001. Иначе цепочка будет представлена в научном
 *       представлении.
 *
 *   'c'-Знак. Значение аргумента преобразуется в знак с порядковым
 *       номером, равным значению аргумента.
 *
 *      Если <вид> не принадлежит {'d','x','c','e','f','g'}, то параметры
 *   применяются не к аргументу, а к знаку <вид>.
 *      Числовые параметры могут извлекаться из текущего аргумента,
 *   если в качестве параметра выступает знак '*'.
 *      Знак 't' обозначает отсуп заданной ширины. По умолчанию ширина = 8.
 *============================================================================*)
ИСПОЛЬЗУЕТ
<*ЕСЛИ НЕ ЗАДАНО("МПГ") ТО*>
  Асм   ИЗ "..\Иное\",
<*КОН*>
  Буква ИЗ "..\Иное\",
  Знак  ИЗ "..\Иное\",
  Цепь  ИЗ "..\Иное\";

ВИД
  Число-=ЦЕПЬ[32];

ВИД
  РядЧВещ=РЯД 4 ИЗ ШИРВЕЩ;
  РядЧЦел=РЯД 4 ИЗ ШИРЦЕЛ;

<*ЕСЛИ НЕ ЗАДАНО("МПГ") ТО*>
(******************************************************************************)
ЗАДАЧА Особенность(число:ШИРВЕЩ; текст+:Число; дл+:ЦЕЛ):КЛЮЧ; 
(* Определяет и обозначает особые состояние <число>
 ******************************************************************************
 * Ответ: ВКЛ, если <число> - не является числом *)
ПОСТ
  ПлюсБеск  = "+БЕСК";
  МинусБеск = "-БЕСК";
  НеЧисло   = "НЕЧ";
УКАЗ
  ВЫБРАТЬ Асм.Особенность(число) ИЗ
  | Асм.МинусБеск:
      текст:=МинусБеск;
      дл:=ДЛИНА(МинусБеск)
  | Асм.ПлюсБеск:
      текст:=ПлюсБеск;
      дл:=ДЛИНА(ПлюсБеск)
  | Асм.НеЧисло:
      текст:=НеЧисло;
      дл:=ДЛИНА(НеЧисло)
  ИНАЧЕ
    ВОЗВРАТ ОТКЛ 
  КОН;
  ВОЗВРАТ ВКЛ
КОН Особенность;
 
(******************************************************************************)
ЗАДАЧА ИзВещЕ-(число:ШИРВЕЩ; точность:ЦЕЛ; текст+:Число; дл+:ЦЕЛ);
(* Вещественное число в научном представлении.
 ******************************************************************************
 * До:    <число>    - преобразуемое число
 *        <точность> - цифр после запятой
 * После: <текст>    - текстовое представление числа
 *        <дл>       - его длина *)
ПЕР
  порядок:ЦЕЛ;   (* порядок числа *)
  цифры:Число;   (* цифры без точки *)
  пц:ЦЕЛ;        (* позиция цифры *)
УКАЗ
  ЕСЛИ Особенность(число,текст,дл) ТО
    ВОЗВРАТ
  КОН;
  ЕСЛИ точность < 0 ТО
    точность:=15
  АЕСЛИ точность > 18 ТО
    точность:=18
  КОН;
  дл:=0;
  ЕСЛИ число < 0 ТО      (* знак перед числом *)
    текст[дл]:='-';
    УВЕЛИЧИТЬ(дл)
  КОН;
  число:=МОДУЛЬ(число);
  порядок:=Асм.Порядок(число);
  Асм.ВЦифры(число,точность+1,цифры); (* 18 цифр *)
  ЕСЛИ цифры[0] = '0' ТО
    пц:=1
  ИНАЧЕ (* есть десятки *)
    пц:=0;
    УВЕЛИЧИТЬ(порядок)
  КОН;
  текст[дл]:=цифры[пц];  (* до запятой *)
  УВЕЛИЧИТЬ(дл); УВЕЛИЧИТЬ(пц);
  текст[дл]:=',';        (* запятая *)
  УВЕЛИЧИТЬ(дл);
  ПОКА точность > 0 ВЫП  (* после запятой *)
    текст[дл]:=цифры[пц];
    УВЕЛИЧИТЬ(дл); УВЕЛИЧИТЬ(пц);
    УМЕНЬШИТЬ(точность)
  КОН;
  текст[дл]:='E';        (* E *)
  УВЕЛИЧИТЬ(дл);
  ЕСЛИ порядок < 0 ТО    (* знак порядка *)
    текст[дл]:='-';
    порядок:=-порядок
  ИНАЧЕ
    текст[дл]:='+'
  КОН;
  пц:=дл+3;
  ПОКА пц > дл ВЫП       (* порядок *)
    текст[пц]:=ВЗНАК(48+(порядок ОСТАТОК 10));
    порядок:=порядок ДЕЛИТЬ 10;
    УМЕНЬШИТЬ(пц)
  КОН;
  УВЕЛИЧИТЬ(дл,4);
  текст[дл]:=0X
КОН ИзВещЕ;

(******************************************************************************)
ЗАДАЧА ИзВещФ-(число:ШИРВЕЩ; точность:ЦЕЛ; текст+:Число; дл+:ЦЕЛ);
(* Вещественное число с неподвижной запятой.
 ******************************************************************************
 * До:    <число>    - преобразуемое число
 *        <точность> - цифр после запятой
 * После: <текст>    - текстовое представление числа
 *        <дл>       - его длина *)
ПЕР
  порядок:ЦЕЛ;   (* порядок числа   *)
  цифры:Число;   (* цифры без точки *)
  пц:ЦЕЛ;        (* позиция цифры   *)
  вхчисло:ШИРВЕЩ;(* двойник <число> *)
УКАЗ
  ЕСЛИ Особенность(число,текст,дл) ТО
    ВОЗВРАТ
  КОН;
  вхчисло:=число;
  ЕСЛИ точность < 0 ТО
    точность:=2
  КОН;
  дл:=0;
  ЕСЛИ число < 0 ТО      (* знак перед числом *)
    текст[дл]:='-';
    УВЕЛИЧИТЬ(дл)
  КОН;
  число:=МОДУЛЬ(число);
  ЕСЛИ число >= 10 ТО
    порядок:=Асм.Порядок(число)+1
  ИНАЧЕ
    порядок:=1
  КОН;
  ЕСЛИ точность+порядок >= РАЗМЕР(цифры) ТО (* совсем большое число *)
    ИзВещЕ(вхчисло,точность,текст,дл);
    ВОЗВРАТ
  КОН;
  Асм.ВЦифры(число,порядок+точность,цифры);
  ЕСЛИ цифры[0] = '0' ТО
    пц:=1
  ИНАЧЕ (* есть десятки *)
    пц:=0;
    УВЕЛИЧИТЬ(порядок)
  КОН;
  ПОКА порядок > 0 ВЫП  (* до запятой *)
    текст[дл]:=цифры[пц];
    УВЕЛИЧИТЬ(дл); УВЕЛИЧИТЬ(пц);
    УМЕНЬШИТЬ(порядок)
  КОН;
  текст[дл]:=',';        (* запятая *)
  УВЕЛИЧИТЬ(дл);
  ПОКА точность > 0 ВЫП  (* после запятой *)
    текст[дл]:=цифры[пц];
    УВЕЛИЧИТЬ(дл); УВЕЛИЧИТЬ(пц);
    УМЕНЬШИТЬ(точность)
  КОН;
  текст[дл]:=0X
КОН ИзВещФ;

(******************************************************************************)
ЗАДАЧА ИзВещГ-(число:ШИРВЕЩ; точность:ЦЕЛ; текст+:Число; дл+:ЦЕЛ);
(* Вещественное число в общем виде.
 ******************************************************************************
 * До:    <число>    - преобразуемое число
 *        <точность> - цифр после запятой
 * После: <текст>    - текстовое представление числа
 *        <дл>       - его длина *)
ПЕР
  порядок:ЦЕЛ;   (* порядок числа   *)
  цифры:Число;   (* цифры без точки *)
  пц:ЦЕЛ;        (* позиция цифры   *)
  вхчисло:ШИРВЕЩ;(* двойник <число> *)
  модвхчисло:ШИРВЕЩ;(* двойник модуля <число> *)
УКАЗ
  ЕСЛИ Особенность(число,текст,дл) ТО
    ВОЗВРАТ
  КОН;
  вхчисло:=число;
  ЕСЛИ точность < 0 ТО
    точность:=15
  АЕСЛИ точность > 18 ТО
    точность:=18
  КОН;
  дл:=0;
  ЕСЛИ число < 0 ТО      (* знак перед числом *)
    текст[дл]:='-';
    УВЕЛИЧИТЬ(дл)
  КОН;
  число:=МОДУЛЬ(число);
  модвхчисло:=число;
  порядок:=Асм.Порядок(число);
  ЕСЛИ (порядок < -5) ИЛИ (порядок >= точность) ТО
    ИзВещЕ(вхчисло,точность,текст,дл);
    ВОЗВРАТ
  КОН;
  ЕСЛИ модвхчисло < 10 ТО
    порядок:=0;
    число:=модвхчисло
  КОН;
  УВЕЛИЧИТЬ(порядок);
  ЕСЛИ точность+порядок >= РАЗМЕР(цифры) ТО (* совсем большое число *)
    ИзВещЕ(вхчисло,точность,текст,дл);
    ВОЗВРАТ
  КОН;
  Асм.ВЦифры(число,порядок+точность,цифры);
  ЕСЛИ цифры[0] = '0' ТО
    пц:=1
  ИНАЧЕ (* есть десятки *)
    пц:=0;
    УВЕЛИЧИТЬ(порядок)
  КОН;
  ПОКА порядок > 0 ВЫП  (* до запятой *)
    текст[дл]:=цифры[пц];
    УВЕЛИЧИТЬ(дл); УВЕЛИЧИТЬ(пц);
    УМЕНЬШИТЬ(порядок)
  КОН;
  ПОКА (точность > 0) И (цифры[пц+точность-1] = '0') ВЫП  (* убираем нули *)
    УМЕНЬШИТЬ(точность)
  КОН;
  ЕСЛИ точность > 0 ТО  (* запятая *)
    текст[дл]:=',';
    УВЕЛИЧИТЬ(дл)
  КОН;
  ПОКА точность > 0 ВЫП (* после запятой *)
    текст[дл]:=цифры[пц];
    УВЕЛИЧИТЬ(дл); УВЕЛИЧИТЬ(пц);
    УМЕНЬШИТЬ(точность)
  КОН;
  текст[дл]:=0X
КОН ИзВещГ;
<*КОН*>

(******************************************************************************)
ЗАДАЧА ЗадомНаПеред(цепь+:ЦЕПЬ; дл:ЦЕЛ);
ПЕР
  поз:ЦЕЛ;
  зн:ЗНАК;
УКАЗ
  поз:=0;
  УМЕНЬШИТЬ(дл);
  ПОКА поз < дл ВЫП
    зн:=цепь[поз]; цепь[поз]:=цепь[дл]; цепь[дл]:=зн;
    УВЕЛИЧИТЬ(поз); УМЕНЬШИТЬ(дл)
  КОН   
КОН ЗадомНаПеред;

(******************************************************************************)
ЗАДАЧА ИзЦел(число:ШИРЦЕЛ; основание,нужноцифр:ЦЕЛ; текст+:Число; дл+:ЦЕЛ);
(* Преобразовать целое число в текстовое представление.
 ******************************************************************************
 * До:    <число>     - преобразуемое число
 *        <основание> - основание системы счисления
 *        <нужноцифр> - нужное количество цифр результата
 * После: <текст>     - текстовое представление числа
 *        <дл>        - его длина *)
ПЕР
  можноцифр:ЦЕЛ; (* количество цифр, которое возможно записать в результат *)
  цифра:ЦЕЛ;     (* текущая цифра *)
  минус:КЛЮЧ;    (* ВКЛ, если число отрицательное *)
УКАЗ
  дл:=0;
  можноцифр:=РАЗМЕР(текст)-1;
  ЕСЛИ нужноцифр > можноцифр ТО
    нужноцифр:=можноцифр
  КОН;
  минус:=число < 0;
  ЕСЛИ минус ТО
    ЕСЛИ основание = 16 ТО
      минус:=ОТКЛ;
      ЕСЛИ нужноцифр = -1 ТО
        нужноцифр:=8
      КОН;
      можноцифр:=16
    АЕСЛИ число = МИН(ШИРЦЕЛ) ТО
      текст:="-9223372036854775808";
      дл:=ДЛИНА(текст);
      ВОЗВРАТ
    ИНАЧЕ
      УМЕНЬШИТЬ(нужноцифр); (* для знака в результате *)
      число:=-число
    КОН
  КОН;
  ПОВТОРЯТЬ
    цифра:=МОДУЛЬ(УЗК(число ОСТАТОК основание));
    ЕСЛИ цифра < 10 ТО
      текст[дл]:=ВЗНАК(48+цифра)
    ИНАЧЕ
      текст[дл]:=ВЗНАК(55+цифра)
    КОН;
    число:=число ДЕЛИТЬ основание;
    УВЕЛИЧИТЬ(дл);
    ЕСЛИ дл >= можноцифр ТО
      число:=0
    КОН
  ДО ((число = 0) ИЛИ (число = -1)) И (дл >= нужноцифр);
  ЕСЛИ минус ТО
    текст[дл]:="-";
    УВЕЛИЧИТЬ(дл)
  КОН;
  ЗадомНаПеред(текст,дл);
  текст[дл]:=0X
КОН ИзЦел;

(******************************************************************************)
ЗАДАЧА ИзЦел10-(число:ШИРЦЕЛ; нужноцифр:ЦЕЛ; текст+:Число);
(* Преобразовать целое число в десятичное представление.
 ******************************************************************************
 * До:    <число>     - преобразуемое число
 *        <нужноцифр> - нужное количество цифр результата
 * После: <текст>     - текстовое представление числа *)
ПЕР
  дл:ЦЕЛ;
УКАЗ
  ИзЦел(число,10,нужноцифр,текст,дл)
КОН ИзЦел10;

(******************************************************************************)
ЗАДАЧА ИзЦел16-(число:ШИРЦЕЛ; нужноцифр:ЦЕЛ; текст+:Число);
(* Преобразовать целое число в шестнадцатеричное представление.
 ******************************************************************************
 * До:    <число>     - преобразуемое число
 *        <нужноцифр> - нужное количество цифр результата
 * После: <текст>     - текстовое представление числа *)
ПЕР
  дл:ЦЕЛ;
УКАЗ
  ИзЦел(число,16,нужноцифр,текст,дл)
КОН ИзЦел16;

(******************************************************************************)
ЗАДАЧА ИзЧЦелВещ(описание-:ЦЕПЬ; царги-:РядЧЦел; варги-:РядЧВещ; текст+:ЦЕПЬ);
(* Составить текст с 4-мя числами, используя описание текста.
 ******************************************************************************
 * До:    <описание> - цепочка знаков, которая содержит обычные знаки,
 *                     которые просто переписываются в <текст> и описатели
 *                     представлений чисел (см. их описание выше)
 *        <царги>    - аргументы преобразования целого вида
 *        <варги>    - аргументы преобразования вещественного вида
 * После: <текст>    - выходной текст *)
ПЕР
  номарг:ЦЕЛ;    (* номер текущего аргумента                            *)
  длт,дло:ЦЕЛ;   (* размер <текст> и <описание>                         *)
  позт,позо:ЦЕЛ; (* позиции текущих знаков в <текст> и <описание>       *)
  зно:ЗНАК;      (* знак, прочитанный из <описание>                     *)
  ширина,точность:ЦЕЛ; (* параметры вывода                              *)
  налево:КЛЮЧ;   (* ВКЛ, если используется левое выравнивание           *)
  число:ЦЕЛ;     (* число из <описание>, используемое для параметра вывода *)
  текста:Число;  (* текстовое представление текущего аргумента          *)
  дла:ЦЕЛ;       (* размер <текста>                                     *)

  ЗАДАЧА СледАрг();
  (* увеличить, если возможно, <номарг> *)
  УКАЗ
    ЕСЛИ номарг < 4-1 ТО
      УВЕЛИЧИТЬ(номарг)
    КОН
  КОН СледАрг;

  ЗАДАЧА ЗнакО(описание-:ЦЕПЬ);
  (* читать следующий знак из <описание> *)
  УКАЗ
    ЕСЛИ позо >= дло ТО зно:=0X КОН;
    ЕСЛИ зно = 0X ТО ВОЗВРАТ КОН;
    зно:=описание[позо];
    УВЕЛИЧИТЬ(позо)
  КОН ЗнакО;

  ЗАДАЧА ЧислоО(описание-:ЦЕПЬ; царги-:РядЧЦел);
  (* читать <число> для параметра из <описание> или из текущего аргумена *)
  УКАЗ
    число:=0;
    ЕСЛИ зно = '*' ТО
      число:=УЗК(царги[номарг]);
      СледАрг();
      ЗнакО(описание)
    ИНАЧЕ
      ПОКА Знак.Цифра(зно) ВЫП
        число:=10*число+ВЦЕЛ(зно)-ВЦЕЛ('0');
        ЗнакО(описание)
      КОН
    КОН
  КОН ЧислоО;

  ЗАДАЧА ПараметрыО(описание-:ЦЕПЬ; царги-:РядЧЦел);
  (* читать параметры <ширина>, <точность>, <налево> и <номарг> из <описание> *)
  УКАЗ
    (* <ширина>, <налево> и <номарг> *)
    КОЛЬЦО
      налево:=зно = '-';
      ЕСЛИ налево ТО ЗнакО(описание) КОН;
      ЧислоО(описание,царги);
      ЕСЛИ зно = ':' ТО
        номарг:=число;
        ЗнакО(описание)
      ИНАЧЕ
        ВЫХОД
      КОН
    КОН;
    ширина:=число;
    (* <точность> *)
    число:=-1;
    ЕСЛИ зно = '.' ТО
      ЗнакО(описание);
      ЧислоО(описание,царги)
    КОН;
    точность:=число
  КОН ПараметрыО;

  ЗАДАЧА ЗнакТ(зн:ЗНАК; текст+:ЦЕПЬ);
  (* писать <зн> в <текст> *)
  УКАЗ
    ЕСЛИ позт < длт ТО
      текст[позт]:=зн;
      УВЕЛИЧИТЬ(позт)
    КОН
  КОН ЗнакТ;

  ЗАДАЧА ЗнакиТ(знаки-:ЦЕПЬ; дл:ЦЕЛ; текст+:ЦЕПЬ);
  (* писать <дл> знаков <знаки> в <текст> *)
  ПЕР
    поз:ЦЕЛ;
  УКАЗ
    поз:=0;
    ПОКА поз < дл ВЫП
      ЗнакТ(знаки[поз],текст);
      УВЕЛИЧИТЬ(поз)
    КОН
  КОН ЗнакиТ;

  ЗАДАЧА ПробелыТ(кво:ЦЕЛ; текст+:ЦЕПЬ);
  (* писать <кво> пробелов в <текст> *)
  УКАЗ
    ПОКА кво > 0 ВЫП
      ЗнакТ(' ',текст);
      УМЕНЬШИТЬ(кво)
    КОН
  КОН ПробелыТ;

УКАЗ
  дло:=РАЗМЕР(описание);
  длт:=РАЗМЕР(текст);
  позо:=0;
  позт:=0;
  номарг:=0;
  зно:=' ';
  ПОВТОРЯТЬ
    ЗнакО(описание);
    ПОКА зно = '%' ВЫП
      ЗнакО(описание);
      ЕСЛИ зно = '%' ТО
        ЗнакТ(зно,текст);
        ЗнакО(описание)
      ИНАЧЕ
        ПараметрыО(описание,царги);
        дла:=0;
        ВЫБРАТЬ Буква.ВСтрочную(зно) ИЗ
        | 't':
          ЕСЛИ ширина = 0 ТО ширина:=8 КОН;
          ПробелыТ(ширина - (позт ОСТАТОК ширина),текст);
          ЗнакО(описание)
        | 'd':
          ИзЦел(царги[номарг],10,точность,текста,дла);
          СледАрг();
          ЗнакО(описание)
        | 'x':
          ИзЦел(царги[номарг],16,точность,текста,дла);
          СледАрг();
          ЗнакО(описание)
        | 'e':
          ИзВещЕ(варги[номарг],точность,текста,дла);
          СледАрг();
          ЗнакО(описание)
        | 'f':
          ИзВещФ(варги[номарг],точность,текста,дла);
          СледАрг();
          ЗнакО(описание)
        | 'g':
          ИзВещГ(варги[номарг],точность,текста,дла);
          СледАрг();
          ЗнакО(описание)
        | 'c':
          ЕСЛИ (царги[номарг] >= ВЦЕЛ(МИН(ЗНАК)))
              И (царги[номарг] <= ВЦЕЛ(МАКС(ЗНАК)))
          ТО
            текста[0]:=ВЗНАК(царги[номарг])
          ИНАЧЕ
            текста:="?"
          КОН;
          дла:=1;
          СледАрг();
          ЗнакО(описание)
        | 0X,'%': (* ничего не делаем *)
        ИНАЧЕ
          текста[0]:=зно;
          дла:=1;
          УВЕЛИЧИТЬ(ширина);
          ЗнакО(описание)
        КОН;
        ЕСЛИ НЕ налево ТО ПробелыТ(ширина-дла,текст) КОН;
        ЗнакиТ(текста,дла,текст);
        ЕСЛИ    налево ТО ПробелыТ(ширина-дла,текст) КОН;
      КОН
    КОН;
    ЗнакТ(зно,текст)
  ДО зно = 0X
КОН ИзЧЦелВещ;

(******************************************************************************)
ЗАДАЧА ИзЧЦел-(описание-:ЦЕПЬ; а0,а1,а2,а3:ШИРЦЕЛ; текст+:ЦЕПЬ);
(* Составить текст с 4-мя целыми числами, используя описание текста.
 ******************************************************************************
 * До:    <описание> - см. ИзЧЦелВещ()
 *        < а0 >,,< а4 > - аргументы преобразования
 * После: <текст>    - выходной текст *)
ПЕР
  царги:РядЧЦел; (* значения аргументов а0,...,а3 в целом виде        *)
  варги:РядЧВещ; (* значения аргументов а0,...,а3 в вещественном виде *)
УКАЗ
  царги[0]:=а0;
  царги[1]:=а1;
  царги[2]:=а2;
  царги[3]:=а3;
  варги[0]:=а0;
  варги[1]:=а1;
  варги[2]:=а2;
  варги[3]:=а3;
  ИзЧЦелВещ(описание,царги,варги,текст);
КОН ИзЧЦел;

(******************************************************************************)
ЗАДАЧА ВШирЦел0(в:ШИРВЕЩ):ШИРЦЕЛ;
УКАЗ
  ЕСЛИ (в >= МИН(ШИРЦЕЛ)) И (в <= МАКС(ШИРЦЕЛ)) ТО
    ВОЗВРАТ ВШИРЦЕЛ(в)
  КОН;
  ВОЗВРАТ 0
КОН ВШирЦел0;

(******************************************************************************)
ЗАДАЧА ИзЧВещ-(описание-:ЦЕПЬ; а0,а1,а2,а3:ШИРВЕЩ; текст+:ЦЕПЬ);
(* Составить текст с 4-мя вещественными числами, используя описание текста.
 ******************************************************************************
 * До:    <описание> - см. ИзЧЦелВещ()
 *        < а0 >,,< а4 > - аргументы преобразования
 * После: <текст>    - выходной текст *)
ПЕР
  царги:РядЧЦел; (* значения аргументов а0,...,а3 в целом виде        *)
  варги:РядЧВещ; (* значения аргументов а0,...,а3 в вещественном виде *)
УКАЗ
  царги[0]:=ВШирЦел0(а0);
  царги[1]:=ВШирЦел0(а1);
  царги[2]:=ВШирЦел0(а2);
  царги[3]:=ВШирЦел0(а3);
  варги[0]:=а0;
  варги[1]:=а1;
  варги[2]:=а2;
  варги[3]:=а3;
  ИзЧЦелВещ(описание,царги,варги,текст);
КОН ИзЧВещ;

(******************************************************************************)
ЗАДАЧА ВЦелое-(цепь-:ЦЕПЬ; поз+:ЦЕЛ; цОтвет+:ШИРЦЕЛ; вОтвет+:ШИРВЕЩ):КЛЮЧ;
(* Считывает из <цепь> начиная с позиции <поз> знаковое представление числа.
 * Если это представление целого числа, то возвращает ВКЛ и записывает
 * значение числа в <цОтвет>, иначе возвращает ОТКЛ, а значение записывает
 * в <вОтвет>. 
 * По окончании <поз> указывает на следующий за числом знак. *)
ПЕР
  i,m,n,d,эксп:ЦЕЛ;
  мант:ШИРВЕЩ;
  цифры:ЦЕПЬ[64];
  знакМант,знакЭксп:ЦЕЛ;
  знак:ЗНАК;
  ошибка:КЛЮЧ;
  длина:ЦЕЛ;

(******************************************************************************)
  ЗАДАЧА ЧитатьЗнак;
  (* Читает следующий <знак> из <цепь> *)
  УКАЗ
    ЕСЛИ поз >= длина ТО
      знак:=0X
    ИНАЧЕ
      УВЕЛИЧИТЬ(поз);
      знак:=цепь[поз]
    КОН
  КОН ЧитатьЗнак;
   
(******************************************************************************)
  ЗАДАЧА ДесятьВ(x:ЦЕЛ):ШИРВЕЩ;
  (* 10 в степени  *)
  ПЕР
    ответ,множитель:ШИРВЕЩ;
  УКАЗ
    ответ:=1;
    множитель:=10;
    ПОКА x > 0 ВЫП
      ЕСЛИ НЕ ЧЕТ(x) ТО ответ:=ответ*множитель КОН;
      x:=x ДЕЛИТЬ 2;
      ЕСЛИ x > 0 ТО (* защита <множитель> от переполнения *)
        множитель:=множитель*множитель 
      КОН
    КОН;
    ВОЗВРАТ ответ
  КОН ДесятьВ;

(******************************************************************************)
  ЗАДАЧА ЗнакВЦел(знак:ЗНАК; система16:КЛЮЧ):ЦЕЛ;
  УКАЗ 
    ЕСЛИ Знак.Цифра(знак) ТО
      ВОЗВРАТ ВЦЕЛ(знак)-ВЦЕЛ("0")
    АЕСЛИ система16 И ("A" <= знак) И (знак <= "F") ТО
      ВОЗВРАТ ВЦЕЛ(знак)-ВЦЕЛ("A")+10
    ИНАЧЕ
      ошибка:=ВКЛ
    КОН
  КОН ЗнакВЦел;

(******************************************************************************)
УКАЗ
  вОтвет:=0;
  цОтвет:=0;
  ошибка:=ОТКЛ;
  длина:=ДЛИНА(цепь);
  ЕСЛИ поз >= длина ТО
    (* ошибка: достигнут конец цепочки *)
    ВОЗВРАТ ВКЛ
  КОН;
  (* <поз> соответствует уже прочтённому знаку *)
  УМЕНЬШИТЬ(поз);
  (* пропускаем пробелы перед первой цифрой *)
  ПОВТОРЯТЬ
    ЕСЛИ поз >= длина ТО
      (* ошибка: достигнут конец цепочки *)
      ВОЗВРАТ ВКЛ
    КОН;
    ЧитатьЗнак
  ДО знак > " ";

  знакМант:=1;
  ЕСЛИ знак = "-" ТО
    знакМант:=-1;
    ЧитатьЗнак
  АЕСЛИ знак = "+" ТО
    ЧитатьЗнак
  АЕСЛИ  НЕ Знак.Цифра(знак) ТО
    (* ошибка: не нашли числа *)
    ВОЗВРАТ ВКЛ
  КОН;
  (* читаем мантиссу *)
  i:=0; m:=0; n:=0; d:=0;
  КОЛЬЦО 
    ЕСЛИ Знак.Цифра(знак) ИЛИ (d = 0) И ("A" <= знак) И (знак <= "F") ТО
      ЕСЛИ (m > 0) ИЛИ (знак # "0") ТО (* предстоящие нули пропускаем *)
        ЕСЛИ n < РАЗМЕР(цифры) ТО
          цифры[n]:=знак;
          УВЕЛИЧИТЬ(n)
        КОН;
        УВЕЛИЧИТЬ(m)
      КОН;
      ЧитатьЗнак;
      УВЕЛИЧИТЬ(i)
    АЕСЛИ  знак = "," ТО
      ЧитатьЗнак;
      ЕСЛИ d = 0 ТО (* i > 0 *)
        d:=i
      ИНАЧЕ
        (* ошибка: неверный знак в записи числа *)
        ВОЗВРАТ ВКЛ
      КОН
    ИНАЧЕ
      ВЫХОД
    КОН
  КОН; (* 0 <= n <= m <= i, 0 <= d <= i *)
  ЕСЛИ d = 0 ТО (* целое *)
    ЕСЛИ n = m ТО
      i:=0;
      ЕСЛИ (знак = "H") ИЛИ (знак = "X") ТО (* 16-тиричное *)
        ЧитатьЗнак;
        ЕСЛИ (n > 16) ИЛИ ((n = 16) И (цифры[0] > "7")) ТО
          (* ошибка: слишком большое целое *)
          ВОЗВРАТ ВКЛ
        КОН;
        ПОКА i < n ВЫП
          цОтвет:=цОтвет*10H+ЗнакВЦел(цифры[i],ВКЛ);
          ЕСЛИ ошибка ТО
            (* ошибка: неверный знак в записи числа *)
            ВОЗВРАТ ВКЛ
          КОН;
          УВЕЛИЧИТЬ(i)
        КОН
      ИНАЧЕ (* 10-тичное *)
        ПОКА i < n ВЫП
          d:=ЗнакВЦел(цифры[i],ОТКЛ);
          ЕСЛИ ошибка ТО
            (* ошибка: неверный знак в записи числа *)
            ВОЗВРАТ ВКЛ
          КОН;
          УВЕЛИЧИТЬ(i);
          ЕСЛИ цОтвет > (МАКС(ШИРЦЕЛ)-d) ДЕЛИТЬ 10 ТО
            (* ошибка: слишком большое целое *)
            ВОЗВРАТ ВКЛ
          КОН;
          цОтвет:=цОтвет*10+d
        КОН
      КОН
    ИНАЧЕ
      (* ошибка: очень большое число *)
      ВОЗВРАТ ВКЛ
    КОН;
    цОтвет:=знакМант*цОтвет;
    ВОЗВРАТ ВКЛ
  ИНАЧЕ (* дробная часть *)
    мант:=0; эксп:=0;
    ПОКА n > 0 ВЫП (* 0 <= мант < 1 *)
      УМЕНЬШИТЬ(n);
      мант:=(ЗнакВЦел(цифры[n],ОТКЛ)+мант)/10;
      ЕСЛИ ошибка ТО
        (* ошибка: неверный знак в записи числа *)
        ВОЗВРАТ ВКЛ
      КОН
    КОН;
    ЕСЛИ (знак = "E") ИЛИ (знак = "D") ТО
      ЧитатьЗнак;
      знакЭксп:=1;
      ЕСЛИ знак = "-" ТО
        знакЭксп:=-1;
        ЧитатьЗнак
      АЕСЛИ знак = "+" ТО
        ЧитатьЗнак
      КОН;
      ЕСЛИ Знак.Цифра(знак) ТО
        ПОВТОРЯТЬ
          n:=ЗнакВЦел(знак,ОТКЛ);
          ЧитатьЗнак;
          ЕСЛИ эксп <= (МАКС(ШИРЦЕЛ)-n) ДЕЛИТЬ 10 ТО
            эксп:=эксп*10+n
          ИНАЧЕ
            (* ошибка: очень большое число *)
            ВОЗВРАТ ВКЛ
          КОН
        ДО НЕ Знак.Цифра(знак);
        эксп:=знакЭксп*эксп
      ИНАЧЕ
        (* ошибка: неверный знак в записи числа *)
        ВОЗВРАТ ВКЛ
      КОН
    КОН;
    УМЕНЬШИТЬ(эксп,i-d-m); (* сдвиг десятичной точки *)
    ЕСЛИ эксп < 0 ТО
      ЕСЛИ эксп <= -307 ТО
        (* ошибка: очень маленькое число *)
        ВОЗВРАТ ВКЛ
      КОН;
      вОтвет:=мант/ДесятьВ(-эксп)
    ИНАЧЕ
      ЕСЛИ эксп > 308 ТО
        (* ошибка: очень большое число *)
        ВОЗВРАТ ВКЛ
      КОН;
      вОтвет:=мант*ДесятьВ(эксп)
    КОН
  КОН;
  вОтвет:=знакМант*вОтвет;
  ВОЗВРАТ ОТКЛ
КОН ВЦелое;

(******************************************************************************)
ЗАДАЧА ВШирВещ-(цепь-:ЦЕПЬ; поз+:ЦЕЛ):ШИРВЕЩ;
(* Считывает из <цепь> начиная с позиции <поз> знаковое представление числа
 * и переводит его в ШИРВЕЩ вид. По окончании <поз> указывает на следующий
 * за числом знак *)
ПЕР
  ширцел:ШИРЦЕЛ;
  ширвещ:ШИРВЕЩ;
УКАЗ
  ЕСЛИ ВЦелое(цепь,поз,ширцел,ширвещ) ТО
    ВОЗВРАТ ширцел
  ИНАЧЕ
    ВОЗВРАТ ширвещ
  КОН
КОН ВШирВещ;

(******************************************************************************)
ЗАДАЧА ВВещ-(цепь-:ЦЕПЬ; поз+:ЦЕЛ):ВЕЩ;
(* Считывает из <цепь> начиная с позиции <поз> знаковое представление числа
 * и переводит его в ВЕЩ вид. По окончании <поз> указывает на следующий
 * за числом знак *)
УКАЗ
  ВОЗВРАТ УЗК(ВШирВещ(цепь,поз))
КОН ВВещ;

(******************************************************************************)
ЗАДАЧА ВШирЦел-(цепь-:ЦЕПЬ; поз+:ЦЕЛ):ШИРЦЕЛ;
(* Считывает из <цепь> начиная с позиции <поз> знаковое представление числа
 * и переводит его в ШИРЦЕЛ вид. По окончании <поз> указывает на следующий
 * за числом знак *)
ПЕР
  ширцел:ШИРЦЕЛ;
  ширвещ:ШИРВЕЩ;
УКАЗ
  ЕСЛИ ВЦелое(цепь,поз,ширцел,ширвещ) ТО
    ВОЗВРАТ ширцел
  ИНАЧЕ
    ВОЗВРАТ ВШИРЦЕЛ(ширвещ)
  КОН
КОН ВШирЦел;

(******************************************************************************)
ЗАДАЧА ВЦел-(цепь-:ЦЕПЬ; поз+:ЦЕЛ):ЦЕЛ;
(* Считывает из <цепь> начиная с позиции <поз> знаковое представление числа
 * и переводит его в ЦЕЛ вид. По окончании <поз> указывает
 * на следующий за числом знак *)
УКАЗ
  ВОЗВРАТ УЗК(ВШирЦел(цепь,поз))
КОН ВЦел;

КОН Текст.

 
 


Вопросы, замечания и предложения высылайте на atimopheyev@yahoo.com

 
Главная     ◄Глагол     ◄Азбука     ◄Задачи на Глаголе     Примеры приложений ►   Среда разработки ►   Отладка программ ►   Отличия от Оберона ►   Отличия от Паскаля ►   Ассемблер ARM ►   Глагол для ARM ►   ? и Ответы