program fraction; uses crt; type cislo=longint; {cisla obsazena v citateli i jmenovateli)} type fract=record {typ zlomek} cit: cislo; {citatel} jmen: cislo; {jmenovatel} end; type pspoj=^spoj; {spojovy seznam promenych} spoj=record name: string; value: fract; next: pspoj; end; var ans: spoj; klavesa: char; priklad: byte; nula, jedna, deset, MAXCISLO: cislo; fnula: fract; vnoreni: integer; preteceni: integer; pozice: integer; rozpoznavam, rounded: boolean; vstup, vystup, tmp, mezi: string; inp,F: text; const funcerr='fnce.log'; {seznam funkci} {funkce cisel} procedure init; forward; {inicializuje globalni promenne} procedure nuluj(var co:cislo);forward; {nastavi dane cislo na nulu} procedure mydiv(var vysl: cislo; co, cim:cislo);forward; {celociselne deleni} function getrad(co:cislo):longint;forward; {zjisti rad cisla} function vetsi(co, nezco:cislo):boolean;forward; {zjisti, co je vetsi} procedure mymod(var vysl:cislo; co, cim: cislo);forward; {vrati modulo} procedure vydel(var vysl:cislo; co, cim:cislo); forward; {deleni cisel} procedure nsd(var vysl:cislo; co1, co2: cislo); forward; {vrati nejvetsi spolecny delitel} procedure secti(var vysl:cislo; co, scim:cislo);forward; {scitani cisel} procedure odecti(var vysl:cislo; co, odceho:cislo);forward; {odcitani cisel} function rovna(co, cemu:cislo):boolean;forward; {zjisti, jestli se cisla vzajemne rovnaji} procedure nasob(var vysl:cislo; co, cim:cislo);forward; {nasobeni cisel} procedure zmenrad(var vysl:cislo; okolik:integer);forward; {zmeni rad cisla} procedure prirad(var vysl:cislo; co:string);forward; {rozpoznani cisel v textovem retezci(zavisi na hodnotach rozpoznavam a pozice) a pracuje s promenou preteceni} function vypis(co: cislo):string;forward; {vypise cislo} {funkce zlomku} function frovna(co, cemu: fract): boolean; forward; {zjisti, jestli se zlomky rovnaj} function fvetsi(co, nezco: fract): boolean; forward; {zjisti, jestli je co mensi nez nezco} procedure fsecti(var vysl:fract; co:fract; scim:fract);forward; {scitani zlomku} procedure fodecti(var vysl:fract; co, odceho:fract); forward; {odcitani zlomku - prevede se na scitani} procedure fnasob(var vysl:fract; co, cim:fract);forward; {nasobeni zlomku} procedure fvydel(var vysl:fract; co, cim:fract);forward; {deleni zlomku - prevede se na nasobeni} procedure fkrat(var co:fract);forward; {kraceni zlomku} function fvypis(co:fract):string;forward; {vypsani zlomku(do stringu)} procedure fprirad(var vysl:fract; co:string);forward; {rozpoznani zlomku} procedure fgetst(var vysl:fract; co:string);forward; {rozpoznani zlomku, promene nebo funkce} procedure fgetmem(var vysl:fract; varname:string); forward; {nacte promenou z pameti} procedure setmemo(varname: string; value: fract); forward; {ulozi promenou do pameti} procedure vyraz(var co: string; var vysl: fract);forward; {rozpozna a vyhodnoti zadany vyraz} {ostatni funkce} function totex(co:string):string; forward; {prevod vypisu do TeXu} procedure hlavicka(var F: text); forward; {zapise TeXovou hlavicku} procedure tolower(var co: string); forward; {zmeni vsechna velka pismena na mala} procedure zpracuj(input: string; output: string; verbose: boolean); forward; {zpracuje vstup} {vlastni funcke} {funkce obycejnych cisel} procedure init; {inicializuje globalni promenne} begin nula:=0; jedna:=1; deset:=10; MAXCISLO:=32000; rounded:=false; vnoreni:=0; ans.name:='ans'; ans.next:=NIL; rozpoznavam:=false; fprirad(fnula, '0'); ans.value:=fnula; vstup:=''; vystup:=''; end; procedure nuluj(var co:cislo); {nastavi dane cislo na nulu} begin secti(co, nula, nula); end; procedure mydiv(var vysl: cislo; co, cim:cislo); {celociselne deleni} begin vysl:= co div cim; end; function getrad(co:cislo):longint; {zjisti rad cisla} var tmp:cislo; i:longint; begin i:=0; while not rovna(co,nula) do begin mydiv(co, co, deset); inc(i); end; getrad:=i; end; function vetsi(co, nezco:cislo):boolean; {zjisti, co je vetsi} begin if co>nezco then begin vetsi:=true; end else vetsi:=false; end; procedure mymod(var vysl:cislo; co, cim: cislo); {vrati modulo} begin mydiv(vysl, co, cim); nasob(vysl, vysl, cim); odecti(vysl, vysl, co); end; procedure vydel(var vysl:cislo; co, cim:cislo); {deleni cisel} var tmp1, tmp2:cislo; begin mydiv(vysl, co, cim); secti(tmp1, jedna, jedna); {zaokrouhlovani} mymod(tmp2, co, cim); mydiv(tmp1, cim, tmp1); if vetsi(tmp2, tmp1) then secti(vysl, vysl, jedna); end; procedure nsd(var vysl:cislo; co1, co2: cislo); {vrati nejvetsi spolecny delitel} var zbytek1, zbytek2, zbytek3: cislo; begin zbytek3:=jedna; if vetsi(co1, co2) then begin secti(zbytek1, nula, co1); secti(zbytek2, nula, co2); end else begin secti(zbytek1, nula, co2); secti(zbytek2, nula, co1); end; while vetsi(zbytek3, nula) do begin mymod(zbytek3, zbytek1, zbytek2); secti(zbytek1, nula, zbytek2); secti(zbytek2, nula, zbytek3); end; secti(vysl, zbytek1, nula); end; procedure secti(var vysl:cislo; co, scim:cislo); {scitani cisel} begin vysl:=co+scim; end; procedure odecti(var vysl:cislo; co, odceho:cislo); {odcitani cisel} begin vysl:=odceho-co; end; function rovna(co, cemu:cislo):boolean; {zjisti, jestli se cisla vzajemne rovnaji} begin if co=cemu then begin rovna:=true; end else rovna:=false; end; procedure nasob(var vysl:cislo; co, cim:cislo); {nasobeni cisel} begin vysl:=co*cim; end; procedure zmenrad(var vysl:cislo; okolik:integer); {zmeni rad cisla} var i:integer; begin if okolik<>0 then begin if okolik>0 then begin for i:=1 to okolik do nasob(vysl, vysl, deset); end else begin for i:=-1 downto okolik do vydel(vysl, vysl, deset); if rovna(vysl, nula) then secti(vysl, vysl, jedna); end; end; end; procedure prirad(var vysl:cislo; co:string); {rozpoznani cisel v textovem retezci(zavisi na hodnotach rozpoznavam a pozice) a pracuje s promenou preteceni} var i,tmp,MAXRAD: integer; begin MAXRAD:=2*getrad(MAXCISLO)-1; if rozpoznavam then begin i:=pozice-1; end else i:=0; nuluj(vysl); while (i='0') and (co[i+1]<='9') do begin i:=i+1; if getrad(vysl)'_') or (pozice>(length(co)-1)) or ((co[pozice]='_') and (co[mez]='('))) then begin inc(pozice); prirad(vysl.jmen, co); end else secti(vysl.jmen, jedna, nula); if (pret1>0) and (pret1>preteceni) then begin zmenrad(vysl.jmen, preteceni-pret1); rounded:=true; end; if (preteceni>0) and (pret10 then pozice:=tmp; end; procedure fgetmem(var vysl:fract; varname:string); {nacte promenou z pameti} var a: pspoj; begin a:=@ans; {prvni ve spojaku je $ans} while (a<>NIL) and (a^.name<>varname) do a:=a^.next; if a^.name=varname then begin vysl:=a^.value; end else vysl:=fnula; end; procedure setmemo(varname:string; value: fract); {nacte promenou z pameti} var a: pspoj; begin a:=@ans; {prvni ve spojaku je $ans} while (a^.next<>NIL) and (a^.name<>varname) do a:=a^.next; if a^.name=varname then begin a^.value:=value; end else begin new(a^.next); if a^.next<>NIL then begin a^.next^.name:=varname; a^.next^.next:=NIL; a^.next^.value:=value; end else writeln('NEDOSTATEK PAMETI!'); end; end; procedure fgetst(var vysl:fract; co:string); {rozpoznani zlomku, promene nebo funkce} var tmp: string; bak: integer; state: boolean; begin while (pozice'' then begin bak:=pozice; pozice:=1; setmemo('result',fnula); state:=rozpoznavam; zpracuj(tmp,funcerr,false); rozpoznavam:=state; pozice:=bak; end; fgetmem(vysl,'result'); end; else begin; inc(pozice); end; end; end; procedure vyraz(var co: string; var vysl: fract); {rozpozna a vyhodnoti zadany vyraz} var konec: integer; zlomek1, zlomek2: fract; tmp: string; last, state: boolean; id: integer; begin tmp:='('; state:=rozpoznavam; inc(vnoreni); id:=vnoreni; inc(pozice); nuluj(vysl.cit); fkrat(vysl); nuluj(zlomek1.cit); fkrat(zlomek1); rozpoznavam:=true; {precte se vstupujici string a do stringu tmp se ulozi tak, ze se vypocitaji veskere zavorky, nasobeni a deleni. Je-li mezi vyrazy znak pro zlomek, nahradi se delenim} while (co[pozice]<>')') and (pozice')') and (pozice')') do begin case co[kde] of '(' : begin cislo:='{({'+vyraztotex(co)+'})}'; inc(kde); last:=true; end; 'a'..'z': while (co[kde]>='a') and (co[kde]<='z') and (kde='a') and (co[kde]<='z') and (kde='0') and (kde='0') and (co[kde]<='9') then begin while (co[kde]<='9') and (co[kde]>='0') and (kde='A') and (co[kdetosem]<='Z')) then co[kdetosem]:=chr(ord(co[kdetosem])-ord('A')+ord('a')); inc(kdetosem); end; end; procedure zpracuj(input:string; output:string; verbose:boolean); {zpracuje vstup} var vstup, err, ext: boolean; F,inp: text; vysl, zlomek1, zlomek2: fract; vysledek: array [1..3] of string; tmp, temp: string; begin err:=false; vstup:=false; if input<>'' then begin Assign(inp, input); {vstup ze souboru} {$I-} reset(inp); if eof(inp) {$I+} or (IOResult<>0) then begin Write(IOResult); Writeln(' - RUNTIME ERROR!!!'); writeln('Vstupni soubor '+input+' neexistuje, nebo je prazdny!'); err:=true; end; end else vstup:=true; if not err then begin repeat ext:=false; if vstup then begin writeln('Zadej vyraz:'); {vstup z klavesnice} readln(tmp); end else Readln(inp, tmp); tolower(tmp); if tmp[1]<>'#' then begin rozpoznavam:=true; pozice:=1; mezi:=''; vysledek[1]:=tmp; tmp:='('+tmp+')'; vyraz(tmp, vysl); vysledek[2]:=mezi; ans.value:=vysl; rozpoznavam:=false; vysledek[3]:=(fvypis(vysl)); if output<>'' then begin Assign(F, output); {vystup do souboru} {$I-} Append(F); {$I+} if IOResult<>0 then begin Rewrite(F); end; Writeln(F, ''); Writeln(F, 'Vyraz'); Writeln(F, 'Zadani:'); Writeln(F, '='+vysledek[1]); if not (vysledek[2]='') then begin Writeln(F, 'Mezivysledek:'); Writeln(F, '='+vysledek[2]); end; Writeln(F, 'Vysledek:'); Writeln(F, '='+vysledek[3]); Close(F); end; if verbose then begin writeln(''); writeln('Zadani:'); writeln(vysledek[1]); if not (vysledek[2]='') then begin Writeln('Mezivysledek:'); Writeln(vysledek[2]); end; Writeln('Vysledek:'); Writeln(vysledek[3]); writeln(''); end; end else if pos('exit',tmp)<=0 then begin err:=false; if pos('if ',tmp)>0 then begin rozpoznavam:=true; pozice:=pos('if ',tmp)+2; fgetst(zlomek1,tmp); while (tmp[pozice]=' ') and (pozice': if not fvetsi(zlomek1, zlomek2) then rozpoznavam:=false; '=': if not frovna(zlomek1, zlomek2) then rozpoznavam:=false; '<': if not fvetsi(zlomek2, zlomek1) then rozpoznavam:=false; else rozpoznavam:=false; end; if not rozpoznavam then err:=true; end; if (pos('goto ',tmp)>0) and not err then begin pozice:=pos('goto ',tmp)+4; while tmp[pozice]=' ' do inc(pozice); mezi:=''; while (tmp[pozice]<>' ') and (pozice0) and not err then begin pozice:=pos('set ',tmp)+3; while tmp[pozice]=' ' do inc(pozice); mezi:=''; while (tmp[pozice]<='z') and (tmp[pozice]>='a') and (pozice0 then setmemo(mezi,vysl); err:=true; end; if (pos('get ',tmp)>0) and not err then begin pozice:=pos('get ',tmp)+3; while tmp[pozice]=' ' do inc(pozice); mezi:=''; while (tmp[pozice]<='z') and (tmp[pozice]>='a') and (pozice0 then fgetmem(vysl, mezi); writeln(mezi+' = '+fvypis(vysl)); err:=true; end; end else ext:=true; until ext or ((not vstup) and (seekeof(inp))); end; end; {vlastni main} begin {inicializace promenych} init; {telo programu} klavesa:=' '; while (klavesa<>'Q') do begin {zobrazeni uvodni nabidky} clrscr; priklad:=0; tmp:=''; while length(tmp)<30 do tmp:=tmp+' '; tmp:=tmp+'Fractions'; writeln(tmp); writeln(''); writeln('Ovladani:'); tmp:=' m - Zobrazovat mezivysledky'; if vnoreni=0 then begin tmp:=tmp+' [X]'; end else tmp:=tmp+' [ ]'; writeln(tmp); tmp:=' i - Vstup ze souboru '; if vstup<>'' then begin tmp:=tmp+' [X]'; end else tmp:=tmp+' [ ]'; writeln(tmp); tmp:=' o - Vystup do souboru '; if vystup<>'' then begin tmp:=tmp+' [X]'; end else tmp:=tmp+' [ ]'; writeln(tmp); writeln(' t - Export do TeXu'); writeln(' p - Pocitat'); writeln(' q - Konec'); writeln(''); writeln('- - - - - - - - - - - - - - - - - - - - -'); writeln(''); klavesa:=readkey; if (klavesa>'Z') then klavesa:=chr(ord(klavesa)-ord('a')+ord('A')); case klavesa of {po stisku klavesy se rozhodne, co dal} 'P': begin Assign(F, vystup); {vycisteni vystupniho souboru} Rewrite(F); writeln(F, ''); Assign(F, funcerr); {vycisteni logu s chybami funkci} Rewrite(F); writeln(F, ''); rounded:=false; zpracuj(vstup,vystup,true); end; 'O': begin if vystup='' then {vystup do souboru (zap/vyp)} begin vystup:='output.txt'; end else vystup:=''; end; 'I': begin if vstup='' then {vstup do souboru (zap/vyp)} begin vstup:='input.txt'; end else vstup:=''; end; 'M': begin {nastaveni zobrazovani mezivysledku} if vnoreni>0 then vnoreni:=-1; inc(vnoreni); end; 'T': begin Assign(F, vystup); {uzavreni souboru a vypis} {$I-} Append(F); {$I+} if IOResult<>0 then begin write(IOResult); Writeln(' - RUNTIME ERROR!!!'); writeln('soubor vysledku neexistuje, nebo se pouziva!'); end else begin close(F); Assign(inp, vystup); Reset(inp); assign(F, 'Vysledky.tex'); rewrite(F); hlavicka(F); while not eof(inp) do begin readln(inp, tmp); writeln(F, totex(tmp)); end; writeln(F,'\end{document}'); close(F); close(inp); writeln('Soubor byl zapsan jako Vysledky.tex'); end; klavesa:=readkey; klavesa:=' '; end; end; end; end.