K R I S T I N A L A P I N
Programavimas C
I dalis
Matematikos ir statistikos
studijų krypčių
pirmo kurso studentams
2013
V I L N I A U S U N I V E R S I T E T A S
M A T E M A T I K O S I R I N F O R M A T I K O S F A K U L T E T A S
P R O G R A M Ų S I S T E M Ų K A T E D R A
2
Programavimas Paskaliu ir C: I dalis
1 KURSO MATEMATIKOS IR STATISTIKOS
STUDIJŲ KRYPČIŲ STUDENTAMS
T U R I N Y S PRATARMĖ ................................................................................................................................................. 3
1. ĮVADAS ................................................................................................................................................ 3
1.1. PRISIJUNGIMAS .............................................................................................................................. 3 1.2. DARBAS SU KATALOGAIS IR FAILAIS TERMINALO LANGE ............................................................... 3 1.3. C PROGRAMŲ VYKDYMAS .............................................................................................................. 5 1.4. DARBO PABAIGA ............................................................................................................................ 5
2. PROGRAMOS STRUKTŪRA ........................................................................................................... 6
3. PAPRATIEJI DUOMENŲ TIPAI ..................................................................................................... 6
4. KINTAMIEJI ....................................................................................................................................... 7
5. OPERACIJOS IR REIŠKINIAI ........................................................................................................ 8
6. SAKINIAI ............................................................................................................................................. 9
6.1. PRISKYRIMAS................................................................................................................................. 9 6.2. SUDĖTINIS SAKINYS ....................................................................................................................... 9 6.3. IŠSIŠAKOJIMAI ..............................................................................................................................10
6.3.1. Sąlyginis sakinys .................................................................................................................10 6.3.2. Variantinis sakinys ..............................................................................................................11
6.4. KARTOJIMAI .................................................................................................................................12 6.4.1. Ciklas while .........................................................................................................................12 6.4.2. Ciklas do while ....................................................................................................................13 6.4.3. Ciklas for .............................................................................................................................14 6.4.4. Ciklo valdymas, naudojant break, continue, goto ...............................................................15
7. STRUKTŪRINIAI TIPAI ..................................................................................................................15
7.1. MASYVAS .....................................................................................................................................15 7.1.1. Daugiamačiai masyvai ........................................................................................................19
7.2. ĮRAŠAI ..........................................................................................................................................19 7.3. SĄJUNGA (UNION) .........................................................................................................................20
8. FUNKCIJOS IR PROCEDŪROS .....................................................................................................21
8.1. ĮVADAS .........................................................................................................................................21 8.2. STANDARTINĖS FUNKCIJOS ...........................................................................................................21 8.3. NAUDOTOJO FUNKCIJOS ................................................................................................................22 8.4. MASYVŲ PERDAVIMAS FUNKCIJOMS AR PROCEDŪROMS ...............................................................23 8.5. ATMINTIES KLASĖS .......................................................................................................................24 8.6. C PARAMETRAI-KINTAMIEJI..........................................................................................................26
8.6.1. Kintamųjų perdavimas parametrais-kintamaisiais .............................................................26 8.6.2. Masyvų perdavimas funkcijoms ir procedūroms .................................................................27
8.7. PAVYZDŽIAI ..................................................................................................................................28
9. FAILAI ................................................................................................................................................29
9.1.1. Atverti failą ..........................................................................................................................29
3
9.1.2. Nuoseklios kreipties failo skaitymas ....................................................................................30 9.1.3. Atsukti failo rodyklę į pradžią .............................................................................................30 9.1.4. Rašymas į nuoseklios kreipties failą ....................................................................................30 9.1.5. Užverti failą .........................................................................................................................30
9.2. C LAISVOSIOS KREIPTIES FAILŲ SKAITYMAS IR RAŠYMAS .............................................................32 9.3. KITI PAVYZDŽIAI ..........................................................................................................................34
LITERATŪRA ............................................................................................................................................36
PRATARMĖ
Metodinė priemonė „Programavimas C: I dalis“ skirta 1 kurso studentams. Ji apima
Informatikos dalyko rudens semestro programą, Ši priemonė papildo doc. dr. S. Ragaišio
metodinę priemonę [2] programavimo aspektu. Šioje priemonėje yra pateikiami sąvokų
realizavimo pavyzdžiai.
Ši medžiaga yra skirta programavimo naujokams. Joje stengiamasi paprastai išdėstyti bazines
programavimo sąvokas. Labiau pažengusiems programavime, siūlyčiau naudoti kitas, aukštesnį
žinių lygį atitinkančias mokymo priemones, pavyzdžiui [4].
Šioje mokymo priemonėje pradedantiesiems programuotojams yra siūloma tokia mokymosi
metodika:
1) nagrinėti pateiktą sąvokos apibūdinimą ir pateikiamus pavyzdžius, papildytus paskaitoje
užrašytais komentarais;
2) ruošiant pratybuose gautą individualią užduotį, pradėti nuo pavyzdžio, pateikto šioje
medžiagoje;
3) pertvarkyti pavyzdį, atsižvelgiant į gautos užduoties reikalavimus.
Dėstomos sąvokos iliustruojamos pavyzdžiais, paruoštais transliavimui. Atsižvelgiant į
ribotas naujokų naujų žinių įgijimo galimybes, sąmoningai stengiamasi vengti visų kalbos
galimybių ir subtilybių dėstymo. Kalbų detalės yra išsamiai dėstomos konkrečių kalbų aprašuose
ir žinynuose ([4]).
Ši priemonė leidžia pasiruošti skaityti ir suprasti programavimo literatūrą, skirtą skaitytojui,
suprantančiam bazines programavimo sąvokas.
1 . ĮVADAS
1.1. PRISIJUNGIMAS
Dirbsime Linux aplinkoje. Pasirinkus Linux aplinką, pasirodo prisijungimo langas, kuriame
įvedamas prisijungimo vardas ir slaptažodis.
1.2. DARBAS SU KATALOGAIS IR FAILAIS TERMINALO LANGE
Spragtelėti programų meniu, po to sistema, po to terminal. Atsiveria komandų (konsolės, angl. console) langas. Šiame lange rašomos komandos. Darbui su katalogais pakanka šių komandų:
● Naujo katalogo kūrimas: mkdir. Pavyzdžiui, jei kuriame katalogą vardu Proc_prog,
surenkame šią eilutę komandų lange: mkdir Proc_prog
4
● Pereiti į naujai sukurtą katalogą: cd Proc_prog
● Grįžti atgal į šakninį katalogą: cd ..
● Pasižiūrėti katalogo turinį: ls arba dir
● Panaikinti katalogą pavadintą Proc_prog: rmdir Proc_prog
Antras būdas – Midnight Commander
Pripatusiems prie failų tvarkymo aplinkų, panašių į Windows Commander ar Far, visose
klasėse galima išsikviesti Midnight Commander programą komandų (konsolės) lange surinkę:
mc –c (žr. 1-1 pav.)
1-1 pav. Midnight Commander programos kvietimas
Surinkus pastarąją komandą, atsivėria langas, parodytas 1-2 pav.
5
1-2 pav. Midnight Commander failų tvarkuymo aplinka
1-3 pav. Komandų lango atvėrimas
1.3. C PROGRAMŲ VYKDYMAS
C programų kompiliavimas ir vykdymas Linux ir Soliaris aplinkose nesiskiria. Kompiliuoti C
programų tekstus galime dviem būdais
1 būdas: transliuojant, atribute –o nurodomas vykdomojo modulio vardas, būtent
gcc vardas1.c –o vardas2
Tuomet programa vykdoma taip:
./vardas2
2 būdas: naudojant standartinį vykdomojo modulio pavadinimą a.out:
gcc vardas.c
Tuomet programa yra vykdoma šitaip:
./a.out
1.4. DARBO PABAIGA
Darbo pabaigoje būtina išsiregistruoti!
6
2 . PROGRAMOS STRUKTŪRA
C programą sudaro:
Preprocesoriaus komandos, pvz. #include <stdio.h>
Tipų apibrėžtys
Funkcijų prototipai
Globalūs kintamieji
Funkcijos. Bent viena funkcija turi būti int main()
C programose komentuoti galima vieną eilutė, tuomet ji turi prasidėti simboliais
//
Komentarai kitose programos vietose yra rašomi taip: /* komentaras */
3 . PAPRATIEJI DUOMENŲ TIPAI
3-1 lentelėje yra išvardijami C paprastieji duomenų tipai kartu su reikšmių aibėmis.
3-1 lentelė. C paprastųjų tipų suvestinė
Tipas Ilgis baitais Reikšmės nuo iki char 1 - -
unsigned char 1 0 255
short int 2 -32768 32767
unsigned short
int
2 0 65536
(long) int 4 -231 +231-1
float 4 -3,2*10±38 +3,2*10±38
Double 8 -1,7*10±308 +1,7*10±308
3-2 lentelėje sugretinami Paskalio ir C kalbų paprastieji tipai.
3-2 lentelė C ir Pascalio kalbų paprastųjų tipų atitikmenys
C tipas Paskalio tipas char Char
unsigned char Byte
Short int Integer
unsigned short
int
Word
long int Longint
Float Real
Double Extended
Spausdinant reikšmes, reikia nurodyti jų formatus:
%d – sveikieji skaičiai,
%f – slankaus kablelio (realieji) skaičiai,
%c – simboliai,
7
%s – simbolių eilutės.
C kalboje nėra loginio tipo, todėl rekomenduojama naudoti unsigned char. Vardinio
tipo reikšmes C kalboje galime naudoti, jei aprašysime jį šiuo būdu:
Enum savd {pirm, antr, trec, ketv, pentk, sest, sekm};
Vardinio tipo naudojimo pavyzdį iliustruoja žemiau pateikiama programėlė, įvedanti mėnesio
numerį ir spausdinanti atitinkamą metų laiką:
#include <stdio.h>
enum months {JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG,SEP, OCT, NOV,
DEC};
int main()
{
enum months month;
int i;
printf("Iveskite skaiciu nuo 1 iki 12 \n");
scanf("%d", &i);
switch (i)
{
case JAN:
case FEB:
case DEC: printf("ZIEMA \n");
break;
case MAR:
case APR:
case MAY: printf("PAVASARIS \n");
break;
case JUN:
case JUL:
case AUG: printf("VASARA \n");
break;
case SEP:
case OCT:
case NOV: printf("RUDUO \n");
break;
default: printf("netinkamas skaicius \n");
}
return 0;
}
4 . KINTAMIEJI
Kintamuosius C kalboje aprašome, pradžioje nurodydami tipo vardą ir kintamųjų
vardus, pavyzdžiui,
int i,j,k;
float x,y,z;
char c;
8
Pradines reikšmes galima suteikti (inicializuoti) jau aprašant kintamuosius:
float sum = 0.0;
int bigsum = 0;
char letter = ‘a‘;
5 . OPERACIJ OS IR REIŠK INIAI
Operacija – tai veiksmas, suformuojantis reikšmę, vadinamą operacijos rezultatu.
Operacijos pradiniai duomenys – operandai – viena arba dvi reikšmės. Atitinkamai
operacija yra vadinama unariąją arba binariąja.
Reiškiniai – tai konstrukcijos naujoms reikšmėms formuoti, atliekant tam tikras
operacijas.
Pagrindinių operacijų prioritetų lentelė: !
++ -- + - (unarinės)
* / %
+ - (binarinės)
< <= >= >
== !=
&&
||
?: (Sąlyginis operatorius)
= += -=
Paskutinė eilutė iliustruoja įdomų C kalbos aspektą: kitaip nei Paskalyje, priskyrimas C
kalboje yra operacija, kuri gamina rezultatą. Tai reiškia, kad ją galima naudoti visur ten, kur gali
būti formuojama reikšmė.
Dar vienas aspektas reikalauja atkreipti dėmisį į dalybos ypatumus. Dviejų sveikų skaičių
dalybos rezultatas yra sveikas skaičius, tai yra veikia kaip Paskalio div operacija. Jei reikalingas
realus rezultatą, reikia atlikti tipo pertvarkymo operaciją:
(float) 7/4
1.4-1 pavyzdys Skaičių dalybos operacijos ypatumai C kalboje.
#include <stdio.h>
int main()
{
float x;
x=7/4;
printf(" 7 / 4 = %.2f \n", x);
x=(float)7/4;
printf("(float) 7 / 4 = %.2f \n",x );
return 0;
}
Šios programos rezultatas yra toks: 7 / 4 = 1.00
9
(float) 7 / 4 = 1.75
Atliekant pirmąsias užduotis dažnai prireikia kėlimo laipsniu funkcijos. Jei reikia skaic
pakelti kvadratu, užrašome pow(skaic, 2), o traukti šaknį – pow(skaic,0.5). Kitas
standartines panagrinėsime vėliau, Error! Reference source not found. skyriuje.
Pavyzdys. Kaip C kalba patikrinti, ar skaičius yra sveikojo skaičiaus kvadratas? Šis reiškinys
užsirašo šiek tiek kitaip nei Paskalio kalboje: trupmeninę dalį atmestime, realaus tipo reikšmę
pertvarkydami į sveikojo tipo reikšmę:
pow ( (int) pow ( skaic, 0.5) , 2) == skaic
6 . SAKINIAI
Programos tikslas – nurodyti veiksmus, kuriuos turi atlikti kompiuteris. Veiksmai
užrašomi sakiniais. Sakiniai baigiami kabliataškiu. Prieš bet kurį sakinį galima rašyti
žymę – tada galime nurodyti, kad toliau turi būti atliekamas su žyme nurodytas sakinys.
6.1. PRISKYRIMAS
Kintamasis = išraiška; kintamasis operacija = išraiška;
C kalba leidžia sutrumpinti kai kurių išraiškų užrašą, pvz.
C = C + 3; galima užrašyti C += 3;
+= operacija reiškia, kad prie reiškinio kairiosios pusės yra pridedama dešinioji pusė ir
rezultatas priskiriamas kairiajai pusei, pavyzdžiui,
int c=3, d=5, e=4, f=6, g=12;
+= c += 3; c = c + 3; c bus 10
-= d -= 7; d = d + 3; d bus 1
*= e *= 5; e = e * 5; e bus 20
/= f /= 3; f = f / 3; f bus 2
%= g %= 9; g = g % 9; g bus 3
c = c + 1; c+=1; c++; ++c;
c = c - 1; c-=1; c--; --c;
++a (--a)padidina (sumažina) a vienetu, o toliau naują reikšmę panaudoja išraiškoje, kurioje
yra a.
a++ (a--)panaudoja a einamąją reikšmę išraiškoje, o toliau padidina (sumažina) a vienetu.
6.2. SUDĖTINIS SAKINYS
Keli sakiniai jungiami į vieną sakinį ten, kur taisyklės leidžia parašyti vieną sakinį, o
reikia daugiau.
C kalboje, panašiai kaip ir Paskalyje, sudėtinis sakinys naudojamas sąlyginiame sakinyje po
sąlygos (<sąlyga>) ir po else, do, jei reikia panaudoti daugiau nei vieną sakinį
apskliaudžiame:
{
sakiniai;
}
10
6.3. IŠSIŠAKOJIMAI
6.3.1. SĄLYGINIS SAKINYS
if (sąlyga) sakinys;
else sakinys;
Pavyzdys:
if (taskai >= 30 && kolokviumas >= 30)
printf( ˝Iskaityta \n˝ );
else printf( ˝Neįskaityta \n˝ );
C kalboje yra sąlygos operacija ?: Naujantis ja, pastarąją sąlygą galime perrašyti taip:
printf("%s \n", taskai >= 30 && kolokviumas >=30 ? "Iskaityta" :
"Neiskaityta");
6.3-1 pavyzdys. Įvesti tris sveikus skaičius a,b,c. Išvesti:
-b, jei a+b+c < 0
y= 0, jei a+b+c = 0
b, jei a+b+a > 0
#include <stdio.h> /* Cissisak.c */
int main()
{
int a,b,c;
printf( "Iveskite tris skaicius: ");
scanf( "%d %d %d", &a, &b, &c);
if ( a + b + c < 0 )
printf("Atsakymas yra %d \n", -b);
else
if (a+b+c==0)
printf("Atsakymas yra 0\n");
else printf("Atsakymas yra %d \n", b);
}
6.3-2 pavyzdys. Įvesti du sveikus skaičius. Apskaičiuoti ir išvesti
reikšmę, nenaudojant standartinių funkcijų:
max ( |a|, |b|) , jei a lyginis,
y=
min (|a|, |b|), jei a nelyginis
#include <stdio.h>
int main()
{ int a,b,am, bm, y;
printf("Iveskite du sveikus skaicius ");
scanf("%d %d",&a, &b );
if ( a < 0 ) am = -a;
else am = a;
if ( b < 0 ) bm = -b;
else bm = b;
if ( a % 2 == 0 )
11
if ( am > bm )
y = am;
else
y = bm;
else
if ( am < bm ) y = am;
else y = bm;
printf("y= %d\n", y);
}
6.3.2. VARIANTINIS SAKINYS
Varinatinis sakinys:
switch (sveikojo tipo išraiška)
{
case reiksme_1:
Operatoriu_seka_1;
Break;
case reiksme_2:
Operatoriu_seka_2;
Break;
…
case reiksme_n:
Operatoriu_seka_n;
Break;
default:
Operatoriu_seka_n_1;
}
Šakos default galima neaprašyti. Ši šaka yra vykdoma, jei netenkinama nei viena iš
ankstesnių sąlygų. Štai keletas variantinių sakinių:
switch (i)
{
case 0: case 2: case 4: case 6: case 8:
printf(“Lyginis skaitmuo \n”);
break;
case 1: case 3: case 5: case 7: case 9:
printf(“\n Nelyginis skaitmuo \n”);
break;
default: printf(“Kiti skaiciai \n”);
}
arba Switch (klaidos_nr)
{
case 1: printf(“\n 1 pranešimas \n”);
break;
case 2: printf(“\n 2 pranešimas \n”);
break;
case 3: printf(“\n 3 pranešimas \n”);
break;
default: printf(“\n Neteisingas klaidos kodas \n”);
}
12
6.4. KARTOJIMAI
Veiksmų kartojimas programose yra realizuojamas ciklo sakiniais.
6.4.1. CIKLAS WHILE
sąlyga
sakinys
+
-
while (sąlyga)
operacija; pvz.: sandauga= 2;
while (sandauga <= 100)
sandauga *=2;
Programos vykdymo stabdymas (Paskalio readln analogas): while (getchar() != ‘\n’);
6.4-1 pavyzdys. Įvesti sveikus skaičius, pabaigos požymis – 999. Išvesti jų vidurkį ir dalių iš 5 skaičių
sumą. .
#include <stdio.h>
#define PAB 999
int main()
{
int skaitliukas, skaicius, suma, dalus_is_5;
float vidurkis;
suma = skaitliukas = dalus_is_5 = 0;
printf("\n Iveskite skaicius. Noredami baigti, iveskite %d \n", PAB);
scanf("%d", &skaicius);
while (skaicius != PAB )
{
skaitliukas++;
suma += skaicius;
if (skaicius % 5 == 0)
dalus_is_5 += skaicius;
scanf("%d", &skaicius);
}
vidurkis = (float) suma/skaitliukas;
printf("Skaiciu vidurkis yra %.2f\n", vidurkis);
printf("Skaiciu, kurie dalinasi is 5, suma yra %d\n", dalus_is_5);
}
Jei reikia paskaičiuoti, kiek yra skaičių, tuomet skaičiuojame, kaip skaitliuką, kiek++;
6.4-2 pavyzdys. Įvesti sveikų teigiamų skaičių seką, kurios pabaiga
žymima 0. Išvesti įvestų skaičių skaitmenų sumą.
#include <stdio.h>
int main()
13
{
short const PAB=0;
int skaicius, sk_suma;
sk_suma=0;
puts("Iveskite sveikus skaicius.");
printf("Noredami baigti, iveskite %d\n", PAB);
scanf("%d", &skaicius);
skaicius=skaicius<0 ? -skaicius : skaicius;
while ( skaicius != PAB )
{ while (skaicius>0)
{ sk_suma += skaicius % 10;
skaicius /= 10;
}
scanf("%d", &skaicius);
}
printf("Skaitmenu suma yra %d \n", sk_suma);
}
6.4.2. CIKLAS DO WHILE
do
Operatorius
while (sąlyginė išraiška);
Bendro didžiausio daliklio pavyzdys: do {
liekana = A % B;
A = B;
B = liekana;
} while (B != 0);
Ciklas baigia darbą, kai sąlyga yra netenkinama. Pavyzdys, įvesti simbolių eilutę, pabaigos
požymis – klavišo Enter paspaudimas. Toliau ją išvesti.
6.4-3 pavyzdys. Simbolių įvedimas, naudojant kartojimus C kalboje
#include <stdio.h>
int main()
{
char ats;
do {
scanf("%c", &ats);
printf("%c", ats);
} while (ats != '\n');
}
#include <stdio.h>
int main()
{
char ats;
printf("Iveskite simboliu seka. Noredami
baigti, spauskite ENTER\n");
scanf("%c", &ats);
while (ats != '\n')
{
printf("%c", ats);
scanf("%c", &ats);
}
}
Iš šio pavyzdžio matome, kad ciklų while ir do while naudojimas šiek tiek skiriasi. Pirmam
prieš tikrinant sąlygą, reikia priskirti ciklo sąlygos kintamajam reikšmę. Lyginant su do while,
turime panaudoti papildomą įvesties sakinį. Vadinasi, jei kartojamą sakinį reikia atlikti bent vieną
kartą, prasmingiau naudoti do while.
Antrasis skirtumas atsiranda perskaičius simbolį „nauja eilutė“. Ciklas while spausdina visus
simbolius, kol pasirodo naujos eilutės simbolis. Ciklas do while spausdina visus simbolius,
14
įjungdamas ir „naujos eilutės“ simbolį. Tik atspausdinus šį simbolį yra lyginama, ar lygus „naujos
eilutės simboliui“. Cikle while ši sąlyga tikrinama prieš vykdant ciklo kūną.
6.4-4 pavyzdys. Įvesti skaičių seką. Paskaičiuoti, kiek iš jų dalinasi
iš 3.
#include <stdio.h>
int main()
{
int sk, kiek=0;
printf("Iveskite skaiciu seka. Noredami baigti, iveskite 0\n");
do{
scanf("%c", &sk);
if ( sk % 10 == 3 ) kiek++;
} while (sk != 0)
printf("Skaiciu, daliu is 3 yra %d\n", kiek);
}
6.4.2.1. C ir Paskalio kartojimų palyginimas
1. While sakinys kartojamas tol, kol sąlyga tenkinama (true). Repeat sakinys atliekamas
tol, kol sąlyga yra netenkinama (false). Taigi, while cikle sąlyga nurodo ciklo tęsimo
sąlygą, o repeat cikle – ciklo pabaigos sąlygą.
2. While cikle kartojamas vienas sakinys, o repeat cikle – sakinių grupė. Todėl jei while
cikle reikia atlikti daugiau sakinių apskliaudžiame juos begin end, o repeat – nereikia.
3. While sakinye iš karto yra tikrinama sąlyga, o po to atliekamas arba neatliekamas po
do einantis sakinys, Repeat sakinyje iš karto yra atliekama sakinių seka, o po to tik
tikrinama sąlyga. Vadinasi, šiuo atveju, sakinių seka yra atliekama bent vieną kartą.
6.4.3. CIKLAS FOR
Dažniausiai naudojama bendra ciklo forma, kai nustatoma ciklo kintamojo pradinė reikšmė,
ciklo pabaigos sąlygos tikrinimas, ciklo kintamojo keitimas:
For (operacija1; operacija2; operacija3) operatorius;
Operacija1 apibrėžia veiksmą vykdomą prieš ciklą. Paprastai šioje vietoje priskiriama pradinė ciklo
skaitliuko reiškmė; operacija2 nustato kartojimų pabaigos sąlygą; operacija3 – apibrėžia veiksmą,
atliekama įvykdzius ciklo iteraciją, paprastai čia keičiama ciklo skaitliuko reikšmė.
// Kvadratų lentelė. FORKVADR.C
#include <stdio.h>
int main()
{
int i;
for(i=1; i<100; i++)
printf("%4d %5d", i, i*i);
printf("\n");
// Raidės nuo a iki z FORSIMB.C
#include <stdio.h>
int main()
{
int r;
for(r='a'; r<='z'; r++)
printf("%c ", r);
15
} printf("\n");
}
6.4.4. CIKLO VALDYMAS, NAUDOJANT BREAK, CONTINUE, GOTO
Ciklo ir sąlyginiai operatoriai yra pagrindinės programos veiksmų sekos valdymo priemonės.
Jos yra taikomos bendrai programos struktūrai realizuoti. Toliau nagrinėjami operatoriai yra
naudojami žymiai rečiau, nes jie apsunkina programos skaitomumą ir modifikavimą. Jie yra
naudojami išimtiniais atvejais.
Break nutraukia programos bloko vykdymą. Jeigu šis operatorius yra cikle, tai to ciklo
kartojimai yra nustraukiami ir pereinama prie po ciklo einančios operacijos. Continue nutraukia
einamąją ciklo iteraciją, o goto nukreipia vykdymą į nurodytu vardu pažymėtą sakinį.
//Su valdymo operatoriais CBREAK.C
#include <stdio.h>
int main()
{
int i, ch;
printf("\n Iveskite iki 20 skaiciu, 0 - pabaiga.\n Ivesta: ");
for ( i = 1; i<=20; i++)
{
scanf("%d", &ch);
if ( ch == 0 ) break;
printf("%d ", ch);
}
printf("\n");
}
Šios programos rezultatas: Iveskite iki 20 skaiciu, 0 - pabaiga.
Įvesta: 1 2 0 3 0 4 0 5 0 5 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0
1 2
Operatorius continue gali būti naudojamas visuose ciklo operatoriuose, bet ne operatoriuje
switch. Jei pasitaiko ciklo operatoriuje, tai likusieji ciklo operatoriai praleidžiami ir pereinama
prie naujos ciklo iteracijos. (goto : failas cgoto.c, continue: Ccontinue.c)
7 . STRUKTŪRINIAI TIPAI
7.1. MASYVAS
Paskalis C
M[1] -45 M[0]
M[2] 6 M[1]
M[3] 0 M[2]
M[4] 25 M[3]
M[5] 1543 M[4]
16
Masyvas – tai vieno tipo reikšmių rinkinys, pavadintas vardu. Aprašant masyvą yra
nurodoma, kiek maksimaliai jame yra elementų. Kreipiantis į masyvo elementą,
nurodome masyvo vardą ir elemento eilės numerį, kitaip vadinamą masyvo indeksu.
Aukščiau pavaizduotame masyve M yra 5 elementai. Indeksas yra diskreti reikšmė.
Vieno indekso masyvas vadinamas vienmačiu, dviejų – dvimačiu, jei n indeksų – n-
mačiu.
Pagrindiniai veiksmai, dirbant su masyvu:
1) didžiausios arba mažiausios reikšmės paieška,
2) skaičiavimai (sumos, sandaugos kiekio, vidurkis),
3) atpažinimas (ar yra rinkinyje tam tikra reikšmė),
4) rikiavimas (didėjimo arba mažėjimo tvarka),
5) elementų šalinimas iš masyvo elementų, kurio indeksas yra k, toliau už jo esančios,
elementus reikia pastumti per vieną poziciją link pradžios.
Masyvas C kalboje aprašomas taip:
Duomenų_tipas masyvo_vardas [masyvo_dydis]
Į masyvo elementus kreipiamasi, nurodant masyvo vardą ir indeksą:
masyvo_vardas [indeksas]
Indekso reikšmės turi būti nuo 0 iki reikšmės, vienetu mažesnės už masyvo dydį, nurodytą
masyvo aprašyme. Keletas pavyzdžių:
char vardas[20];
int reiksmes[12]
float dydis[30];
Pirmasis iš masyvų turi 20 simbolių. Kreipiniai į šio masyvo elementus yra šie: vardas[0],
vardas[1], … vardas[19]. Toliau pateikiami svarbiausių operacijų su masyvais šablonai:
Didžiausia masyvo reikšmė: max = m[0];
for (I = 0; i < n; i++)
if ( max < m[i] ) max = m[i];
Sumos skaičiavimas suma = 0;
for ( i = 0; i < n; i++ )
suma += m[i];
Atpažinimas:
yra = 0;
for ( i = 0; i < N; i++)
if ( ieskoma_reiksme == m[i] )
yra = 1;
Pašalinti k-tąjį elementą for (i = --k; i < N-1; i++)
mas[i] = mas[i+1];
Įterpti reikšmę į k-tąją vietą k--;
for (i = N; i >= k; i-- )
mas[i+1] = mas[i];
mas[k] = iterpiama_reiksme;
Pastaba. Reikšmės įterpimo fragmente N-toji reikšmė yra perkeliama į N+1 vietą. Kadangi
elementų skaičius negali viršyti atmintyje išskirtų elementų kiekio, vadinasi prieš įterpiant reikia
isitikinti, kad įterpinėti dar galima. Kitaip tariant, jei N = NUM (atmintyje išskirtam elementų
skaičiui), tai įterpimas neturi būti vykdomas.
7.1-1 pavyzdys Įvesti masyvo reikšmes ir jį atspausdinti po 5 eilutėje.
#include <stdio.h>
17
#define NUM 50
int main()
{
int i, N, mas[NUM];
printf("Kiek bus elementu? \n");
scanf("%d", &N);
printf("Iveskite %d elementu\n", N);
for ( i = 0; i < N; i++)
scanf( "%d", &mas[i] );
printf( "Ivesta:\n" );
for ( i = 0; i < n; i++ )
{
printf( "%d ", mas[i] );
if ( (i+1) % 5 == 0 )
printf("\n");
}
printf("\n");
return(0);
}
7.1-2 pavyzdys. Skaičių masyvo apdorojimo programėlė.
#include <stdio.h>
#define ILGIS 100
int main()
{ int kiek,i,p, mas[ILGIS];
char baigti;
printf("Kiek ivesite skaiciu? ");
scanf("%d", &N);
printf("Iveskite %d skaiciu:\n ", N );
for ( i = 0; i<N; i++)
scanf("%d", &mas[i] );
do {
printf("Iveskite dalumo pozymi: ");
scanf("%d", &p);
while ( getchar() != ’\n’ );
if (p==0) {
printf("Is 0 dalinti negalima\n");
continue;
}
printf("Skaiciai, kurie dalinasi is %d:", p);
for (i=0; i < N; i++)
if (mas[i] % p == 0)
printf("%7d", mas[i]);
printf("\n");
printf("Jei norite baigti, spauskite T arba t.");
baigti = getchar(); /* scanf("%c", &baigti);*/
}
while (baigti !='t'&& baigti !='T');
return(0);
}
18
7.1-3 pavyzdys. Realiųjų skaičių masyvo apdorojimo programėlė.
7.1-4 pavyzdys. Klaviatūra įvedami n skritulių spinduliai. Išvesti
spindulius, kurių plotas yra didesnis už p.
#include <stdio.h>
int main()
{
const short ILG = 100;
const float PI = 3.14159;
float p, pl, spind[100];
short n, /* skrituliu kiekis */
i;
printf( "Iveskite skrituliu kieki: ");
scanf( "%d", &n );
printf( "Iveskite plota P: " );
scanf( "%f", &p );
for ( i = 1; i <= n; i++ ) /* Ivedame spindulius */
{ printf( "Iveskite %3d - ji spinduli: ", i );
scanf ( "%f", &spind[i] );
}
printf("Spinduliai, kuriu plotas yra didesnis uz %.2f:\n", p);
for ( i = 1; i <= n; i++)
{
pl = PI * spind[i] + spind[i];
if ( pl > p )
printf(" %.2f", spind[i] );
}
}
7.1-5 pavyzdys. Įvesti tekstą su tarpais. Paskaičiuoti, kiek jame yra
žodžių.
#include <stdio.h>
#define L 80
int main()
{
int i, n, zd;
char a[L+1];
zd = n = 0;
printf("Iveskite teksta:\n");
do
a[ ++n ] = getchar();
while( a[n] != '\n' && n < L );
a[0]=' ';
for ( i = 1; i < n; i++ )
if (a [i-1] == ' ' && a[i] != ' ')
zd++;
printf("Zodziu tekste yra %d \n", zd);
19
return(0);
}
7.1.1. DAUGIAMAČIAI MASYVAI
Paskalyje pradines reikšmes galima priskirti tik masyvo tipo konstantoms. C kalboje masyvui
pradines reikšmes galima priskirti taip, kaip ir kitiems kintamiesiems.
7.1-6 pavyzdys. Dvimačio masyvo inicializacija, įverstis ir išvestis C
kalboje.
#include <stdio.h>
#define N 2
#define M 3
int main()
{
int mas1[ N ][ M ] = { { 1, 2, 3 }, { 4, 5, 6 } },
mas2[N][N],
i,j;
puts("Inicializuotas masyvas:" );
for ( i = 0; i < N; i++ )
{
for ( j = 0; j < M; j++ )
printf( "%d ", mas1[ i ][ j ] );
printf( "\n" );
}
puts("Iveskite 4 reiksmes:");
for ( i = 0; i < N; i++ )
for ( j = 0; j < N; j++ )
scanf( "%d", &mas2[ i ][ j ] );
puts("Ivestas masyvas");
for ( i = 0; i < N; i++ ){
for ( j = 0; j < N; j++ )
printf( "%d ", mas2[ i ][ j ] );
printf("\n");
}
return 0;
}
Šių pavyzdžių veikimo rezultatas:
Inicializuotas masyvas:
1 2 3
4 5 6
Iveskite 4 reiksmes:
1 2 3 4
Ivestas masyvas
1 2
3 4
7.2. ĮRAŠAI
Jau angrinėjome struktūrinį duomenų tipą – masyvus. Masyvo elementai yra vieno tipo. Įrašo
tipas yra sudaromas iš įvairios struktūros duomenų. Įrašas yra sudaromas iš skirtingų tipų
20
komponentų, kurie yra vadinami laukais. Kiekvienas įrašo laukas nusakomas tipu ir
vardu, kuriuo jis yra žymimas. Vardas naudojamas nurodant lauką. To paties įrašo laukai
gali būti skirtingų tipų. Tuo įrašai skiriasi nuo masyvo – šio visi elementai turi būti to
paties tipo.
C kalboje įrašai yra aprašomi, naudojant reikšminį žodį struct. Todėl kai kada jie yra
vadinami struktūromis.
Struct strukturos_vardas {
tipas_1 laukas_1;
tipas_2 laukas_2;
…
tipas_n laukas_n;
}; /* dažna klaida – pamirštama ; */
Datos įrašo aprašas atrodo taip: struct data {
int metai, menuo, diena;
};
7.2-1 pavyzdys. Įrašų naudojimą C kalba iliustruoja Ca kalba perrašytas
Error! Reference source not found..
#include <stdio.h>
struct asmuo {
char vardas[20], pavarde[20];
short gmmetai;
};
int main()
{
struct asmuo a;
printf( "\n Iveskite varda: " );
scanf( "%s", a.vardas );
printf( "Iveskite pavarde: " );
scanf( "%s", a.pavarde );
printf( "Iveskite gimimo metus: " );
scanf( "%d", &a.gmmetai );
printf( "\n Vardas: %s \n Pavarde: %s \n ", a.vardas, a.pavarde );
printf( "Gimimo metai: %d\n", a.gmmetai );
return(0);
}
7.3. SĄJUNGA (UNION)
Sąjunga – tai priemonė, kurią naudojant galima įsiminti skirtingų tipų duomenis toje pačioje
vietoje. Sąjungos aprašas:
Union sąjunga {
int sk;
double ilgis;
char sb;
};
Sajungos tipo kintamųjų aprašai:
union sąjunga vienas;
union sąjunga mas[10]; /* sąjungos elementų masyvas */
21
Pirmasis aprašymas sukuria vieną kintamąjį vienas. Kompiliatorius išsikiria tiek atminties,
kad tilptų didžiausias iš sąjungos kintamųjų. Šiuo atveju didžiausias yra double tipo kintamasis.
Jam reikia 8 baitų. Masyvas mas[10] turi 10 elementų. Kiekvieno elemento plotis yra 8 baitai.
Reikšmių priskirimas:
Vienas.sk=2;
Vienas.ilgis=20.0;
Vienas.sb=’a’;
Sąjungoje yra saugoma tik paskutinė pristkirta reikšmė. Programuotojas pats turi sekti, kad
būtų įrašyta reikiamo tipo reikšmė. Klaidingi veiksmai:
Vienas.sb = ’a’;
Skaic = 55.4 * vienas.ilgis; /* klaida, nes paskutinis priskyrimas įrašė simbolį,
o čia tikimasi double tipo reikšmės*/
8 . FUNKCIJOS IR PROCEDŪ ROS
8.1. ĮVADAS
Didesnį uždavinį lengviau yra programuoti dalimis. Kuo savarankiškesnės dalys ir kuo
mažiau ryšių yra tarp tų dalių, tuo lengviau sudaryti ir nagrinėti programą. Pageidautina,
kad programoje aiškiai matytųsi dalių ribos ir būtų nurodyti jų ryšiai. Šios atskiros dalys
gauna pradinius duomenis ir grąžina rezultatus.
Funkcija – programos dalis, kurianti vieną rezultatą. Funkcija turi atlikti vieną užduotį,
o jos vardas turi atitikti šios užduoties esmę. Procedūra – gali turėti 0 ir daugiau rezultatų.
Programos aiškumui yra siekiama labiau naudoti funkcijas, nes tuomet viena dalis
„gamina“ vieną rezultatą.
Į vieną kartą parašytą procedūrą ar funkciją galima kreiptis daug kartų ir atlikti jose
aprašytus veiksmus. Tai užtikrina pakartotiną kodo naudojimą, kad pagreitina
programuotojo darbo našumą.
Informacija tarp funkcijų ir procedūrų yra keičiamasi keliais būdais:
a) parametrais (kintamųjų reikšmės ir vardai),
b) funkcijų vardais (rezultatų reikšmės);
c) globaliais vardais (konstantų, tipų, kintamųjų, funkcijų ir procedūrų vardai).
8.2. STANDARTINĖS FUNKCIJOS
Standartinių funkcijų biblioteka vadinasi ANSI C. Jai priklauso jau žinomos funkcijos printf,
scanf ir pan. Naudojant matematinės bibliotekos funkcijas reikia įtraukti šių funkcijų aprašų failą,
naudojant preprocesoriaus komandą #include <math.h>
Funkcija Tikslas Pavyzdžiai
sqrt(x) Kvadratinė šaknis iš x sqrt(900.0) yra 30.0
exp(x) ex exp(1.0) yras 2.718282
log(x) ln x log(2.718282) yra 1.0
log10(x) lg x log10(1.0) yra 0.0
log10(10.0) yra 1.0
abs(m) Absoliuti reikšmė abs(-10) yra 10
fabs(x) Absoliuti reikšmė Jei x>0, tai fabs(x) yra x
22
Jei x=0, tai fabs(x) yra 0.0
Jei x<0, tai fabs(x) yra –x
ceil(x) Apvalina iki artimiausio nemažesnio sveikojo
skaičiaus
ceil(9.2) yra 10.0
ceil(-9.8) yra –9.0
floor(x) Apvalina iki artimiausio nedidesnio sveikojo
skaičiaus
floor(9.2) yra 9.0
floor(-9.8) yra –10.0
pow(x,y) xy pow(2,7) yra 128.0
pow(9,0.5) yra 3.0
sin(x),
cos(x), tan(x)
Trigonometrinės funkcijos, x – radianuose sin(0.0) yra 0.0
Cos(0.0) yra 1.0
Tan (0.0) yra 0.0
Programos su standartinėmis matematinėmis funkcijomis yra transliuojamos, papildomai
nurodant raktą –lm: gcc fvardas.c –o fvardas –lm
8.3. NAUDOTOJO FUNKCIJOS
Programa dalinama į funkcijas. C kalboje funkcijos negali būti įdėtos viena į kitą.
Kiekviena funkcija turi atlikti vieną užduotį, o jos vardas turi atitikti šios užduoties esmę.
Jei sunku parinkti vardą, vadinasi funkcijoje yra per daug veiksmų. Juos reikia dar
suskaidyti į paprastesnius.
C programą sudaro funkcijos, kurių viena privalo būti main(). Paprastai pagrindinė
funkcija yra pirma, joje yra kviečiamos kitos funkcijos. Kiekvienas vardas turi būti
aprašytas, taigi, ir funkcijos vardas taip pat. Aprašant funkciją, prieš funkcijos vardą yra
nurodomas grąžinamos reikšmės tipas. Jei funkcija nieko negrąžina, tai nurodomas tipas
void. Skliaustuose už funkcijos vardo nurodomi parametrų tipai ir vardai. Jei nieko
neperduodama, rašoma void.
Po preprocesoriaus komandų yra talpinami tipų ir finkcijų aprašai (prototipai,
pirmavaizdžiai). Prototipą (pirmavaizdį) sudaro
<grąžinamos reikšmės tipas> <funkcijos vardas> (<parametrų tipai>);
pavyzdžiui, int maximum (int, int, int);
Šis užrašas reiškia, kad į funkciją maximum ateina tris sveiki skaičiai, o funkcija
grąžina taip sveikąją reikšmę. Parametrų vardai čia nereikalingi.
8.3-1 pavyzdys. Programos su funkcija pavyzdys.
#include <stdio.h>
int main()
{ extern int square(int a); /* prototipas */
int x;
for (x=1; x<=10; x++)
printf("%d ", square(x));
printf("\n");
return 0;
}
int square (int y)
23
{
return y*y;
}
Šios programėlės išvestis:
1 4 9 16 25 36 49 64 81 100
8.4. MASYVŲ PERDAVIMAS FUNKCIJOMS AR PROCEDŪROMS
Paprasčiausias būdas perduoti masyvą kaip parametrą yra jo vardo ir apimties nurodymas.
Masyvo reikšmės yra generuojami atsitiktiniai skaičiai. pavyzdžiai Error! Reference source not
found. ir 8.4-1 pavyzdys iliustruoja masyvo perdavimą funkcijai.
8.4-1 pavyzdys. Šioje programėlėje Error! Reference source not found.
perašytas c kalba. Kadangi masyvo vardas – tai jo pradžios
adresas, todėl perduodamas adresu. o ne reikšme.
#include <stdio.h> /* min_func.c */
#include <stdlib.h>
#include <time.h>
#define ILG 15
extern int Minimumas(int mas[], int apimtis);
int main()
{
int i, mas[ILG];
for (i=0; i<ILG; i++)
{
mas[i]=rand()%(ILG*10);
printf("mas[%2d]=%6d\n", i,mas[i]);
}
i=Minimumas(mas, ILG);
printf("min: mas[%2d]=%6d\n",i,mas[i]);
return 0;
}
int Minimumas(int list[], int size)
{
int i,min, minindex=0;
min=list[minindex];
for (i=1; i<size; i++)
if (list[i]<min)
{
min=list[i];
minindex=i;
}
return minindex;
}
Šios programos rezultatas:
mas[ 0]= 90
mas[ 1]= 75
mas[ 2]= 34
mas[ 3]= 31
mas[ 4]= 124
mas[ 5]= 99
mas[ 6]= 2
mas[ 7]= 135
24
mas[ 8]= 86
mas[ 9]= 97
mas[10]= 8
mas[11]= 71
mas[12]= 16
mas[13]= 101
mas[14]= 38
min: mas[ 6]= 2
8.5. ATMINTIES KLASĖS
Bet koks kintamasis galioja tame bloke, kuriame yra aprašytas.
Kiekvienas kintamasis ir funkcija C kalboje priklauso kokiai nors atminties klasei.
Kintamojo atminties klasė nusako jo egzistavimo laiką ir matomumo sritį. Kintamojo
atminties klasė nustatoma, atsižvelgiant į jo buvimo vietą arba raktinį žodį. Šis žodis yra
dedamas prieš aprašą. Funkcijos klasė visada yra external, jei prieš funkcijos aprašymą
nenurodytas žodis static. C kalboje yra galimos keturios atminties klasės: automatic,
register, extern ir static.
8.5.1.1. Vietiniai kintamieji
Bet koks kintamasis, aprašytas funkcijoje ar bloke ir neturintis išreikšto atminties
klasės nurodymo, laikomas vietiniu. Tokį kintamąjį galima aprašyti nurodant auto.
Tačiau toks aprašymas yra retai taikomas. Vietinis kintamasis galioja nuo aprašo taško iki
bloko pabaigos, kuriame jis yra aprašytas. Naudotis tokiu kintamuoju kitame bloke
negalima. Šie kintamieji pavadinti „automatic“ todėl, kad atmintis jiems yra skiriama, kai
įeinama į bloką, kuriame jis aprašytas. „Išeinant iš bloko“ atmintis, skirta vietiniams
kintamiesiems yra atlaisvinama.
#include <stdio.h>
int main()
{ auto int i;
for (i=10; i>0; i--)
printf("\n %d", i);
printf("\n"); {return 0; Turbo sistemoms}
}
Aprašyti automatiniai kintamieji automatiškai nulio reikšmės negauna, todėl tai reikia
padaryti programuotojui.
8.5.1.2. Registriniai kintamieji
Bazinį žodį register galima naudoti tik automatiniams kintamiesiems arba
formaliems funkcijos parametrams. Šis žodis reiškia, kad naudotojas pageidauja
patalpinti duotą kintamąjį į vieną iš greitaeigių registrų. Kompiliatorius neprivalo
įvykdyti šio reikalavimo. Šį aprašymą rekomenduojama naudoti kintamajam, dažnai
naudojama funkcijoje. Atlikus šį veiksmą, gautas kodas yra kompaktiškas ir greičiau
vykdomas.
Registrinių kintamųjų apribojimas – negalima kreiptis į jo adresą. Be to į registrus
gali būti patalpinti tik short ir int tipo kintamieji bei artimos rodyklės.
25
8.5.1.3. Išoriniai kintamieji
Bet koks kintamasis, aprašytas faile prieš funkcijas ir neturintis atminties klasės
apibrėžimo, yra laikomas išoriniu (dar vadinamas globaliu). Globalūs kintamieji galioja
nuo aprašo vietos iki failo pabaigos. Jei bloke yra aprašytas vietinis kintamasis, kurio
vardas sutampa su globaliojo kintamojo vardu, tai šiame bloke galioja vietinis kintamasis.
Išėjus iš bloko, vėl galioja globalus kintamasis.
Išoriniams kintamiesiems kartą paskiriama atmintis yra saugoma iki programos
vykdymo pabaigos. Globaliems kintamiesiems yra automatiškai priskiriama nulinė
reikšmė. Išorinį kintamąjį galima aprašyti ir funkcijoje, kurioje jis yra naudojamas,
naudojant raktinį žodį extern.
Jei programoje yra naudojami kintamieji, aprašyti kitame faile, yra būtina naudoti
extern. Aprašius išorinius kintamuosius ir funkcijas viename faile, naudojant extern,
juos galima naudoti ir kituose failuose.
8.5.1.4. Statiniai kintamieji
Statiniai kintamieji gali būti globalūs ir vietiniai. Vietinis statinis kintamasis yra
aprašomas funkcijoje ir turi tokią pačią galiojimo sritį, kaip ir automatinis kintamasis. Jis
įgyja pradinę reikšmę, pirmąkart aktyvuojant funkciją. Bet kintamasis neišnyksta. Kai
turinti jį funkcija baigia darbą, statinio kintamojo reikšmė yra saugoma nuo vieno
funkcijos kreipinio iki kito.
8.5-1 pavyzdys. Statinių paramterų veikimą iliustruojanti programėlė
#include <stdio.h>
int a=5;
int main()
{
void skaic(void);
int kiekis;
printf("main: a=%d\n", a);
for (kiekis=1; kiekis<=3; kiekis++)
{
printf("Iteracija %d\n", kiekis);
a--;
skaic();
}
printf("\n");
return 0;
}
void skaic (void)
{
int fa=1;
static int sta=1;
printf("funkcija: fa=%d ir sta=%d a=%d\n", fa++, sta++, a++);
}
26
Funkcija skaic() padidina kiekvieno kintamojo reikšmę atspausdinus. Perjungti
srautą galima taip: ./prog>rez.dat
Šios programos rezultatai tokie:
main: a=5
Iteracija 1
fa=1 ir sta=1 a=4
Iteracija 2
fa=1 ir sta=2 a=4
Iteracija 3
fa=1 ir sta=3 a=4
Statinis kintamasis sta atsimena savo reikšmę, tuo tarpu kintamajam fa pradinė
reikšmė yra suteikiama kiekvieną kartą iš naujo.
Globalūs statiniai kintamieji aprašomi failo pradžioje raktiniu žodžiu static. Šis žodis
gali būti naudojamas ir funkcijoms aprašyti. Šios klasės kintamieji ir funkcijos matomi
nuo aprašymo taško iki failo pabaigos. Juos galios panaudoti tik tame pačiame faile, nes
iš kitų failų jie nematomi.
Susipažinus su kintamųjų klasėmis, kyla klausimas, kokius kintamuosius naudoti.
Atsakymas paprastas – jei tik įmanoma, reikia naudoti vietinius (automatinius, lokalius)
kintamuosius. Labai patraukliai atrodo išoriniai kintamieji. Tačiau jie pavojingi tuo, kad
šių kintamųjų reikšmė gali būti pakeista bet kurioje funkcijoje. Funkcijos turi būti kiek
galima labiau savarankiškesnės. Prieš naudojant kokią nors kitą kintamųjų klasę, reikia
įsitikinti, ar tikrai ji yra būtina.
8.6. C PARAMETRAI-KINTAMIEJI
8.6.1. KINTAMŲJŲ PERDAVIMAS PARAMETRAIS-KINTAMAISIAIS
Funkcija grąžina vieną reikšmę. Tais atvejais, kai būtina grąžinti kelias reikšmes, parametrus
galima perduoti ir parametrais-kintamaisiais.
8.6-1 pavyzdys. Sveikas skaičius perduodamas parametru-reikšme
#include <stdio.h>
int kubas_par_reiksme( int );
int main()
{
int skaicius = 5;
printf( "\n Pradine reiksme yra %d " , skaicius );
skaicius = kubas_par_reiksme ( skaicius );
printf( "\n Po funkcijos reiksme yra %d \n", skaicius);
return 0;
}
int kubas_par_reiksme(int n)
{
return n * n * n;
27
}
8.6-2 pavyzdys. Skaičius perduodamas parametru-kintamuoju
#include <stdio.h>
void kubas_par_kint( int *);
int main()
{
int skaicius = 5;
printf("\n Pradine reiksme yra %d ", skaicius);
kubas_par_kint ( &skaicius);
printf("\n Po funkcijos reiksme yra %d \n", skaicius );
return 0;
}
void kubas_par_kint (int *n)
{
*n=*n * *n * *n;
}
Abiem atvejais rezultatas yra toks pat.:
Pradine reiksme yra 5
Po funkcijos reiksme yra 125
8.6.2. MASYVŲ PERDAVIMAS FUNKCIJOMS IR PROCEDŪROMS
Perduodant masyvą fiunkcijai, parametrų sąraše tiesiog rašome jo vardą. Masyvo vardas – tai
pirmo jo elemento adresas. Šios funkcijos prototipo parametrų sąraše nurodome, kad bus
perduodamas masyvas. masyvaS
8.6-3 pavyzdys. Masyvo perdavimas
#include <stdio.h>
#define DYDIS 5
void KeistiMasyva (int[], int);
int main()
{
int a[DYDIS] = { 0, 1, 2, 3, 4}, i;
printf( "\n Masyvo perdavimas parametru-kintamuoju\n",
" Pradinis masyvas yra:\n" );
for ( i = 0; i < DYDIS; i++ )
printf("%3d", a[i]);
printf("\n");
KeistiMasyva( a, DYDIS);
printf("\n Pakeistas masyvas:\n");
for ( i = 0; i < DYDIS; i++ )
printf("%3d", a[i] );
printf( "\n" );
return 0;
}
28
void KeistiMasyva (int b[], int size)
{
int j;
for ( j = 0; j <= size - 1; j++ )
b[j] *= 2;
}
Šios programos rezultatas yra
Masyvo perdavimas parametru-kintamuoju
0 1 2 3 4
Pakeistas masyvas:
0 2 4 6 8
8.7. PAVYZDŽIAI
8.7-1 pavyzdys Paskaičiuoti atstumą tarp dviejų dvimatės plokštumos
taškų.
program atstumo_skaiciavimas;
type taskas = record
x,y:real
end;
var v1, v2: taskas;
ats : real;
function atstumas( c1, c2 : taskas) : real;
begin
atstumas := sqrt (sqr(c2.x-c1.x)+sqr(c2.y-c1.y))
end;
begin
write( 'Iveskite pirmo tasko x ir y kordinates:' );
readln( v1.x , v1.y );
write( 'Iveskite antro tasko x ir y kordinates:' );
readln( v2.x , v2.y );
ats := atstumas( v1, v2 );
writeln( 'Atstumas yra ', ats:7:2 )
end.
8.7-2 pavyzdys. Ta pati programėlė perrašyta C kalba.
#include <stdio.h>
#include <math.h>
#define TASKAS struct taskas
TASKAS {
float x,y;
};
double atstumas (TASKAS t1, TASKAS t2);
int main()
{
TASKAS v1,v2;
double ats;
29
printf("Iveskite pirmo tasko koordinates:");
scanf("%f %f", &v1.x, &v1.y);
printf("Iveskite antro tasko koordinates:");
scanf("%f %f", &v2.x, &v2.y);
ats= atstumas(v1, v2);
printf("Atstumas yra %.2f \n", ats);
return 0;
}
double atstumas (TASKAS c1, TASKAS c2)
{
double atstum;
atstum = sqrt(pow(c2.x-c1.x,2)+pow(c2.y-c1.y,2));
return atstum;
}
9 . FAILAI
C kalboje duomenų įvesčiai ir išvesčiai naudojami trys standartiniai failai:
stdin – įvesties failas, skaitymui iš klaviatūros,
stdout – išvesties failas, rašymui į monitorių,
stderr – klaidos failas.
Į failą rodo nuoroda į struktūrą FILE:
FILE *f;
C kalboje nėra užduota konkreti failo struktūra. Tai yra programuotojo rūpestis. C
kalboje dirbti su failais galime nuoseklios ir tiesioginės kreipties režimu.
C kalboje duomenų įvedimui yra naudojama funkcija scanf(). Simbolio įvesčiai iš input
galima naudoti specializuotą funkciją getchar().
Funkcijos scanf() argumentai – įvesties formatas ir kintamųjų adresai. Naudojant šią funkciją
reikia atsiminti šias taisykles:
1. Jeigu įvedama vieno iš pagrindinių tipų reikšmės, tai prieš kintamojo vardą reikia
rašyti ampersendo simbolį &.
2. Jeigu įvedama simbolių eilutės tipo reikšmė, simbolio & naudoti nereikia.
Įvedami duomenys vienas nuo kito skiriami tarpais. Tarpų kiekis neribotas. Norint duomenis
skirti kableliais, valdančiojoje eilutėje tarp formatų specifikacijų reikia padėti kablelius
9.1.1. ATVERTI FAILĄ
Funkcija fopen atveria failą tam tikru režimu:
f=fopen(“duom.dat”, režimas);
Režimai:
“r” – skaitymui, failas turi egzistuoti
“w” – rašymui, jei failas egzistuoja, tuomet jo turinys \yra išvalomas
“a” – papildymui prie failo pabaigos.
Jei reikia skaityti ir rašyti, tuomet galimi tokie režimai:
30
“r+” – skaitymui ir rašymui,
“w+” – skaitymui ir rašymui, jei failas egzistuoja, tuoemt atvėriant jis yra išvalomas
“a+” – skaitymui ir rašymui, o įrašai yra daromi failo pabaigoje.
Jei atveriant failą įvyksta klaida, fopen grąžina NULL.
9.1.2. NUOSEKLIOS KREIPTIES FAILO SKAITYMAS
fscanf (failo_nuoroda, formatas, įvedamų_kintamųjų_adresai);
9.1.3. ATSUKTI FAILO RODYKLĘ Į PRADŽIĄ
Nuosekliame faile skaitome duomenis nuo pradžios iki pabaigos. C kalboje yra
galimybė “atsukti”
rewind ( failo_nuoroda );
9.1.4. RAŠYMAS Į NUOSEKLIOS KREIPTIES FAILĄ
fprintf(failo_nuoroda, formatas, išvedamų_kintamųjų_sąrašas);
pvz. Išvesti į failą sveiką skaičių
fprintf(f, “%d”, number);
9.1.5. UŽVERTI FAILĄ
fclose( failo_nuoroda);
8.7-1 pavyzdys. Nuoseklios kreipties failo apdorojimas.
#include <stdio.h>
int main()
{
int account;
char name[20], duom[12], rez[12];
double balance;
FILE *f, *r;
puts( "Iveskite ivesties failo varda:" );
scanf( "%s", duom);
if ( ( f = fopen ( duom,"r" ) ) == NULL )
printf( "Negalime atverti failo \"%s\"\n ", duom );
else
{
puts( "Iveskite isvesties failo varda:" );
scanf( "%s", rez );
if ( ( r = fopen(rez,"w") ) == NULL )
printf ( "Negalime atverti failo \"%s\"\n ", rez );
else
{
fprintf( r,"%-13s%-13s%s \n", "Saskaitos nr", "Vardas",
"Likutis");
fscanf ( f, "%d%s%lf", &account, name, &balance);
31
while ( !feof( f ) )
{
fprintf( r, "%-13d%-13s%7.2f\n", account, name, balance );
fscanf( f, "%d%s%lf", &account, name, &balance );
}
fclose( f );
fclose( r );
}
}
return 0;
}
Tarkime, duomenų faile turime šiuos duomenis:
45 Jonas 4545.2
215 Petras 2541.25
52 Ona 1114.5
541 Jurate 2525
Tuomet rezultatų faile yra:
Saskaitos nr Vardas Likutis
45 Jonas 4545.20
215 Petras 2541.25
52 Ona 1114.50
541 Jurate 2525.00
8.7-2 pavyzdys Nuoseklios kreipties failo apdorojimas (Paskaliu).
program failai;
var f, r:text;
duom, rez: string[15];
c:char;
name: string[10];
account : integer;
balance : real;
begin
write('Iveskite ivesties failo varda: ');
readln(duom);
Assign(f, duom);
{$I-}
Reset(f);
{$I+}
if Ioresult<> 0 then
writeln('Negalime atverti failo: ', duom)
else
begin
write('Iveskite isvesties failo varda: ');
readln(rez);
Assign(r,rez);
{$I-}
Rewrite(r);
{$I+}
if Ioresult<> 0 then
writeln('Negalime atverti failo: ', rez)
else
begin
32
writeln(r,'Saskaitos nr Vardas Likutis');
while not Eof(f) do
if not eoln(f) then
begin
read(f,account);
read(f,c);
name:='';
while c=' ' do read(f,c);
while (c<>' ') and not Eoln(f) do
begin
name:=name+c;
read(f,c);
end;
readln(f,balance);
writeln(r,account:12, name:12, balance:13:2);
end
else readln(f)
end;
close(f);
close(r)
end
end.
Įvesties failas yra tas pats, kaip ir aukščiau pateiktame pavyzdyje (Error! Reference
source not found.), o rezultatai yra:
Saskaitos nr Vardas Likutis
45 Jonas 4545.20
215 Petras 2541.25
52 Ona 1114.50
541 sdfsdfsdf 2525.10
9.2. C LAISVOSIOS KREIPTIES FAILŲ SKAITYMAS IR RAŠYMAS
Laisvosios kreipties failų duomenis skaito funkcija fread , pavyzdžiui
fread(&klientas, sizeof(klientoduom), 1, f);
Funkcija fwrite 5ra6o tam tikrą blokų skaičių į tą failo vietą, į kurią rodo failo nuoroda fwrite(&klientas, sizeof(klientoduom), 1, f); /* iš pavyzdžio */
int i;
fwrite(&number, sizeof(int), 1, f);
Funkcija fseek perkelia failo nuorodą per tiek blokų, kiek nurodo išraiška int fseek(FILE *file, long int per_kiek, int nuo_kurios_vietos);
Funkcijos pavyzdys: Fseek (f, kiek*sizeof(klientoduom), SEEK_SET);
Parametras nuo_kurios_vietos yra apibrėžiamas taip:
33
SEEK_SET – nuo pradžios
SEEK_CUR – nuo einamosios pozicijos
SEEK_END – nuo faiko pabaigos
9.2-1 pavyzdys. Darbas su laisvosios kreipties failu. Error! Reference
source not found. yra šios programos, analogija Paskalio kalba.
#include <stdio.h> /* sask_fun.c */
#include <stdlib.h>
#define KLIENTO_DUOM struct klientoduom
struct klientoduom
{
int sasknr;
char pavarde[13];
char vardas[13];
float likutis;
};
void Pildyti(FILE *);
void Tuscias (FILE *);
int main()
{
int i;
KLIENTO_DUOM klientas;
FILE *f;
if ((f=fopen("sask.dat", "w"))==NULL)
printf("Failas sask.dat negali buti atvertas\n");
else {
Tuscias(f);
fclose(f);
if ( (f=fopen("sask.dat", "r+"))==NULL)
printf("Failas sask.dat negali buti atvertas\n");
else {
Pildyti(f);
rewind(f);
while ( !feof(f) ) {
fread(&klientas, sizeof(KLIENTO_DUOM),1,f);
/* if (klientas.sasknr != 0) */
printf("%-8d%-13s%-13s%7.2f\n", klientas.sasknr,
klientas.pavarde, klientas.vardas,
klientas.likutis);
}
fclose(f);
}
}
return 0;
}
void Tuscias(FILE *g)
{
34
int i;
KLIENTO_DUOM kl={0,"", "", 0.0};
for (i=1; i<=10; i++)
fwrite(&kl, sizeof(KLIENTO_DUOM), 1, g);
}
void Pildyti( FILE *g)
{
int i;
KLIENTO_DUOM kl;
/* duomenu ivedimas */
puts("Iveskite saskaitos numeri (nuo 1 iki 10)");
scanf("%d",&kl.sasknr );
while(kl.sasknr != 0)
{
printf("Iveskite pavarde, varda ir likutis\n");
fscanf(stdin, "%s%s%f", kl.pavarde, kl.vardas,
&kl.likutis);
fseek(g, (kl.sasknr-1)*sizeof(KLIENTO_DUOM), SEEK_SET);
fwrite(&kl, sizeof(KLIENTO_DUOM),1,g);
puts("Iveskite saskaitos nr:");
scanf("%d", &kl.sasknr);
}
}
}
9.3. KITI PAVYZDŽIAI
9.3-1 pavyzdys Failo atvėrimas funkcijoje arba procedūroje.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int account;
char name[20];
double balance;
FILE *skait, *ras;
extern FILE *atverti(char []);
skait =atverti("r");
ras =atverti("w");
fprintf(ras,"%-13s%-13s%s \n", "Saskaitos nr", "Vardas", "Likutis");
fscanf (skait, "%d%s%lf", &account, name, &balance);
while (!feof(skait))
{
fprintf(ras,"%-13d%-13s%7.2f\n", account, name, balance);
fscanf(skait,"%d%s%lf", &account, name, &balance);
}
fclose(skait);
35
fclose(ras);
return 0;
}
FILE *atverti(char rez[])
{
FILE *file;
char duom[12];
if (strcmp(rez,"r")==0)
puts("Iveskite ivesties failo varda:");
else
puts("Iveskite isvesties failo varda:");
scanf("%s", duom);
if ((file=fopen(duom,rez))==NULL )
{
printf("Negalime atverti failo \"%s\"\n ", duom);
exit(0);
}
return file;
}
9.3-2 pavyzdys. 9.3-1 pavyzdys perrašytas Paskalio kalba.
program failai;
var skait, ras:text;
c:char;
name: string[10];
account : integer;
balance : real;
procedure ivesti (rez:string; var f:text);
var duom: string[12];
begin
if rez='ivesti' then
begin
write('Iveskite ivesties failo varda: ');
readln(duom);
Assign(f, duom);
{$I-}
Reset(f);
if Ioresult<> 0 then
begin
writeln('Negalime atverti failo: ', duom);
exit;
end;
{$I+}
end
else
begin
write('Iveskite isvesties failo varda: ');
readln(duom);
Assign(f, duom);
{$I-}
Rewrite(f);
if Ioresult<> 0 then
begin
36
writeln('Negalime atverti failo: ', duom);
exit;
end;
{$I+}
end;
end;
begin
ivesti('ivesti', skait);
ivesti('isvesti', ras);
writeln(ras,'Saskaitos nr Vardas Likutis');
while not Eof(skait) do
if not eoln(skait) then
begin
read(skait,account);
read(skait,c);
name:='';
while c=' ' do read(skait,c);
while (c<>' ') and not Eoln(skait) do
begin
name:=name+c;
read(skait,c);
end;
readln(skait,balance);
writeln(ras,account:13, name:13, balance:13:2);
end
else readln(skait);
close(skait);
close(ras)
end.
LITERATŪRA
1. Vladas Tumasonis. Paskalis ir Turbo Paskalis 7.0. Ūkas, Vilnius, 1993.
2. Saulius Ragaišis. Informatikos įvadas: metodinė priemonė. 2001.
http://www.mif.vu.lt/~ragaisis/InfIvadas/index.html
3. Jonas Blonskis, Vytautas Bukšnaitis, Jonas Smolinskas, Antanas Vidžiūnas.
Programavimo praktikumas: programavimas su Turbo Paskaliu. „Smaltijos“ leidykla,
Kaunas, 2000.
4. H. M. Deitel, P. J. Deitel. C: how to program. Third edition. Prentice Hall, 2001.
5. С. А. Абрамов, Г.Г. Гнездилова, Е. Н. Капустина, М. И. Селюн. Задачи по
программированию. Наука, Москиа, 19887