asyan.org
добавить свой файл
1
Київський національний університет ім Т.Шевченка

Факультет кібернетики

Кафедра теорії програмування


Звіт

з лабораторної роботи №5

"Калькулятор"

з курсу програмування

Виконав: студент I курсу

факультету кібернетики

групи К-12

Ратушний Т.О.
Перевірив: викладач Коваль Ю.В.


Київ 23.03.2008

Зміст


1. Формулювання задачі 3

1.1 Формулювання задачі 3

1.2 Постановка задачі 3

2. Аналіз задачі 4

2.1 Аналіз вхідних данних, перевірка вхідних данних на припустимість 5

3. Проектування програми 6

4. Тести, які повинна виконати програма 7

5. Тестування 8

6. Додаток 9

6.1 Текст програми 9

6.2 Текст модулів 13


^

1. Формулювання задачі




1.1 Формулювання задачі


Написати програму-калькулятор.

1.2 Постановка задачі



1) Написати командний інтерфейс до програми ;

2) Реалізувати модулі, що аналізуватимуть вираз (синтаксичний аналізатор);

3) Написати програму, що обчислює арифметичний вираз, що складається з операцій, констант, дужок, змінних
^









2. Аналіз задачі


Калькулятор повинен виконувати дії додавання, віднімання, множення, ділення, піднесення до степеня, він має правильно реагувати на дужки та рахувати в різних системах числення.
Обчислення виразу подамо за допомогою БНФ:

::= <+ - > ;

::= <*/> ;

::= <^> ;

::=|‘(‘’)’|[‘=’ ];

::=’Id’{‘0-9’}.

Для вирішення задачі використовуємо поняття лексеми . Перелік лексем :

help, exit ;

i-,o-, hex, dec, oct, bin - команди для переходу в різні системи числення;

bl – «bad lexem»;

ne –
нейтральний елемент;

eol, eob

{0-9,A-F} (,),+,-,*,/,^ .

Наша програма повинна адекватно реагувати на введений неправильно вираз. Поведінка неправильних символів: те що може зрозуміти програма залишається, інтерпретація іншого – викидається і підставляється нейтральний елемент, тобто вираз (1++3) має значення 4 тому що в програмі він матиме вигляд (1+03)=4.

Для обчислення виразу потрібно в програмі побудувати бінарне дерево обчислень у вигляді записів, причому даний запис матиме два вказівника на ліве і праве піддерево, дужки маємо обчислювати як окреме дерево, у вузлах дерева зберігаємо знак операції

^

2.1 Аналіз вхідних данних, перевірка вхідних данних на припустимість


Вхідні данні можуть бути будь-якими їх коректність врахована в программі. Тобто на введені некоректно лексеми отримаємо “bl” , а при неправильному символі в виразі замінимо його на “ne” відповідно до операції

^



3. Проектування програми




Маємо таку схему будови калькулятора:




- програма-калькулятор;

- модуль обробки лексем, модуль роботи зі змінними;

- буфер вводу ввиду, функції обробки символів;
В модулі bufio маємо такі функції: buf, getchar, ungetchar.

Buf – текстовий буфер;

Getchar – функція, яка послідовно бере з buf символи;

Ungetchar – функція, що повертає символ в buf.

В модулі lexan обробляємо лексеми і маємо такі процедури і функції: procedure getlex, ungetlex і процедури переходів в різні системи числення і роботі в них.

Getlex – аналізує та складає лексеми за допомогою модуля bufio , відповідно ungetlex – повертає лексеми.

Модуль memory має функції : initmem(заповнює пам’ять змінних нулями), initval(ініціалізує змінну), getval(записує змінну в пам’ять).

В самій програмі створюємо функції операцій з виразами, описуємо командний інтерфейс і процедуру аналізу виразу.

Так як наша програма не повинна повідомляти про помилку, то при діленні на ноль будемо отримувати значення МАХINT, що дорівнює 2000000000.

^

4. Тести, які повинна виконати програма


Те що вводить користувач будемо підкреслювати, а без підкреслень відповідь комп’ютера:

1)Use for detail information 4) Use for detail information

> (1+2)*3^2 >2/0

=27 =2000000000

>ibin >quit

>obin

>101+1

=110

>idec

>odec

>1++

=1

>obin

>2

=10

>ntr

=bl

>idec

>odec

>7*2*+

=14

>ihex

>ohex

>1+A

=B

>quit

2)Use for detail information

>id1=1

>id2=id1*2

>id1+id2

=3

>id1=2

>id2=2*(1+1)-id1

>id1*id2

=4

>quit
3) Use for detail information

>2^3^2

=512

>1+2*3^2 – (5+4)*2/3-10+2*(1+1)^2^1

=11

>(1+1)^2*3-4*(1+3/2)/2-2^2^2+3*4*1/(1+1)

=-2

>quit

5. Тестування


Заплановне тестування программа виконала успішно. Перевіряючи роботу в різних системах числення отримали вірний результат. Нейтральний елемент і невірна лексема працює. Пам’ять калькулятора працює, відповідно операції зі змінними виконуються.

^

6. Додаток

6.1 Текст програми


program Calculator;
uses crt,lexan,bufio,mem;
function e:longint; forward;
type systemm = (bin,oct,dec,hex,quo);

sys = record si:systemm; so:systemm end;

const MaxMax = 2000000000;

var ch:char;

inf:boolean;

w:longint;

k:byte;

sc:sys;

s:string;
function stepen(osn,s:longint):longint;

var sum,i:longint;

begin

sum:=1;

for i:=1 to s do

sum:=sum*osn;

stepen:=sum;

end;
function c:longint;

begin

c:=0;

getlex(s);

case l.tlex of

30: initval(nid,e);

31: c:=getval(nid);

8 : begin

c:=e;

end;

1: begin

case sc.si of

bin: c:=ibin(l.nlex);

dec: c:=idec(l.nlex);

oct: c:=ioct(l.nlex);

hex: c:=ihex(l.nlex);

quo: c:=iquo(l.nlex)

end;

if ne=true then

c:=1;

end;

end;

end;
function m:longint;

var sum3:longint;

begin

m:=0;

sum3:=c;

getlex(s);

if l.nlex='^' then begin

sum3:=stepen(sum3,m);

getlex(s);

end;

ungetlex;

m:=sum3

end;
function ss:longint;

var sum2,k:longint;

begin

ss:=1;

sum2:=m;

getlex(s);

while l.tlex=3 do begin

if l.nlex='*' then

sum2:=sum2*m

else if l.nlex='/' then begin

k:=m;

if k=0 then begin

inf:=true;

sum2:=MAXMAX

end else

sum2:=sum2 div k

end else if l.nlex='%' then begin

k:=m;

if k=0 then begin

inf:=true;

sum2:=0

end else

sum2:=sum2 mod k;

end;

getlex(s)

end;

ungetlex;

ss:=sum2;

end;
function e:longint;

var sum1:longint;

begin

e:=0;

sum1:=ss;

getlex(s);

while l.tlex=2 do begin

if l.nlex='+' then

sum1:=sum1+ss

else

sum1:=sum1-ss;

getlex(s);

end;

e:=sum1;

end;
procedure helpin;

begin

writeln('Use commands to switch the system:');

writeln('ibin-input binary');
end;
procedure analys;

var x:longint;

s2:string;

begin

repeat

begin

s:=buf;

bl:=false;

ne:=false;

inf:=false;

getlex(s);

if bl=true then

writeln('Warning! Syntax error')

else

if (l.tlex>10) and (l.tlex<15) then begin

case l.tlex of

11: begin

if l.nlex='ibin' then

sc.si:=bin;

if l.nlex='ioct' then

sc.si:=oct;

if l.nlex='idec' then

sc.si:=dec;

if l.nlex='ihex' then

sc.si:=hex;

if l.nlex='iquo' then

sc.si:=quo

end;

12: begin

if l.nlex='obin' then

sc.so:=bin;

if l.nlex='ooct' then

sc.so:=oct;

if l.nlex='odec' then

sc.so:=dec;

if l.nlex='ohex' then

sc.so:=hex;

if l.nlex='oquo' then

sc.so:=quo;

end;

13: helpin;

14: exit;

end;
end;

if (l.tlex=1) or (l.nlex='(') or (l.tlex=31) then begin

ungetlex;

x:=e;

case sc.so of

dec: s2:=odec(x);

bin: s2:=obin(x);

quo: s2:=oquo(x);

hex: s2:=ohex(x);

oct: s2:=ooct(x);

end;

writeln('=',s2);

if ne=true then writeln('Warning! Syntax error');

if inf=true then

writeln('Warning! Division by zero');

inf:=false;

end;

end;

if l.tlex=30 then begin

ungetlex;

c;

end;
until (l.nlex='quit')or(l.nlex='exit');

end;
begin

clrscr;

initmem;

writeln('Use for detail information');

sc.si:=dec;

sc.so:=dec;

analys;
end.

^

6.2 Текст модулів


unit bufio;

interface

function buf:string;

function ungetchar(s:string):char;

function getchar(s:string):char;

var i:integer;

eob:boolean;

implementation

function buf:string;

var s:string;

begin

i:=1;

eob:=false;

write('>');

readln(s);

buf:=s;

end;
function getchar(s:string):char;

begin

if i>length(s) then

begin

eob:=true;

getchar:='x';

i:=i+1;

end

else

begin

getchar:=s[i];

i:=i+1;

end;

end;
function ungetchar(s:string):char;

begin

ungetchar:=s[i-2];

i:=i-1;

end;

end.

unit lexan;

interface

uses bufio;

type systemm = (bin,oct,dec,hex,quo);

lex = record nlex:string; tlex:byte end;

const sign = ['(',')','+','-','*','/','%','^'];

comchars = ['o','i','q','h'];

decbase = ['0'..'9'];

binbase = ['0'..'1'];

octbase = ['0'..'7'];

hexbase = ['0'..'9','A'..'F','a'..'f'];

quobase = ['0'..'3'];

hexabc = ['a'..'f'];

hexbigabc = ['A'..'F'];

chars = ['!'..'~'];

erchars = chars-(hexbase+sign+comchars);

var l:lex;

lengl:byte;

ne,bl:boolean;

nid:byte;

procedure getlex(s:string);

procedure ungetlex;

function ibin(s:string):longint;

function idec(s:string):longint;

function ioct(s:string):longint;

function ihex(s:string):longint;

function iquo(s:string):longint;

function odec(x:longint):string;

function obin(x:longint):string;

function ooct(x:longint):string;

function ohex(x:longint):string;

function oquo(x:longint):string;

implementation

procedure getlex(s:string);

var c:char;

begin

l.nlex:='';

l.tlex:=0;

c:=getchar(s);

if c in erchars then begin

bl:=true;

exit;

end;

if c in comchars then

begin

case c of

'o': begin

c:=getchar(s);

l.tlex:=12;

case c of

'd': l.nlex:='odec';

'b': l.nlex:='obin';

'h': l.nlex:='ohex';

'q': l.nlex:='oquo';

'o': l.nlex:='ooct'

else

begin

bl:=true;

exit;

end;

end;

end;

'i': begin

c:=getchar(s);

l.tlex:=11;

case c of

'd': begin

c:=getchar(s);

if c='e' then

l.nlex:='idec'

else if c in decbase then

begin

nid:=ord(c)-48;

c:=getchar(s);

if c='=' then

begin

l.nlex:='id'+chr(nid)+'=';

l.tlex:=30;

end;

if (c in sign) or (c='x') then

begin

l.tlex:=31;

l.nlex:='id'+chr(nid);

c:=ungetchar(s);

end;

end;

end;

'b': l.nlex:='ibin';

'h': l.nlex:='ihex';

'q': l.nlex:='iquo';

'o': l.nlex:='ioct'

else

begin

bl:=true;

exit;

end;

end;

end;

'h': begin

l.tlex:=13;

c:=getchar(s);

if c='e' then

begin

c:=getchar(s);

if c='l' then

l.nlex:='help'

else

begin

bl:=true;

exit;

end;

end

else

begin

bl:=true;

exit;

end;

end;

'q': begin

c:=getchar(s);

l.tlex:=14;

if c='u' then

l.nlex:='quit'

else

begin

bl:=true;

exit;

end;

end;

end;

c:='x';

end;

if c in hexbase then

begin

l.tlex:=1;

while c in hexbase do

begin

l.nlex:=l.nlex+c;

c:=getchar(s);

end;

c:=ungetchar(s);

end;

if c in sign then

case c of

'+':begin

l.nlex:='+';

l.tlex:=2;

end;

'-':begin

l.nlex:='-';

l.tlex:=2;

end;

'*':begin

l.nlex:='*';

l.tlex:=3;

end;

'/':begin

l.nlex:='/';

l.tlex:=3;

end;

'%':begin

l.nlex:='%';

l.tlex:=3;

end;

'^': l.nlex:='^';
'(': begin

l.tlex:=8;

l.nlex:='('

end;

')': begin

l.nlex:=')';

l.tlex:=9;

end;

end;

lengl:=length(l.nlex);

end;
procedure ungetlex;

begin

if i>lengl then

i:=i-lengl;

end;

function ibin(s:string):longint;

var d,result:longint;

i,j,n: byte;

begin

ibin:=0;

result:=0;

for i:=1 to length(s) do

begin

n:=ord(s[i])-48;

d:=1;

for j:=1 to (length(s)-i) do d:=d*2;

result:=n*d+result;

if not (s[i] in binbase) then ne:=true;

end;

ibin:=result;

end;
function idec(s:string):longint;

var d,result:longint;

i,j,n: byte;

begin

idec:=0;

result:=0;

for i:=1 to length(s) do

begin

n:=ord(s[i])-48;

d:=1;

for j:=1 to (length(s)-i) do d:=d*10;

result:=n*d+result;

if not (s[i] in decbase) then ne:=true;

end;

idec:=result;

end;
function ioct(s:string):longint;

var d,result:longint;

i,j,n: byte;

begin

ioct:=0;

result:=0;

for i:=1 to length(s) do

begin

n:=ord(s[i])-48;

d:=1;

for j:=1 to (length(s)-i) do d:=d*8;

result:=n*d+result;

if not (s[i] in octbase) then ne:=true;

end;

ioct:=result;

end;
function ihex(s:string):longint;

var d,result:longint;

i,j,n: byte;

begin

ihex:=0;

result:=0;

for i:=1 to length(s) do

begin

if (s[i] in decbase) then n:=ord(s[i])-48;

if (s[i] in hexabc) then n:=ord(s[i])-87;

if (s[i] in hexBigabc) then n:=ord(s[i])-55;

d:=1;

for j:=1 to (length(s)-i) do d:=d*16;

result:=n*d+result;

if not (s[i] in hexbase) then ne:=true;

end;

ihex:=result;

end;
function iquo(s:string):longint;

var d,result:longint;

i,j,n: byte;

begin

iquo:=0;

result:=0;

for i:=1 to length(s) do

begin

n:=ord(s[i])-48;

d:=1;

for j:=1 to (length(s)-i) do d:=d*4;

result:=n*d+result;

if not (s[i] in quobase) then ne:=true;

end;

iquo:=result;

end;
function odec(x:longint):string;

var s2:string;

begin

str(x,s2);

odec:=s2;

end;

function obin(x:longint):string;

var s2:string;

a:shortint;

begin

a:=1;

if x<0 then

begin a:=-1; x:=-x; end;

s2:='';

while x>=2 do

begin

s2:=chr((x mod 2)+48)+s2;

x:=x div 2;

end;

s2:=chr(x+48)+s2;

case a of

1: obin:=s2;

-1: obin:='-'+s2;

end;

end;

function oquo(x:longint):string;

var s2:string;

a:shortint;

begin

a:=1;

if x<0 then

begin a:=-1; x:=-x; end;

s2:='';

while x>=4 do

begin

s2:=chr((x mod 4)+48)+s2;

x:=x div 4;

end;

s2:=chr(x+48)+s2;

case a of

1: oquo:=s2;

-1: oquo:='-'+s2;

end;

end;

function ooct(x:longint):string;

var s2:string;

a:shortint;

begin

a:=1;

if x<0 then

begin a:=-1; x:=-x; end;

s2:='';

while x>=8 do

begin

s2:=chr((x mod 8)+48)+s2;

x:=x div 8;

end;

s2:=chr(x+48)+s2;

case a of

1: ooct:=s2;

-1: ooct:='-'+s2;

end;

end;

function ohex(x:longint):string;

var s2:string;

a:shortint;

begin

a:=1;

if x<0 then

begin a:=-1; x:=-x; end;

s2:='';

while x>=16 do

begin

if chr((x mod 16)+48) in decbase then

s2:=chr((x mod 16)+48)+s2;

if chr((x mod 16)+55) in hexBigabc then

s2:=chr((x mod 16)+55)+s2;

x:=x div 16;

end;

if chr((x)+48) in decbase then

s2:=chr(x+48)+s2;

if chr((x)+55) in hexBigabc then

s2:=chr(x+55)+s2;

case a of

1: ohex:=s2;

-1: ohex:='-'+s2;

end;

end;

end.
unit mem;

interface

var id : array [0..9] of longint;

procedure initmem;

function getval(n:byte):longint;

procedure initval(n:byte;x:longint);

implementation

procedure initmem;

var i:byte;

begin

for i:=0 to 9 do

id[i]:=0;

end;

procedure initval(n:byte;x:longint);

begin

id[n]:=x;

end;

function getval(n:byte):longint;

begin

getval:=id[n];

end;

end.