Программа
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.
Бесплатные примеры программ
Примеры написанных программ
Помощь студентам по программированию