NÉV
- Provided by: manpages-hu (Version: 20010119-5)
- Report a bug
bc [ -lws ] [ fájl ... ]
Ez a kézikönyv lap a GNU bc 1.03-as verzióját írja le.
bc egy olyan nyelv, amely lebegõpontos számolást nyújt, interaktív végrehajtással. Van némi hasonlóság a C programozási nyelvvel. Egy standard matematikai könyvtár megadható parancssor paraméterként. Ha szükséges, a matematikai könyvtárat definiálni kell, mielõtt bármilyen más fájlt feldolgoznánk. A bc a megadott fájlokban levõ kódot a megadás sorrenjében dolgozza fel. Miután minden fájlt feldolgozott a bc a szabványos bemenetrõl vár további utasításokat. Minden kódot a beolvasás pillanatában végrehajt. (Ha egy fájlban olyan utasítás található, amely megállítja a feldolgozót, a bc nem fog a szabványos bemenetrõl olvasni.
A bc ezen implementációja sok bõvítéssel rendelkezik a POSIX standardhoz képest. Parancssor opcióval megadható, hogy a program ezeknél figyelmeztessen, vagy dobja vissza õket. Ez a dokumentum az ezen feldolgozó által elfogadott nyelvet írja le. A kiterjesztések természetesen jelölésre kerülnek.
A bc legalapvetõbb eleme a szám. A számok pontossága bármekkora lehet. Ez a pontosság mind az egész, mind a tört részre vonatkozik. Minden szám belsõleg decimálisan tárolódik, és a számítások is decimálisan hajtódnak végre. (Ez a verzió az osztásnál és a szorzásnál csonkít.) A számoknak két jellemzõje van, a hossz és a lépték. A hossz a szignifikáns decimális számjegyek számát jelenti, a lépték pedig a tizedspont után levõkét. Például:
.000001 számnak a hossza és a léptéke is 6. míg az 1935.000 számnak a hossza 7, a léptéke 3.
A számokat két fajta változóban lehet tárolni, egyszerû változóban vagy tömbben. Mind az egyszerû, mind a tömbváltozónak van neve. A neveknek betûvel kell kezdõdniük, ezt követhetik számok, betûk vagy aláhúzások. Minden betûnek kisbetûnek kell lennie. (A teljes alfanumerikus nevek már egy kiterjesztés. A POSIX bc-ben minden név egy kisbetûbõl áll.) A változó típusa a kontextusból tisztán kiderül, mivel minden tömb változót egy szögletes zárójel pár ([]) követ.
Négy speciális változó van, scale, ibase, obase, és last. A scale azt definiálja, hogy néhány mûvelet a tizdes pont után hány számjegyet használjon. A scale alapértelmezett értéke 0. Az ibase és az obase definiálja a bemeneti és a kimeneti számrendszer konverziót. Az alapértelmezett számrendszer mind a bemenetre, mind a kimenetre 10-es. A last (kiterjesztés) változóban az utolsó kiírt érték szerepel. Ez késõbb kerül részletezésre. Ezeknek vátlozóknak lehet értéket adni, de kifejezésben is használhatóak.
A megjegyzések a bc-ben a /* karakterekkel kezdõdnek és a */ karakterek jelzik a végét. A megjegyzések bárhol megjelenhetnek, és a bemenetben egy szóközt jelentenek. (Ez azt jelenti, hogy a megjegyzések elhatárolnak más objektumokat. Például, egy megjegyzés nem lehet egy változónév közepén.) A megjegyzésekben bármennyi újsor lehet (sor vége), a megjegyzés kezdete és vége között.
A számokat kifejezésekkel és utasításokkal lehet manipulálni. Mivel a nyelvet interaktívra készítették, az utasítások és a kifejezések rögtön végrehajtódnak. Nincs "fõ" program (main függvény). A kód olyan sorrendben hajtódik végre, ahogy a bc beolvassa. (A függvények, késõbb kerülnek leírásra, a beolvasás sorrendjében kerülnek definiálásra.)
Egy egyszerû kifejezés egy konstans. A bc a konstanst az ibase változóban megadott bemeneti számrendszer szerint decimális számmá konvertálja. (Kivétel a függvényeknél.) Az ibase érvényes értékei 2-tõl 16-ig terjednek. Ezen a határon túli értéket megadva az ibase változónak, a változó értéke 2 vagy 16 lesz. A bemenõ számok a 0-9-ig és az A-F-ig terjedõ karaktereket tartalmazhatják. (Megjegyzés: Nagybetûknek kell lenniük. A kisbetûk a változóknak vannak fenntartva.) Az egy számjegyû számoknak mindig a számjegy az értéke, az ibase változótól függetlenül (pl.: A = 10). A több számjegyû számoknál a bc az ibase-nél nagyobb számjegyeket bc - 1-re cseréli. Ezáltal, a FFF mindig a lehetó legnagyobb háromjegyû számot jelenti.
A teljes kifejezések hasonlóak a többi magas szintû nyelvben levõkhöz. Mivel csak egyetlen típusú szám van, nincs szabály a típusok keverésének kezelésére. Minden kifejezésnek van egy pontossága. Ez az eredeti számokból, az elvégzett mûveletekból és még sok egyébbõl tevõdik össze, az értéke a scale változóban található. Ezen változó legális értékei a 0-tól a C nyelvben egész számnak megadható legnagyobb értékig terjednek.
Itt következik a legalis kifejezések leírása, az "expr" a teljes kifejezésre, a "var" pedig egy egyszerû, vagy egy tömb változóra vonatkozik. Egy egyszerû változóra a
A relációs kifejezések speciális kifejezés
fajták, amelyek mindig 0-t, vagy 1-et adnak vissza, 0-át, ha a
reláció hamis, és 1-et, ha igaz. Ezek bármilyen
legális kifejezésben megjelenhetnek. (A bc POSIX
változatában, hogy a relációs kifejezések
csak if, while és for utasításokban szerepelhetnek,
illetve csak egy tesztelésük lehetséges.) A
relációs operátorok a következõk:
A boolean mûveletek is legálisak. ( A POSIX bc-ben nincsenek boolean mûveletek.) Minden boolean mûveletnek az értéke 0, vagy 1 (hamis, vagy igaz), mint a relációs mûveleteknél. A boolean mûveletek a következõek:
A kifejezések precedenciája a következõ (alacsonytól a magas felé):
|| operátor, balról asszociatív && operátor, balról asszociatív ! operátor, nem asszociatív Relációs operátorok, balról asszociatív Értékadó operátor, jobbról asszociatív + és - operátorok, balról associative *, / és % operátorok, balról asszociatív ^ operátor, jobbról asszociatív unáris - operátor, nem asszociatív ++ és -- operátorok, nem asszociatív
Ez a precedencia úgy van megválasztva, hogy a POSIX bc alá programok is korrekten fussanak. Emiatt, a relációs és logikai operátorokat az értékadó operátoroknál néha szokatlan eredmény is kijöhet. Lásd a következõ kifejezést:
A legtöbb C programozó ezt úgy értelmezi, hogy a "3 < 5" (az értéke 1) kerül az "a" változóba. A bc itt a következõt csinálja, hozzárendeli a 3-at az "a" változóhoz, majd a 3-at összehasonlítja az 5-tel. A legjobb, hogyha értékadó operátort használsz relációs, és logikai operátorokkal, akkor használsz zárójeleket.
Van néhány egyéb speciális kifejezés, amelyet még a bc nyújt. Ezek a felhasználó által definiálható függvények, és a standard függvények hívása. Ezek a következõ alakban jelennek meg: name(parameters) A függvényekhez lásd még a felhasználó által definiált függvények fejezetet. A standard függvények a következõek:
Az utasítások (mint a legtöbb algebrai nyelvnél) határozzák meg a kifejezések kiértékelésének sorrendjét. A bc-ben az utasítások akkor hajtódnak végre, amint "arra mód van". A végrehajtás akkor történik meg, mikor az interpreter új sor karakterrel találkozik, illetve, mikor egy, vagy több komplett utasítás felépül. Ezen azonnali végrehajtás miatt, az újsorok nagyon fontosak a bc-ben. Valójában, mind a pontosvesszõ, mind az újsor használható utasításelválasztóként. Egy rossz helyre rakott újsor szintaktikai hibát okoz. Mivel az újsorok utasítás elhatárolók, el lehet õket rejteni, a backslash karakter segítségével. A "\<nl>" karaktersorozattal, ahol az <nl> az újsort jelenti, az újsor csak egy szóközként jelenik meg a bc-ben. Egy utasítás lista a pontosvesszõvel, vagy újsorral elválasztott utasítások sorozata. Itt következnek a bc utasításai, és az, hogy mit csinálnak: (A szögletes zárójelbe ([]) zárt részek az utasításból elhagyhatóak.)
kifejezés1;
while (kifejezés2) {
utasítás;
kifejezés3;
}
Ezek az utasítások a tradicionális értelemben nem utasítások. Nem hajtódnak végre. Funkciójukat "fordítási" idõben fejtik ki.
A függvényekkel definiálhatunk számításokat, amelyeket csak késõbb kívánunk végrehajtani. A függvények a bc -ben mindig egy értéket számolnak, és azt visszaadják a hívónak. A függvény definíciója "dinamikus" abban az értelemben, hogy mindaddig definiálatlan, amíg a feldolgozó nem találkozik vele a bemeneten. Ez a definícó mindaddig használható, amíg egy ugyanezen névû függvény definicóval nem találkozik. Az új definíció felülírja a régit. Egy függvény definíciója a következõképpen néz ki:
define name ( parameters ) { newline
auto_list statement_list }
A függvényhívás is egy kifejezés, a következõ formában: "name(parameters)".
A paraméterek számok, vagy tömbök lehetnek (kiterjesztés). A függvény definícójában nulla, vagy több paraméter definiálható, vesszõvel elválasztva. A számok csak érték szerinti átadással, a tömbök csak cím szerinti átadással hívódnak meg. A tömböket a paraméterek között a "név[]" módon kell specifikálni. A függvényhívásnál a szám paraméterek teljes kifejezések lehetnek. A tömböknél ugyanaz a jelölés használandó, mint a definiáláskor. A nevesitett tömbök cím szerinti átadással kerülnek a függvényhez. Mivel a függvény definíciója dinamikus, a paraméterek száma és típusa csak a hívás pillanatában kerül ellenõrzésre. Ha ebben eltérés mutatkozik, egy futási-hiba váltódik ki. Futási-hiba váltódik ki akkor is, ha egy nem létezõ függvényt hívunk meg.
Az auto_list egy opcionális változó lista, amely "helyi" változókat tartalmazza. A szintaxisa: "auto név, ... ;". (A pontosvesszõ opcionális.) Minden név egy auto változó neve. Tömbök is definiálhatóak így, a szokásos módon. Ezek a változók a vermen kapnak helyet, a függvény belépése után. A változók ezután inicializálásra kerülnek nulla kezdõértékkel, és a függvény végrehajtása során használhatóak. Amikor a függvény kilép, ezeket a változókat eltávolítja a verembõl, így az eredeti értékük helyreállítódik. A paraméterek is auto változók, amelyek a függvény meghívásakor kapják meg értéküket. Az auto változók különböznek a tradícionális helyi változóktól a következõ dologban: ha A meghívja a B függvényt, B látja az A auto változóit, hacsak B-ben nincs ugyanezen néven is auto változó definiálva. Azon tény miatt, hogy az auto változók és a paraméterek egy vermen kapnak helyet, a bc kezeli a rekurzív függvényeket is.
A függvény törzse bc utasítások listája. Az utasításokat pontosvesszõk, vagy újsorok választják el. A return utasítás hatására a függvény végrehajtása véget ér, és visszatér egy értékkel. Az elsõ forma, a "return", 0-át ad vissza a hívónak, míg a második, "return ( kifejezés )", kiértékeli a kifejezést, és az eredményt adja vissza. A függvény végén, ha mást nem írunk ki, mindig van egy "return (0)", ez megkímél attól, hogy explicite ki kelljen írni a return utasítást.
A függvényeknél megváltozik az ibase változó használata is. A függvény törzsében szereplõ minden konstans, a függvény hívásakor használatos ibase alapján konvertálódik. Ha az ibase-t megváltoztatjuk egy függvényben, annak nem lesz hatása, kivéve a read standard függvényt, amely mindig az ibase aktuális értékét használja a számok konvertálásához.
Ha a bc-t a -l opcióval indítjuk, a matematikai könyvtár betöltõdik, és a pontosság 20-as lesz. A matematikai függvények azzal a pontossággal számolják ki az eredményt, amely a meghívásukkor be volt állítva. A matematikai könyvtár a következõ függvényeket definiálja:
A /bin/sh-ban a következõ utasítás visszaadja a "pi" értékét a pi környezeti változóban.
Az itt következõ példában a matematikai könyvtárban található hatvány függvény definícióját mutatjuk be. A függvény POSIX bc nyelven íródott.
scale = 20 /* Kihasználja a következó tényt: e^x = (e^(x/2))^2. Mikor az x elég kicsi, a következõ sort használjuk: e^x = 1 + x + x^2/2! + x^3/3! + ... */ define e(x) { auto a, d, e, f, i, m, v, z /* Ellenõrzi az x elõjelét. */ if (x<0) { m = 1 x = -x } /* Elófeltétel. */ z = scale; scale = 4 + z + .44*x; while (x > 1) { f += 1; x /= 2; } /* Inicializálja a változókat. */ v = 1+x a = x d = 1 for (i=2; 1; i++) { e = (a *= x) / (d *= i) if (e == 0) { if (f>0) while (f--) v = v*v; scale = z if (m) return (1/v); return (v/1); } v += e } }
A következõ kód a bc kiterjesztett szolgáltatásait használja, egy egyszerû csekkfüzet egyenleg kiszámolására. Legjobb, ha ezt a programot fájlba lementjük, hogy többször is használhassuk anélkül, hogy újra be kelljen gépelni.
scale=2 print "\nCsekkfüzet program!\n" print " Emlékeztetõ, a letétek negatív tranzakciók.\n" print " Kilépés 0 összegû tranzakció bevitelével.\n\n" print "Kezdeti egyenleg? "; bal = read() bal /= 1 print "\n" while (1) { "jelenlegi egyenleg = "; bal "tranzakció? "; trans = read() if (trans == 0) break; bal -= trans bal /= 1 } quit
A következõ függvény a faktoriális rekurzív definíciója.
define f (x) { if (x <= 1) return (1); return (f(x-1) * x); }
A bc ezen verziója a POSIX P1003.2/D11 tervezete alapján készült és a tervezethez és a tradícionális implementációhoz képest sok bõvítést és különbséget tartalmaz. Ez nincs implementálva a tradícionális dc(1)-ben. Ez a verzió egy egyszerû feldolgozó, amely csak átfordítja a programot. Egy "nem dokumentált" kapcsoló (-c) kiírja az átfordított programot a szabványos kimenetre, és nem futtatja le. Ez fõleg az értelmezõ nyomkövetésekor és a matematikai könyvtár elõkészítésekor használatos.
A különbségek legfõbb forrásai a kiterjesztések, hol egy szolgáltatás lett kiterjesztve, hogy több lehetõsége legyen, hol pedig új szolgáltatás lett létrehozva. A következó lista megmutatja a különbségeket és a kiterjesztéseket.
a = 1 b = 2
{ a = 1
b = 2 }
ez egy. A futási-hibák hatására a jelenlegi blokk végrehajtása befejezõdik. A futási-figyelmezetetés nem állítja meg a blokk végrehajtását.
A következõ határok vannak beépítve ebbe a bc -be. Néhányuk egy installálással megváltoztatható. Az aktuális értékeik megszerzéséhez használd a limits utasítást.
A legtöbb installációban a bc-nek nincs szüksége egyéb fájlokra. Míg a végrehajtható program hossza fontos, illetve a C fordító nem tudja kezelni a nagyon hosszú stringeket, a bc a standard matematikai könyvtárat a /usr/local/lib/libmath.b fájlból olvassa be. (A fájl helye rendszerenként változhat, lehet /lib/libmath.b is.)
Ha egy a parancssorban szereplõ fájl nem nyitható meg, a bc üzen, hogy a fájl nem elérhetõ, és kilép. Ugyanígy, a fordítási és a futási idejû diagnosztika is önmagyarázó.
A hibakezelés még nem túl jó.
Philip A. Nelson phil@cs.wwu.edu
A szerzõ szeretné megköszönni Setve Sommars-nak (Steve.Sommars@att.com), hogy oly nagy mértékben segített az implementáció tesztelésében. Sok nagyon jó tanácsot adott. Segítségével egy sokkal jobb terméket sikerült létrehozni.
Csehi András <acsehi@flexum.hu>