19.

Maija uzzina par failiem

Jau ne vienreiz vien Maija bija pārmetusi Pēcim, ka viņas programmas iegūtos rezultātus tikai parāda uz ekrāna, bet viņa tos labprāt arī izdrukātu, lai varētu saglabāt, parādīt mājās. Taču to Pēcis viņai nezin kāpēc nemācot. Pēcis visu laiku bija atrunājies, 172ka vēl par agru un vispār visērtāk šo mākslu ir apgūt visu uzreiz — iemācīties par visiem failiem, kādi vien var būt. Tāpēc arī Maija nopriecājās, izdzirdusi:

— Tad nu tā, šodien sākam iedziļināties zinātnē par failiem jeb, kā es to saucu, failoloģijā.

— Beidzot! Sen jau bija laiks.

— Protams, varēja arī agrāk, bet, manuprāt, pirms ķeramies pie failiem, tev vajadzēja pierast pie programmēšanas, pie mašīnas. Tagad tev tie faili var likties pat ļoti vienkārši, taču tikai tāpēc, ka tava galviņa jau ir dabūjusi just, kas ir formālā domāšana — tāda domāšana, kāda ir vajadzīga programmistam. Bet darboties ar failiem ir jāprot. Mēdz būt programmas, turklāt ļoti svarīgas, kuras strādā gandrīz tikai ar failiem.

— Labi, beidz kult tukšus salmus! Runā konkrētāk! Skolotājs!

— Es jau tev kādreiz teicu, ka failu var saprast kā vietu uz ārējā informācijas nesēja — diska vai lentes. Un šai vietai ir apzīmējums, pēc kura to un tur uzrakstītos datus vajadzīgajā brīdī var atrast.

Fails=grāmata!

FAILA ATVĒRŠANAKatrs fails var būt vai nu atvērts, vai aizvērts. Protams, neviens neko uz ārējā informācijas nesēja ne aizver, ne atver. Tas tikai ir tāds izteiksmes veids. Atvērt failu nozīmē atļaut ar to kaut ko darīt — datus tajā rakstīt vai nolasīt. Bet aizvērt failu nozīmē uz laiku par to aizmirst. Pie tā netiek klāt, tā it kā nav, un, pirms šis fails netiek no jauna atvērts, izdarīt ar to nevar neko.

Kad OPEN atver failu, tiekam pie datiem
Kad OPEN atver failu, tiekam pie datiem

173— Un kā tad to atver?

— Lūk, piemērs faila atvēršanai.

OPEN «DK1:FAILS» FOR INPUT AS FILE 3

Kā redzi, tas ir pats garākais operators beisikā. Pārtulkosim to.

OPENDK1:FAILSFOR INPUTASFILE 3Beisikā
Atvērtfailu ar šādu aprakstuievadeikāfailu Nr. 3Latviski

— Nav gluži skaidrs, kāpēc te parādās kaut kāds «Nr. 3».

Faila loģiskais numurs

FAILA LOĢISKAIS NUMURS— Es to saprotu šādi. Šo operatoru apstrādā interpretators, kurš arī ir programma. Tam atmiņā ir paredzēta vieta, kur glabāt informāciju par atvērtajiem failiem, varētu teikt — masīvs ar failu aprakstiem, kuri nav nekas cits kā simbolu virknes. Bet masīva elementi ir jānumurē. Un šis numurs tad arī ir faila numurs! To sauc arī par faila loģisko numuru. Failu ar numuru 3 var atvērt uzreiz — pirms tam nebūt nav jāatver faili Nr. 1 un Nr. 2. Atverot failu, interpretators pārbauda, vai tāds fails uz norādītās iekārtas vispār eksistē un, ja eksistē, — vai tas jau nav atvērts. Ja izdodas atklāt kādu nepareizību, tas tiek ziņots.

Vai atceries, ko nozīmē faila apraksts, piemēram, «DK1:FAILS»?

— Jā, es atceros gan. DK1 norāda iekārtu un tās numuru, bet FAILS ir faila apzīmējums.

— Operatorā OPEN faila apraksts nav obligāti jāuzdod kā simboliska konstante. To var uzdot arī kā simboliskā mainīgā vērtību. Tas nozīmē, ka faila aprakstu var izveidot, saķēdējot atsevišķus simbolus. Paskaties, piemēram, šādu programmas gabaliņu.

100 PRINT «IEVADIET DISKA NUMURU»
110 INPUT N¤
120 PRINT «IEVADIET FAILA APZIHMEHJUMU»
130 INPUT F¤
140 OPEN «DK»+N¤+«:»+F¤ FOR INPUT AS FILE 1

Sākumā te ievadām diska numuru. Kā simbolu! Tad ievadām faila apzīmējumu.

— Kā simbolus!

— Dabiski. Un pēc tam saķēdējam pilnu faila aprakstu.

Ilustrācija

Tagad par vārdu INPUT operatorā OPEN. Tā vietā var būt arī OUTPUT.

— «Autput»... ko gan tas varētu nozīmēt? Varbūt «izvade». «Ievade» jau bija.

— Jā, un šajā gadījumā fails tiek atvērts izvadei. Vienlaikus ievadei un izvadei viens un tas pats fails nevar būt atvērts. Interpretators to neļauj. Lai vienā un tajā pašā failā vispirms ierakstītu un tad nolasītu, pirmkārt, fails jāatver ievadei, otrkārt, tajā jāieraksta, treškārt, fails jāaizver, ceturtkārt, fails jāatver izvadei un, visbeidzot piektkārt, jānolasa tas, kas ir vajadzīgs.

— Tik sarežģīti!

— Redzi, kā tas ir. Lasīt no faila var tikai pēc kārtas. Un rakstīt failā arī. Kad no faila lasām, tad interpretatoram ir zināms, cik daudz esam nolasījuši — līdz kurai vietai failā. Un, kad failā rakstām, arī tad katrreiz ir zināms, kur mēs atrodamies. Bet, ja kādā failā gribēsim gan rakstīt, gan arī lasīt, tad var iznākt, ka vienā un tajā pašā brīdī atrodamies divās vietās. Bet to mēs nevaram. Iedomājies, ka lasām failu no magnetofona lentes. Mēs taču varēsim lasīt tikai līdz tai vietai, līdz kurai lente ir aiztīta.

— Skaidrs, ka var sākt lasīt no jauna, ja failu aizver un atkal atver. Bet tu jau netaisies stāstīt, kā failu aizver.

Darbības ar failiem

Ilustrācija

— Taisos gan. To aizver ar operatoru CLOSE.

— Kā tad! «Klouz» taču nozīmē «aizvērt»!

— Šis operators ir daudz vienkāršāks par operatoru OPEN. Pēc tā ir tikai jāuzraksta tā faila loģiskais numurs, kuru tu gribi aizvērt:

CLOSE 3

Bet, ja numura pēc CLOSE nav, tad tiks aizvērti 175visi faili, kas šajā brīdī bija atvērti. Par aizvēršanu būtu viss.

— Lieliski. Vēl viens ķieģelītis Maijas Saprātiņas zināšanu pilī. Vai būdiņā.

— Vēl ir viens svarīgs, bet ļoti bīstams operators.

KILL «DK1:FAILS»

— «Kil»... Nezinu.

— «Nogalināt»! Operators nevienu jau nu nenogalina, bet tikai nodzēš failu. Kad šāds operators būs izpildīts, diskā Nr. 1 faila ar apzīmējumu FAILS vairs nebūs. Kā redzi, dzēšamais fails ir jānorāda pēc operatora KILL. Vai nu kā simboliskā konstante, vai arī kā simboliskais mainīgais, kura vērtība ir nodzēšamā faila apraksts.

Ilustrācija

— Nodzēš... Tik vienkārši — ņem un nodzēš. Bet ja nu pēc tam ievajagas?

— Ievajagas vai neievajagas, taču nekādi spēki šo failu no nebūtības neizsauks. Tā, starp citu, ir liela magnētisko disku priekšrocība atšķirībā no papīra, ka informāciju no tiem var viegli nodzēst. Bet, ja nodzēsīsi ne to, ko vajag, vaino pati sevi.

— Brrr. Auksti sametās.

Ierakstīšana failā

— Vēl jāparunā par to, kā failā ieraksta un kā no tā nolasa. To dara ar tiem pašiem vecajiem labajiem operatoriem INPUT un PRINT, kurus tu jau pazīsti. Tie ir tikai papildināti. Skaties, kā es rakstu.

PRINT # 3, A, B

Pēc vārda PRINT ir numura zīme «#», faila numurs, komats un mainīgo saraksts. Līdz ar to mainīgie tiks izvadīti failā Nr. 3. Līdzīgi dara ar operatoru INPUT.

INPUT # 4, B¤

176Šajā piemērā mainīgā B¤ vērtība tiks ievadīta no faila, kurš ir atvērts ievadei kā fails ar loģisko numuru 4.

Ilustrācija

— Vai par izvadi un ievadi tas ir viss?

— Nē, nav viss. Vēl tev ir jāzina, ka operatoros PRINT un INPUT pēc numura zīmes var būt ne tikai skaitliskā konstante, bet arī skaitliskais mainīgais. Ja šīs skaitliskās konstantes vai arī skaitliskā mainīgā vērtība ir nulle, tad ievade un izvade notiek pa vecam — uz displeja. It kā uz displeja būtu fails ar loģisko numuru 0. Tagad gan ir viss.

— Tā kā būtu sapratusi. Tas loģiskais faila numurs gan ir mazliet neskaidrāks. Bet viss gan nevar būt, jo tu neko neesi stāstījis par drukāšanu.

— Uz drukas iekārtas jāatver izvades fails, kura apraksts sastāv tikai no iekārtas koda — līdzīgi, kā tas bija, izdrukājot programmu.

OPEN «LP:» FOR OUTPUT AS FILE 4

Protams, ja šim failam esi izvēlējusies ceturto loģisko numuru.

Par drukāšanu būtu viss. Arī par failiem. Paklausies, Maija, tagad var teikt, ka tu esi apguvusi visu būtisko programmēšanā — un visu mazāk būtisko arī. Palikušas vairs tikai dažas detaļas. Tagad papētīsim šādus tādus programmas piemērus un — pie darba.

— Tieši tā. Programmēt, programmēt un vēlreiz programmēt! Tāda lai ir mūsu devīze!

Skaitļotājs apsveic svētkos

— Vispirms papētīsim apsveikuma programmu. Kas tai ir jādara un ko tā dara? Tai ir skaisti jāizdrukā apsveikums dzimšanas dienā vai kādos citos svētkos. Skaisti — tas šajā gadījumā nozīmē, ka apsveikuma tekstam visapkārt ir izdrukāts rāmītis, kuru veido kaut kāds simbols. Es to saucu par dekoratīvo simbolu.

Apsveikuma sākumā ir uzruna, kas sastāv no vārda «Dārgais», «Cienījamais» u. tml. un no paša apsveicamā cilvēka vārda. Pie tam apsveicamā vārds ir vokatīvā, kaut arī ievadīts tiek nominatīvā. Tātad vajag noprogrammēt vokatīva veidošanu. Programma, vokatīvu meklēdama, pie reizes arī noskaidro, vai 177tas ir vīrieša vai sievietes vārds. Vēl programma lietotājam pavaicā, vai apsveicamo uzrunāt ar Tu vai Jūs un vai apsveicamais ir skolēns vai pieaugušais. Varbūt sāksim pētīt pašu programmu, tad arī redzēsi, kas tur notiek.

10 REM PROGRAMMA APSVEIKUMU DRUKAHSHANAI
20 R=16 \ REM RINDU SKAITS APSVEIKUMA'
30 N=30 \ REM ZIHMJU SKAITS VIENA' RINDA'
40 S¤="*" \ REM DEKORATIHVAIS SIMBOLS
50 S1¤="DZIMSANAS DIENA." \ REM SAKARA' AR KO APSVEIC
60 DIM L1¤(2,2),T¤(10)
70 L1¤(1,1)="DARGAIS" \ L1¤(1,2)="DARGA"
80 L1¤(2,1)="CIENIJAMAIS" \ L1¤(2,2)="CIENIJAMA"
90 DIM L2¤(2) \ L2¤(1)="TEVI" \ L2¤(2)="JUS"
100 DIM L3¤(2) \ L3¤(1)="TEV" \ L3¤(2)="JUMS"
105 \
110 DATA " ","APSVEICU "," ","VELU ","DAUDZ PRIEKA,"
120 DATA "LAIMES, SKAISTUMA","PAVASARA UN"," "," "
130 DATA "        PECIS"
135 \
140 PRINT "PROGRAMMA IZDRUKA' APSVEIKUMUS"
150 PRINT "IZVADE UZ EKRAHNA   - 1"
160 PRINT "       UZ PAPIHRA   - 2" \ INPUT F
170 F=F-1 \ REM TAGAD F IR FAILA NUMURS
180 IF F=0 THEN 200 \ REM IZVADE UZ EKRAHNA
190 OPEN "LP:" FOR OUTPUT AS FILE 1 \ REM DRUKAHSHANA
195 \
200 PRINT "UZRUNAHT AR    TU - 1"
210 PRINT "         AR  JUHS - 2"
220 INPUT T \ PRINT
230 PRINT " DAHRGAIS      - 1"
240 PRINT " CIENIHJAMAIS  - 2"
250 INPUT C \ PRINT
260 PRINT "SKOLEHNS      - 1"
270 PRINT "PIEAUGUSHAIS  - 2"
280 INPUT S \ PRINT
290 PRINT "KA' VINJU SAUC"; \ INPUT V¤
295 \
300 L=LEN(V¤) \ REM VAHRDA GARUMS
310 P¤=SEG¤(V¤,L,L) \ REM ATROD PEHDEHJO BURTU
320 REM SAHKAS VOKATIHVA VEIDOSHANA
325 \
330 IF P¤<>"S" THEN 370
340 V1¤=SEG¤(V¤,1,L-1) \ REM UZRUNA, JA GALOTNE -S
350 D=1 \ REM TAS IR VIHRIESHA VAHRDS
360 GO TO 470
365 \
370 IF P¤<>"A" THEN 400
371 IF SEG¤(V¤,L-2,L-1)<>"IN" THEN 380 \ REM GALOTNE -INA?
372 V1¤=SEG¤(V¤,1,L-1) \ D=2 \ GO TO 470
380 V1¤=V¤ \ REM VOKATIHVS    \ D=2 \ REM SIEVIESHU DZIMTE
390 GO TO 470
395 \
400 IF P¤<>"E" THEN 430
410 IF SEG¤(V¤,L-2,L-1)<>"IT" THEN 380 \ REM GALOTNE -IHTE?
420 V1¤=SEG¤(V¤,1,L-1) \ D=2 \ GO TO 470
425 \
430 IF P¤<>"O" THEN 450
440 V1¤=V¤ \ D=1 \ GO TO 470
450 PRINT "IEVADS NEPAREIZS" \ GO TO 290
455 \
460 REM SAHKAS TEKSTA SAGATAVOSHANA =======================
465 \
470 RESTORE  \ FOR J=1 TO 10 \ READ T¤(J) \ NEXT J
480 T¤(1)=L1¤(C,D)+" "+V1¤+"!" \ REM UZRUNA
490 T¤(2)=T¤(2)+L2¤(T) \ REM APSVEICU TEVI(JUHS)
500 T¤(3)=S1¤ \ REM SAKARA' AR KO APSVEIC
510 T¤(4)=T¤(4)+L3¤(T) \ REM VEHLU TEV (JUMS)
520 IF S=1 THEN 540
530 T¤(7)="UN LABU VESELIBU." \ GO TO 560
540 T¤(7)="UN LABAS SEKMES SKOLA."
545 \
550 REM SAHKAS IZVADE ====================================
555 \
560 GOSUB 1000 \ REM DEKORATIHVA' RAHMJA PIRMA' RINDA
570 R1=INT((R-10)/2) \ REM ATROD RINDU SKAITU BEZ TEKSTA
580 GOSUB 2000 \ REM UN TIKPAT DAUDZ ARI' IZDRUKA'
585 \
590 REM TAGAD TEKSTS RAHMI'
600 FOR J=1 TO 10 \ REM CIKLS TEKSTA IZDRUKAHSHANAI
610 N1=INT((N-2-LEN(T¤(J)))/2) \ REM ATSTARPJU SKAITS
620 PRINT #F,TAB(5);S¤;TAB(N1+6);T¤(J);TAB(N+4);S¤
630 NEXT J
635 \
640 GOSUB 2000 \ REM IZDRUKA' RINDAS BEZ TEKSTA
650 GOSUB 1000 \ REM UN PEHDEHJO RINDU
660 CLOSE  \ PRINT  \ PRINT  \ REM AIZVER VISUS FAILUS
665 \
670 PRINT "IZDRUKAHT VISU, KA' IR         - 1"
680 PRINT "IZMAINIHT APSVEICAMA' VAHRDU   - 2"
690 PRINT "SAGATAVOT VISU NO JAUNA        - 3"
700 PRINT "BEIGT DARBU                    - 4"
710 INPUT I1
715 \
720 F=0 \ ON I1 GO TO 740,290,150,730
725 \
730 STOP
740 F=1
750 OPEN "LP:" FOR OUTPUT AS FILE 1
760 GO TO 560
770 END
775 \
1000 REM IZDRUKA' RINDU AR DEKORATIHVAJIEM SIMBOLIEM
1010 PRINT #F,TAB(5); \ FOR I=1 TO N \ PRINT #F,S¤; \ NEXT I
1020 PRINT #F \ RETURN
1025 \
2000 REM IZDRUKA' DEKORATIHVO RAHMI BEZ TEKSTA
2010 FOR I=1 TO R1
2020 PRINT #F,TAB(5);S¤;TAB(N+4);S¤
2030 NEXT I
2040 RETURN
3000 END

Vai, gandrīz aizmirsu! Man ir arī izdrukātā apsveikuma paraugs.

******************************
*                            *
*                            *
*                            *
*      CIENĪJAMĀ MAIJA!      *
*       APSVEICU TEVI        *
*      DZIMŠANAS DIENĀ.      *
*          VĒLU TEV          *
*       DAUDZ PRIEKA,        *
*     LAIMES, SKAISTUMA      *
*   UN LABAS SEKMES SKOLĀ.   *
*                            *
*                            *
*               PĒCIS        *
*                            *
*                            *
*                            *
******************************
Ilustrācija

Kā redzi, mašīna izdrukā bez garumzīmēm, un «š» vietā ir «s», pēc tam es ar lodīšu pildspalvu piezīmēju klāt visu vajadzīgo.

— Vienreizēji! Kāpēc tu man dzimšanas dienā neatsūtīji tādu apsveikumu?

— Kā es to varēju izdarīt! Šo tikai vakar izdrukāju. Bet uz nākamo dzimšanas dienu pati varēsi piedrukāt vai simtu.

— Tā nebūs interesanti.

— Bet nu par programmu. Pašā sākumā piešķiru vērtību diviem mainīgajiem R un N. Patiesībā šie mainīgie nosaka dekoratīvā rāmīša garumu un platumu. Pēc tam tiek piešķirta vērtība simboliskajam mainīgajam S¤ — zvaigznīte, kura būs rāmīti veidojošais simbols. Tālāk, par simboliskā mainīgā S1¤ vērtību tiek pieņemti svētki, kuros apsveic.

— Un šī vērtība būs jāmaina, ja gribēšu apsveikt nevis dzimšanas dienā, bet gan ar skolas beigšanu.

Par divdimensiju masīviem

— Pilnīgi pareizi. Nākamajā rindā sākas šis tas jauns. Tur tiek aprakstīts divdimensiju simboliskais masīvs L1¤. Šādi gan skaitliskie, gan simboliskie divdimensiju masīvi parādās tad, ja mainīgo vērtībām ir divi numuri, piemēram, atzīmei liecībā — priekšmeta un ceturkšņa numurs. Taču priekšmetiem tad jābūt iepriekš sanumurētiem. Cits piemērs — daiļslidošanas sacensību protokolā ierakstītās atzīmes ar daiļslidotāja numuru un tiesneša numuru. Atkal gan daiļslidotājiem, gan tiesnešiem jābūt saviem kārtas numuriem. Parasti ar divdimensiju masīviem programmā apraksta kaut kādus sarakstus, kuros ir rindas un kolonnas. Šāds saraksts var būt gan liecība, gan arī sacensību protokols. Iedomājies, piemēram, tādu sarakstu: rindās uzrakstīti zooloģiskā dārza zvēri, bet kolonnās — cik katram dienā ir jāapēd. Te ir tāds mazs fragments:

Ilustrācija

Ja gribēsi sastādīt programmu, kas apstrādā šādu informāciju, būs jānodibina divdimensiju masīvs.

— Neticu, ka dzīvnieki ar tavām normām var izdzīvot; un vispār — kas gan te būtu ko rēķināt!

— Arī es tam neticu, jo man nav ne mazākās nojausmas, cik tādai vārnai vajag. Un tiešām — kas te 181ko rēķināt, ja mums ir tikai trīs dzīvnieki! Bet ja būtu trīs simti? Tad varētu izrēķināt, cik daudz produktu tiks patērēts, cik tas izmaksās un varbūt vēl kaut ko. Līdzīgu sarakstu varētu sastādīt rūpnīcai, kur vajag tik un tik naglu, tik un tik uzgriežņu, tik un tik integrālshēmu, tik un tik tādu un šitādu vadu, lai iztaisītu vienu tādu, vienu šitādu un vēl vienu nezin kādu radioaparātu.

— Bet kādēļ tev tieši šajā programmā ievajadzējies divdimensiju masīvs?

— Manā programmā tas ir ārkārtīgi vienkāršs. Vispirms sanumurēju cieņas pakāpes: 1 — dārgais; 2 — cienījamais. Pēc tam dzimtes: 1 — vīriešu dzimte; 2 — sieviešu dzimte. Pēc tam izveidoju divdimensiju masīvu:

Cieņas pakāpe
12
Dzimte1. Vīriešudārgaiscienījamais
2. Sieviešudārgācienījamā

— Tālāk tu acīmredzot atkal nodibini simboliskos masīvus un to elementiem piešķir tās vērtības, kuras, apsveikumu drukājot, būs vajadzīgas.

Apsveikt ir jāprot

— Jā gan. Un pie tam abos masīvos L2¤ un L3¤ pirmie elementi atbilst gadījumam, kur apsveicamo uzrunā ar «Tu», un otrie — kur ar «Jūs». Varētu teikt, visus iespējamos uzrunāšanas veidus esmu sanumurējis šādi: 1 — «Tu»; 2 — «Jūs».

— Nesaprotu, kāpēc tu tik daudz par to runā. Kādas vērtības gribēji, tādas piešķīri.

— Tev taisnība. Bet es gribu uzsvērt, ka man ir jāgrib piešķirt šīs vērtības, jāizdomā, kādas tās būs un kā programma tās atradīs.

— Labi. Tālāk ir DATA operatori, kuros, spriežot pēc visa, tu glabā pašu apsveikuma tekstu.

— Es teiktu, teksta sagatavi. Pēc tam kad visas simbolu virknes no DATA operatoriem būs pārvērstas par mainīgo vērtībām — skaties rindu 60 —, tās vēl tiks papildinātas, un tas arī būs īstais teksts.

182— Interesanti, kāpēc rindā 70 pieminēta izvade uz ekrāna, ja tu taisies drukāt?

Ilustrācija

— Tā vajadzīga pārbaudei. Nedomā, ka šādu programmu varu uztaisīt uzreiz un bez kļūdām. To vajadzēja lāgot, un lāgošanas laikā pārbaudāmos fragmentus labāk ir izvadīt uz ekrāna, lai lieki netērētu papīru. Tālāk. Savu vēlmi par to, kur izvadīt apsveikumu, tu esi ievadījusi: to izsaka mainīgā F vērtība. No tās tūdaļ atņemam vienu. Kādēļ? Lai iznāktu faila numurs. Numurs failam, kuru izvadām uz ekrāna, vienmēr ir nulle, bet drukas failam varam dot tādu numuru, kādu gribam. Šoreiz vislabāk ir gribēt vieninieku.

— Bet tu jau varēji uzreiz pieprasīt, lai ievada nulli vai vienu. Nebūtu jāatņem.

— Varēju. Nedarīju tāpēc, ka tālāk programmā tiek prasītas vērtības 1 vai 2 un es gribēju, lai tādas tās tiktu prasītas visur.

— Liela muiža! Dažādās vietās būtu dažāda ievade, toties pašam mazāk jāprogrammē.

— Par sevi šeit nav jādomā. Jādomā par lietotāju.

— Eh, labāk pasaki, ko sazarošanās operators dara šeit, rindā 180!

— Te mēs izrēķināto faila numuru salīdzinām ar nulli. Ja tas ir nulle, tad ejam tālāk, jo tas nozīmē, ka lietotājs izvadu grib redzēt uz ekrāna. Bet, ja tas nav nulle, tad rindā 190 atveram drukas iekārtu — kā failu ar numuru 1.

— Tālākais ir skaidrs. Lietotājam tiek jautāts, ko viņam vajag.

— Jā, kaut kas interesantāks sākas, kad ievada apsveicamā vārdu, atrod tā garumu un pēdējo burtu rindās 300 un 310.

Cilvēkam vienkārši, mašīnai sarežģīti

— Ahā! Šeit sākas vokatīva veidošana, kā vēstī piezīme rindā 320.

— Vokatīva veidošanas algoritms ir šāds. Ja vārds beidzas ar galotni -s, tad to atmet; ja beidzas ar -a, tad nedara neko; ja beidzas ar -ina, tad -a atmet. Pēdējais noteikums attiecas gan uz tādiem vārdiem kā «Katrīna», «Janīna», gan arī uz tādiem kā «Aijiņa», 183«Maijiņa». Ja vārda galotne ir -e, tad vokatīvs sakrīt ar nominatīvu, izņemot gadījumu, kur vārds beidzas ar -īte, piemēram, «Skaidrīte», «Mudīte», «Sarmīte». Tad beigu -e ir jāatmet. Programmā nav paredzēta vokatīva veidošana tādiem vārdiem kā «Kristīne», «Hermīne» u. tml., kas beidzas ar -īne. Ja grib, lai vokatīvs būtu «Kristīn», tad jāievada nevis «Kristīne», bet «Kristīna».

— Tā nu tāda izlāpīšanās vien ir.

— Protams, varēja noprogrammēt pēdējā burta atmešanu arī šādiem vārdiem. Bet galu galā nemaz tik šausmīgi neizklausās arī uzruna «Cienījamā Kristīne».

Skaidrības labad uzzīmēšu vokatīva veidošanas algoritma blokshēmu.

Ilustrācija

184Programmā reizē ar vokatīva veidošanu tiek aprēķināta mainīgā D vērtība: D=1, ja vārds beidzas ar -s vai -o, un tātad tas ir vīrieša vārds; D=2, ja vārds beidzas ar -a vai -e, tātad — sievietes vārds. Bet atšķirt vīriešu un sieviešu vārdus nebūt nav tik vienkārši, jo ir arī izņēmumi: vīrieša vārds var beigties ar -a vai -e, piemēram, krievu «Savva», «Koļa», «Vaņa» vai vācu «Ūve» utt.

— Ahā! Šādā gadījumā programma drukās «Cienījamā Koļa!», vai ne?

— Tā būs. Bet arī šajā gadījumā programmu var «apmānīt». Ievadīt nevis «Koļa», bet «Koļas», un tad liekais -s tiks atmests. Sliktāk ir ar tiem sieviešu vārdiem, kurus algoritmā ielikt nepratu. Tā, piemēram, vārdiem «Ina», «Tīna», «Zina» tiks atmests beigu -a, turpretī «Emīlijai», «Stefānijai» — netiks atmests. Nelaime ir tāda, ka nav precīza algoritma, kuriem vārdiem galotne jāatmet un kuriem — ne.

Vispār pati svarīgākā vieta programmā ir galotnes atmešana, bet to jau tu labi atceries no lietvārdu locīšanas programmas.

Sāk veidoties apsveikuma teksts

— Drusku atceros gan. Bet par to pietiks. Pārejam pie teksta sagatavošanas, kura sākas ar rindu 470. Un uzreiz tiek nolasīti DATA operatori masīvā T¤. Bet nākamajā rindā...

— Nākamajā rindā noskaidrojas, kāpēc visur prasīju ievadīt viens vai divi.

— Ahā! Mainīgais C! Tā vērtība bija... paskatīsimies... viens, ja jāuzrunā «dārgais», un divi, ja — «cienījamais». Mainīgais D tika aprēķināts tur, kur veidojām vokatīvu.

— Bet svarīgi ir tas, ka šo mainīgo vērtības tiek...

— ...tiek izmantotas, lai iegūtu vajadzīgo divdimensiju simboliskā masīva L1¤ elementu: «dārgo» vai «cienījamo» — sieviešu vai vīriešu dzimtē.

— Tu man nemaz neļauj palepoties ar labi izdomātu vietu. Tev vajadzēja mierīgi noklausīties un beigās izsaukties: «Vai, Pēci, cik tu labi izdomāji ar tiem mainīgajiem C un D!»

185— Vai, Pēci, cik tu labi izdomāji to, ka pie atrastās masīva elementa vērtības var pieķēdēt atstarpi! Un pēc tam jau agrāk atrasto vokatīvu! Un vēl izsaukuma zīmi! Tagad tiks izdrukāts nevis «CIENIJAMAISPECI», bet gan smuki — «CIENIJAMAIS PECI!».

— To atstarpi varēja arī nelikt, bet tad masīvā L1¤ būtu jāglabā nevis vienkārši vārds «CIENIJAMAIS», bet gan «CIENIJAMAIS » ar atstarpi beigās.

Ilustrācija

— Es jau arī saku, ka tas ir lieliski.

— Vari smieties, bet es teikšu, ka programmēt jau tāpēc vien ir interesanti, ka kaut vai sīkumu, bet var labi izdomāt.

— Un tas sniedz «radošu gandarījumu».

— Vienam sniedz radošu gandarījumu strādāt, otram — smieties.

— Es jau nemaz nesmejos! Man tikai gribas tevi paķircināt.

— Labāk paskaties, kā tiek veidots masīva T¤ trešais un ceturtais elements. Šeit saķēdēju divas simbolu virknes un atstarpi starp tām nelieku, jo tā man jau bija DATA operatoros pēc vārdiem «apsveicu» un «vēlu».

— Un ko tu dari rindā 520 un tālāk? Atkal netaisnīga izturēšanās pret skolēniem! Pieaugušajiem vēli labu veselību, bet skolēniem — «labas sekmes skolā». Labas sekmes skolā, bērniņ! Kam tev laba veselība, ka tikai būtu labas sekmes.

— Neticu gan, ka kāds labu sekmju dēļ būtu zaudējis veselību.

— Nabaga Pēci! Ja tu nebūtu tik smieklīgs, tad tavu nopietnību nemaz nevarētu izturēt!

— Nesaprotu, vai turpināsim vai atliksim uz citu reizi.

Pavisam vienkārša apakšprogramma

Ilustrācija

— Viss, beidzu. Turpinām. Skatāmies rindu 550. Sākas izvade. Aizsūta uz apakšprogrammu, kura sākas ar rindu 1000... Kas tā par apakšprogrammu?

— Šeit būs divas apakšprogrammas. Pirmā izdrukā rindu ar dekoratīvajiem simboliem. Tur ir cikls, kas pa vienam simbolam drukā tik daudz reižu, cik vajag.

186— Jā, cikls ir. Bet kas tas par PRINT pirms tā?

— Ak jā! Par funkciju TAB tu vēl neko nezini. Šo funkciju var izsaukt tikai operatorā PRINT, un tā norāda rindas pozīciju, no kuras jāturpina drukāt. Labāk to paskaidrošu ar piemēriem.

PRINT «SVEIKA»; TAB(40); «MAIJA»

Vārdu SVEIKA šāds operators uz ekrāna izvadīs, sākot ar pirmo rindas pozīciju, bet vārdu MAIJA, sākot ar četrdesmito.

PRINT TAB(40); «SVEIKA»; «MAIJA»

Tekstu SVEIKAMAIJA šis operators izvadīs, sākot ar četrdesmito pozīciju.

Ilustrācija

Funkcijas argumentā nebūt nav jāuzrāda tieši skaitliska konstante, tur var būt arī jebkura aritmētiska izteiksme. Un tagad pasaki — ko dara šāds operators?

PRINT TAB(5);

— Nezinu. Man liekas, ka tas... nedara neko.

— Tev būtu taisnība, ja tam beigās nebūtu semikola. Bet, tā kā tas ir, tad nākamais PRINT operators izvadi sāks ar sesto pozīciju. Līdzīgu operatoru es rakstu rindā 110 — tādējādi pirmās piecas pozīcijas man ir tukšas un drukāšana nesākas no pašas papīra malas.

— Tad jau citas rindas arī būs jāsāk drukāt ar sesto pozīciju.

— Tā arī darīšu.

— Bet ko nozīmē šis te vientuļais PRINT operators pēc cikla?

— Lai ar vienu simbolu varētu piedrukāt veselu rindu, ciklā esošajam PRINT operatoram beigās ir semikols. Semikols savu darīs arī tad, kad cikls būs beidzies un nākamais izvads turpinās dekoratīvo rindu. Pārlēkšanu uz nākamo rindu nodrošina PRINT 187operators pēc cikla. Tas it kā pārtrauc semikola darbību.

— Un, atgriezdamies no tās apakšprogrammas, uzreiz atduramies pret kaut kādu sarežģītu aprēķinu.

— Šeit tiek aprēķināts, cik tukšu rindu ir jāatstāj starp rāmīša augšējo malu, kuru tikko izdrukāja, un apsveikuma tekstu. Tāpat arī zem teksta būs tukšas rindas. To skaitu es aprēķinu šādi. Mainīgā R vērtība — kopējais rindu skaits — man ir zināma: 15. No tā atņem 10 — rindu skaitu apsveikuma tekstā. Starpība ir visu tukšo rindu skaits. Bet cik no tām atstāt augšā? Vislabāk — pusi. Ja dalījums (R-10)/2 nav vesels skaitlis, tad no tā paņem veselo daļu. Man gribas, lai mainīgā R1 vērtība būtu vesels skaitlis, jo apakšprogrammā, kura sākas ar rindu 2000, es to izmantoju par cikla robežu.

Vēl viena apakšprogramma

Ilustrācija

— Kur ir tā tava otrā apakšprogramma? Ahā! Šeit atkal tā funkcija TAB. Bet operators PRINT šoreiz ir daudz sarežģītāks. Kaut gan nē... Saprast var. Vispirms paej piecas pozīcijas uz priekšu, tad izdrukā dekoratīvo simbolu, tad uzreiz aizlec uz rindas beigām, kur izdrukā vēl vienu dekoratīvo simbolu. Un tik vien!

— Ko tu vēl gribēji? Nekas vairāk nav vajadzīgs. Kad izvadītas tukšās rindas, var sākt drukāt tekstu. To dara cikls rindās 600—630. Vispirms tiek aprēķināts, cik tukšo vietu būs starp dekoratīvo rāmīti un pirmo teksta simbolu. Tas jādara pirms katras rindas izdrukāšanas, jo rindu garumi apsveikuma tekstā ir dažādi.

— Paskatīsimies, kā tas notiek. No visa rindas garuma atņem teksta garumu, iznākumu izdala ar divi un atrod veselo daļu. Jā, gandrīz tāpat kā toreiz, kad noteica tukšo rindu skaitu augšā un apakšā.

— Taču ir arī neliela atšķirība. Toreiz rāmīša augšējā un apakšējā mala pie rindām pieskaitīta netika: R bija rindu skaits starp rāmīša rindām, bet N ir simbolu skaits vienā rindā, ieskaitot dekoratīvo simbolu rāmīša kreisajā un labajā malā.

— Manuprāt, tas ir mazsvarīgi. Tik un tā es izraudzīšos tādus R un N, lai apsveikums izskatītos labi.

188Bet atgriežamies pie teksta drukāšanas! Mani interesē pats izvades operators rindā 620. Vispirms tas drukāšanas vietu pārbīda par piecām pozīcijām, sestajā izdrukā dekoratīvo simbolu, kā tas jau bija, tad atkal pārlec uz vietu, kur jādrukā simboli... To tu esi labi izdomājis!

— Vispār... vispār to es pats neizdomāju, man to izstāstīja Algoritms.

— Te tev nu bija! Bet tiešām tā TAB ir viena vērtīga funkcija. Nemaz nevajadzēja iepriekš zināt, cik simbolu ir apsveikuma rindā, lai to izdrukātu tieši vidū starp abiem dekoratīvajiem simboliem.

— Vēl tiek izdrukātas tukšās rindas zem teksta, tad apakšējā rāmīša rindiņa, un tas arī ir viss par teksta izvadi. Tālāk ar operatoru CLOSE tiek aizvērti visi faili, lai patiešām sāktos drukāšana.

Lietotājs izvēlas turpmāko rīcību

— Un tad programma noskaidro, kas darāms, un nu lietotājs var izvēlēties.

— Parunāsim par pirmo iespēju — izdrukāt visu, kā ir. Šajā gadījumā vadība tiek nodota uz rindu 740 un pirmā darbība ir šāda: mainīgajam F piešķir vērtību 1. Pēc tam atver drukas iekārtu, jo visi faili ir aizvērti, — atceries rindu 660.

— Bet kāpēc rindā 720 pirms operatora ON tu mainīgajam F piešķir vērtību nulle?

— Visi faili, izņemot nullto, ir aizvērti, un, ja operators ON vadību nodos uz rindu 290, tad nevarēs izpildīties operatori PRINT # F. Vienīgi gadījumā, ja F=0, tie tiks izpildīti normāli un viss tiks izvadīts uz ekrāna.

— Un, ja lietotājs gribēs izdrukāt ar cita apsveicamā cilvēka vārdu, tad nākamreiz vajadzēs izvēlēties pirmo režīmu?

— Jā, tā nu tas ir noprogrammēts... Vēl programmu varētu uzlabot, uzrakstot apakšprogrammu vokatīva atrašanai.

— Nesaprotu! Manuprāt, tā būtu vajadzīga tikai vienu reizi, bet apakšprogrammas ir vērts rakstīt tikai tad, ja tās izmanto vairākas reizes, vismaz divas, kā šajā programmā. Tā taču tu pats teici!

Ilustrācija

— Teicu gan. Bet apakšprogrammas var izmantot arī pavisam citās programmās. Piemēram, ar mašīnu spēlējot, pašā sākumā tiek noskaidrots, kā sauc spēlētāju. Viņš ievada — «Pēcis». Un beigās programma izvada: tu, Pēci, esi zaudējis! Kaut kādam sīkajam, kas no programmēšanas nekā nesajēdz, acis no pieres izsprāgs: mašīna zina, kā mani sauc! Tiesa, ar tādām iepriekš sagatavotām apakšprogrammām vajag apieties diezgan uzmanīgi, jo tajās izmantotie mainīgo apzīmējumi var sakrist ar mainīgo apzīmējumiem programmā, kura šo apakšprogrammu izmantos, un, ja šādu sakrišanu laikus nepamanīsi un nenovērsīsi, mainīgo vērtības var tikt sabojātas.

Ilustrācija

Programmas pareizības pārbaude

Bet atgriezīsimies pie apsveikumu drukāšanas programmas. Tad, kad tā bija gatava, to vajadzēja testēt — pārliecināties, ka ar visiem ievaddatiem tā tiešām strādā. Saki — kādi personvārdi man bija jāievada, lai pārliecinātos, ka uzrunas forma tiek atrasta pareizi?

Ilustrācija

— Tas taču viss ir blokshēmā! Pēcis, Pēcītis, Maija, Maijiņa, Zane, Zanīte.

— Un tas ir viss?

— Citu variantu tur nav.

— Vēl vajadzīgs vārds, kas nebeidzas ne ar vienu no šīm galotnēm. Piemēram, Krkrk.

— Labi. Kopā ar «Krkrk» iznāk septiņi vārdi. Tātad testēšanai programma būtu jāizlaiž septiņas reizes.

190— Lai notestētu vokatīva atrašanu. Bet vēl pirms personvārda ievades četrreiz tiek ievadīts vieninieks vai divnieks. Testējot sarežģītu programmu, šie septiņi vārdi mašīnā būtu jāielaiž kopā ar jebkuru kombināciju no četriem skaitļiem — vieniniekiem vai divniekiem. Tas nozīmē, ka vispār mums būtu 7.2.2.2.2=112 variantu.

— Šausmas!

— Neuztraucies. Šoreiz tas nebija jādara, jo mūsu programma ir ļoti vienkārša un pilnīgi pietiek ar vienu pārbaudi.

Ilustrācija

— Vai gribi teikt, ka ir diezgan, ja ievadām variantus «skolēns» — «Pēcis» un «pieaugušais» — «Pēcis», lai viss būtu kārtībā un nebūtu jāpārbauda varianti «skolēns» — «Maija» un «pieaugušais» — «Maija»?

— Gribu teikt vēl vairāk: pietiek, ja pārbauda vienīgi variantus «skolēns» — «Pēcis» un «pieaugušais» — «Maija» — tas ir, ja uzrunas veidošanas pārbaudi apvieno ar ievada «skolēns» — «pieaugušais» jeb mainīgā S vērtības apstrādes pārbaudi. Šis ievads programmā ļoti maz ko ietekmē: mainīgais S piedalās tikai vienā nosacītās pārejas operatorā rindā 520. Ja te būtu nevis piešķiršana, bet gan sarežģīti aprēķini, kuros izmantotu ievadīto vārdu, tad mums būtu jāizlaiž visi iespējamie varianti — divi S ievada varianti reiz septiņi vārda ievada varianti.

— Manuprāt, par mainīgā C vērtības ievadu var teikt to pašu. Šis mainīgais atbild par to, vai apsveicamais mums ir dārgs vai cienījams. Un šo mainīgo izmanto arī tikai vienreiz. Tur, kur no masīva izvēlas vārdus «dārgais» vai «cienījamais» attiecīgajā dzimtē. Ja programma pareizi izvēlēsies Maijai, tad arī Zanei būs pareizi.

— Bet atkal: ja šī C vērtība piedalītos kaut kādos sarežģītos aprēķinos, tad būtu jāpārbauda visi iespējamie varianti.

— Acīmredzot to pašu varētu teikt arī par mainīgo T, kas atrod vajadzīgo pieklājības formu. Un vēl vairāk to var teikt par mainīgo F, kurš atbild par izvadu uz ekrāna vai papīra. Ja tika pieprasīts izvadīt uz papīra un uz papīra arī izvadīja, tad, to pašu pieprasīdami nākamreiz, arī dabūsim izvadi uz papīra.

— Var cerēt.

191— Cik tad īsti to variantu sanāca?

— Tikai septiņi. Mums jāpārbauda visi personvārdi, bet, kad mašīnā būsim ielaiduši kādu variantu, tad, pirms programma liks ievadīt apsveicamā vārdu, vajadzēs ievadīt arī šādu ciparu kombināciju: vispirms — 1, 1, 1, 1; pēc tam — 2, 2, 2, 2. Bet, kā jau teicu, tik vienkārši sanāca tāpēc, ka mēs mazliet nohaltūrējām, apgalvodami, ka ievaddati cits citu neietekmē.

— Ūja! Kas tur par haltūru! Mēs kārtīgi un godīgi izspriedām, ka savstarpējās ietekmes nav; ja jau vienreiz programma vārdu «cienījamais» izvēlējās pareizi, tad arī citreiz izvēlēsies pareizi. Viss ir loģiski.

Vēl dažas iespējamās kļūdas

— Loģiski viss ir ar pareizu programmu. Bet programma var būt nepareiza, un pie tam gadās tā, ka programma strādā pareizi, bet, tikai ievadot dažas ievaddatu kombinācijas, atklājas kļūdas.

— Neticu, ka tādas kļūdas varētu būt.

— Visgrūtāk atrodamas ir tās kļūdas, kuru nevarot būt. Tā, starp citu, saka Algoritms.

— Nu tad izdomā šajā programmā kādu tamlīdzīgu kļūdu!

— Es nerunāju par šo programmu, bet vispār. Šeit tādas kļūdas varbūt arī nevar piedzejot, ja nu vienīgi pieliekam klāt vēl kādu pilnīgi jocīgu rindiņu. Piemēram, meklēdami pēdējo burtu apsveicamā vārdam, rakstām nevis

P¤=SEG¤(V¤, L, L),

bet gan kļūdaini

P¤=SEG¤(V¤, S, S).

Kas tad notiks?

— Kas notiks? Gadījumā, ja apsveicamais ir skolēns, tiks atrasts vārda pirmais burts, bet gadījumā, ja apsveicamais ir pieaugušais, — otrais.

— Programma nostrādās pareizi, ja Maiju sveiksim kā pieaugušo, un nepareizi, ja kā skolnieci. Pateiks, ka šāds vārds neder, un pieprasīs jaunu; tu atkal ievadīsi to pašu, atkal pieprasīs citu, un nekad nevarēsi ne iedomāties, kādu vārdu programmai vajag, lai tā nomierinātos. Bet ja būs šāda kļūda?

P¤=SEG¤(V¤,5,5)

— Tad apsveicamā vārdā tiks atrasts piektais burts. Tikai tiem apsveicamajiem, kuru vārdiem ir pieci burti, programma uzrunu izdrukās pareizi.

— Jāatzīstas, ka mūsu testēšanas sistēma šādu kļūdu atklāšanu nenodrošina.

— Bet kā lai tās atrod?

Ilustrācija

— Tas nav viegli. Ja mašīna atsakās ņemt pretī pilnīgi pareizu vārdu, tad pirmais, ko var iedomāties, ir gadījums, kur kāds no salīdzināšanas operatoriem strādā nepareizi. Kurš — to var noteikt, vienīgi programmā pārbaudot visus šādus operatorus. Ja tie izrādās pareizi, tad nepareizi ir dati, kuri tiek izmantoti. Bet izmantojam tikai mainīgā P¤ vērtību. Ja tā, tad pēc P¤ vērtības atrašanas ieliekam papildu rindu 315 STOP. Kad programma pie šīs rindas ir apstājusies, tad tiešajā režīmā varam izvadīt P¤ vērtību, L vērtību, kā arī tās programmas rindas, kuras šīs vērtības nosaka un piešķir. Tad arī uzzināsi, kura rinda nav pareiza.

— Tradicionāli mums tagad šī programma būtu jāpārdomā. Bet mēs ar to esam tik daudz noņēmušies, ka pārdomāšanu varam atlikt uz citu reizi.