Программа


PROGRAM Stolbik;
CONST Dig=['0'..'9']; { Множество символов цифр }
TYPE Numeral=^Digit;      { Тип - число }
     Digit=record         { Тип - цифра }
             N:byte;        { цифра (разряд числа) }
             L,R:Numeral;   { левый и правый разряды числа }
           end;
PROCEDURE MakeData(var F:text); { Процедура создания файла исходных данных }
  Var i,j:longint;
  Begin
    Randomize;  { Инициализация генератора случайных чисел }
    Rewrite(F); { Открытие файла для записи }
    while Random(15)>0 do { Цикл формирования файла }
    begin
      while Random(10)>0 do Write(F,Random(10)); { Цикл формирования левого операнда }
      case Random(4) of { Определение операции }
        0:Write(F,'+');
        1:Write(F,'-');
        2:Write(F,'*');
        3:Write(F,'/');
      end;
      while Random(10)>0 do Write(F,Random(10)); { Цикл формирования правого операнда }
      WriteLn(F); { Завершение строки }
    end;
    Close(F)    { Закрытие файла }
  End;
PROCEDURE InsertDigInL(Dig:byte; N:Numeral); { Процедура вставки разряда "слева" от разряда текущего указателя }
  Var Buf:Numeral; { Указатель переменной вставляемого разряда }
  Begin
    New(Buf);    { Создание разряда }
    Buf^.N:=Dig; { Инициализация разряда }
    { Вставка разряда в число слева от N: }
    Buf^.L:=N^.L;
    Buf^.R:=N;
    N^.L^.R:=Buf;
    N^.L:=Buf
  End;
PROCEDURE InsertDigInR(Dig:byte; N:Numeral); { Процедура вставки разряда "справа" от разряда текущего указателя }
  Var Buf:Numeral; { Указатель переменной вставляемого разряда }
  Begin
    New(Buf);     { Создание разряда }
    Buf^.N:=Dig;  { Инициализация разряда }
    { Вставка разряда в число справа от N: }
    N^.R^.L:=Buf;
    Buf^.R:=N^.R;
    Buf^.L:=N;
    N^.R:=Buf
  End;
PROCEDURE ToRight(var N:Numeral); { Процедура перевода указателя на младший разряд }
  Begin
    while N^.R<>nil do N:=N^.R { Цикл перехода на младший разряд }
  End;
PROCEDURE ToLeft(var N:Numeral); { Процедура перевода указателя на старший разряд }
  Begin
    while N^.L<>nil do N:=N^.L { Цикл перехода на старший разряд }
  End;
PROCEDURE WriteNumToDisplay(N:Numeral); { Вспомогательная процедура для вывода числа на экран и контроля ссылок по разрядам }
  Begin
    ToLeft(N);
    while N<>nil do
    begin
      Write(N^.N,'(',N^.L<>nil,N^.R<>nil,')');
      N:=N^.R
    end;
  End;
PROCEDURE WriteLnNumToDisplay(N:Numeral); { Вспомогательная процедура для вывода числа на экран и контроля ссылок по разрядам }
  Begin
    WriteNumToDisplay(N);
    WriteLn
  End;
PROCEDURE InsertDigRightSide(Dig:byte; var N:Numeral); { Процедура вставки знака в младший разряд }
  Begin
    ToRight(N); { Перевод указателя на младший разряд }
    InsertDigInR(Dig,N) { Вставка числа справа от разряда текущего указателя }
  End;
PROCEDURE InsertDigLeftSide(Dig:byte; var N:Numeral); { Процедура вставки знака в старший разряд }
  Begin
    ToLeft(N); { Перевод указателя на старший разряд }
    InsertDigInL(Dig,N) { Вставка числа слева от разряда текущего указателя }
  End;
FUNCTION Val(Ch:Char):byte; { Функция преобразования символа в число }
  Var N:byte; { Число }
      Code:integer; { Переменная для процедуры "Val" из модуля System }
  Begin
    System.Val(Ch,N,Code); { Преобразование символа в число }
    Val:=N { Определение значения функции }
  End;
PROCEDURE InsertDigR(Buf:byte; var Num:Numeral); { Процедура вставки цифры в число }
  Begin
    if Num=nil { Проверка наличия разрядов }
    then begin { разрядов нет: }
           New(Num); { Создание разряда }
           Num^.L:=nil; { Сброс ссылки на левый разряд }
           Num^.R:=nil; { Сброс ссылки на правый разряд }
           Num^.N:=Buf { Преобразование символа и определение разряда }
         end
    else InsertDigRightSide(Buf,Num) { разряды есть => вставка разряда справа }
  End;
PROCEDURE InsertDigL(Buf:byte; var Num:Numeral); { Процедура вставки цифры в число }
  Begin
    if Num=nil { Проверка наличия разрядов }
    then begin { разрядов нет: }
           New(Num); { Создание разряда }
           Num^.L:=nil; { Сброс ссылки на левый разряд }
           Num^.R:=nil; { Сброс ссылки на правый разряд }
           Num^.N:=Buf { Преобразование символа и определение разряда }
         end
    else InsertDigLeftSide(Buf,Num) { разряды есть => вставка разряда слева }
  End;
PROCEDURE ReadOperation(var F:text; var LNum:Numeral; var Sign:Char; var RNum:Numeral);
  Var Buf:Char; { Символ для чтения из файла }
  Begin
    Sign:=' '; { Сброс знака арифметической операции (одна из защит от от ошибок в файле исходных данных) }
    while not EOLn(F) do { Цикл чтения левого операнда и знака арифметической операции }
    begin
      Read(F,Buf);               { Чтение символа из файла данных }
      if Buf in Dig              { Если символ является числом, }
      then InsertDigR(Val(Buf),LNum) { то - вставка "цифры" в число }
      else begin                     { иначе -  }
             Sign:=Buf;                { определение арифметической операции }
             Break                     { выход из цикла }
           end
    end;
    while not EOLn(F) do { Цикл чтения правого операнда }
    begin
      Read(F,Buf);               { Чтение символа из файла данных }
      if Buf in Dig              { Если символ является числом, }
      then InsertDigR(Val(Buf),RNum)      { то - вставка "цифры" в число }
      else Break                    { иначе - выход из цикла }
    end;
    ReadLn(F) { Пропуск конца строки }
  End;
FUNCTION Max(A,B:Longint):longint;  { Функция выбора максимального числа }
  Begin
    if A>B then Max:=A else Max:=B
  End;
FUNCTION Len(N:Numeral):longint; { Функция определения длины числа }
  Var L:longint; { Переменная для определения длины числа }
  Begin
    ToRight(N);         { Перевод указателя на младший разряд }
    L:=1;               { Начальное определение количества разрядов в числе }
    while N^.L<>Nil do  { Цикл просмотра числа }
    begin
      Inc(L);             { Набор количества разрядов }
      N:=N^.L             { Переход на ближайший старший разряд }
    end;
    Len:=L;             { Определение функции }
  End;
PROCEDURE WriteChar(var F:text; Ch:char; Width:longint);
  Begin                   { Процедура вывода заполняющего строку символа }
    while Width>0 do { Цикл вывода символа }
    begin
      Write(F,Ch); { Вывод символа }
      Dec(Width)   { Пересчет оставшегося количества символов }
    end;
  End;
PROCEDURE WriteLnChar(var F:text; Ch:char; Width:longint);
  Begin { Процедура вывода заполняющего строку символа с завершением строки }
     WriteChar(F,Ch,Width); { Вывод строки }
     WriteLn(F)             { Вывод конца строки }
  End;
PROCEDURE WriteNum(var F:text; N:Numeral); { Вывод числа }
  Begin
    if N=nil  { Проверка неопределенности числа }
    then Write(F,'"ЧИСЛО НЕ ОПРЕДЕЛЕНО"') { Вывод сообщения вместо числа }
    else begin
           ToLeft(N);  { Перевод указателя на старший разряд }
           repeat      { Цикл вывода числа }
             Write(F,N^.N); { Вывод цифры }
             N:=N^.R        { Перевод указателя на следующий младший разряд }
           until N=nil
         end
  End;
PROCEDURE WriteNumFormat(var F:text; S1,S2:String; N:Numeral; RPos:longint);
  Begin  { Процедура форматированного вывода знака операции и числа.
           Форматирующие пробелы вставляются между S1 и S2, позволяя выводить
           число со знаком или знак операции и число, возможно, разделенные
           форматирующими пробелами }
    Write(F,S1);    { Вывод первой подстроки в файл }
    WriteChar(F,' ',RPos-Length(S1)-Length(S2)-Len(N)); { Вывод форматирующих пробелов }
    Write(F,S2);    { Вывод второй подстроки в файл }
    WriteNum(F,N);  { Вывод числа }
  End;
PROCEDURE WriteLnNumFormat(var F:text; S1,S2:String; N:Numeral; RPos:longint);
  Begin  { Процедура форматированного вывода знака операции и числа с завершением строки }
    WriteNumFormat(F,S1,S2,N,RPos); { Вывод числа }
    WriteLn(F)                      { Вывод конца строки }
  End;
PROCEDURE DisposeNum(var N:Numeral); { Процедура уничтожения числа }
  Var Buf:Numeral; { Буферная переменная }
  Begin
    ToLeft(N);  { Переход на старший разряд числа }
    if N=nil then begin
                    WriteLn(N=nil);
                    ReadLn
                  end;
    while N<>nil do { Цикл уничтожения числа }
    begin
      Buf:=N; { Сохранение ссылки на текущий разряд }
      N:=N^.R; { Переход на следующий младший разряд }
      Dispose(Buf) { Уничтожение старшего разряда }
    end
  End;
FUNCTION GetDig(N:Numeral):byte; { Функция получения текущего разряда }
 Begin
   if N<>nil { Проверка существования разряда }
   { и определение значения функции: }
   then GetDig:=N^.N
   else GetDig:=0
 End;
PROCEDURE CorrectionNum(var A:Numeral); { Процедура исправления переполнения разрядов }
  Begin
    ToRight(A); { Перевод указателя на младший разряд }
    while A^.L<>nil do { Цикл просмотра числа от младшего разряда к старшему }
    begin
      A^.L^.N:=A^.L^.N+A^.N div 10; { Перевод переполнения на следующий старший разряд }
      A^.N:=A^.N mod 10;            { Сброс переполнения }
      A:=A^.L                       { Переход на следующий старший разряд }
    end;
    if A^.N>=10 then { Проверка переполнения старшего разряда }
    begin
      InsertDigInL(A^.N div 10, A); { Вставка разряда слева от старшего }
      A^.N:=A^.N mod 10             { Сброс переполнения }
    end
  End;
PROCEDURE GetSum(var C:Numeral; A,B:Numeral); { Процедура сложения чисел }
  Begin
    ToRight(A); { Перевод указателя на младший разряд }
    ToRight(B); { Перевод указателя на младший разряд }
    New(C);     { Создание младшего разряда результата }
    C^.N:=GetDig(A)+GetDig(B);    { Определение значения разряда }
    C^.L:=nil;  { Сброс ссылки }
    C^.R:=nil;  { Сброс ссылки }
    while (A<>nil)or(B<>nil) do { Цикл поразрядного сложения }
    begin
      if A<>nil then A:=A^.L;    { "Перевод" разряда операнда на следующий старший }
      if B<>nil then B:=B^.L;    { "Перевод" разряда операнда на следующий старший }
      if (A<>nil)or(B<>nil) then { Проверка наличия разрядов }
      begin
        InsertDigInL(GetDig(A)+GetDig(B),C); { Вставка нового разряда }
        C:=C^.L    { Переход на старший разряд результата }
      end;
    end;
    CorrectionNum(C)  { Исправление переполнения разрядов }
  End;
PROCEDURE CopyNum(A:Numeral; var B:Numeral); { Процедура копирования числа }
  Begin
    ToLeft(A); { Перевод указателя на старший разряд }
    while A<>nil do  { Цикл перебора разрядов A }
    begin
      InsertDigR(A^.N,B); { Копирование (вставка) разряда из A в B }
      A:=A^.R            { Перевод указателя на следующий младший разряд }
    end
  End;
PROCEDURE Sum(var C:Numeral; B:Numeral); { Процедура прибавления к C числа B }
  Var Buf:Numeral; { Вспомогательная переменная }
  Begin
    Buf:=nil;  { Сброс ссылки }
    GetSum(Buf,C,B); { Вычисление суммы }
    DisposeNum(C);  { Уничтожение исходного числа }
    C:=Buf       { Переопределение ссылки на результат }
  End;
PROCEDURE Addition(var F:text; LNum,RNum:Numeral); { Процедура сложения и вывода результата }
  Var Width:longint;  { Ширина вывода процесса и результата }
      Result:Numeral; { Результат операции }
  Begin
    Result:=nil; { Сброс ссылки }
    Width:=Max(Len(LNum),Len(RNum))+1; { Определение ширины вывода }
    WriteLnNumFormat(F,' ','',LNum,Width); { Вывод левого операнда }
    WriteLnNumFormat(F,'+','',RNum,Width); { Вывод правого операнда }
    WriteLnChar(F,'-',Width);     { Вывод черты }
    GetSum(Result,LNum,RNum);   { Сложение }
    WriteLnNumFormat(F,'','',Result,Width);{ Вывод результата }
    DisposeNum(Result)          { Уничтожение результата }
  End;
PROCEDURE DelLeftZero(var Num:Numeral); { Процедура удаление нулей из старших разрядов }
  Begin
    ToLeft(Num); { Перевод указателя на старший разряд }
    while (Num^.N=0)and(Num^.R<>nil) do
    begin    { Цикл просмотра и удаления нулей в старших разрядах числа }
      Num:=Num^.R; { Перевод указателя на второй разряд }
      Dispose(Num^.L);  { Уничтожение старшего разряда }
      Num^.L:=nil       { Сброс ссылки на левый разряд }
    end
  End;
FUNCTION GetSignDiff(var LNum,RNum:Numeral):Char;
  Begin  { Определение знака результата вычитания }
    DelLeftZero(LNum);
    DelLeftZero(RNum); { Удаление начальных нулей }
    if Len(LNum)>Len(RNum)   { Сравнение операндов по длине }
    then GetSignDiff:='+'    { Определение "положительного" значения функции }
    else if Len(LNum)<Len(RNum)  { Сравнение опрерандов по длине }
         then GetSignDiff:='-'   { Определение "отрицательного" значения функции }
         else begin { Сравнение операндов по значению разрядов: }
                ToLeft(LNum); { Перевод указателя на старший разряд }
                ToLeft(RNum); { Перевод указателя на старший разряд }
                while (LNum^.N=RNum^.N)and(LNum^.R<>nil) do
                begin { Цикл просмотра операндов до первого несовпадающего разряда }
                  LNum:=LNum^.R; RNum:=RNum^.R; { Переопределение указателей }
                end;
                if RNum^.N<LNum^.N  { Определение знака функции по первым
                     несовпавшим разрядам операндов или по младшим разрядам: }
                then GetSignDiff:='+'
                else if RNum^.N>LNum^.N
                     then GetSignDiff:='-'
                     else GetSignDiff:='0'
              end
  End;
PROCEDURE Loan10(A:Numeral); { Процедура заимствования разряда }
  Begin
    while A^.N=0 do { Цикл прохода по нулевым разрядам }
    begin
      A^.N:=9; { Пересчет разряда }
      A:=A^.L  { Переопределение ссылки на следующий старший разряд }
    end;
    A^.N:=A^.N-1 { Пересчет разряда }
  End;
PROCEDURE GetDiff(var C:Numeral; A,B:Numeral); { Процедура вычитания }
  Begin
    CopyNum(A,C);          { Копирование уменьшаемого в разность }
    ToRight(C);            { Перевод указателя на старший разряд разности }
    ToRight(B);            { Перевод указателя на старший разряд вычитаемого }
    while B<>nil do        { Цикл перебора разрядов вычитаемого }
    begin
      if C^.N>=B^.N   { Проверка превосходства значения разряда уменьшаемого }
      then C^.N:=C^.N-B^.N { Непосредственное вычитание разрядов }
      else begin { Заимствование "единицы" из старшего разряда и вычитание: }
             Loan10(C^.L); { Вычитание единицы из старшего разряда }
             C^.N:=10+C^.N-B^.N { Вычитание разряда }
           end;
      B:=B^.L; { Переход на следующий старший разряд }
      if B<>nil then C:=C^.L { Переход на следующий старший разряд при наличии разрядов в вычитаемом }
    end;
    DelLeftZero(C) { Удаление нулей из старших разрядов }
  End;
PROCEDURE Diff(var C:Numeral; B:Numeral); { Процедура вычитания из C числа B }
  Var Buf:Numeral; { Вспомогательная переменная }
  Begin
    Buf:=nil;  { Сброс ссылки }
    GetDiff(Buf,C,B); { Вычисление разности }
    DisposeNum(C);  { Уничтожение исходного числа }
    C:=Buf       { Переопределение ссылки на результат }
  End;
PROCEDURE Subtraction(var F:text; var LNum,RNum:Numeral); { Процедура вычитания и вывода результата }
  Var Width:longint;  { Ширина вывода процесса и результата }
      Result:Numeral; { Результат операции }
      ResSign:Char;   { Знак результата }
  Begin
    Result:=nil; { Сброс ссылки }
    Width:=Max(Len(LNum),Len(RNum))+1; { Определение ширины вывода }
    WriteLnNumFormat(F,' ','',LNum,Width); { Вывод левого операнда }
    WriteLnNumFormat(F,'-','',RNum,Width); { Вывод правого операнда }
    WriteLnChar(F,'-',Width);     { Вывод черты }
    ResSign:=GetSignDiff(LNum,RNum); { Определение знака результата }
    if ResSign='-' { Проверка знака операции }
    then GetDiff(Result,RNum,LNum)    { Вычитание }
    else GetDiff(Result,LNum,RNum);   { Вычитание }
    WriteLnNumFormat(F,'',ResSign,Result,Width); { Вывод результата }
    DisposeNum(Result)          { Уничтожение результата }
  End;
PROCEDURE MultiplyDig(Num:Numeral; A:byte; var Res:Numeral);
  Begin                                { Процедура умножения числа на цифру }
    ToRight(Num); { Перевод указателя на младший разряд }
    while Num<>nil do  { Цикл перебора разрядов умножаемого }
    begin
      if A>9 then
      begin
        WriteLn('A=',A,'*',Num^.N);
        ;
      end;
      InsertDigL(A*Num^.N,Res); { Вычисление разряда }
      Num:=Num^.L                 { Переход на следующий старший разряд }
    end;
    CorrectionNum(Res);     { Исправление переполнения разрядов }
    DelLeftZero(Res)        { Удаление начальных нулей }
  End;
PROCEDURE MultPower10(Power:longint; var Num:Numeral);
  Begin  { Процедура умножения числа на степень 10-ти }
    while Power>0 do { Цикл умножения }
    begin
      InsertDigR(0,Num); { Приписывание нуля }
      Dec(Power)        { Пересчет оставшихся разрядов }
    end
  End;
PROCEDURE DivPower10(Power:longint; var Num:Numeral);
  Begin  { Процедура деления числа на степень 10-ти (отсечение младших разрядов)}
    ToRight(Num);  { Переход на младший разряд }
    while Power>0 do { Цикл деления }
    begin
      Dec(Power);        { Пересчет оставшихся разрядов }
      if Num^.L<>nil     { Проверка наличия старших разрядов }
      then begin
             Num:=Num^.L;     { Переход на следующий старший разряд }
             Dispose(Num^.R); { Уничтожение младшего разряда }
             Num^.R:=nil      { Оформление правого "хвоста" списка }
           end
      else Num^.N:=0  { Сброс разряда }
    end
  End;
PROCEDURE Multiply(var F:text; var LNum,RNum:Numeral); { Процедура умножения и вывода результата }
  Var Width:longint;  { Ширина вывода процесса и результата }
      Result:Numeral; { Результат операции }
      SResult:Numeral;{ Результат операции набора суммы }
      Element:Numeral; { Промежуточный результат умножения числа на разряд }
      EWidth:longint; { Ширина вывода промежуточных результатов }
      RN:Numeral;  { Дополнительная ссылка на множитель }
  Begin
    Result:=nil; { Сброс ссылки }
    InsertDigR(0,Result); { Начальное определение результата }
    Width:=Len(LNum)+Len(RNum)+1; { Определение ширины вывода }
    EWidth:=Width; { Начальное определение ширины вывода промежуточных результатов }
    WriteLnNumFormat(F,' ','',LNum,Width); { Вывод левого операнда }
    WriteLnNumFormat(F,'*','',RNum,Width); { Вывод правого операнда }
    WriteLnChar(F,'-',Width);     { Вывод черты }
    RN:=RNum; { Начальное определение указателя на множитель }
    ToRight(RN); {  Перевод указателя на старший разряд }
    while RN<>nil do  { Цикл перебора разрядов множителя }
    begin
      Element:=nil; { Сброс ссылки }
      MultiplyDig(LNum,RN^.N,Element); { Умножение умножаемого на разряд множителя }
      WriteLnNumFormat(F,'','',Element,EWidth); { Вывод промежуточного результата }
      MultPower10(Width-EWidth,Element); { Приведение промежуточного результата в соответствие разряду множителя }
      Dec(EWidth); { Пересчет ширины поля вывода промежуточных результатов }
      SResult:=nil; { Сброс ссылки на промежуточную сумму }
      GetSum(SResult,Result,Element); { Набор суммы }
      Dispose(Result); { Удаление предыдущего результата суммирования }
      Result:=SResult; { Переопределение ссылки на сумму }
      DisposeNum(Element); { Уничтожение промежуточного результата }
      RN:=RN^.L           { Переход на старший разряд }
    end;
    WriteLnChar(F,'-',Width);     { Вывод черты }
    WriteLnNumFormat(F,'','',Result,Width); { Вывод результата }
    DisposeNum(Result)          { Уничтожение результата }
  End;
FUNCTION CompZero(Num:Numeral):boolean; { Функция сравнения числа с нулем }
  Begin
    ToLeft(Num); { Перевод указателя на старший разряд }
    CompZero:=TRUE; { Начальное определение функции }
    while Num<>nil do  { Цикл поразрядного просмотра числа }
    begin
      if Num^.N <>0   { Сравнение разряда с нулем }
      then begin
             CompZero:=FALSE;  { Переопределение значения функции }
             Break             { Выход из цикла }
           end;
      Num:=Num^.R   { Переход на следующий младший разряд числа }
    end;
  End;
PROCEDURE GetHead(A:Numeral; var B:Numeral; C:Numeral); { Процедура копирования начальной части A в B, пока B меньше C }
  Var CBuf:Numeral; { Ссылка на вспомогательную переменную, необходима, т.к.
                     GetSignDiff формально может изменить число и значение указателя }
  Begin
    CBuf:=nil; CopyNum(C,CBuf); { Создание копии C }
    B:=nil; { Начальный сброс указателя }
    ToLeft(A); { Перевод указателя на старший разряд }
    repeat   { Цикл копирования }
      InsertDigR(A^.N,B);  { Вставка разряда справа }
      A:=A^.R              { Переход на следующий правый разряд }
    until (A=nil)or(GetSignDiff(B,CBuf)<>'-');
    DisposeNum(CBuf) { Уничтожение числа }
  End;
PROCEDURE GetDiv(var Dividend, Divisor, Quotient, Rest:Numeral);
{ Процедура деления: Dividend - делимое, Divisor - делитель,
                     Quotient - частное, Rest - остаток }
  Var QuotientBuf, { Частное от деления заимствованных разрядов на Divisor }
      Head,        { Заимствованные разряды от делимого }
      S:Numeral;   { Сумма для набора произведения разряда на делитель }
      Z:byte;      { Разряд частного }
  Begin
    Quotient:=nil; { Сброс частного }
    Rest:=nil;     { Сброс остатка }
    InsertDigR(0,Quotient); { Начальное определение частного }
    CopyNum(Dividend,Rest);  { Начальное определение остатка }
    while GetSignDiff(Rest,Divisor)<>'-' do
    begin { Цикл вычисления, пока остаток больше или равен делителю }
      ToLeft(Rest);  { Перевод указателя на старший разряд остатка }
      Head:=nil; InsertDigR(Rest^.N,Head); { Выделение начальной части делимого в Head: }
      while GetSignDiff(Head,Divisor)='-' do
      begin { Продолжение выделения начальной части делимого, пока Head<Divisor }
        Rest:=Rest^.R; { Перевод указателя на разряд вправо }
        InsertDigRightSide(Rest^.N,Head) { Заимствование разряда из делимого (остатка) }
      end;
      S:=nil; InsertDigR(0,S); { Сброс суммы для набора произведения, при котором будет определен новый разряд Quotient }
      Z:=0; { "Сброс" разряда }
      while GetSignDiff(S,Head)<>'+' do
      begin { Цикл набора произведения делителя на разряд }
        Sum(S,Divisor); { Суммирование - набор произведения }
        Inc(Z);         { Набор разряда чатного }
      end;
      DisposeNum(Head); { Уничтожение заимствованных разрядов }
      Dec(Z); { Приведение к действительному значению разряда }
      Diff(S,Divisor); { "Откат" суммы для определения истинного значения произведения разряда Z на Divisor }
      QuotientBuf:=nil; { Сброс вспомогательного частного }
      InsertDigR(Z,QuotientBuf); { Вставка разряда во вспомогательное частное }
      while Rest^.R<>nil do
      begin { Цикл согласования по разрядам вспомогательного частного и произведения разряда частного на делитель }
        Rest:=Rest^.R;  { Переход по остатку на разряд вправо }
        InsertDigRightSide(0,QuotientBuf); { "Приписывание" нуля к вспомогательному частному }
        InsertDigRightSide(0,S); { "Приписывание" нуля к произведению разряда на делитель }
      end;
      Diff(Rest,S); { Вычитание - получение остатка от делимого после нахождения разряда }
      DisposeNum(S); { Уничтожение произведения }
      Sum(Quotient,QuotientBuf); { Суммирование частного и вспомогательного частного }
      DisposeNum(QuotientBuf)  { Уничтожение вспомогательного частного }
    end
  End;
PROCEDURE Division(var F:text; var LNum,RNum:Numeral); { Процедура деления и вывода результата }
  Var Width:longint;  { Ширина вывода процесса и результата }
      ResDiv, ResMod:Numeral; { Результаты операции - частное и остаток }
      R, Sub:Numeral; { Вспомогательные ссылки на частное и вычитаемое при выводе процесса деления }
      LNumBuf:Numeral; { Вспомогательная переменная }
      Head:Numeral; { Ссылка на число, соответствующее занятым разрядам у делимого }
      Pos:longint; { Позиция правого разряда при выводе произведения делителя на разряд частного }
  Begin
    DelLeftZero(LNum); DelLeftZero(RNum); { Сброс незначащих нулей в старших разрядах }
    if CompZero(RNum) { Проверка деления на ноль }
    then WriteLn(F,'ОШИБКА: деление на ноль ')  { Вывод сообщения об ошибки }
    else begin

    {-------- Процесс деления: }
           ResDiv:=nil; ResMod:=nil; { Сброс ссылок результатов }
           WriteNum(F,LNum); { Вывод делимого }
           Write(F,'│'); { Вывод черты отделяющей делимое от делителя }
           WriteNum(F,RNum); { Вывод делителя }
           WriteLn(F); { Перевод строки }
           ResDiv:=nil; { Сброс ссылки на частное }
           ResMod:=nil; { Сброс ссылки на остаток }
           GetDiv(LNum,RNum,ResDiv,ResMod); { Деление }

    {-------- Вывод процесса деления:}
           Width:=Len(LNum); { Фиксация ширины вывода процесса деления (без делителя и частного) }
           R:=ResDiv; { Определение вспомогательной ссылки на частное для отслеживания отдельных разрядов }
           ToLeft(R); { Перевод ссылки на старший разряд частного }
           Sub:=nil; MultiplyDig(RNum,R^.N,Sub); { Определение вычитаемого из делимого }
           R:=R^.R; { Перевод указателя на следующий разряд частного }
           Head:=nil; GetHead(LNum,Head,Sub); { Определение начальных разрядов делимого }
           Pos:=Len(Head); { Определение позиции младшего разряда вычитаемого и остатка на данной операции }
           DisposeNum(Head); { Удаление числа }
           WriteNumFormat(F,'','',Sub,Pos); { Вывод вычитаемого }
           WriteChar(F,' ',Width-Pos);      { Вывод пробелов перед "уголком" }
           Write(F,'├');      { Первый символ "уголка" }
           WriteLnChar(F,'-',Max(Len(RNum),Len(ResDiv))); { Вывод черты "уголка" }
           WriteChar(F,' ',Pos-Len(Sub)); WriteChar(F,'─',Len(Sub)); { Вывод черты под вычитаемым }
           MultPower10(Width-Pos,Sub); { "Приписывание" нулей к вычитаемому }
           WriteLnNumFormat(F,'','│',ResDiv,Width-Pos+Len(ResDiv)+1);  { Вывод частного }
           Diff(LNum,Sub);{ Определение остатка от делимого после "последней" операции умножения разряда частного на делитель }
           LNumBuf:=nil; { Сброс ссылки }
           while R<>nil do { Цикл вывода процесса деления (перебор оставшихся разрядов частного) }
           begin
             Inc(Pos);   { Переопределение позиции младшего разряда вычитаемого }
             CopyNum(LNum, LNumBuf); DivPower10(Width-Pos,LNumBuf); { Заимствование разрядов }
             WriteLnNumFormat(F,'','',LNumBuf,Pos);  { Вывод остатка от вычитания и заимствованного разряда }
             DisposeNum(LNumBuf);  { Уничтожение остатка }
             DisposeNum(Sub); MultiplyDig(RNum,R^.N,Sub); { Определение вычитаемого из делимого }
             R:=R^.R; { Перевод указателя на следующий разряд частного }
             WriteLnNumFormat(F,'','',Sub,Pos); { Вывод вычитаемого }
             WriteChar(F,' ',Pos-Len(Sub)); WriteLnChar(F,'-',Len(Sub)); { Вывод черты под вычитаемым }
             MultPower10(Width-Pos,Sub); { "Приписывание" нулей к вычитаемому }
             Diff(LNum,Sub);
                  { Определение остатка от делимого после "последней" операции умножения разряда частного на делитель }
           end;
           WriteLnNumFormat(F,'','',LNum,Pos); { Вывод остатка }
    {+++++++ Завершение процедуры: }
           DisposeNum(Sub); { Уничтожение разности }
           DisposeNum(ResDiv); DisposeNum(ResMod)  { Уничтожение результата }
         end
  End;
PROCEDURE Calculate(var InF,OutF:text); { Процедура обработки файла заданий }
  Var LNum,RNum:Numeral; { Левый и правый операнды }
      Sign:Char;         { Знак арифметической операции }
  Begin
    Reset(InF); { Открытие файла для чтения }
    Rewrite(OutF); { Открытие файла для записи }
    LNum:=nil; { Сброс ссылки }
    RNum:=nil; { Сброс ссылки }
    while not EOF(InF) do { Цикл чтения файла исходных данных }
    begin
      ReadOperation(InF,LNum,Sign,RNum); { Чтение операндов и операции }
      if (LNum=nil)or(RNum=nil) then Sign:=' '; { Защита от отсутствия операндов }
      WriteNum(OutF,LNum); Write(OutF,Sign); WriteNum(OutF,RNum); WriteLn(OutF);
                                                 { Вывод вычисляемого выражения }
      WriteLn(OutF); { Пропуск строки }
      case Sign of
        '+':Addition(OutF,LNum,RNum);
        '-':Subtraction(OutF,LNum,RNum);
        '*':Multiply(OutF,LNum,RNum);
        '/':Division(OutF,LNum,RNum);
        else WriteLn(OutF,'ОШИБКА: операция не определена');
      end;
      WriteLnChar(OutF,'=',50); { Вывод разделителя между заданиями }
      if LNum<>nil then DisposeNum(LNum); { "Стирание" левого операнда }
      if RNum<>nil then DisposeNum(RNum); { "Стирание" правого операнда }
    end;
    Close(InF); Close(OutF)  { Закрытие файлов: }
  End;
PROCEDURE CopyFileToDisplay(var F:text); { Процедура копирования файла на экран }
  Var S:String;  { Строка для чтения файла }
  Begin
    Reset(F); { Открытие файла }
    while not EOF(F) do { Цикл чтения файла }
    begin
      ReadLn(F,S); { Чтение строки файла }
      WriteLn(Copy(S,1,79)) { Вывод начальной части строки на экран }
    end;
    Close(F)  { Закрытие файла }
  End;
VAR InF, OutF: text; { Файловые указатели }
BEGIN
  Assign(InF,'_input.txt');  { Связывание файлового указателя с именем }
  MakeData(InF);             { Создание файла исходных данных }
  Assign(OutF,'_output.txt');{ Связывание файлового указателя с именем }
  Calculate(InF,OutF);       { Вычисление выражений из файла исходных данных }
  CopyFileToDisplay(OutF);{ Вывод файла результата на экран }
  WriteLn;
  WriteLn('Реализовать опрации + - * / для целых неотрицательных неограниченных целых');
  WriteLn('с демонстрацией вычислений "в столбик"');
  WriteLn('Результат работы программы см. в файлах _input.txt и _output.txt');
  WriteLn('Для просмотра, используйте текстовый DOS редактор или TurboPascal');
  WriteLn('=========================');
  WriteLn('Stud-Prog.narod.ru - помощь студентам по программированию');
  WriteLn('StudDraw.narod.ru - помощь студентам по черчению');
  WriteLn('English-Translator.narod.ru - английский язык: рефераты, переводы');
  WriteLn('+7-(904)-601-65-28 Александр Евгеньевич');
  ReadLn;
END.

Бесплатные примеры программ
Примеры написанных программ
Помощь студентам по программированию