clrscrQ ;
cout << "Берілген
жиым:\п";
for(i=0;icout « setw(4) « m[i];
cout « endl;
cout << "Ізделетін санды енгізіңіз: ”;
cin '>> n;
a=0; first=0;last=count-l;
found=0;
// әлі элемент табылмаған
do
// іздеуді қайталау
{ i=(first+last)/2; // жиымды 2 бөлікке бөлу
if(m[i]==n)
found=l;
if(m[i]>n)
first=i+l; // сан оң жақ бөлікте
last=i-l;
// сан сол жақ бөлікте
а++;
} // керек элемент табылса немесе жиым толық қарастырылса, аяқтау
while(!(found || first>last));
if (found)
{ cout << "Керекті элемент “ << n <<" жиымдағы
cout << i << " позицияда орналаскан\п“;
>
else cout << "Жиымда керекті элемент жоқ...” << n << endl;
cout
"Іздеу " << a << " итерацияда орындалды\п";
getch();
}
,
| | | ^ I Ц ; B |njj
/
Программа жұмысынын нэтижесі:
Берілген жиым:
20 20 19 19 19 18 17 17 12 12 11 10 9 9 5 5 3 3 2
1
Ізделетін санды енх^ідіңіз: 10
Керекті элемент 10 ж и ы м д а т 11 позицияда орналасқан
Іздеу 3 итерацяда орындалды
5 3 3 Ж иым элементтерін жою жэне ж иы мга жаца элемент кірістіру
Жиым элементтері бірінен соны бірі тізбектеліп катар түрған жады ұяларында
орналасады. Сондыктан еш киындықсыз соңгы элементті жоюга (өшіріп тастауға)
немесе жиым соңына жаңа элемент қосуға болады. Қалган жағдайларда, бір
элемент өшірілсе, одан кейінгілерін алға бір орынга жылжытуға тура келеді. Ал
128
Н Н
бір элемент қосу керек болса, оған орын босатып алу үшін, элементтер арасын
«ашу» керек. Мысал ретінде жиымнан берілген мэнге тең элементтерді өшіретін
программа мәтінін қарастырайық.
//Программа берілген мәні бар элементті тауып өшіреді
#include
#include
#include
main()
{const count=10; // элементтер саны
int m[count
]={33,43,
2,
33,
90,
78,
60,
33,33,
21},
n, // эл-ттер саны айнымалысы
i, // санауыш
j, // эл-ттерді жылжыту кезіндегі цикл параметрі
х; // өшірілетін элемент
clrscr();
cout << "Берілген массив:\n";
for(i=0;icout « setw(4) « m[i];
cout << endl;
cout << "Өшірілетін элементті енгізіңіз: ";
cin >> x;
n=count; i=j=0; // инициалдау
do
// іздеуді
қайталау
{ while(ra[i]==x)
{ j=i;
do
{ m [j]= m [j+ l];
j++;
>
while(j
n--; // жиым эл-ттерін азайту
>
i++;
>
while(ifor(i=n;iсоңры жакты нөлге теңеу
cout << "Алынган жиым:";
// егер соңғы нөлдерді шығару керек болмаса, циклдегі count
// айнымалысын п айнымалысына өзгерту керек
for(i=0;іcout << setw(4) << m[i];
cout << endl;
getch();
\
129
П р о г р а м м а ж ұ м ы с ы н ә т и ж е с і:
Бер±лг*ея массив:
33 43
2 33
90 78 60 33 33 21
Өшірілетін элемөнтті еягіаің і з: 60
Альютан жиым:
33 43
2 33
90 78 33 33 21
0
5.4 Адрестік операциялар
Адреспк операциялар үшін С/С-н- тілінде екі арнайы оператор қодданылады.
& - адресті анықтау (алу) үшін қодданылатын операция;
* - адрес арқылы қатынас жасау үшін қолданылатын операция (көрсетілген
адрестегі мэнді пайдалану).
& операциясы берілген айнымалының адресін қайтарады. Мысалы, программа
мәтініиде р айнымалысы былай сипатгалған болсын:
int р;
оңда &р жазуы осы айнымалының компьютер жадында орналасқан ұясының
адресі больш табылады.
Н ұсқауыш тар. Нұсқауыш мәліметтердің адресін сактайтын айнымалы болып
табылады. Жалпы алганда, нұскауыш адрестің символдық кескінделуі болып
саналады.
Қарастырылатын мысалда &р — р атты айнымалыга сілтейтін нұскауыш болып
табылады. Накты адрес ретінде белгілі бір сан тұрады, ал &р нұскауыш типті
константа болып табылады. Басқаша айтар болсақ, erep ptr нұскауыш атауы
болса, онда ptr=& p өрнегі р адресін ptr айнымалысына меншіктейді. & — адрес алу
операциясы. P t r көрсетіп түрган мэнді аныктау үшін келесідей жанамалы
адрестеу операциясын пайдалану қажет:
V=*ptr;
C/C++ тілінде нүскауыш типті айнымалылар да бар. Нұскауыш типті айныма-
лылар мәні болып белгілі бір шаманын адресі санапады.
Мысалы, нұсқауыш типті айнымалы p t r идентификаторы аркылы белгіленген
болсын, онда төмендегі оператор р айнымалысының адресін p t r атты нұсқауыш
типті айнымалыга меншіктейді. P t r атты нүсқауыш типті айнымалы баска да
объектіге сілтеуі мүмкін.
Мысалы:
int *ptr;
ptr=&p; ptr=&max;
*
операциясы - адрес арқылы катынас жасау үшін пайдаланылатын операция,
ол одан кейін тұрган айнымалының нұскауыш екенін білдіреді. Мысалы, p t r
нұсқауыш типті айнымалысында жогарыда көрсетілгендей max айнымалысының
адресі сакталган болсын. Осы айнымалынын мәнін білу үшін * адресі бойынша
ізо
каты нас жасау операциясын қолдануға
үшін келесі операцияны орындау кажет
нұсқауышы
res=*’p t r ; /* r e s айнымапысына p t r айнымалысында сақталған адрестегі
мәнді меншіктеу * /
Төмендегі екі меншіктеу операциялары
ptr=&x;
y=*ptr;
мынадай бір оператор орыңдайтын
у=х;
әрекетті гана жүзеге асырады. Бірак жиымдарды және құрыльгмдарды пайдалг
әрекеттерді
детеді.
Нұсқауыиіты сипаттау. Нұсқауыш типті айнымапыны сипаттағанда берілген
нұскауыш қандай типтегіі айнымалыга сілтейтінін көрсету қажет. Өйткені әртүрлі
типті айнымалыга компьютер жадында ұялардың да әртүрлі саны бөлініп
беріледі. Мысалы:
i n t * р і;
/ / бүтін типті айнымалыга нұсқауыш
c h a r *рс;
/ / символдык айнымалыга нұсқауыш
f l o a t * p f , *pg; / / накты типтегі айнымалыга нұсқауыш
Нұскауыштармен орындалатын
көруге болады.
#include
#include
main()
{
float x=15.15,y,*ptr;
ptr=&x; clrscr();
y=*ptr;
printf("x=%f y=%f\n",x,y);
*ptr++;
printf(”x=%f y=%f\n",x,y);
y=l+*ptr*y;
карапайым әрекеттерді келесі мысалдан
getch();
return 0:
y=%f\n”Jx,y);
x=15.150000 y = 1 5 .150000
x=15.150000 y=15.150000
>
аинымалылар сиякты
Бұл программа нәтижесі төртбұрыш ішінде көрсетілген.
Нұскауыштарга меншіктеу операциясын колдана апамыз. Бір типтегі
нұсқауыштар меншіктеу операцияларында қарапайым
пайдаланыла апады. Тагы бір мысал қарастырайык.
#include
#include
main()
{ int x-10,*g/ p;
131
clrscr();
I
p=&x;
j
g = p;
'
■
printf ("p=%p\n",p); // p
ішкі мэнін шыгару
printf (,,g=%p\n,,Jg); // g
ішкі мәнін шыгару
p r in tf ( " x = % d *g=% d\n"J x , * g ) ; / / х -т іж эн еg адресіндегі
/ / шаманы шығару
getch();
р
return
0
;
i
Бұл мысалда p r i n t f ( ) функциясынын тағы бір %р форматы көрсетілген. Ол
жады адресін оналтылық түрде экранга шығарады. Мысал нәтижесі:
Нұсқауышка кез келген жады адресін меншіктеуге болады. Бірақ бүтін типке
мынадай нұсқауыш сипатталса,
i n t *р;
Ал, бұл нұскауышка берілген адресге накты f l o a t типіндегі х айнымалысы
тұрса, оны орындау кезінде
р=&х;
жолында қате шыгады. Мұндай қатені int типіндегі нұскауышты f l o a t типіне
төмендегідей түрде әдейілеп түрлендіру аркылы дұрыстай аламыз:
p = (in t* )& x ;
М^нда бірақ бастапқы нұсқауыштың қай типті көрсеткені жайлы мэлімет
жоғалады. Осыган мысал келтірейік.
# in c l u d e < s td io .h >
# i n c l u d e < c o n io .h >
/ / нұсқауы ш т и п т е р і н і ң с ә й к е с с і з д і г і
m ain ( )
{ f l o a t х=
1
Ө .
1
, у , *p;
d r s c r Q ;
p = & x ;// мұны p = ( i n t ) & x ; д е п ө з г е р т у к е р е к
У=Рі I I осы жолда кате шыгады
p r in tf ( " x = % f y= % f\n” >x J y ) ;
g e t c h ( ) ;
r e t u r n
0
;
}
Басқа айнымалылармен жұмыс істеу кезіндегі тэрізді нұскауыштармен де
арифметикалык операцияларды: косу мен азайтуды орындауға болады (++ жэне —
- амалдары
косу/алудың бір түрі
болып табылады).
Нұсқауыштармен
орындалатын операциялардын өз өзгешеліктері бар. Оган мысал келтірейік.
132
#mclude
#include
main ()
{ int
* p , * g , x }
clrscr();
//x=5;
p=&xj
g=p+i;
printf("p=%p g=%p\n",p,g);
getch();
return 0;
>
Программа нәтижесінен p мэнін бірге арттыргаңда, g нұсқауыш мәні екіге
өзгергенін байкаймыз. Бұл дұрыс, өйткені нұсқауыштың жаңа мәні жады ұясының
келесі адресін емес, келесі бүтін санның адресін көрсетуі тиіс.
Ал бүтін санның компьютер жадында екі байт орын алатыны белгілі гой. Егер
нұсқауыштың типі
float
болса, онда адрес 4-ке, ал
double
болса,
8
-ге өзгеретін
еді, ягни адрес берілген типтің жадыда алатын орнына (ұзындыгына) сэйкес
артып отырады.
Нұсқауыштарга тек бірді гана косу/азайту емес, оларга шагын бүтін сандарды
косып алуга болады. Мысалы бүтін типтегі р нұсқауышынын мәні 2000 болатын
болса, онда g=p+3 нәтижесінде g мәні 2006 болып өзгереді. Ал егерде float
типіндегі нұсқауыш мәні р
1
=
2
Ө
0 0
болса, онда мынадай амап
g l= p l+ 1 0 ;
нэтижесінде g l мәні 2040 болар еді. Жаппы нұскауыш мәнін
мынадай р+n амалынан сон есептеу өрнегі:
<р>=<р>+п*<нұсқауыштың базалық типі алатын байттар саны>;
Осындай жолмен бір нұсқауыш мэнінен екінші нұсқауыш мәнін азайта
аламыз. Мысалы р мен р і бір жиым элементтеріне нұскауыш болатын болса, онда
р - р і сол жиым элементтерінің нұскауыштарга сәйкес иңдекстерінің айьфмасын
береді.
Нұсқауыштармен баска арифметикалык операцияларды орындай алмаймыз,
мысалы, екі нұскауышты қосуга болмайды, нұсқауышты бір санга көбейтудің де
мағынасы жоқ.
Нұсқауыштарды салыстыруга болады, мұнда барлық
6
операцияны да колдана
аламыз: <, >, <=, >=, ==, ! = .
Мысалы, pкіші екенін білдіреді. Егер бұлар бір жиым элементтерін нұсқап тұрса, онда р
көрсетіп тұрған элемент индексі g көрсетіп тұрган элемент индексінен кіші
болады.
133
5.4.1 Функциялар арасында байланыс жасау үшін
нүсқауыштарды панд алану
Кейде функцияны нұсқауышсыз пайдалана алмайтын кездер болады.
Нұсқауышсыз қодданылатын функция мысалын келтірейік, мұнда екі айны-
малынын мәндерін бір-бірімен алмастырамыз.
#include
щ
void change(int u,int v);
void main()
{
int x=5,y=10;
cout << x « " * « у << endl;
change(x,y);
cout << x « " “ « у << endl;
}
change(int u,int v)
{
int temp;
temp=u;
u=v;
v=temp;
}
Программаны орындаған соң, оның нәтижесі мынадай болады:
I
5 10 I
Мун да change функциясы ішінде u,v айнымалылары мәндерін алмастырады,
бірақ ол негізгі профаммадағы х,у мәндеріне эсер етпейді.
Функция (return операторы да) негізгі программага тек бір шаманы гана
кайтарады, ал оған екі мән қайтару керек. Функция дұрыс жұмыс істеуі үшін
нұскауыштарды пайдалану керек.
1-мысал. Бұл профаммада айнымалынын мэндерін ауыстыру үшін нұскауыштар
пайдал аны л ган:
tinclude
void change(int *u,int *v);
void main()
{ f
:
int x=5,y=10;
cout << x << " " « у « endl;
change(&x,&y);
cout << x << ” ** << у << endl;
>
change(int *u,int *v)
{
int temp;
134
temp=*u;
*u=*v;
♦v=tempj
}
Нәтижесі:
x=5
y=10
Функцияны шақырғанда, айнымалы туралы ақпарат функцияға екі түрде
беріле алады екен.
Erep functionl(x)
түрі пайдаланылса, х мәні беріледі. Ал
erep func-
tion2(&x)
түрі пайдаланылса, онда х адресі беріледі.
Нұскауыштарды инициалдау
Нұсқауыштарды инициалдауды оларды хабарлау кезінде жасауға болады.
Мысалы:
int ir;
int *pr=&ir;
Нұсқауышты * p r деп жарияласақ, оған
ir
айнымалысының адресі меншік-
теледі, ал і г айнымалысы элі инициалданбаган. Адресті алу операциясын кез
келген өрнекпен қолдана алмаймыз.
5.4.2 Н ұскауыш тардың ж иымдарға қолданылуы
Жиымдарды белгілеп жазу нұсқауыштарды қолданудың жасырын бір түрі болып
табылады. Жиым аты оның алғашкы элементін көрсетіп тұрган нұскауыш болып
саналады, мысалы,
f [ ]
— жиым болса, онда
f =&f [
0
] ;
болады,
сонгы теңдіктің екі жагы да жиымның алғашқы элементін анықтайды. Екі
белгілеу де нұсқауыш типіндегі тұрақты (константа) болып саналады, өйткені
олар программа жұмысы барысында ешқандай өзгеріске ұшырамайды. Бірақ
оларды нұскауыш типіндегі айнымалыга меншіктеп, сол айнымапының мәнін
өзгертуге болады. Мысап келтірейік.
# i n c l u d e < i o s t r e a m . h >
v o i d m a i n ()
I
i n t d [ 4 ] = { l , 2 , 3 , 4 } ;
i n t ^ p , i , g ;
f l o a t b [ 4 ] = { l , 2 , 3 , 4 } ;
f l o a t ^ p l ;
p=d; g=*(p+
2
);
p l = b ; i = * ( p l +
1
) ;
c o u t « g « " w « i ;
>
135
Бұл профамма нәтижесі:
теңдіктер дұрыс болып
d+2==&d[2]
*(d+2)==d[2] - бұлард а бірдей.
Мынадай өрнек *(d+2) -
(*d+2) - жиымның алғаи
адресті көрсетіп тұр
береді
Kocaj
синоним болып есептеледі
in t у [ ] ;
in t *у;
Жиымдармен жұмыс істеу кезінде нұсқауышты пайдалану мысаді
/ / жиым э л е м е н т т е р ін ің арифметикалық ортасын таб у
# in clu d e
void main()
{
in t d [ ] = { l J2 ,3 J4 } ,* p Ji Jn;
f l o a t s = 0 ,s r ;
n = siz e o f d / ( s i z e o f ( i n t ) ) ;
cout << n << en d l;
P=d;
f o r ( i= 0 ; i < n ; i+ + )
s-f=*(p+i);
sr= s/n ;
cout << sr << en d l;
Алдымен жиымды, сонан соң нұсқауышты пайдаланып, арифметикалык ортаны
анықтайтын функция жазайық.
/ / жиым арқылы арифметикалык ортаны аны қтау
# in c lu d e < io stream .h >
i n t m n(int p [ ] , i n t n );
i n t m ain()
{
i n t d [ ] = { l , 2 , 3 , 4 } , r ;
r= m n(d,4);
cout< < r;
}
int
{
m n(int p [ ] , i n t n)
j
i n t i ; long s ;
if ( n >
0
)
{
f o r ( i =
0
J s=
0
;i< n ;i+ + )
s+ = p [i];
n e t u r n ( ( i n t ) ( s / n ) );>
136
// нұсқауыш арқылы арифметикалық ортаны анықтау
#include
int mn(int *p,int n);
void main()
{
int d [ M l ,
2
,
3
,
4
b r ;
г^|п
1
| ( ^
4
);
cout<
I
I
I
'
int mn(int *p,int n)
int i; long s;
if(n>
0
)
{
for(i=
0
,s=
0
;i
s+ = * (p + i);
return((int)(s/n));}
}
Функцияны пайдаланбай, жиым элементтерінің ең кіші (min) және ең үлкен
(max) мәндерін аныктайтын тағы бір мысап келтірейік.
#include
void main()
{
int d[]={l,
2
,
3
,
4
},*p,i,n,min,max;
float s=
0
,sr;
n=sizeof d/(sizeof(int));
P=d;
min=*p;max=*p;
for(i=
0
;i
if(*(p+i)
min=*(p+i);
else
if(*(p+i)>max)
max=*(p+i);
cout << min << endl << max << endl;
>
i f
: 1
; I
Осы мысалдың тағы бір нұсқасы:
#include
void main()
{
int гі[]={
1
,
2
,
3
,
4
},*р,і,п,тіп,тах;
float s=
0
,sr;
n=sizeof d/(sizeof(int));
P = d ;
min=*p;max=*p;
for(i=
0
;i
137
if(* (p + i)< m in )
m in= *(p+ i);
if(* (p + i)> m a x )
m ax=*(p+i);
co u t << min << e n d l << max << e n d l;
>
Енді функция арқылы орындайық.
# in c lu d e < io stream .h >
void m inm ax(int * p ,i n t * m in ,in t *m ax,in t n );
void m ain()
{
i n t d [ ] = { l , 2 , 3 J4 } ,* p ,n ;
i n t min,max;
n = siz e o f d / ( s i z e o f ( i n t ) ) ;
P=d;
Ш
!
minmax(d,&min,&max,n);
co u t << min << e n d l << max << e n d l;
>
void m inm ax(int * p , i n t * m in ,in t *maxJi n t n)
{
i n t i ;
*min=*p; *max=*p;
f o r ( i =
0
;i< n ;i+ + )
if(* (p + i)< * m in )
*m in= *(p+ i);
if(* (p + i)> * m ax )
*m ax=*(p+i);
>
S жиымының индекстері екінін дәрежелері болып келетін элементтерін экранга
шығару есебін карастырайык.
# in c lu d e < std io .h >
# in c lu d e
# in c lu d e
void main ()
{
i n t i , n, *s;
ml: c l r s c r ( ) ;
printf(M\n Жиым элементтері санын енгіз (<360) : ");
scanf ( ,e%d”,
8
n);
s = ( in t* ) m a llo c ( n * s iz e o f ( in t) ) ;
/ /
жады бөлеміз
p u t s ( " \ n \ t Берілген жиым " ) ;
f o r ( i =
0
; i< n ; i++)
{
s [ i l = i ;
/ /
жиым элементтері өз индекстеріне тең
138
p r in tf ("%4сі", s [ i ] ) ;
}
p r i n t f (" \п
Керекті жиым элементтері:
" ) ;
f o r ( i= l;i< n ; p rin tf(" * d H> s [ i ] ) , i*=
2
);
f r e e ( s ) ;
/ /
жадыны босатамыз
p r i n t f
(”\пЖалғастырамыз ба ? Иә болса - 7 енгіз:")
scan f
& і);
i f (і==7) goto ml;
>
Нұскауыштарды көпөлшемді жиымдарда пайдалану
Мынадай түрде сипатталу болсын делік:
i n t z [ 4 ] [ 2 ] ; i n t *р;
онда,
p==&z [
0
] [
0
]
-
1
-ші жолдың
1
-ші элементін көрсетеді.
p+l==&z[
0
] [
1
] -
1
-ші жол,
2
-ші багана.
р
+ 2
==&z [
1
] [
0
] -
2
-ші жол,
1
-ші бағана.
р+З ==&z [
1
] [
1
] -
2
-ші жол,
2
-ші бағана.
# in c lu d e < iostream .h>
void main( )
{
i n t d [2 ][2 ]= { { 1 ,2 } ,{ 3 ,4 } >;
i n t * p ,* p i ,g ,g i ;
p=&d[
0
] [Ө]; p l= p + l;
g=*p;
g l= * p l;
cout<Екіөлшемді жиымды функцияға беру
# in c lu d e < iostream .h>
i n t m n(int p [
2
] [
2
] , i n t m ,in t n ) ;
i n t m ain()
i n t r ;
i n t a [
2
] [
2
] = {
(
1
,
2
) ,
{3,4}
};
r * m n(a,
2
,
2
);
cout << r << e n d l;
}
" A f : - ;
-
: ;
;
.
i n t m n(int p [
2
] [
2
] , i n t m#i n t n)
139
w
•
I
{
m
• i'i
int i,j,s=0;
for(i=0;ifor(j=0;js + = p [ i ] [ j ] ;
r e t u r n ( s ) ;
Жиымдарды сипаттаганда, элементтер типі жэне жалпы жағдайда компьютер
жадының қажетгі класы көрсетіледі. Қарапайым айнымалыларда қарастырылатын
касиеттер жиымдарды да сипаттау кезінде қолданылуы мүмкін. Мысалы:
i n t b [3 0 ];
m ain()
{ f l o a t a [3 0 ];
s t a t i c c h a r c [
2 0
];
e x te rn b[ ] ;
}
Жиымдарды инициапдауды қарастырайык. Жиым сипатталуында тек сырткы
немесе статистикалық жиымдар гана инициалдануы мүмкін. Мысалы,
8
-топтагы
студенттер саны s t u d [
8
] жиымы ретінде көрсетілген:
# in c lu d e
# in c lu d e < s td io .h >
i n t s tu d [8 ]= { 1 5 ,1 6 ,1 4 ,1 8 ,1 5 ,2 0 ,1 7 ,1 9 } ;
m ain()
{ i n t i ;
c l r s c r ( ) ;
e x te rn i n t s tu d [ ];
f o r ( i =
0
; i<
8
; i++)
p r in tf ( " N %i тобында %i сту д ен т\п ",
i + l , s t u d [ i ] ) ;
}
.
щ ж
Жиымның нұскауыштарын карастырайык. Мысалы:
i n t * a;
Жиым аты нұсқауышты қолданған жагдайда, жиымнын Ө-інші элементін
аныктайды, яғни а жиымы сипатталған болса, программа мэтініндегі а
идентификаторы Ө-інші элементті көрсетеді деп санапады:
a == &а[
0
] ;
бұл теңдеудің екі бөлігі де - а да және &а[Ө]-де жиымның Ө-ші элементінің
адресін аныктайды. Осы екі белгілеу де нұсқауыш типті константа болып
табылады. Сондыктан оларды мэн ретінде нұскауыш типті айнымалыга
меншіктеуге болады немесе кажет болса, нұскауыш типті айнымалынын мэнін
өзгертуге болады.
1-мысал. Нұсқауыштың мэніне санды косуға болатынын көрсететін профамма
қарастырай ы қ.
m ain()
140
{int a[4], *pti, i;
float b[4], *ptf;
pti=a;
ptf=b;
for(i=0; i<4; i++)
printf("нұсқауыштар +% d: %
Поделитесь с Вашими друзьями: |