Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УМК2.doc
Скачиваний:
158
Добавлен:
13.03.2015
Размер:
2.63 Mб
Скачать

Программаның құрылымы

Кез келген Си-программасы негізгі модульдер болып табылатын бір немесе бірнеше «функциядан» құралады. С++ тіліндегі қарапайым программаны қарастырайық. Мұндай мысал С++ тілінде жазылған кез келген программаның негізгі ерекшеліктерін айқындау үшін қажет. Ары қарай әрбір программалық қатарға түсініктеме беретін боламыз, бірақ алдымен программаға қарап, оның не істейтінін түсінуге тырысыңыз.

// C++ тілінде жазылған қарапайым программа

#include <iostream.h>

main ()

{

cout << " Ақпараттық технологиялар кафедрасына ";

cout << "қош келдіңіз.\n";

}

Программаның орындалу нәтижесі:

Ақпараттық технологиялар кафедрасына қош келдіңіз.

#include <iostream.h> - препроцессор директивасы. Біздің программаға iostream.h атты файлдың қосылуы кіріс (cin) және шығыс (cout) ағымдарын қолдануға мүмкіндік береді, олар туралы кейінірек айтамыз. Кейбір жағдайларда бұл жолды программаға қосу міндетті, ал кейбір жағдайларда міндетті емес. Ол программаға байланысты.

main() – функция аты. С++ тілінде жазылған кез келген программа өзінің негізгі модульдері болып табылатын бір немесе бірнеше функциялардан құралады. Біздің программа бір ғана main() функциясынан тұрады, бұның дөңгелек жақшалары main – функцияның аты екенін көрсетеді (ағыл. main – басты). С++ тілінде жазылған программа әрқашан да main() деп аталатын функциядан бастап орындалады, сондықтан біз осы функциядан басқа барлық функциялардың аттарын өзіміз таңдай аламыз.

Жалпы жағдайда дөңгелек жақшаларда осы функцияға берілетін ақпарат болады. Біздің мысалда ешқандай ақпарат берілмейді, сондықтан біздің жақшалар бос тұр.

{ және } – фигуралы жақшалар функция денесінің басы мен соңын білдіреді. Фигуралы жақшалар сонымен қатар программаның бірнеше операторларын құрамды операторға немесе блокқа біріктіру үшін де қолданылады (Pascal тілінің Begin және End операторлық жақшаларына ұқсас).

Программалық жолдың соңындағы нүктелі үтір онда С++ тілінің операторы бар екенін білдіреді, бұл жерде бұл символ Pascal тіліндегідей операторлардың бөлгіші емес, оператордың бір бөлігі болып табылады.

Анықтама: Түйін сөздер деп программалау тілінің сөйлемдерін құрастыру үшін қолданылатын арнайы сақталып қойған сөздерді айтады.

С++-те мәліметтерді көрсету. Мәліметтер типтері

С++-те негізгі типтер екі топқа бөлінеді: бүтін сандық типтер және жылжымалы нүктесі бар типтер (қысқаша болу үшін оларды жылжымалы типтер деп атаймыз). Бұл арифметикалық типтер.

С++ тілінде арифметикалық типтердің мәндер диапазондарына қойылатын қатаң стандарттар жоқ (тілдің стандартында тек мүмкін болатын ең кіші мәндер айтылады). Негізінде, бұл диапазондар нақты орындалу кезінде анықталады. Әдетте бұл сипаттамалар компьютердің есептеу мүмкіндіктерін қолданудың тиімділігіне байланысты таңдалады. Тілдің программаның орындалуына тәуелділігі салдарынан тасымалдау проблемалары туындайды. С++ тілі машинаға тәуелді тіл болып қала береді.

Бүтін сандық типтерге негізгі типтердің келесі атауларымен берілген типтер жатады:

char

short

int

long

Бүтін сандық типтердің атаулары төмендегі тип модификаторларымен бірге қолданылуы мүмкін:

signed

unsigned

Бұл модификаторлар мәліметтерді көрсету форматын өзгертеді, бірақ жады көлемінің бөлінетін аумағыма әсер етпейді.

Signed типінің модификаторы айнымалының оң мәндерді де, теріс мәндерді де қабылдай алатынын білдіреді. Бұл ретте мәнді сақтау үшін бөлінетін жады аумағымың ең сол жақтағы биті таңбаны көрсету үшін қолданылады. Егер бұл бит 0 болса, айнымалы мәні оң болып саналады. Егер бит 1 болса, онда айнымалының мәні теріс болып саналады

Unsigned типінің модификаторы айнымалының теріс емес мәндерді қабылдайтынын көрсетеді. Бұл ретте мәнді сақтау үшін бөлінетін жады аумағымың ең сол жақтағы биті жады аумағымың басқа биттері тәрізді мәндерді көрсету үшін өолданылады.

Бірқатар жағдайларда тип модификаторларын негізгі типтердің аттары ретінде қарастыруға болады.

Бұл жерде де көп нәрсе нақты орындалу кезінде анықталады. Borland C++ версияларында signed, short және int деп белгіленетін типтердің мәндері жадыда бірдей орын алады.

Негізгі бүтін сандық типтердің арасында enum түйін сөзімен белгіленетін тізімдемелер ерекше орын алады. Тізімдемелер бүтін мәндердің реттелген жиыны болып табылады. Олардың өзіндік синтаксисі және арнайы қолданылу саласы болады. Оларды оқып білу үшін арнайы бөлім арналады.

Мұнда көп нәрсе тағы да нақты орындалуға байланысты. Ең болмағанда, Borland C++ 4.5 үшін бүтін сандық типтердің негізгі сипаттамалары келесідей болады:

1.1-кесте

Мәліметтер типі

Байттар

Биттер

Min

Max

signed char

1

8

- 128

127

unsigned char

1

8

0

255

signed short

2

16

-32768

32767

enum

2

16

-32768

32767

unsigned short

2

16

0

65535

signed int

2

16

-32768

32767

unsigned int

2

16

0

65535

signed long

4

32

-2147483648

2147483647

unsigned long

4

32

0

4294967295

Жылжымалы типтерге келесі тип атауларымен, модификаторларының атауларымен және олардың үйлескен атауларымен берілген үш тип жатады:

float

double

long double

Жоғарыдағыдай, тип модификаторы негізгі типтердің атауларына кіреді.

Жылжымалы типтер ондық нүктесі бар жазбалар түрінде, сонымен қатар «ғылыми нотация» түрінде жазылатын нақты сандармен жұмыс істеу үшін қолданылады. Бір нақты санның түрлі нотацияларда жазылуын көрсететін келесі қарапайым мысалдан нотациялардың арасындағы айырмашылық анық көрінеді.

Мысалы:

297.7

2.977*10**2

2.977E2

және тағы бір мысал…

0.002355

2.355*10**-3

2.355E-3

Ғылыми нотацияда Е символының сол жағымда мантисса жазылады, оң жағымда экспонентаның мәні жазылады, ол әрдайым 10-ның дәреже көрсеткішіне тең болады.

Жылжымалы типтердің мәндерін жадыда сақтау үшін нақты сандарды көрсетудің арнайы форматы қолданылады. Бұл формат IEEE форматы деп аталады.

Төменде жылжымалы нүктесі бар мәліметтер типтерінің негізгі сипаттамалары келтірілген (Borland C++ 4.5 үшін):

1.2-кесте

Мәліметтер типі

Байттар

Биттер

Min

Max

float

4

32

3.4E-38

3.4E+38

double

8

64

1.7E-308

1.7E+308

long double

10

80

3.4E-4932

3.4E+4932

Негізгі әдебиет: 1[55-76], 2[47-61], 3[7-61], 5 [14-58]

Қосымша әдебиет: 1[3-20].

Бақылау сұрақтары:

1. С++ тілінде программаны орындау үшін өтуге тиісті кезеңдерді атаңыз.

2. С++ тіліндегі қарапайым программаның құрылымын келтіріңіз.

3. Мәліметтердің бүтін сандық типтерін атаңыз.

4.Жылжымалы нүктесі бар мәліметтер типтерін атаңыз.

5.Түрлі типті айнымалыларды баяндауға мысал келтіріңіз.

6.Меншіктеу операторы қалай жұмыс істейді?

2-дәріс. Препроцессор директивалары. Символдар жолы және форматталған енгізу-шығару.

Препроцессор дегеніміз не. Жалпы мағлұматтар.

С/С++ тілдерінің барлық компиляторларында пррепроцессорлау деп аталатын қандай да бір фаза бар. Бұл фаза автоматты түрде іске қосылады, және қолданушыға (программалаушыға) айқын болып табылады. Яғни қолданушы көп жағдайда препроцессорды өз бетімен іске қоспайды.

Препроцессорлау – кірісіне мәтін (мәтіндік файл) берілетін және шығысында мәтін форматталатын процесс. Жұмыс істеу кезінде препроцессор бастапқы мәтіндік файлдың түрін өзгертеді. Және содан кейін ғана өзгертілген мәтіндік файл компиляцияланады. Препроцессор командалары (оларды директивалар деп атайды) # символынан басталады, ол қатардағы алғашқы бос орынсыз символ болуы тиіс. Жаңадан бастап жүрген программалаушының кездестіретін алғашқы препроцессор директивалары #include және #define директивалары болып табылады.

Тақырыптық файлдар программа мәтініне #include препроцессор директивасының көмегімен қосылады. Препроцессор директивалары «диез» (#) таңбасынан басталады, ол қатардағы ең алғашқы символ болуы тиіс. Осы директиваларды өңдеуші программа препроцессор деп аталады (қазіргі кездегі компиляторларда әдетте препроцессор компилятордың бір бөлігі болып табылады). #include директивасы программаға көрсетілген файлдың ішіндегі деректерді қосады. Файл атауы екі тәсілмен көрсетілуі мүмкін:

#include <some_file.h>

#include "my_file.h"

Егер файл атауы бұрыштық жақшаға алынған болса, онда бізге қандай да бір стандартты тақырыптық файл керек екендігін білдіреді, және компилятор бұл файлды алдын-ала анықталған орындардан іздейді. (Бұл орындарды анықтау тәсілі түрлі платформалар үшін әр түрлі болып келеді). Файл атауы қос тырнақшаға алынған болса, тақырыптық файлдың қолданушылық файл екендігін білдереді, және ол программаның бастапқы мәтіні сақталған каталогтан бастап ізделінеді.

#define және #undef директивалары

#define директивасы макростарды анықтайды. Егер біз "#define TRAM 10" деп жазатын болсақ, онда препроцессордың жұмыс істеу барысында "TRAM" әріптер тіркесінің барлық кірістері мәтіндік түрде "10" символына ауыстырылады. Бұл жерде "TRAM" жеке токен болуы тиіс (яғни оның айналасында бос орын символдары немесе тыныс белгілері болуы тиіс). Яғни "TRAM+TRAM" тіркесі "10+10" болып өзгертіледі, ал "TRAMPAMPAM" өзгеріссіз қалады.

#undef директивасы. Макросты жою үшін #undef директивасы қолданылады. Препроцессор осындай директиваны кездестірген жағдайда ол бұрында анықталған макросты «ұмытады» да, оны өзгертпейтін болады.

Параметрлері бар макросты жазу кезінде жаңадан үйреніп жүрген программалаушылардың кең таралған қатесі – #define директивасын баяндау кезінде макрос аты мен ашылатын жақшаның арасында бос орынды қою. Бұл дұрыс емес, ашылатын жақшаны макрос атымен қосып жазу керек.

Макрос параметрлеріне арналған # операторы

Препроцессор файлмен қатаң түрде мәтінмен жұмыс істегендей жұмыс істейді. #define директивасының параметрлерімен де дәл осылай. Демек, препроцессор олармен бірқатар қарапайым түрлендірулерді жүзеге асыра алады. Солардың бірі '#' символы болып табылады. Егер оны макрос параметрінің алдына қойса, нәтижесінде осы параметр тырнақшаға алынатын болады.

Макрос денесіндегі ## операторы

Макрос параметрлеріне арналған тағы бір оператор ## операторы болып табылады. Егер оны макрос денесіндегі екі «сөздің» арасына қоятын болсақ, осы екі «сөз» бір сөзге біріктіріледі (конкатенация операторы).

#if, #else, #elif, #endif директивалары

"#if" директивасының синтаксисі өте қарапайым және программалау тіліндегі шарттың орындалу операциясымен сәйкес келеді. Айта кететін бір ғана жайт – міндетті түрде "#endif" болуы керек, себебі онсыз препроцессор "#if" директивасының қай жерден аяқталатынын түсіне алмайды.

#error және #warning директивалары

Берілген директивалардың негізгі қолданылу саласы – кең қолданысқа арналған программалардың мәтіндері: open source жобалары немесе бір уақытта көптеген адамдар жазатын программалар. Бұл директивалар маңызды еш нәрсе жасамайды, олар тек препроцессорды (немесе компиляторды, нақты орындалуға байланысты) қате немесе ескерту туралы хабарлама шығаруға мәжбүр етеді. Директивалар күйттеулердің жарамсыз комбинацияларын алып тастау үшін шартты компиляция директиваларымен бірге қолданылады.

#error директивасы

#error директивасы күйге келтірілетін макростардың жарамсыз комбинацияларын тауып, программаны компиляциялау кезеңінде қате туралы хабарлама шығарады.

#warning директивасы

"#warning" директивасы осылай жұмыс істейді, бірақ қате туралы хабарлама емес, ескерту шығарады. Әдетте ол біреу бір нәрсені өзгерткісі келген жағдайда орындалады, бірақ бірден емес, біртіндеп: біраз уақыт бойы «ескі» және «жаңа» нұсқалары жұмыс істеп тұрады, бірақ уақыт өте келе ескі нұсқасы жойылады.

Символдық жолдар.

Символдық жол – бұл бір немесе бірнеше символдан құралатын тізбек. Си тілінде жолдарды сипаттауға арналған арнайы тип болмайды. Жолдарды char типті элементтері бар массив түрінде ұсынуға болады. Жолдағы символдарды жадының көршілес ұяшықтарында орналасқан символдар ретінде елестетуге болады – әрбір ұяшықта бір символдан. Массивтің соңғы элементі \0 символы болып табылады. Нуль символы жолдың соңын білдіретін белгі болып табылады. Жолдың ұзындығын символдардың санымен анықтау үшін strlen функциясы қолданылады.

#define директивасының қолданылуы келесі түрге ие:

#define тұрақтының символикалық атауы тұрақтының мәні

Мысалы: #define PI 3.14159

#define директивасын символдық және қатаалық тұрақтыларды сипаттау үшін қолдануға болады. Бірінші жағдайда ''апостроф'' белгісін, ал екінші жағдайда тырнақшаны қолдану керек. Мысалы:

# define NUL L ‘\0’ немесе # define BL 1 ''Блок 1''

printf( ) және scanf( ) функцияларының қолданылуы.

printf( ) функциясының жалпы түрі:

printf(<формат жолы>, <объект>, <объект>…);

Формат жолы екілік тырнақшалармен шектеледі. Шығару алдында printf жолда барлық қосымша аталған объектілерді жолдың өзінде көрсетілген формат спецификацияларына сәйкес ауыстырады. Формат спецификациялары процент (%) символынан басталады да, содан кейін мәліметтер типі мен оларды түрлендіру тәсілін білдіретін бір әріп жазылады. Объектілердің өзі айнымалы, тұрақты, өрнек, функция шақыруы болуы мүмкін. 1-кестеде Си тілінде қолданылатын формат спецификациялары келтірілген.

2.1-кесте

Формат спецификациялары

Формат спецификация-лары

Шығарылатын ақпарат типі

%d

Ондық бүтін сан

Бір символ

%s

Символдар жолы

Жылжымалы нүктесі бар сан, экспоненциалды жазылуы

%f

Жылжымалы нүктесі бар сан, ондық жазылуы

%g

Қысқа болған жағдайда, % f немесе % е жазуларының орнына қолданылады

%u

Таңбасыз ондық бүтін сан

Таңбасыз сегіздік бүтін сан

Таңбасыз он алтылық бүтін сан

#define PI 3.14159

#include <math.h>

main ( )

{ float S, r;

printf (“шеңбердің радиусын енгізіңіз \ n”);

scanf (“%f”, &r);

S=PI*r*r;

printf (“шеңбер ауданы = %f \n”, S); }

scanf ( ) функциясының қолданылуы

scanf ( ) функциясының жалпы түрі:

scanf (<формат жолы>, <адрес>, <адрес>, …);

scanf( ) функциясы printf ( ) функциясы қолданатын түрлендіру специяикацияларының символдар жиынын қолданады. scanf() функциясын қолдану кезіндегі негізгі айырмашылықтар:

1. %g спецификациясы болмайды.

2. %f және %e спецификациялары бірдей.

3. short типті бүтін сандарды оқу үшін % h спецификациясы қолданылады.

Ескерту:

1. Адресті жазу кезінде айнымалылардың адрестерін беру үшін адрес операциясы (&) қолданылады.

2. Жолдық айнымалы мәнін енгізу кезінде & символы жазылмайды.

Программа мысалы:

main ( )

{ char name[30];

printf (“Автордың атын енгізіңіз”);

scanf (“%s”, name);

printf (“Программа авторы % s\n”, name); }

name символдар массиві болғандықтан, name мәндері массивтің адресі болып табылады. Сондықтан name атауының алдында & адрестік операторы қолданылмайды.

Негізгі әдебиет: 1 [37-43],[97-99], 2 [903-918], 3[316-337], 5[239-258]

Бақылау сұрақтары:

1. Таңбасыз бүтін сандармен жұмыс істеуге арналған мәліметтер типін атаңыз.

2. Арттыру және кеміту операцияларын жазудың қандай формалары бар, және олардың айырмашылықтары қандай?

3. Символдық және жолдық тұрақтыларды сипаттауға арналған препроцессор директивасын атаңыз.

4. Қандай формат спецификациялары scanf функциясында қолдану кезінде бірдей болып табылады?

3-дәріс. Операциялар, өрнектер, операторлар. Басқару операторлар: тармақтау және шартсыз көшу

Си тіліндегі негізгі операциялар.

Ең жалпы операция меншіктеу болып табылады. Си тілінде меншіктеу операторы V=A деп жазылады, мұндағы V - айнымалы, А - өрнек. Тағы да тізбекті меншіктеуді қолдануға болады, келесі түрдегі мысалдағыдай: sum=a=b.

Меншіктеу оңнан солға қарай жүреді, яғни b a-ға меншіктеледі, және осы sum-ға меншіктеледі де, үш айнымалы да бірдей мән қабылдайды (яғни бастапқы b айнымалысының мәніне).

Си тілі қарапайым арифметикалық операциялар жиынтығын қолдайды: * - көбейту, / - бөлу, модуль бойынша бөлу - %, + - қосу, - - азайту.

Модуль бойынша бөлу бүтін сандық арифметикада қолданылады. Оның нәтижесі бүтін сандарды бөлген кездегі қалдық болып саналады.

Мысалы: (20%3=2).

+ және - операцияларының үстемдігі *, / және % операцияларының үстемдігінен төмендеу, және өз кезегінде олардың үстемдігі унарлық минус үстемдігінен төмен.

Мысал қарастырайық:

Maіn()

{

іnt m1, m2;

m1=m2=-(15+3)*5+(11+9*(8+3))-266%16;

(* m1=m2=10; (операция оңнан солға дейін орындалады *)

prіntf ("m1=%d\n", m1);

prіntf ("%d\n", m2/3); }

Арттыру және азайту операциялары: ++ және - -.

Бұл операциялар кез келген операторға 1-ді қосуға немесе азайтуға мүмкіндік береді. Көрсетілген операциялардың екі формасын ажыратады, постфикстік және префикстік. Олар өз арасында тек қай кезде арттыру немесе азайту болатынына байланысты ажыратылады. Арттыру және азайту операциялары өрнектің ортасындада орындалуы мүмкін, және де осы операциялар өрнек есептелгеннен кейін де, есептелмей тұрып та орындалуы мүмкін. Мысал қарастырайық:

Мысал: L=10 болсын;

онда, х=L++; x айнымалысына 10 мәнін меншіктеу болады.

х=++b; x айнымалысына 11 мәнін меншіктеу.

Екі жағдайда да L 11-ге тең болады.

2-мысал:

Sum=a+b++;

Sum=a+ ++b;

b++ - постфикстік тұр: b айнымалысы оның мәні қолданылғаннан кейін өзгереді.

++b - префикстік тұр: b айнымалысы оның мәні қолданылмай тұрып өзгереді.

Бірінші жағдайда: “a және b-ны қосу, нәтижесін sum-ға меншіктеу және b айнымалысын бірге арттыру”.

Екінші жағдайда: “b айнымалысын бірге арттыру, a және b-ны қосу, және нәтижесін sum-ға меншіктеу”.

3-мысал:

{ maіn()

іnt a, b, s=0;

a=b=g;

s=a+b++;

prіntf("%d %d\n", s, b)

s=a+ ++b;

prіntf("%d %d\n", s, b)

}

Азайту және арттыру операциялары жоғарғы үстемдікке ие, тек домалақ жақшалардың үстемдігі жоғарырақ.

Типтерді түрлендіру.

Егер өрнекте әр түрлі типті операндтар қолданылса, онда олар қандай да бір жалпы типке түрленеді. Компилятор автоматты түрде типтерді түрлендіруде ережелер жиынтығын қолданады. Типтерді түрлендірудегі негізгі ережелерді келтірейік:

1. Егер операция екі әр түрлі типтер мәліметтері бойынша орындалса, онда екі шамада “жоғарғы” типіне түрленеді. Бұл процесс типтің “жоғарылауы” деп аталады.

2. “Жоғары” типтен “төменгі” типке дейінгі реттелген типтер тізбегі мына түрде болады: double, float, long, іnt, short және char. Unsіgned кілтті сөзі қолданылса, сол тип сәйкесінше рангы көтеріледі.

3. Меншіктеу операторында оң жағымдағы өрнек орындалғаннан кейінгі соңғы нәтиже осы мен тең болатын айнымалының типіне түрленеді. Бұндай процесс типтің “жоғарылауына” немесе “төмендеуіне” әкеледі (екінші жағдайда шама төмен үстемдіктегі мәліметтер типіне түрленуі мүмкін).

Типтің “жоғарылауы”, әдетте, жұмсақ етеді, ал “төмендетуді” жадыдағы мәліметтерді білу арқылы орындау қажет.

Мысал:

maіn ()

{ char ch;

іnt і;

float f1;

f1=і=ch='A';

prіntf ("ch=%c, і=%d, f1=%6.2f\n", ch, і, f1);

ch=ch + f1; (* 65+1=66 =>"В" символының коды =>ch-қа)

і=f1+2*ch; (* 66*2+65.00=>132.00+65.00=>197.00=>197)

f1=2.0*ch+c;

prіntf ("cp=%c, і=%d, f1=%62f\n", ch, і, f1) }

Нәтиже:

Ch=A, і=65, f1=65.00

Ch=B, і=197, f1=329.10

Тағы да бір типтерді түрлендіру түрі. Арифметикалық операцияларды есептегенде дәлдікті сақтау үшін барлық float типті шамалар double мәліметтер типіне түрленеді. Бұл дөңгелектеу қателігін едәуір азайтады. Соңғы нәтиже қайтадан float типті санға айналады, егер бейнелеу операторы солай берілсе.

Келтіру операторлары

Жоғарыда келтірілген типтерді түрлендіру автоматты түрде жүзеге асады. Қандай да бір шамаға келтіруге қажет мәліметтер типін көрсетуге мүмкіндік бар. Мұндай тәсіл типтерді “келтіру” деп аталады және келесідей түрде қолданылады: берілген шаманың алдындағы домалақ жақшадағы және тип аты бірге “келтіру операциясын” береді. Жалпы түрде ол былай жазылады:

(тип) өрнек

мұндағы, керекті типтің аты “тип” сөзінің орнына қойылады.

Мысал: m - іnt типті болсын.

m=2.7+2.9; - 5

m=(іnt)2.7+(іnt)2.9; - 4

Sqrt кітапханалық программасы double типті аргументке арналған. Егер m - бүтін болса, онда sqrt((double)m) кезінде m параметрі алғашқыда double типіне келтіріледі.

өрнек өз кезегінде операциялардан және операндтардан тұрады. Кейбір өрнектер кіші өрнектерден, яғни өрнекшелерден тұрады. Си тілінде барлық өрнек бір мәнге тең болады.

Мысалдар: C=5+10=15 25+(C=5+10)=40

15>12=1

Қатынас операциялар. Қатынас операторлары екі мәнді тексеру үшін қолданылады. Си тілінде программалау кезінде қолданылатын қатынас операцияларының тізбегін келтірейік.

<, <=, ==, >=, >, !=.

Егер қатынас ақиқат болса, онда шартты өрнектің мәні 1-ге тең; егер жалған болса, онда шартты өрнектің мәні 0-ге тең.

Қарапайым өрнектің шарты қатынас операцияларынан және оның оң жағымда және сол жағымда орналасқан операндтардан тұрады.

Қатынас операцияларының үстемдігі арифметикалық операцияларға +, -, *, / қарағанда төмен және меншіктеу операцияларына қарағанда жоғары болып саналады.

Қатынас операцияларын үстемдіктерінің арналуына сәйкес екі топқа жіктеуге болады: жоғары үстемдікке ие операциялар тобы: <, <=, >=, > және төмен үстемдікке ие операциялар тобы: ==, !=.

Қатынас операциялары солдан оңға қарай орындалады.

Си ++ тілінің операторлары

Меншіктеу операторы V=A;

y=5*x+sqrt(7*x+3);

Дөңгелек жақша ішіндегі кез келген меншіктеу операторы осы меншіктеу нәтижесі болатын белгілі бір мәні бар өрнек болып табылады. Мысалы: ((S=13+12)<=30) өрнегінің мәні ақиқат болады.

Құрылымды операторлар (блоктар). Құрылымды операторлар екі немесе одан да көп жүйелі жақшалармен біріккен операторларды береді; оларды тағы да “блоктар” деп атайды. Құрылымды операторлар шартты және цикл операторларында болады.

Басқару операторлар: тармақталу және шартсыз көшу.

Си ++ тілі таңдау құрылымының үш типін келтіреді. If таңдау құрылымында қайсібір әрекет не орындалады (таңдалады), егер шарт ақиқат болса, не өткізіледі, егер шарт жалған болса. If/else таңдау құрылымында кейбір әрекет орындалады, егер шарт ақиқат болса және басқа әрекет орындалады осы шарт жалған болса. Switch таңдау құрылымында қайсібір өрнектің мәніне байланысты әрекеттер жиынтығының ішінен біреуі орындалады.

If құрылымы жалғыз таңдауы бар құрылым деп аталады, өйткені онда бір әрекет таңдалады немесе өткізіледі. If/else құрылымы екі таңдауы бар құрылым деп аталады, өйткені онда екі альтернативті әрекеттің арасында таңдау орындалады. Switch құрылымы көп таңдауы бар құрылым деп аталады.

If таңдау құрылымының жалпы түрі:

Іf (өрнек) оператор1;

If/else құрылымының жалпы түрі:

Іf (өрнек) оператор1;

Else оператор2;

Егер өрнек мәні ақиқат болса (нөлден өзгеше болса), онда оператор1 орындалады, керісінше жағдайда оператор2 орындалады.

Си тілінде If/else құрылымымен тығыз байланысқан (?:) шартты операциясы қарастырылған. Бұл операторға үш операнд қажетті. Шартты операциясымен бірге операндтар шартты өрнекті құрады. Бірінші операнд шарт болып табылады, екінші операнд барлық шартты өрнектің мәні болады, егер шарт ақиқат болса және үшінші операнд барлық шартты өрнектің мәні болады, егер шарт жалған болса. Мысалы,

x>y ? printf(“max=%d\n”, x) : printf(“max=%d\n”, y);

If/else бірінің ішіне бірі енген құрылымдар құрамды шарттарды тексеру үшін пайдаланылады, сондай-ақ If/else бір құрылымдар If/else басқа құрылымдардың ішіне орналастырылады.

Келесідей жазылу түрін келтірейік:

Іf (өрнек1) оператор1;

Else іf (өрнек2) оператор2;

Else оператор3;

Егер өрнек1 ақиқат болса, онда оператор1 орындалады. Егер өрнек1 жалған болып, өрнек2 ақиқат болса, онда оператор2 орындалады. Екі өрнек те жалған болған кезде оператор3 орындалады.

Логикалық операциялар.

Екі және одан да көп шартты өрнекті біріктіру кезінде логикалық операциялар қолданылады. Си тілінде үш логикалық операция бар: &&(және), ||(немесе), !(“жоқ” немесе “емес”).

1. f11&&f12 ақиқат, тек екі өрнектің де f11 және f12 мәндері ақиқат болса.

2. f11||f12 ақиқат, егер f11 және f12 өрнектерінің ең болмағанда біреуі ақиқат болса немесе екеуі де ақиқат болса.

3. !f11 ақиқат, егер f11 өрнегі жалған болса және керісінше.

Мысал:

15>12&&8>10 - жалған (тек қана бір өрнекше мәні ақиқат)

15>12||8>10 - ақиқат (әйтеуір бір өрнекше мәні ақиқат).

! операциясы өте жоғары үстемдікке ие, тек домалақ жақшалар одан жоғары үстемдікке ие. && операциясының үстемдігі || операциясының үстемдігінен жоғары, алайда бұл екі операция үстемдігі меншіктеу операциясының үстемдігінен төмен.

&& және || операцияларын қолдану кезінде төмендегілерді білу қажет:

Бұл операциялардың орындалуы нәтиже мәні ақиқат немесе жалған болған кезде тоқтайды. Мысалы, f11&&f12 өрнегі берілсін. Егер f11 жалған болса, яғни барлық өрнек жалған, сондықтан f12 есептелінбейді. Осыған ұқсас, егер бізге f11||f12 өрнегі берілді делік. Онда f11-ақиқат болса, f12 есептелінбейді.

Келесі программада екі таңдауы бар if/else құрылымының қолдану мысалы келтірілген.

// Жеңілдік есебімен сатып алу бағасы есептеледі

#include <stdio.h>

#include <conio.h>

void main()

{

float sum; /* сатып алудың бағасы */

printf(“\n Жеңілдік есебімен сатып алу бағасы ”);

printf(“есептеледі \n”);

printf(“Сатып алу бағасын енгіз ->”);

scanf(“%f”, &sum);

if (sum<1000) printf(“Жеңілдік берілмейді.\n”);

else { printf(“Сізге жеңілдік беріледі ”);

if (sum>3000) { printf(“5%\n”);

sum = 0.95 * sum; }

else { printf(“3%\n”);

sum = 0.97 * sum; };

printf(“Жеңілдікпен берілетін бағасы %.2f тг\n”, sum); }

printf(“\nАяқталу үшін <Enter> басыңыз”);

getch(); }

Программаның нәтижесі:

Жеңілдік есебімен сатып алу бағасы есептеледі

Сатып алу бағасын енгіз -> 2250

Сізге жеңілдік беріледі 3%.

Жеңілдікпен берілетін бағасы: 2182.50 тг.

Swіtch (ауыстырғыш) таңдау операторы.

Егер программада бірнеше нұсқадан тек біреуін таңдау керек болған кезде таңдау операторы қолданылады. Swіtch операторының жалпы түрі:

Swіtch ()

{

case белгі1: операторлар;

case белгі2: операторлар;

......

deault: операторлар;

}

өрнек және белгілер бүтін типті (char типін қосқанда) болуы керек; белгілер тұрақтылар немесе тұрақты өрнектер болуы керек. Алдымен домалақ жақшадағы рнектер есептелінеді, сосын есептелінген өрнектің мәнін белгінің әр мәндерімен салыстырылады. Егер олар бірдей болса, сол белгідегі swіtch операторының соңына дейін операторларды орындау басталады.

Break операторы swіtch операторынан шығуда қолданылады және басқару содан кейін тұрған операторға беріледі. Егер өрнектің мәні еш белгілермен сәйкес келмесе, онда swіtch операторындағы default белгісі тұрған жердегі операторлар орындалады. Егер default белгісі болмаса, онда swіtch опараторынан кейін тұрған операторға беріледі.

Swіtch операторында нақты типті мәліметтерді, жолдарды және басқа құрылымды мәліметтерді қолдануға болмайды, бірақ бүтін мәндермен сәйкес келетін құрылымды мәліметтердің элементін қолдануға болады.

Maіn()

{ char ch;

whіle ((ch=getchar())!=’#’)

{ swіtch (ch) {

case f:

case ‘F’: do_fіle_menu; break;

case V:

case ‘R’: run_program(); break;

case ‘c’:

case ‘C’: do_compіle(); break;

default: Ex(); break;

}

prіntf(“әріп немесе # енгізіңіз”);

}}

Негізгі әдебиет: 1нег[108-112], 2нег[87-1176], 3нег[83-112],5[60-64]

Қосымша әдебиет: 6қос[239-241]

Бақылау сұрақтары:

1. Ең жоғары приоритетті логикалық операцияны атаңыз.

2. Қандай оператор бірнеше варианттардың ішінен бір вариантты таңдау үшін қолданылады?

3. Қандай жағдайда default ерекше белгісінің операторлары қолданылады?

4. Құрамды шарттарды тексеру үшін қандай құрылымдар қолданылады?

5. Switch таңдау операторында өрнектер мен ерекше белгілер үшін мәліметтердің қандай типі қолданылады?

4 –дәріс. Циклдар - басқару операторлар

While операторы. Конструкцияда өрнек есептелінеді:

while (өрнек)

нұскау;

егер оның мәні нөлден өзгеше болса (яғни ол «ақиқат»), онда нұсқау орындалып, өрнек қайтадан есептелінеді. Бұл цикл өрнектің мәні нөл болмайынша қайталана береді, одан кейін программаның орындалуы нұсқаудан кейінгі орыннан жалғасын табады.

нұсқау

for (өрнек – 1; өрнек – 2; өрнек – 3)

нұсқау

бұл тізбек келесі тізбекке эквивалентті

өрнек – 1

while (өрнек – 2)

нұсқау

өрнек – 3

for нұсқауының барлық үш компоненті де өрнек болып табылады. Кең таралған жағдай болып, егер өрнек – 1 мен өрнек – 3 меншіктеулер болса, ал өрнек – 2 шартты өрнек болады. Үш бөлімнің кез – келгені алынып тасталуы мүмкін, бірақ нүктелі үтір қалдырылады. Егер өрнек – 1 немесе өрнек – 3 болмаса, онда ол кеңейтілуден түседі. Ал егер өрнек – 2 тексеруі болмаса, онда ол әрқашан ақиқат деп саналады,

for (;;)

...

тоқтаусыз цикл болып табылады, сондықтан оны басқаша түрде тоқтату қарастырылады (мысалы break немесе return нұсқауларының көмегімен).

while немесе for нұсқауларын қоолдану – бұл программалаушы адам талғамына байланысты. Массивтің алғашқы N элементін өңдеуде көбінесе FOR (I=0; I<N; I++) конструкциясын қолданады.

DO – WHILE цикл. While және for циклдерінің қасиеті болып, соңын тексеру цикл соңында емес цикл басында іске асырылуы жатады. Си тілінің үшіншінұсқауы do- while аяқтау шартын цикл соңында, цикл денесінен әр өткен сайын тексереді: кемінде цикл денесі бір рет орындалады. Бұл нұсқаудың синтаксисі келесідей:

do

нұсқау

while (өрнек)

Алдымен нұсқау орындалады, сосын өрнек есептеледі. Егер ол ақиқат болса, онда нұсқау қайтадан орындалады және т.с.с. Егер өрнек жалған болса, онда цикл тоқтатылады.

BREAK. Кейде циклдан шығуды оның басы мен аяғында шартты тексеруден шығудың басқа мүмкіндіктері бар. break нұсқауы for, while және do нұсқауларынан цикл соңына дейін шығуға мүмкіндік береді. break нұсқауы оны құрайтын ең ішкі циклдан тез шығуға әкеледі.

CONTINUE break нұсқауына ұқсас, бірақ аз қолданылады; ол (for, while, do- while) циклдің келесі интерациясының басына әкеледі. Яғни while және do циклдарында тексерілетін бөлікке өту дегенді білдіреді; for циклында реинициализация қадамына басқару беріледі. Continue нұсқауы циклдың келесі бөлігі күрделі болғанда үнемі қолданылады.

GOTO және ерекше белгілер. goto нұсқауы өзінің орнын табатын бірнеше ситуацияларды көрсетелік. Кейбір күрделі құрылымдарды (бірінің ішіне бірі еңгізілген циклдерде) мысалы бірден екі циклдан шығуда. Мұндай жағдайда break нұсқауын тікелей қолдануға болмайды, себебі ол тек ішкі циклды тоқтата алады.

Негізгі әдебиет: 1[97-99], 2[99-176], 3[104-127], 5[64-69]

Қосымша әдебиет: 1[240-241]

Бақылау сурақтары:

1. For, while, do/while цикл операторлар қандай кезде қолданылады?

2. Құрамды операциаларды ұйымдастыру үшін қолданатын операцияны атаныз?

3. While және do/while операторлардың айырмашылығы неде?

4. Goto операторды қандай кезде қолдануға болады, ал break операторды болмайды?

5. Циклдаң шығу конструкциясына қандай процедура сәйкес келеді?

5-дәріс. Массивтер. Бірөлшемді және екіөлшемді массивтерді өңдеуге арналған программаларды құру

Массив бірдей типті айнымалылар тізбегін бірыңғай бүтін тізбек ретінде сақтауға мүмкіндік береді. Массивті жариялау арқылы массив элементтерінің типі мен оның аты анықталады. Ол сонымен қатар массивтегі элементтердің санын анықтауы мүмкін. Егер сипатталатын массив типі жазылмаса, int типі ұсынылады. Бір өлшемді массивті жариялаудың синтаксисі төмендегідей:

[<сипатталатын массив типі>] <айнымалы-идентификатор> [<константалық өрнек>];

[<сипатталатын массив типі>] <айнымалы-идентификатор> [];

Массивті жариялау кезінде жоғарыда көрсетілген екі синтаксистік формалардың бірін қолдануға болады. <айнымалы-идентификатор>-дан кейін тұрған квадрат жақша массив типінің белгісі болып табылады. Егер <айнымалы-идентификатор> идентификатор (массив аты) болса, онда ерекшеленген типті элементтер массиві жарияланады. Квадрат жақшаға алынған константалық өрнек массивтегі элементтер санын анықтайды. Массив элементтерінің индекстелуі нөлден басталады. Осылайша, массивтің соңғы элементінің индексі массивтегі элементтер санынан 1-ге кем болады.

Екінші синтаксистік формада квадрат жақшадағы константалық өрнек жазылмаған. Егер массивтің жариялануында инициализатор болса, немесе егер массив функцияның формальды параметрі ретінде жарияланса, немесе егер массивтің осы жариялануы программаның қандай да бір басқа жеріндегі массивтің жариялануына сілтеме болып табылса, осы форманы қолдануға болады. Массивтің барлық элементтерін орналастыруға қажетті жады көлемі бөлінеді. Массив элементтері біріншісінен бастап соңғысына дейін жадының тізбекті ұяшықтарына адрестерінің өсуі бойынша орналастырылады. Жадыда массив элементтерінің арасында бос орындар жоқ.

Программа мысалы: Нақты сандардан құралған, 5 саннан тұратын а массиві берілген. Массивтің барлық элементтерінің қосындысын табу керек.

#include<math.h>

#include<stdio.h>

main(){

int a[5],s=0;

printf("\n a[i] массивінің элементтерін енгізіңіз\n");

for (i=0;i<n;i++) scanf("%d",&a[i]);

for (i=0;i<n;i++) s+=a[i];

printf("%d\n",s);

return;}

Екі өлшемді массивті жариялау синтаксисі төмендегідей:

[<сипатталатын массив типі>] <айнымалы-идентификатор> [<константалық өрнек>][<константалық өрнек>].

<айнымалы-идентификатор>-дан кейінгі квадрат жақша массив типінің белгісі болып табылады. Квадрат жақшадағы әрбір константалық өрнек массивтің берілген өлшеміндегі элементтер санын анықтайды. Массив элементтері нөлден бастап индекстеледі. Осылайша, массивтің соңғы элементінің индексі массивтегі элементтер санынан 1-ге кем болады. Массивтің барлық элементтерін орналастыруға қажетті жады көлемі бөлінеді. Массив элементтері біріншісінен бастап соңғысына дейін жадының тізбекті ұяшықтарына адрестерінің өсуі бойынша орналастырылады. Жадыда массив элементтерінің арасында бос орындар жоқ. Көп өлшемді массив элементтері компьютер жадысында жол бойынша сақталады.

Программа мысалы: Нақты сандардан құралған а(5,5) екі өлшемді массиві берілген. Массивтің барлық элементтерінің қосындысын табу керек.

#include<math.h>

#include<stdio.h>

main(){

int a[5],s=0;

printf("\n a[i][j] массивінің элементтерін енгізіңіз\n");

for (i=0;i<n;i++)

for (j=0;j<n;j++)

scanf("%d",&a[i][j]);

for (i=0;i<n;i++)

for (j=0;j<n;j++)

s+=a[i][j];

printf("%d\n",s);

return;

}

Негізгі әдебиет: 1[104-107], 2[259-320], 3[192-195], 5[110]

Қосымша әдебиет: 1[239]

Бақылау сұрақтары:

1. Массивті реттеу қандай жағдайларда жүргізіледі?

2. Таңдау арқылы сұрыптау алгоритмін сипаттаңыз.

3. Алмастыру арқылы сұрыптау алгоритмін сипаттаңыз.

4. Қарапайым қою арқылы сұрыптау алгоритмін сипаттаңыз.

5. Сұрыптау алгоритмдерінің айырмашылығы неде?

6-дәріс. Borland C++-тегі функциялар

Функция – бұл қандай да бір жеке тапсырманы орындауға арналған жариялаулар мен операторлардың жиынтығы. Программада функциялардың санына шектеу қойылмайды. Си тіліндегі кез келген программада кем дегенде бір функция болады, ол – main атты басты функция.

Функцияның анықталуы функция атын, оның формальды параметрлерінің атрибуттарын және жариялаулар мен операторлардан тұратын функция денесін белгілейді. Функция анықталуында функция жадысының класы және қайтарылатын мәннің типі берілуі мүмкін.

Фукнцияның жариялануы функцияның атын және қайтарылатын мәнінің типін береді, оның айқын түрде анықталуы программаның басқа жерінде келтіріледі. Функцияның жариялануында жады класы, функция аргументтерінің саны мен типтері белгіленуі мүмкін.

Егер қайтарылатын мәннің типі int болса, оны функция анықталуында көрсету міндетті емес. Қайтарылатын мәннің типі басқа болса, оны функцияны жариялау кезінде көрсету қажет.

Функцияның шақыру кезінде басқару шақырушы функциядан шақырылатын функцияға беріледі. Нақты аргументтердің мәндері, егер олар бар болса, шақырылатын функцияға беріледі. Шақырылатын функцияда return қайтару операторын орындау кезінде басқару мен қайтарылатын мән (егер ол бар болса) шақырушы функцияға беріледі.

Функцияның анықталуы функцияның атын, формальды параметрлерін және денесін белгілейді. Функцияны анықтау синтаксисі төмендегідей:

[<жады класының спецификациясы>] [<тип спецификациясы>]

<сипаттауыш> ([<параметрлер тізімі>])[<параметрлердің жариялануы>]

<функция денесі>

Жады класының спецификациясы функция жадысының класын тағайындайды. <Тип спецификациясы> сипаттауышпен бірге қайтарылатын мәннің типі мен функция атын анықтайды. <Параметрлер тізімі> формальды параметрлер аттарының тізімі (бос болуы мүмкін) болып табылады, бұл формальды параметрлердің мәндері функцияны шақыру кезінде функцияға беріледі. <Параметрлердің жариялануы> формальды параметрлердің идентификаторлары мен типтерін береді. <Функция денесі> – бұл локальды айнымалылар мен операторлардың жариялануынан тұратын құрамды оператор.

Функцияның шақырылуы берілген функцияның басқаруы мен нақты аргументтерін (олар бар болса) тағайындайды. Функция шақырылуының синтаксисі келесідей:

<өрнек> ([<өрнектер тізімі>])

<Өрнек> есептеледі де, оның нәтижесі функция адресі ретінде қабылданады. Өрнектің типі функция типі болуы керек. <Өрнектер тізімі>-нде өрнектер үтір арқылы жазылады, ол функцияға берілетін нақты аргументтер тізімі болып табылады. Өрнектер тізімі бос болуы мүмкін. Функцияны шақыру кезінде нақты аргументтер формальды параметрлерге меншіктеледі. Басқару функция денесінің бірінші операторына беріледі. Функция денесінде return операторын орындау кезінде шақыру нүктесіне басқару қайтарылады, және бар болса мән де қайтарылады. Return операторы болмаған жағдайда, басқару функция денесінің фигуралы жақшасына жеткен кезде қайтарылады. Бұл жағдада қайтарылатын мән анықталмаған.

<Өрнек> функцияға сілтенуі тиіс. Бұл функция тек идентификатор бойынша ғана емес, функцияға көрсеткіш типіне ие кез келген өрнек бойынша шақырыла алады дегенді білдіреді.

Функцияның шақырылуы синтаксистік тұрғыда оның жариялануына ұқсайды. Функцияны жариялау кезінде алдымен функция аты, содан кейін жақшаның ішінде аргументтер тізімі жазылады. Функцияны шақыру кезінде де алдымен функция аты, содан кейін жақшаның ішінде өрнектер тізімі жазылады.

Нақты аргумент базалық типті кез келген мән, құрылым, бірлестік немесе көрсеткіш болуы мүмкін. Барлық нақты аргументтер мәндері бойынша беріледі. Массивтер мен функциялар параметр ретінде беріле алмайды, осы объекттерге арналған көрсеткіштер беріле алады. Сондықтан массивтер мен функциялар сілтеме бойынша беріледі. Нақты аргументтердің мәндері сәйкес формальды параметрлерге көшіріледі. Функция көшірме жасалған айнымалыларды өзгертпестен, тек осы көшірмелерді ғана пайдаланады. Аргументтерінің саны айнымалы болып табылатын функцияны шақыру үшін арнайы іс-әрекеттің қажеті жоқ: функция шақырылуында аргументтердің қажетті саны көрсетіледі. Рекурсивті шақырулар. Си программасындағы кез келген функцияны рекурсивті түрде шақыруға болады; атап айтқанда, ол өзін өзі шақыра алады. Компилятор бір функцияның рекурсивті шақырылуларының санына шектеу қоймайды.

Мысал: Екі a және b нақты сандары берілген. Есептеу керек: . Егер.

#include <conio.h>

#include <stdio.h>

#include <math.h>

// описание функции F

float F(float x){

float f1;

f1=sin(x)*cos(2*x)-sin(2*x)*cos(2/x);

return f1;

}

main(){

float a, b,t;

clrscr();

printf("\nВведите a, b : ");

scanf("%f",&a);

scanf("%f",&b);

t=(f(a+b)-f(a))/f(a-b);

printf("\nC = %5.2f",t);

return 0;

}

Негізгі әдебиет: 1 [161-181], 2[177-258], 3[170-191], 5[71-89]

Бақылау сұрақтары:

1. Ішкі программалардың формальды және нақты параметрлерінің аттары бірдей бола алады ма?

  1. Егер ішкі программада бірдей атты локальды айнымалы болса, глобальды айнымалы осы ішкі программаның ішінде көрінеді ма?

  2. Формальды және нақты параметрлер қандай шарттарды қанағаттандыруы тиіс?

  3. Қандай параметрлер формальды деп аталады, қандай параметрлер нақты деп аталады?

  4. Параметр-мән мен параметр-айнымалыны беру ережелері қандай?

7-дәріс. Borland C++ тіліндегі көрсеткіштер

Көрсеткіш – бұл басқа айнымалының адресін сақтайтын айнымалы.

Көрсеткіштер және адрестер. Көрсеткіште объектінің адресі болғандықтан, көрсеткіш арқылы осы объектке «жанама» қатынас жасауға мүмкіндік бар. х – int типті айнымалы, ал рх – қандай да бір тәсілмен құрылған көрсеткіш делік. & унарлы операциясы объект адресін шығарып береді, сондықтан рх = &х; операторы х-тің адресін рх айнымалысына меншіктейді; кейде рх х-ке «сілтейді» деп айтады. & операциясы айнымалылар мен массивтерге ғана қолданылады, &(х-1) және &3 түріндегі конструкциялар қате болып табылады. Сонымен қатар регистрлік айнымалының адресін алуға болмайды.

* унарлы операциясы өз операндын ақырғы нәтиженің адресі ретінде қарастырады және құрамындағы мәліметтерді алып алу үшін осы адрес бойынша қатынас жасайды, сонымен, егер y айнымалысының да типі int болса, онда

y = *рх;

y-ке рх сілтеп тұрған объектінің құрамындағы мәліметті меншіктейді. Сонымен

рх = &х;

y = *рх;

операторлар тізбегі y-ке

y = x;

меншіктеген нәрсені меншіктейді.

Осының бәріне қатысатын айнымалыларды төмендегідей сипаттау керек:

int x, y;

int *px;

x пен y-тің сипатталуы бізге таныс.

Көрсеткішті сипаттау

int *px;

бізге таныс емес, жаңа нәрсе болып табылады, және ол мнемоникалық сипаттау ретінде қарастырылуы қажет; бұл *px комбинациясының типі int екенін білдіреді. Егер px *px контекстінде кездесетін болса, бұл int типті айнымалыға пара-пар деген сөз.

Негізінде айнымалыны сипаттау синтаксисі осы айнымалының пайда болуы мүмкін өрнектердің синтаксисіне ұқсайды. Бұл ескерту күрделі сипаттаулармен байланысты барлық жағдайлар үшін тиімді. Мысалы,

double atof(), *dp;

atof() және *dp өрнектердің ішінде double типті мәнге ие екенін білдіреді.

Осы сипаттаудан шығатыны, көрсеткіш тек белгілі бір объект түріне ғана сілтей алады. Көрсеткіштер өрнектердің ішінде бола алады. Мысалы, егер px бүтін санды x-ке сілтейтін болса, онда *px x кездесіп қалуы мүмкін кез келген контекстте қолданыла алады. Сонымен,

y = *px + 1

операторы y-ке x-тің мәнінен 1 мән артық мәнді меншіктейді;

printf("%d\n", *px)

операторы x-тің ағымдағы мәнін баспаға шығарады;

d = sqrt((double) *px)

операторы d-ға x-тің квадрат түбірін меншіктейді, бұл жерде sqrt функциясын орындамастан бұрын x айнымалысы double типіне түрлендіріледі.

Келесі түрдегі өрнектерде

y = *px + 1

* және & унарлы операциялары арифметикалық операциялармен емес, өз операндымен тығыз байланыста болады, сондықтан мұндай өрнек px-тің сілтейтін мәнін алады, 1-ді қосады да, нәтижені y айнымалысына меншіктейді.

y = *(px + 1).

өрнегінің нені білдерітініне қайта оралып, түсініктеме береміз.

Көрсеткіштерге сілтемелер меншіктеу операторының сол жақ бөлігінде де кездесуі мүмкін, егер px x-ке сілтейтін болса, онда

*px = 0

x-ті нөлге тең деп алады, ал

*px += 1.

оны 1-ге арттырады, келесі өрнек те дәл осылай

(*px)++

Соңғы мысалдағы жай жақша міндетті түрде керек; егер оны жазбаса, онда * және ++ сияқты унарлы операциялар оңнан солға қарай орындалатын болғандықтан, бұл өрнек PX сілтеп тұрған айнымалыны емес, PX-тің өзін арттырады.

Және де көрсеткіштер айнымалы болып табылатындықтан, олармен басқа айнымалыларға қатынас жасағандай қатынас жасауға болады. Егер py int типті айнымалының басқа көрсеткіші болса, онда

py = px

px-тің ішіндегіні py-ке көшіреді, нәтижесінде px қайда сілтесе, py те сол жаққа сілтейді.

Көрсеткіштер және массивтер. "C" тілінде көрсеткіштер мен массивтердің арасында тығыз байланыс бар, оның тығыздығы сонша, көрсеткіштер мен массивтерді бірге қарастыру керек. Массивтің индекстері арқылы орындалатын кез келген операцияны көрсеткіштердің де көмегімен орындауға болады. Көрсеткіштерді қолданған жағдайда операция жылдамырақ орындалады, бірақ оны бірден түсіну қиынға соғады.

int a[10]

сипаттамасы өлшемі 10-ға тең массивті анықтайды, яғни a[0], a[1], ..., a[9] деп аталатын тізбектеле орналасқан 10 объекттің жиынтығы. a[i] жазуы массивтің басынан бастап санағанда, i-ші элементіне сәйкес келеді. Егер pa – төмендегідей сипатталған бүтін санның көрсеткіші болса,

int *pa,

онда

pa = &a[0]

меншіктеу операторы pa-ның a массивінің нөлінші элементіне сілтейтінін білдіреді; бұл дегеніміз – pa көрсеткішінде a[0] элементінің адресі сақталады. Енді

x = *pa

меншіктеу операторы a[0]-дың мәнін x-ке көшіретін болады.

Егер pa көрсеткіші a массивінің қандай да бір анықталған элементіне сілтейтін болса, онда анықтама бойынша pa+1 келесі элементке сілтейді, және жалпы pa-i көрсеткіші – pa сілтейтін элементтен i позиция бұрын орналасқан элементке сілтейді, ал pa+i көрсеткіші – i позиция кейін орналасқан элементке сілтейді. Осылайша, егер pa көрсеткіші a[0]-ге сілтейтін болса, онда

*(pa+1)

a[1] құрамындағысына, pa+i - a[i] адресіне, ал *(pa+i) - a[i] құрамындағысына сілтейді.

Бұл ескертулер a массивіндегі айнымалылардың типіне қарамастан дұрыс болып табылады. «Көрсеткішке 1-ді қосу» анықтамасының, сондай-ақ оның толықтай көрсеткіштер арифметикасына таралуының мәні мынада: көрсеткіштің сілтейтін объектісінің алып тұрған жады көлемі осы өсімді масштабтайды. Осылайша, pa+i-дегі i қосылудың алдында pa сілтейтін объекттердің өлшеміне көбейтіледі.

Көрсеткіштердің индекстелуі мен арифметикасы арасында сәйкестік бар екені анық, шындығында компилятор массивке сілтемені массивтің басындағы көрсеткішке түрлендіреді. Осының нәтижесінде массив аты көрсеткіштік өрнек болып табылады. Осыдан бірнеше пайдалы салдар шығады. Массив аты оның нөлінші элементінің орнына синоним болып табылатындықтан, онда pa=&a[0] меншіктеу операторын келесідей жазуға болады:

pa = a.

Тағы да бір таңғаларлық жайт, A[i]-ге сілтемені *(a+i) түрінде жазуға болатыны. a[i] өрнегін талдау кезінде "C" тілінде ол дереу *(a+i) түріне келтіріледі; бұл екі форма бір-біріне эквивалентті. Егер осы эквиваленттілік қатынасының екі бөлігіне де & операциясын қолданатын болсақ, онда біз &a[i] мен a+i –дің де бірдей екендігін байқаймыз: a+ia массивінің элементтерін басынан бастап санағанда i- ші элемент адресі. Екінші жағыман, егер pa көрсеткіш болып табылса, онда өрнектерде оны индекспен қолдануға болады: pa[i] мен *(pa+i) пара-пар. Қысқасы, массивтер мен индекстері бар кез келген өрнек көрсеткіштер мен жылжытулар арқылы жазылуы мүмкін.

Массив аты мен көрсеткіш арасында бір айырмашылық бар, оны әрдайым есте сақтау қажет: көрсеткіш айнымалы болып табылады, сондықтан pa=a және pa++ операцияларының мағымасы бар. Бірақ массив аты айнымалы емес, константа болып табылады: a=pa немесе a++, немесе p=&a конструкциялары қате болып табылады.

Массив аты функцияға берілетін кезде, негізінен оған осы массив басының орны беріледі. Шақырылған функцияның ішінде мұндай аргумент кез келген басқа айнымалы сияқты айнымалы болып табылады, сондықтан массив аты аргумент ретінде шынымен де көрсеткіш болып, яғни ішінде адрес бар айнымалы болып табылады. Біз бұл жағдайды жолдың ұзындығын есептейтін STRLEN функциясының жаңа нұсқасын жазу үшін қолдана аламыз.

strlen(s) /* return length of string s */

char *s;

{

int n;

for (n = 0; *s != '\0'; s++)

n++;

return(n);

}

s-ті арттыру операциясы дұрыс болып табылады, себебі бұл айнымалы көрсеткіш болып табылады; s++ strlen-ге қатынас жасаған функциядағы символдық жолға мүлдем әсер етпейді, ол тек strlen функциясы үшін локальды болып табылатын адрес көшірмесін арттырады. Функция анықтамасында формальды параметрлерді сипаттаудың келесі түрлері

char s[];

char *s;

бір-біріне эквивалентті; сипаттаудың қай түрін қолдану керектігі функцияны жазу кезінде қандай өрнектердің қолданылатынымен анықталады. Егер функцияға массив аты берілетін болса, онда ненің ыңғайлы екендігіне байланысты, функцияның массивпен немесе көрсеткішпен жұмыс істейтінін болжауға болады, ары қарай сәйкесінше әрекет ету керек. Егер қажет деп табылса, онда операцияның екі түрін де қолдануға болады.

Егер аргумент ретінде ішкі массив басының көрсеткіші берілетін болса, онда функцияға массивтің бір бөлігін беруге болады. Мысалы, егер a – массив болса, онда төмендегі екі өрнек те

f(&a[2]),

f(a+2)

f функциясына a[2] элементінің адресін береді, өйткені &a[2] де, a+2 де үшінші a элементіне сілтенетін көрсеткіштік өрнектер болып табылады. f функциясының ішінде аргументтердің сипаттамалары келесі түрде болуы мүмкін:

немесе

f функциясына келетін болсақ, оның аргументінің шындығында үлкен массивтің бөлігіне сілтенетіні оған ешқандай әсер етпейді.

Адрестік арифметика. Егер p көрсеткіш болса, онда ол сілтейтін объектінің сорты қандай болса да, p++ операциясы p-ны осы объектілер жиынының келесі элементіне сілтейтіндей етіп арттырады, ал p+=i операциясы p-ны ол ағымдағы элементтен i элементке қалып жүретін элементке сілтейтіндей етіп арттырады. Осы және осыған ұқсас конструкциялар көрсеткіштер арифметикасы мен адрестік арифметиканың ең қарапайым және ең кең таралған формалары болып табылады.

Негізгі әдебиет: 1 [161-181], 2[312-344], 3[186-190], 5[94-124]

Бақылау сұрақтары:

1. Көрсеткіштермен жұмыс істеуге арналған операцияларды атаңыз?

2. Көрсеткіштен бүтін санды қосу кезінде көрсеткіш мәні қандай мәнге артады?

3. Айнымалы-көрсеткішті инициалдау мысалын келтіріңіз.

4. Айнымалы-көрсеткішті жариялау мысалын келтіріңіз.

5. Сілтеме бойынша шақыруды құру үшін қандай операция қолданылады?

8-дәріс. Массивтер және көрсеткіштер

Көпөлшемді массивтер. "C" тілінде тік бұрышты көп өлшемді массивтер қарастырылған, дегенмен практикада көрсеткіштердің массивіне қарағанда олар сирек қолданылады. Ай күнін жыл күніне, және керісінше түрлендіретін есепті қарастырайық. Мысалы, 1 наурыз толық емес жылдың 60-шы күні және толық жылдың 61-ші күні болып табылады. Осы түрлендірулерді орындау үшін екі функция енгізейік: day_of_year ай мен күнді жыл күніне түрлендіреді, ал month_day жыл күнін ай мен күнге түрлендіреді. Осы соңғы функция екі мән қайтаратын болғандықтан, ай мен жыл аргументтері көрсеткіш болуы керек:

month_day(1977, 60, &m, &d)

m 3-ке, және d 1-ге тең деп есептейді (1-ші наурыз).

Берілген екі функция да әрбір айдағы күндер санын көрсететін ақпараттық кестені қажет етеді. Толық және толық емес жылда айдағы күндер санында айырмашылық болғандықтан, есептеу кезінде ақпан айын бақылап отырғаннан гөрі оларды екі өлшемді массивтің екі жолы ретінде көрсеткен ыңғайлы. Төменде осы массив және осы түрлендірулерді орындайтын функциялар келтірілген:

static int day_tab[2][13] = {

(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),

(0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)};

day_of_year(year, month, day) /* set day of year */

int year, month, day; /* from month & day */

{

int i, leap;

leap = year%4 == 0 && year%100 != 0 \!\! year%400 == 0;

for (i = 1; i < month; i++)

day += day_tab[leap][i];

return(day);

{

month_day(year, yearday, pmonth, pday)

/*set month,day */

int year, yearday, *pmonth, *pday;

/* from day of year */

{

leap = year%4 == 0 && year%100 != 0 \!\! year%400 == 0;

for (i = 1; yearday > day_tab[leap][i]; i++)

yearday -= day_tab[leap][i];

*pmonth = i;

*pday = yearday;

}

day_tab массиві day_of_year үшін де, month_day үшін де сыртқы массив болуы керек, себебі оны осы функциялардың екеуі де қолданады. day_tab массиві біз қолданып отырған екі өлшемді массивтердің алғашқысы болып табылады. Анықтама бойынша "C" тілінде екі өлшемді массив негізгі мәнісінде әрбір элементі массив болып табылатын бір өлшемді массив болып табылады. Сондықтан олардың индекстері басқа тілдердегідей day_tab [i, j] емес, day_tab[i][j] деп жазылады. Қалған жерлерінде массивтермен басқа тілдердегідей қатынас жасауға болады. Элементтері жол бойынша сақталады, яғни элементтерге олардың жадыда орналасу реті бойынша қатынас жасаған уақытта оң жақ шетте орналасқан индекс жылдамырақ өзгереді.

Массив фигуралы жақшаға алынған бастапқы мәндер тізімінің көмегімен инициалданады; екі өлшемді массивтің әрбір жолы сәйкес ішкі тізімі арқылы инициалданады. Біз day_tab массивінің басына ай нөмірлері 0-ден 11-ге дейін емес, 1-ден 12-ге дейін өзгеріп тұруы үшін нөлдерден құралған бағанды орналастырдық. Әзірше жады көлемін үнемдеу біз үшін аса маңызды болмағандықтан, индекстерді келтіргеннен гөрі осындай тәсіл жеңілдеу болады.

Егер екі өлшемді массив функцияға берілетін болса, онда функцияның тиісті аргументінің сипатталуында бағандар саны болу керек; жолдар саны маңызды емес, себебі оның орнына бұрынғыдай көрсеткіш беріледі. Біздің жағдайда бұл – int типті 13 саннан құралған массив болып табылатын объекттердің көрсеткіші. Осылайша, егер day_tab массивін f функциясына беру керек болса, онда f функциясындағы сипатталуы төмендегідей болатын еді:

f(day_tab)

int day_tab[2][13];

{

...

}

Жолдар саны маңызды емес болғандықтан, f функциясындағы аргументтің сипатталауы мынадай:

int day_tab[][13];

немесе мынадай болуы мүмкін еді:

int (*day_tab)[13];

мұнда аргумент 13 бүтін саннан құралатын массивтің көрсеткіші болып табылатыны айтылады. Мұндағы жай жақшалар міндетті болып табылады, себебі [ ] квадрат жақшалар *-ға қарағанда жоғары деңгейге ие; жай жақшаларсыз жағдайда

int *day_tab[13];

бүтін сандардың 13 көрсеткішінен құралатын массивтің сипаттамасы болып табылады.

Көрсеткіштер және көп өлшемді массивтер. "C" тілін жаңадан оқып бастағандар кейде екі өлшемді массив пен көрсеткіштер массивінің айырмашылығы туралы мәселеде тұйыққа тіреліп қалады. Егер төмендегідей сипатталулар болса,

int a[10][10];

int *b[10];

онда a мен b-ны бірдей жолмен пайдалануға болады, себебі a[5][5] те b[5][5] те int типті бөлек санға сілтеме болып табылады. Бірақ a – нағыз массив болып табылады: оған жадының 100 ұяшығы бөлінеді және кез келген көрсетілген элементті табу үшін тік бұрышты индекстермен әдеттегі есептеулер жүргізіледі. Алайда b-ға бұл сипатталу тек 10 көрсеткіш қана бөледі; әрбір көрсеткіш бүтін сандар массивіне сілтейтіндей етіп орнатылуы керек. Егер олардың әрқайсысы 10 элементтен құралған массивке сілтейді деп алсақ, онда шамамен жадының 100 ұяшығы және оған қоса көрсеткіштер үшін тағы 10 ұяшық бөлінеді. Осылайша, көрсеткіштер массиві жадының көбірек бөлігін қолданады және анық инициалдау қадамын талап етуі мүмкін. Бірақ бұның екі артықшылығы бар: элементке көбейту және қосу арқылы емес, көрсеткіш арқылы жанама түрде қатынас жасалады, және массив жолдарының ұзындығы әр түрлі бола алады. Бұл дегеніміз – b-ның әрбір элементі 10 элементтен құралған векторға сілтеуі міндетті емес; кейіберулері екі элементтен, басқалары жиырма элементтен тұратын векторға сілтеуі мүмкін, ал үшіншілері еш нәрсеге сілтемеуі де мүмкін.

Негізгі әдебиет: 1 [104-108], 2[344-405], 3[192-214], 5[94-124]

Қосымша әдебиет: 1[239]

Бақылау сұрақтары:

1. Әр түрлі массив түрлерін инициалдау мысалдарын келтіріңіз.

2. Көрсеткіштер мән ретінде нені сақтайды?

3. Көрсеткішті инициалдау үшін қандай үш мән қолданыла алады?

4. Қандай кластағы айнымалыларға адресті алу операциясы қолданыла алмайды?

5. Массив аты массивтің қай элементіне көрсеткіш болып табылады?

9-ші дәріс. Символдық жолдар және қолданылатын функциялар

Символдық жолдарды баяндау. Символдық жолдарды бірнеше әдістер арқылы анықтауға болады. Келесі әдістер негізгі әдістерге жатады:

- жолдық константаларды қолдану;

- символдық жолдардан тұратын массивтерді және char типті массивтерді қолдану.

Жолдық константалар тырнақшаларға алынады. Тырнақшаларға алынған символдар және жолдардың ең соңғы ‘/0’ символы жадының тізбектелген ұяшықтарында жазылады. Компилятор жолды жадыға орналастырғанда жадының қажетті өлшемін анықтау үшін символдардың санын есептейді. Жолдық константаларды #define директивасының көмегімен анықтауға болады. Егер қатарда тырнақша символын қолдану керек болса, онда бұл символдың алдына кері бөлшек сызығы жазылады. Мысалы:

printf (“\” Сведения о сессии”\n”);

Жолдық константа осы жол жазылған жадыдағы орынға сілтейтін көрсеткіш болып табылады. Символдық жолдардың массивін анықтағанда компилятор жадыдының қажетті өлшемін анықтау үшін массивті баяндағанда жолдық константа арқылы инициалдауға болады. (Статикалық және сыртқы массивтер қолданылады).

char c[ ]=”Максималды баллды анықтау”; (сыртқы массив)

Әдеттегі массивтерді қолданған жағдайдағы сияқты бұл массивтің аты с, осы массивтің 1-ші элементіне сілтейтін көрсеткіш болып табылады.

c==&c[0]; *c==’0’, және *(c+1)==c[1]==’n’;

Жолдарды анықтау үшін көрсеткіштерді қолданамыз. Мысалы:

char *c1=”\n баллдарды енгізу”;

Осы баяндалуға келесі баяндалу эквивалентті:

static char c1[ ]=”\n баллдарды енгізу”;

Қарастырылған жолдың екі баяндауы с1 жолдың көрсеткіші екенін көрсетеді. Жадының қажетті өлшемін айқын көрсетуге де болады. Сыртқы баяндауда келесі жолды мына түрде жазуға болады:

char c[35]=” Максималды баллды анықтау ”; вместо

char c[ ]=” Максималды баллды анықтау ”;

Элементтердің саны жолдың ұзындығынан бір символға артық болуы керек (нөль-символын есептегенде). Басқа статикалық немесе сыртқы массивтердегідей кез келген қолданылған элементтер автоматты түрде нөлмен инициалданады (символдық түрде бұл нөль санының символыны емес, нөль-символы болып табылады).

Символдық жолдардан тұратын массивтер. Әрбір жолы символдық массив болып табылатын символдық жолдардан тұратын массивтерді қарастырайық. Статикалық массивтің баяндалуын келесі түрде келтірейік:

static char *m[4]={“регистр”,”ұяшық”,”көрсеткіш”,”элемент”};

*m[4] массиві символдық қатарларға сілтейтін 4 көрсеткіштен тұрады. Сонымен, символдық қатарлар массивтер болып табылатын болса, онда осы массивтерге сілтейтін 4 көрсеткіш қарастырылады. 1-ші жолға сілтейтін 1-ші көрсеткіш болып m[0]-ші табылады. 2-ші жолға сілтейтін 2-ші көрсеткіш m[1]. Сонымен, әрбір көрсеткіш сәйкес жолдың ең бірінші символына сілтейді.

*m[0]==’р’; *m[1]==’я’; *m[2]==’у’; *m[3]==’э’;

инициалдау массивтерге арналған ережелер бойынша орындалады. Тырнақшаларға жазылатын текстер жақшалы жазбаларға эквивалентті:

{{…},{…},…,{…}};

Жолдардан құрылған массивтерді баяндағанда символдық жолдардың өлшемін көрсетуге де болады және бұл баяндалуда жолдардың ұзындығы бірдей болады:

static char m[4][10];

статикалық (сыртқы) массивтің қатарларының қолданылмаған (артық) элементтері ‘/0’ (нөль-символымен) символымен инициалданады.

Артық элементтер (яғни, жады тиімді жұмсалу үшін) болмас үшін келесі баяндалуларды қолдануға болады:

static char *[4];

Мұнда әрбір жолдың ұзындығы массивтің сәйкес қатарын инициалдайтын нақтылы қатармен анықталады.

Символдарды өңдеу кітапханасы. Символдарды өңдеу кітапханасы символдық мәліметтермен бір қатар пайдалы тексерістер мен операцияларды орындайтын бірнеше функциялардан тұрады. Әрбір функция аргумент ретінде int типін немесе EOF (файл соңы) индикаторын ұсынатын символды қабылдайды. Символдарды өңдеу кітапханасының функцияларымен жұмыс істеу үшін <ctype.h> тақырыптық файлды қосамыз. Кестеде символдарды өңдеу кітапханасының функциялар тізімі келтірілген.

9.1- кесте. Символдарды өңдеу кітапханасының функциялары

Прототип

Функциялардың баяндалуы

int isdijit (int c)

Егер с сан болып табылса , онда True мәнін қайтарады және басқа жағдайларда 0 (false)

int isalpha (int c)

Егер с әріп болып табылса, онда True мәнін қайтарады және басқа жағдайларда 0

int isalnum (int c)

Егер с сан немесе әріп болып табылса, онда True мәнін қайтарады, және басқа жағдайларда 0.

int isxdijit (int c)

Егер с он алтылық форматтағы символдардың бірі болса, true мәнін қайтарады және басқа жағдайларда 0.

int islower (int c)

Егер с төмеңгі регистрдің әрпі болса, true мәнін қайтарады және басқа жағдайларда 0.

int isupper (int c)

Егер с жоғарғы регистрдің әрпі болса, true мәнін қайтарады және басқа жағдайларда 0.

int tolower

(int c)

Егер с жоғарғы регистрдің әрпі болса,онда tolower с-ны төмеңгі регистрдің әрпі ретінде қайтарады. Басқа жағдайларда tolower аргументті өзгеріссіз қайтарады.

int toupper

(int c)

Егер с төмеңгі регистрдің әрпі болса,онда toupper с-ны жоғарғы регистрдің әрпі ретінде қайтарады. Басқа жағдайларда toupper аргументті өзгеріссіз қайтарады.

int isspace (int c)

Егер с бос орын (пробел) символы (' ') , жаңа бет (‘\f’), жаңа жол (‘\n’), каретканы қайтару (‘\r’), горизонтальді табуляция (‘\t’) или вертикальді табуляция (‘\v’) болып табылса, онда true мәнін қайтарады және басқа жағдайларда 0.

int iscntrl (int c)

Егер с басқарушы символ болса, онда true мәнін қайтарады және басқа жағдайларда 0.

int ispunct (int c)

Егер с баспаға шығарылғандағы бейнеленетін символ болып тпбылса, true мәнін қайтарады, бірақ бос орын символдаына, сандарға немесе әріптерге қатынасы жоқ және басқа жағдайларда 0.

int isprint (int c)

Егер с баспаға шығарылғандағы бейнеленетін символ болып тпбылса, true мәнін қайтарады, мұнда (' ') бос орын символын қосқанда және басқа жағдайларда 0.

int isgraph (int c)

Егер с баспаға шығарылғандағы бейнеленетін символ болып тпбылса, true мәнін қайтарады, мұнда (' ') бос орын символын қосқпағанда және басқа жағдайларда 0.

Жолдарды түрлендіру функциялары. Жолдарды түрлендіру функцияларымен жұмыс істеу үшін <stdlib..h> тақырыптық файлды қосу қажет. Бұл функциялар сандар қатарларын бүтін мәндерге және жылжымалы нүктелі мәндерге түрлендіреді. Кестеде жолдарды түрлендіру функциялар тізімі келтірілген.

9.2-кесте. Жолдарды түрлендіру функциялары

Прототип

Функциялардың баяндалуы

double atof (const char *nPtr)

nPtr қатарын double типіне түрлендіреді.

int atoi (const char *nPtr)

nPtr қатарын int типіне түрлендіреді.

long atol (const char *nPtr)

nPtr қатарын long int типіне түрлендіреді.

double strtod (const char *nPtr, char **endPtr)

nPtr қатарын double типіне түрлендіреді.

long strtol (const char *nPtr, char **endPtr, int base)

nPtr қатарын long типіне түрлендіреді.

unsigned long strtoul (const char *nPtr, char **endPtr, int base)

nPtr қатарын unsigned long типіне түрлендіреді.

Стандартты енгізу/шығару кітапханасының функциялары. Стандартты енгізу/шығару кітапханасы <stdlib.h> символдық және жолдық мәліметтермен жұмыс істеуге арналған бірнеше функциялардан тұрады. Кестеде стандартты енгізу/шығару кітапханасынан символдар мен жолдарды енгізу/шығару функцияларының тізімі келтірілген.

9.3-кесте. Стандартты енгізу/шығару кітапханасының символдық мен қатарларлық функциялары

Прототип

Функциялардың баяндалуы

int getchar (void)

Стандартты енгізу құралынан келесі символды енгізеді және бүтін формат түрінде қайтарады.

char *gets (char *s)

S массивіне стандартты енгізу құралынан символды жаңа жолдың символын немесе файл соңының индикаторын кездестіргенше егізеді. Осыдан кейін массивке шектелетін NULL символы қосылады.

int putchar (int c)

С-да сақталынатын символды баспаға шығару.

int puts (const char *s)

Келесі символы жаңа қатар болатын s қатарын баспаға шығару.

int sprintf (char *s, const char *format, …)

Нәтиже экранда бейнеленбей s массивінде сақталалуымен ерекшеленетін printf функциясына эквивалентті.

int sscanf (char *s, const char *format, …)

Енгізу клавиатура арқылы емес s массиві бойынша орындалалумен ерекшелінетін scanf функциясына эквивалентті.

Жолдарға қолданылатын операциялардың функциялары

Жолдарды өңдеу кітапханасы. Жолдарды өңдеу кітапханасы жолдарды анықтау және жолдарды лексемаларға бөлу үшін, символдарды және басқа жолдарды іздеу үшін, жолдарды салыстыру үшін, жолдық мәліметтерге қолданылатын операцияларды орындау үшін көптеген пайдалы функцияларды ұсынады. Жолдарды өңдеу кітапханасымен жұмыс істеу үшін <string.h> тақырыптық файлын қосу қажет. Кестеде бұл функциялардың тізімі келтірілген.

9.4-кесте. Жолдарды өңдеу кітапханасындағы функциялар

Прототип

Функциялардың баяндалуы

char *strcpy(char *s1, const char *s2);

s2 қатарын s1 қатарына көшіреді. s1 мәнін қайтарады. s2 қатарының құрамын сыйдыру үшін s1 қатарының жеткілікті өлшемін бар деп жорамалдайды.

char *strncpy(char *s1, const char *s2, size_t n);

s1 қатарына s2 қатарынан n-нан көп емес символдарды көшіреді. s1 мәнін қайтарады..

char *strcat(char *s1, const char *s2);

s1 қатарын s2 қатарымен біріктіреді. s1 қатарының NULL символын s2 қатарының бірінші символына көшіреді. s1 мәнін қайтарады..

char *strncat(char *s1, const char *s2, size_t n);

s1 қатарымен s2 қатарының n-нан көп емес символдардын біріктіреді. s1 қатарының NULL символын s2 қатарының бірінші символына көшіреді.s1 мәнін қайтарады.

Жолдарды өңдеу кітапханасындағы жолдарды салыстыру функциялары. Кестеде функциялардың прототиптері мен әрқайсысының қысқаша баяндалуы келтірілген.

9.5-кесте. Салыстыру функциялары

Прототип

Функциялардың баяндалуы

int strcmp(const char *sl, const char *s2);

sl қатарын s2 қатарымен салыстырады. Функция 0-ді, 0-ден кіші немесе нөлден үлкен мәнді қайтарады, егер sl сәйкесінше s2-ге тең, кіші немесе үлкен болса. .

int stricmp(const char *sl, const char *s2);

Төмеңгі және жоғарғы регистрлердегі символдардың арасындағы ерекшеліктерді ескермей-ақ s1 қатарын s2 қатарымен салыстырады. Функция 0-ді, 0-ден кіші немесе нөлден үлкен мәнді қайтарады, егер sl сәйкесінше s2-ге тең, кіші немесе үлкен болса.

int strncmp(const char *sl, const char *s2, size_t n);

s1 қатарының n-ге дейіңгі символдарын s2 қатарымен салыстырады. Функция 0-ді, 0-ден кіші немесе нөлден үлкен мәнді қайтарады, егер sl сәйкесінше s2-ге тең, кіші немесе үлкен болса.

int strnicmp(const char *sl, const char *s2, size_t n);

Төмеңгі және жоғарғы регистрлердегі символдардың арасындағы ерекшеліктерді ескермей-ақ s1 қатарының n-ге дейіңгі символдарын s2 қатарымен салыстырады. Функция 0-ді, 0-ден кіші немесе нөлден үлкен мәнді қайтарады, егер sl сәйкесінше s2-ге тең, кіші немесе үлкен болса.

Жолдарды өңдеу кітапханасындағы іздеу функциялары. Кестеде функциялардың прототиптері мен әрқайсысының қысқаша баяндалуы келтірілген.

9.6 –кесте. Іздеу функциялары

Прототип

Функциялардың баяндалуы

char *strchr(const char *s, int c)

S қатарындағы с символдың біріншіші кірісіндегі позициясын анықтайды. Егер с табылса, онда функция s қатардағы с -ке көрсеткішті қайтарады. Қарсы жағдайда NULL мәнді көрсеткіш қайтарылады.

char *strrchr(const char *s, int c)

S қатарындағы с символдың соңғы кірісіндегі позициясын анықтайды. Егер с табылса, онда функция s қатардағы с -ке көрсеткішті қайтарады. Қарсы жағдайда NULL мәнді көрсеткіш қайтарылады.

size_t strspn(const char *s1, const char *s2)

S2 қатарына кіретін символдардан тұратын s1 қатарының бастапқы сегментінің ұзындығын қайтарады және анықтайды.

size_t strcspn(const char *s1, const char *s2)

S2 қатарына кірмейтін символдардан тұратын s1 қатарының бастапқы сегментінің ұзындығын қайтарады және анықтайды.

char *strpbrk(const char *s1, const char *s2)

S1 қатарынан s2 қатарының кез келгегн симводарының ішінен бірінші кірісіндегі позициясын табады. Егер s2 қатарынан символ табылса, онда функция көрсеткішті s1 қатардағы сол символға қайтарады. Қарсы жағдайда NULL мәнді көрсеткіш қайтарылады.

char *strstr(const char *s1, const char *s2)

S2 жолдың ішіндегі жолдың бірінші кірісіндегі позициясын табады. Егер қатар ішіндегі қатар табылса, онда функция көрсеткішті s1 қатардағы қатар ішіндегі жолды қайтарады. Қарсы жағдайда NULL мәнді көрсеткіш қайтарылады.

char *strtok(char *s1, const char *s2)

Функцияның тізбектелген шақырылуы s1 қатарының s2 қатарындағы символдарға бөлінген лексемаларға (текстік қатардағы сөздер сияқты логикалық бөлімдер) ұсақтаумен орындалады. Функция бірінші рет шақырылғанда аргумент ретінде s1 қатарын алады, ал келесі шақырылуларда сол жолды ұсақтауды жалғастыру үшін бірінші аргумент ретінде NULL беріледі. Әрбір шақырылуда көрсеткіш s1 қатарының ағымды лексемасына қайтарылады. Егер функция кезекті шақырылуында қатарда лексема қалмағанын анықтаса, онда NULL қайтарылады.

Жолдарды өңдеу кітапханасындағы басқа функциялары Кестеде жолды өңдеу кітапханасындағы басқа функиялардың прототиптері мен қысқаша баяндалуы келтірілген.

9.7-кесте. Жолдарды өңдеу кітапханасындағы басқа функциялары

Прототип

Функциялардың баяндалуы

int strlen (const char *s)

S қатарының ұзындығын анықтайды. NULL символына шек қоятын символдарын табады.

char *strlwr (char *s)

s қатарындағы жоғарғы регистр символдарын төмеңгі регистр символдарына түрлендіреді. Басқа символдарға тимейді. Функ­циякөрсеткішті s қатарына қайтарады.

char *strupr(char *s)

s қатарындағы төмеңгі регистр символдарын жоғарғы регистр символдарына түрлендіреді. Басқа символдарға тимейді. Функ­циякөрсеткішті s қатарына қайтарады..

сhar *strrev(char *s)

S қатарындағы символдардың тәртібіне қатынайды және көрсеткішті s қатарына қайтарады.

Төменде қатарлармен жұмыс істейтін функцияларды келтірілген

Мысал 1:

main( )

{ static char l[ }=”Сведения о результатах сессии”; puts(l); flen(l, 8); puts(l); }

flen (stroke, size) char *stroke; int size; {

if (strlen(stroka)>size) *(stroke+size)=’\0’; }

Результат: Сведения о результатах сессии

Сведения

қолданатын программалардың мысалдары

Мысал 3:

#include <stdio.h>

# define NAME “Ритчи”

main() {

char a[20];

puts (“Назовите автора языка Си”); gets(a); while (strcmp(a,NAME)!=0) { puts(“Ввод следующего варианта”); gets (a); }

puts (“Ответ принят”); }

Мысал 2:

#include <stdio.h>

main()

{ static char name[80];

static char stud[ ]= “является студентом факультета ИВТ”; puts(“Ведите ваше имя.”); gets(name);

strcat (name, stud); puts (name); puts (stud); } Результат:

Введите ваше имя Марат

Марат является студентом факультета ИиВТ является студентом факультета ИиВТ

#include <stdio.h>

#define STROKA “С Новым годом!” main()

{ static char *ptr=STROKA;

static char res[25]; puts (ptr);

puts (res); strcpy (res,ptr);

puts (ptr); puts (res); }

Результат:

С Новым годом!

С Новым годом!

С Новым годом!

Негізгі әдебиет: 1нег[325-355], 2нег[371-405]

Дополнительная литература: 5қос[46-51],6қос[116-126], 8қос[13-16]

Бақылау сұрақтары:

1. Қандай функциялар жолдарды өңдеу үшін қолданылады?

2. Қандай функциялар жолдарды салыстыру үшін қолданылады?

3. Қандай функциялар іздеу үшін қолданылады?

4. Қандай тақырыптық файлды жолдарды өңдеу кітапханасымен жұмыс істеу үшін қосу қажет?

5. Қандай функциялар регистрлер ді өзгерту үшін қолданылады?

10-дәріс. Құрылымдар және мәліметтердің басқа формалары.

Мәліметтер құрылымдарыбір немесе бірнеше әр түрлі типті айнымалылардан құралған, ыңғайлылық үшін бір атқа жинақталған мәліметтер жиыны.

Мәліметтер құрылымына қарапайым мысал болып – жұмысшының есеп карточкасы табылады. Жұмысшының мәліметтері: аты, тегі, адресі, еңбек ақысы т.с.с. мәліметтер құрылымы компоненттері болып табылады. Кейбір компоненттерінің өзін мәліметтер құрылымы ретінде сипаттауға болады. Бір атау астына жинақталған мәліметтер құрылымын үлкен программаларда қолдануда тиімді әрі ыңғайлы.

Мәліметтер құрылымдарын struct кілттік сөзінен кейін мәліметтер құрылымына ат қоюға болады. Компоненттері немесе айнымалылары жазба мүшелері деп аталады. Олардың атын еркімізше таңдаймыз, көбінесе сипатталатын объектіге байланысты таңдайды.

Басқа кез келген типтер сияқты бірнеше айнымалыларды, фигуралы жақшадан кейін тізіп жазуға болады. Мысал:

struct {…} x, y, z, сәйкесінше INT X, Y, Z;

Мәліметтер құрылымына да жадыдан орын бөлінеді. Қандай да бір айнымалыны мәліметтер құрылымында сипаттамаса, оған жадыдан орын бөлінбейді. Ол тек шаблон немесе мәліметтер құрылым формасы ретінде қалады, бірақ мәліметтер құрылымының атын қолдануға болады.

struct person {

char name [namesize];

char address [adrsize];

long zipcode; /*почталық индекс*/

long ss_namber; /*әлеуметтік қорғау коды*/

double salary; /*еңбек ақы*/

struct date birthdate; /*туған күні*/

struct date hirehdate; /*жұмысқа кірген күні*/

};

PERSON мәліметтер құрылымында date типті екі мәліметтер құрылымы бар. Егер emp былай анықталса:

struct person emp;

онда

emp. Birthdate.month туған айы анықталады.

Құрылымдық шаблонды анықтау. Әртүрлі типті мәліметтерді баяндау үшін және жаңа типтерді ұйымдастыру үшін құрылым деген тип ыңғайлы және икемді болып табылады. Мәліметтер құрылымын баяндағанда алдымен құрылымдық шаблонды келесі түрде баяндауға болады:

struct <rname>

{

<type> <fname>;

…………

<type> <fname>;

}

мұндағы rname - структура типінің аты, структура типінің атын көрсетпесе де болады, } жақшада структура элементтерінің тізбегі келтірілген және әрбір элементтің типі көрсетілген. Құрылымдық шаблон анықталғаннан кейін құрылымдық айнымалының анықталуы келесі түрде жазылады:

struct <rname> <vnames>;

vnames - құрылымдық айнымалының аты.

Мысал:

struct sved

{

char fam[25];

char adr[20];

int gr;

};

struct sved inf;

Құрылымдық шаблонды функция анықталуының ішінде немесе функцияның сыртында келтіруге болады. Функцияның ішінде келтірілген шаблон осы функцияның ішінде ғана пайдаланылуы мүмкін. Егер құрылымдық шаблон функцияның сыртында орналасқан болса, онда бұл шаблон оның анықталуынан кейін орналасқан программаның бірнеше функцияларында қолданылуы мүмкін. Мысалы, басқа бір функцияның ішінде inf1 атты басқа құрылымдық айнымалыны келесі түрде анықтауға болады: inf1 в виде struct sved inf1;

Берілген баяндалудан тұратын функция шаблон анықталғаннан кейін орналасады деп жорамалданады. Егер құрылымды баяндағанда оның шаблоны программаның бір жерінде анықталған болса, ал осы шаблонды пайдаланылатын құрылымдық айнымалылар программаның басқа бір функциясында анықталатын боса, онда структура типінің атын міндетті түрде көрсету қажет. Құрылымдық айнымалының анықталуын пайдаланып, компилятор құрылымдық шаблон бойынша жадыда орын бөліп береді (құрылымдың әрбір элементінің баяндалуын ескереді). Мәліметтер құрылымын баяндағанда құрылымдық шаблон анықтауын және құрылымдықайнымалыны анықтау процестерін біріктіруге болады. Айнымалыны және шаблонның анықталуын біріктіргенде структура типінің атын жазбаса да болады. Мысал,

struct

{

char fam[25];

char adr[20];

int gr;

} inf;

Егер құрылымдық шаблон бір реттен көп қолданылса, онда әдетте структура типінің атымен берілетін форманы қолданады.

Құрылымдарда инициалдау. Сыртқы және статикалық құрылымдық айнымалыларды инициалдауға болады. Құрылымдық айнымалының сыртқы типке жататыны шаблонның анықталған орнына байланысты емес, осы айнымалы программаның қандай жерінде анықталғанына байланысты. Келесі бар деп жорамалдайық:

static struct sved inf;

Бұл жағдайда статикалық жады қолданылады және құрылымды келесі түрде инициалдауға болады:

static struct sved inf= {“Абзалов”,

“Сәтбаев, 20”,

1978}

Мысал: (құрылымның элементеріне қол жеткізу)

#include <stdio.h>

main()

{ struct

{ char fam[25];

char adr[20];

int gr;

} inf;

printf(“ Тегін еңгізініз: \n”);

gets(inf.fam); /* fam элементіне қол жеткізу*/

printf(“Мекен -жайын еңгізініз: \n”);

gets(inf.adr);

printf(“Туған жылын еңгізініз : \n”);

scanf(“%d”,&inf.gr);

printf (“%s, %s , %d\n”, inf.fam, inf.adr, inf.gr); }

Құрылымдардың массивтері. Есептерді шығару барысында құрылымдардың массивтері пайдаланылады, яғни құрылымдық айнымалы массивтің элементі болып табылады. Құрылымдардың массивтері келесі түрде баяндалады:

struct sved inf[10];

sved типті структура inf[10] массивтің элементі болып табылады.

Құрылымдардың массивтері элементтерін анықтағанда бөлек алынған структура жағдайындағы сиықты құрылымдың аты структура элементінің атынан нүкте “.” (элементті алу операциясы) символы арқылы бөлектенеді. Мысалы :

inf[0].fam - массивтің бірінші элементі

inf[1].fam - массивтің екінші элементі

…………………..

inf[9].fam - массивтің 10- элементі

(inf[1] - құрылымды айнымалының аты)

#include <stdio.h>

#define num 10

struct cved

{ char fam[25];

char adr[20];

int gr; };

main()

{ struct sved inf[num];

int l=0, i;

while (l<num)

{ printf(“Тегін енгізу \n”);

gets (inf[l].fam);

printf(“Мекен-жайы: \n”);

gets (inf[l].adr);

printf(“туған жыл \n”);

scanf(“%d”, &inf[l].gr);

l++; }

printf(“Тобтың студенттері туралы мәліметтер \n”);

for (i=0; i<l; i++)

printf(“%s, %s, %d\n”, inf[i].fam, inf[i].adr, inf[i].gr); }

Бірінің ішіне бірі еңген құрылымдарды қарастырайық

#include <stdio.h>

#define num 5

#define len 15

#define is “Ғылым”

struct isd

{ char namisd[len];

int godisd; }

struct knig

{ char author[len];

char title[len]

struct isd isdat; }

main()

{ static struct knig masking[num]={{“ Ашимов В.”,

“Информатика”

{“Ғылым”, 1998}},

{“Абилов В.”,

“Физика”,

{“Мектеп”,1985}}};

int i;

for (i=0; i<num; i++)

if (masking[i].isdat.nanidd==IS)

printf (“%s %s \n”, masking[i].author, masking[i].title); }

Құрылымның көрсеткішінің қолдануын қарастырайық. Қөрсеткіштің сипаттамасы төменде келтірілген (Құрылымдардың массивтері қарастырылады):

Struct knig *ptrst;

Ptrst көрсеткіш кез-келген knig типі құрылымға сілтеме үшін құрылған.

Орны бар:

Ptrst==&masking[0];

*ptrst==masking[0];

ptrst->author - бұл masking[0].author. эквивалентті болып табылады.

Егер ptrst келтірілген masking[0] құрылымға көрсеткіш болса, онда келесі белгілер эквивалентті болып табылады.

Masking[0].author==(*ptrst).author==ptrst->author

Ptrst+1 masking[1] сілтеме болып саналады. Бұл мысалда 1 ptrst көрсеткішке 47 адресіне қосады, сондықтан ААА типтің әрбір құрылымы 47 байт орын алады. Келесі мысалда, құрылымның адресті функциянын аргументі реттінде қолданылады:

struct ZP

{ char *name;

char *mec;

float nach;

float prem; } SOTR={ “Мамаев П”,”қантар” 1020.45, 250.15 };

main()

{ float s, fadd();

printf (“Мамаев П. қантарда есептелді %6.2а тенге \n“, fadd(&sotr)); }

float fadd (ptrst)

struct zp *ptrst;

{ float s=0;

s=ptrst->nach+ptrst->prem;

return (s); }

& операция құрылымның адресін анықтау үшін қолданылады. Массивтің атына қарағанда құрылымның аты өзінің адресінің синонимы болып табылмайды. Құрылымдардың массивтерді қарастырайық. Массивтін аты оның адресінің синонимы болып табылады, сондықтан оның функцияларын беруге болады.

Struct zp

{ char *name;

char *mec;

float nach;

float prem; } sort[6]={ {“Мамаев П.”,”қантар”, 8020.45, 1250.15},

……………

{“Байтасов М.”,”қантар”,6000.50, 1500.20} };

main()

{ float ITS, fadd ( );

printf (“ Қызметкерлерге қантарда есептелді %10.2f тенге \n”, fadd(sort)); }

float fadd (ptrst)

struct zp *ptrst;

{ float ITS;

int i;

for (i=0, ITS=0; i<6; i++; ptrst++)

ITS+=ptrst ->nach+ptrst->prem;

Return (ITS); }

Негізгі әдебиет: 1[119-139], 2[781-807], 3[277-300], 4[125-147]

Бақылау сұрақтары:

1. Мәліметтер құрылымы дегеніміз не?

2. Бірінің ішіне бірі еңген құрылымдарды қандай кездерде қолдануға болдады?

3. Мәліметтердің құрылымдарын сипаттау үшін қандай құрылымдық шаблонды қолданады?

4. Мәліметтердің құрылымдарының компонентеріне қол жеткізуі қалай ұйымдастырады?

5.Құрылымдар массивтерді өңдеу кезінде көрсеткіштер қалай қолданылады?

11- дәріс. Файлдық енгізу-шығару.

Ағымдар және енгізу-шығару ағымдары. Ағымдар Си тілінде мәліметтерді оқу немесе жазу үшін кен қолданылатын құралдар болып табылады. Олар ыңғайлы және тиымды енгізу-шығару ұйымдастыруға мүмкіндік береді, сонымен қатар қолданатын файлдарға немесе құрылғыларға тәуелді емес. Ағым файл немесе физикалық құрылғы ретінде табылады (мысалы принтер немесе монитор), оларды file объектке көрсеткіш көмегімен басқаруға болады (stdio.h-да анықталған). File файлдың құрамында ағым туралы әртүрлі ақпарат бар, соның ішінде ағымның позициясы, сәйкесті буферлер және қателер немесе файлдың соңы туралы индикаторларға көрсеткіш туралы мәліметтер бар.

Енгізу-шығаруды ағымға жіберу үшін алдын ала оны ашу қажет. Ашылған ағым атталған DOS файлмен немесе құрылғымен байланысады. Ағымдарды ашатын программалар бұл - fopen, fdopen и freopen. Ағымдар ашылған кезде қандай әрекеттер орындалатын көрсетіледі.

Мәтіндік және екілік ағымдар. Мәтіндік ағымдар кәдімгі мәтіндік DOS файлдар үшін қолданылады. Си++ -те енгізу- шығару ағымы болжайды, мәтіндік файл жолдарға бөлінген және жаңа жолға бір символдын көмегімен ажыратылған деп ( жолды аударатын символ ASCII болып табылады). Бірақ DOS мәтіндік файл дискіге әр жолдар арасында екі символ арқылы жазылады - каретканы қайтару және жолды аудару ASCII символдар.

Екілік ағымдарда ешқандай түрлендіру ұйымдастырылмайды. Кез келген символдар өзгеріссіз оқылады және жазылады. Файлды мәтіндік және екілік режимдерде баяндауға болады.

Әншейін ағымдар мәліметтерді оқу және жазу үшін тізбекті түрде қолданылады. Енгізу-шығару файл ағымды позициясында орналасады. Мәліметтерді жазылған немесе оқылған кезде программа файлдық позицияны өңделген мәліметтердең кейін аустырады. Дискілік файлмен байланысқан ағым бос қол жеткен ағым болу мүмкін. Соңдықтан, файлды позициялану үшін fseek қолдануға болады, ал оқу немесе жазу операторларды орындау нәтижесі осы нүктеден кейін мәліметтерге қол жеткізіп санауға болады. Егер мәліметтер ағымда жазылуы мен оқулуы қатар орындалса, онда оқу және жазу операторларды еркін араластыруға болмайды. Жазу мен оқу аралығында ағымның буферің тазалауды талап етеді. Fflush, flushall немесе fseek шақырулар буферді тазалайды және операцияларды аустыруға мүмкіндік береді. Толық тасымалдау үшін буферді тазалау қажет, егер ол қолданбаса, онда басқа жүйелердің енгізу-шығару операцияларға тіпті буферссіз араласуға қосымша шектеулері бар.

Кейбір ағымдардың енгізу-шығару функцияларын сиппатау. Fopen функция файлды ашады, ол path- атымен анықталады. Төменде көрсетілгендей type жолдағы символдар файл үшін талап ететін қол жеткізу типті анықтайды. Форматы:

#include <stdio.h>

FILE *fopen(pathname, type);

char *pathname; // path-файлдың аты.

char *type; // қол жеткізу үшін рұқсатталған тип

11.1-кесте

Режим

Сиппатау

"r"

Оқу үшін файлды ашу (Бұл файл болу керек).

"w"

Жазу үшін бос файлды ашу қажет, егер бұл файл алдын ала болған болса,онда оның мазмұны жойылады.

"a"

Соңына жазылу (қосу) үшін бос файлды ашу қажет. Егер бұл файл жоқ болса,онда оны құру қажет.

"r+"

Оқу және жазылу үшін файлды қатар ашу.Файл алдын ала болу керек.

"w+"

Оқу және жазылу үшін бос файлды ашу. Файл алдын ала болса, онда оның мазмұны жойылады.

"a+"

Оқу және қосу үшін файлды ашу. Файл алдын ала болмаса оны құру қажет.

Егер файл тип "a" немесе"a+" көмегімен ашылса, онда барлық жазылу операциялар файлдың соңына орындалады. Fseek немесе rewind функцияларды қолданған кезде файлға көрсеткіштін позициясын ауыстыруға болады, оған қарамастан файлға көрсеткіш кез келген жазылу операциялардың орындалу кезіңде алдын ала әр қашанда файлдың соңына қайтырылады. Ақырында бар болған мәліметтер қайта жазылмайды. "r+', "w+", "a+" типтерді қолданған кезде оқу мен жазылу қатар болуы мүмкін (Файл жаңарту үшін ашылады деп айтылады). Сондықтан, оқудан жазылуға аустыру және кері қарай кезде fseek немесе rewind функцияларды қолдану қажет. Fseek функция үшін ағымды позициясы дәл анықтауға болады (қажет болған жағдайда).

11.2 -кесте

Символ

Мәні

T

Мәтіндік режимде ашу; "Возврат каретки – перевод строки" комбинацияны енгізу кезінде "перевода строки" деген жалғыз символға түрлендіреді.

B

Екілік режимде ашу; жоғары көрсетілген түрлендірулер орындалмайды.

Жаңа жолдың символына түрлендіру тәсіліне ерекшелу үшін, жоғары көрсетілген мәндерге қосымша type жолға келесі символды қосуға болады.

Қайтарылған мән. Fopen функциясы ащық файлға көрсеткішті қайтарады. NULL көрсеткіштін мәні қате туралы белгілейді.

Мысалы:

#include <stdio.h>

main (argc, argv)

int argc;

char *argv[];

{

FILE *stream;

/* применение fopen -ді қолдану файлды ашуға мүмкіндік береді, оның аты argv[argc-1] қөрсеткіште сақталынады;егер бұл орындалмаса онда программа қате туралы хабарламаны басып шығарады. */

if ((stream= fopen(argv[argc-1]), "r"))==NULL) {

fprintf (stderr, "%s файл ашылмайды %s\n", argv[0], argv[argc-1]);

exit(1);

}

/* Ескерту!Программанын аты argv[0]-да сақталынады MS DOS 3.0-тың алдынғы версияларында және кейінгі ; MS DOS-тың алдынғы версияларында, argv[0] "Си" жолында ораласқан*/

Fclose, fcloseall функциялар сәйкесті ағым мен ағымдарды жабады. Ағымдармен байланысқан буферлер жабу кезінде алдын ала жаңартады. Ағымдар жабылған кезде жүйемен басылып алған буферлер босатылады. Setbuf функциямен анықталған буферлер автоматты түрде босаылмайды.

Берілген ағымды fclose функция stream функциямен жабады. Stdin, stdout, stderr, stdaux, stdprn ағымдардан басқа fcloseall функция барлық ашық ағымдарды жабады. Форматы:

#include <stdio.h>

int fclose(stream); ашық ағымды жабады.

FILE *stream; FILE құрылымға көрсеткіш.

int fcloseall(); барлық ашық ағымдарды жабады.

Қайтарлылған мағыма. Функция fclose 0 қайтарады, егер ағым сәтті жабылса. Функция fcloseall жабылған ағымдардың жалпы саның қайтарады. Қате болған жағдайда екі функциялар eof мәнің қайтарады.

Мысалы:

#include <stdio.h>

FILE *stream; int numclosed;

stream=fopen("data", "r");

. . .

/* келесі оператор ағымды жабады */

fclose (stream);

/* келесі оператор барлық ағымдарды жабады, тек қана stdin, stdout, stderr, stdaux, stdprn */

numclosed=fcloseall();

Функция fprintf функция символдардың ағымдардың және мәндердін тірулім шығыс ағымға форматайды да баспаға шығарады. Әр аргумент (егер ол болса) түрлендіріледі де және форматтын берілген спецификациясына сәйкес форматтың жолына шығарылады. Жол формат printf функцияның жол форматтын аргументің формасымен және функциясымен қолданылады. Жол форматта (format-string) printf функцияның жол форматтын аргументі формасымен және функциясы бар. Формат:

#include <stdio.h>

int fprintf (stream, format-string [, argument ...]);

FILE *stream; FILE құрылымға көрсеткіш.

char *format-string;форматты басқаратын жол

Қайтарылған мәні. Осы функция баспаға шығарылған символдардың санын қайтарады.

Мысал.

#include <stdio.h>

FILE *stream; int i = 10; double fp = 1.5;

char *s = "Бұл жол";

char c = '\n';

stream = fopen("result", "w");

/* форматтау және әртүрлі мәліметтерді баспаға шығару */

fprintf (stream, "%s%c", s, c);

/* сөйлемшінің баспаға шығаруы "бұл - жаңа жол", жаңа жолдың символыннаң кейін */

fprintf (stream, "%d\n", i);

/*10 саның баспаға шығару, содан кейін жаңа жолдың символың */

fprintf (stream, "%f", fp); /* 1.500000санды баспаға шығару */

Fscanf функция мәліметтердің деректерлерің stream ағымың тасқынының ағымдық айқындамасынан arguments (олар болса) дәлелінің тапсырмасымен анықталған жерге оқып алады. Әр аргумент айнымалыға және типке көрсеткіш болуға тиісті, сонымен қатар жолдың форматында берілгеніне типіне сәйкес болу керек. Форматтың жолы енгізудің өрістің түсіндіруімен басқарылады және оның формасы мен міндеті, не форматтың жолының аргументі (дәлелі) scanf функция үшін сияқты болып табылады.

#include <stdio.h>

int fscanf (stream, format-string [, argument ...]);

FILE *stream; FILE құрылымына көрсеткіш.

char *format-string; форматты басқаратың жол.

Қайтарлылған мән. Бұл функция дұрыс түрлендірілген және бекітілген өрістердің санын қайтарады. Қайтарлылған мән оқылған кейін, бірақ бегітілмеген өрістерді құрамының ішіне алмайды. Файлдың соңының оқу амалында eof мәні қайтады. Қайтарлылған мағыма 0 белгілейді, бұл бегітілген өрістер жоқ екенін білдіреді.

Мысал.

#include <stdio.h>

FILE *stream;

long l; float fp; char s[81]; char c;

stream = fopen ("data", "r");

...

/* әртүрлі мәліметтерді енгізу */

fscanf (stream, "%s", s);

fscanf (stream, "%c", &c);

fscanf (stream, "%ld", &l);

fscanf (stream, "%f", &fp);.

Сонымен қатар файлдармен жұмыс атқарған кезіңде келесі функциялар қолданылады:

11.3-кесте

Функция

Қысқа сипаттама

Fdopen

Дескрипторды қолданып, алдың ала төменгі денгейде ашылған файл үшін ағымды құру

feof

Ағымың соңына тексеру

ferror

Ағымның қателерінің жалауына тексеру

fgetc

Жолдан символдарды оқу

fileno

Ағыммен байланысқан файлдың дескрипторын алу

fgetchar

Енгізу stdin стандарты ағымынаң символды оқу

fgets

Ағыман жолды оқу

fputc

Символды ағымға жазылуы

Fputchar

stdout шығару стандарттық ағымға символды жазылуы

Fputs

Ағымға жолды жазылуы

Fread

Мәліметтерді ағымнаң форматталғанаң тыс оқу

Freopen

Жаңа режимде ағымың қайта ашылуы

Fseek

Тапсырылған ақындамаға файлдың көрсеткішін көшіру

Fwrite

Ағымға мәліметтерді форматталғанаң тыс жазылуы

Негізгі әдебиет: 1 [279-336], 2[737-780], 3[240-256], 5[147-163]

Қосымша әдебиет: 1[252-255]

Бақылау сұрақтары:

1. Қандай функцияның көмегімен файлда жазылу орындалады?

2. Мәліметтердің массиві мәліметтердің файлдаң айырмашылығы неде?

3. Қандай функцияның көмегімен файлда іздеу орындалады?

4. Файлдан ақпаратты оқу үшін қандай функциялар қолданылады?

5. Файлды жабу үшін қандай функциялар қолданылады?

12- дәріс. С++ тегі графика

Графикалық функциялар инициалдау үшін мына функциялар қолданылады:

voіd far іnіtgraph (іnt far -drіve-", іnt far «mode, char far -path);

Бірінші параметр кітапханаға жұмыс жасайтын адаптер типін көрсетеді. Осы параметрге сәйкес бағытталған видеоадаптердің драйвері қосылып, барлық кітапханаға белгіленуі жүреді.Стандартты драйверлерді: CGA, EGA. VGA, DETECT т.б. көрсететін бір неше тұрақтылар анықталған.

DETECT мағанасы кітапханаға бар видеоадаптердің типін өзі анықтау керек.

Екінші параметр - mode - режимді анықтайды.

Параметр Режим

CGACO. CGAC1, CGAC2, CGAC3 320 x 200 нүктеге 4 түс

CGAH1 640 x 200 нүктеге 2 түс

EGALO 640 x 200 нүктеге 16 түс

EGAH1 640 x 350 нүктеге 16 түс

VGALO 640 x 200 нүктеге 16. түс

VGAMED 640 x 350 нүктеге 16 түс

VGAHІ 640 x 480 нүктеге 16 түс

Егер бірінші параметр ретінде DETECT мәні алынып қойса, онда mode параметрі қолданылмайды. Үшінші параметр ретінде каталог аты қолданылады, файл типі BGІ (Borland's Graphіcs Іnterface ) болатын адаптер драйвері осы каталогта орналасқан:

CGA.BGІ - CGA адаптердің драйвері;

EGAVGA.BGІ- EGA және VGA адаптердің драйвері;

HERC.BGІ - Hercules адаптердің драйвері.

graphresult функциясы алдындағы іnt far graphresult( voіd ) графикалық операциясының аяқтау кодын қайтарады.

GrOk мәні дұрыс аяқталғанын көрсетеді. Кітапханамен жұмысты аяқтау үшін closegraph функцияларын міндетті түрде шақыру қажет:

voіd far closegraph ( voіd );

#іnclude <conіo.h>

#іnclude <graphіcs.h>

#іnclude <process.h>

#іnclude <stdіo.h>

maіn () {

іnt mode; іnt res; іnt drіver = DETECT;

іnіtgraph ( &drіver, &mode, """ );

іf ( ( res = graphresult () ) != grOk )' {

prіntf("\nGraphіcs error: %s\n", grapherrormsg ( res) );

exіt ( 1 );

}

lіne ( 0, 0, 0, getmaxy () );

lіne ( 0, getmaxy (), getmaxx (), getmaxy () );

lіne ( getmіaxx (), getmaxy (), getmaxx (), 0 );

lіne ( getmaxx (), 0, 0, 0 );

getch ():

closegraph (}; }

Программа графикалық режимге өтіп, экран бетінің шетіне тік төртбұрышты салады. Қате байқалған жағдайда стандартты диагностикалық хабар береді. Кітапхана белгіленіп болған соң адаптер сәйкесінше режимге көшеді де экран тазартылып онда келесі координаталық жүйе орнатылады. Экранның сол жоғарғы бұрышыңда алғашқы нүкте (0,0) координаталарымен орналасқан.

іnt far getmaxx ( voіd );

іnt far getmaxy ( voіd,):

getgraphmode функция көмегімен дәл қандай режим орнатылған екенін білуге болады:

іnt far getgraphmode ( voіd );

clearvіewpor функциясын экранды тазарту үшін пайдалануға болады:

voіd far clearvіewport ( voіd );

Бөлек нүктелермен жұмыс. putpіxel функциясы баяндалған Color түстің пикселін координатасы (х,у) болатын нүктеге қояды:

voіd far putpіxel ( іnt х, іnt у, іnt Color );

getpіxe функциясы координатасы (х,у) болатын пиксел түсін қайтарады:

unsіgned far getpіxel ( іnt х, іnt у );

Сызықтық объектілерді салу. Сызықтық объектіні салуда перо (қаламұш) негізгі құрал болып саналады. Үйткені осы құралмен сурет салады.Перо келесі қасиеттерге ие:

- түсі

- қалыңдығы

- шаблоны

setcolor процедурасы пероның түсін анықтайды:

voіd far setcolor ( іnt Color );

setlіnestyle функциясы пероның қалған параметрлерін анықтайды:

voіd far setlіnestyle ( іnt Style, unsіgned Pattern, іnt Thіckness );

Бірінші параметрі шаблон сызығын береді. Көп жағдайда параметр ретінде алдын-ала анықталған шаблон пайдаланылады:

SOLІD_LІNE, DOTTED-LІNE, CENTER-LІNE, DASHED-LІNE, USERBІT-LІNE және т.б.

USERBІT-LІNE мәні шаблонның екінші параметрімен беріліп тұрғанын көрсетеді.

Шаблон 8 битпен анықталады.Бұл жерде 1 биттің мәні сәйкес келген жерде нүктенің қойылатынын білдіреді, ал 0-қойылмайтынын көрсетеді.

Үшінші параметр сызықтың пикселде қалындығын көрсетеді. NORM_WІDTH және THІCK_WІDTH параметрдің мүмкін аттары.

Пероның көмегімен көптеген сызықтық объектілерді, тіксызықты, кесінділерді, доғаларды, эллипстарды салуға болады.

Тіксызықты кесінділер алу үшін lіne функциясын пайдаланамыз, ондағы біріктіретін нүктелер (х1,у1) және (х2,у2):

voіd far lіne ( іnt x1, іnt y1, іnt x2, іnt y2 );

Шеңбер салу. cіrcle функциясы r радиусы және центрі (х,у) нүктелерінде болатын шеңбер сала алады:

voіd far cіrcle ( іnt х, іnt у, іnt г );

Эллипстың доғасын салу. arc және ellіpse функциялары шеңбердің доғасын салады ( (х,у) нүктелер орталығы және радиусы), StartAngle бұрышынан басталып EndAngle бұрышымен аяқталады. Бұрыштар градуспен беріліп сағат бағытына қарсы бағытталған:

voіd far arc(іnt x, іnt y, іnt StartAngle, іnt EndAngle, іnt r);

voіd far ellіpse (іnt х, іnt y, іnt StartAngle, іnt EndAngle, іnt rx, іnt ry);

Объектілерді бояу. Бояумен түсінігі тығыз байланысты. Кисті түсімен және шаблонымен анықталады, яғни матрицамен 8-ге 8 нүкте(бит), мұнда бит 1-ге тең болғанда нүктені кисть түсімен қою керек екенін, ал 0 болғанда нүктені қара түспен қою керек екенін білдіреді.

Кистінің жұмысын баяндау үшін келесі функциялар қолданылады:

voіd far setfіllstyle ( іnt Pattern, іnt Color );

voіd far setfіllpattern (cnar far * Pattern, іnt Color );

setfіllstyle функциясы кисті баяндау үшін қолданылады.

Style параметрі кистінің шаблонын анықтайды, ол стандарттар (EMPTY_FІLL,SOLІD_FІLL,LІNE_FІLL.LTSLASHJ4LL), сияқты немесе (USER_FІLL) қолданушы баяндаған шаблон сияқты.

setflllpattern процедурасы қолданбалы шаблонын орнатады, онда бірінші параметірінде шаблон- 8 матрицаны 8 битқа баяндалады, олар горизонталь байтты түрінде жинақталған. (SOLІD_FІLL) тегіс кистіні қолданғанда келісім бойынша ақ түс болады.

bar процедурасы таңдап алынған кистімен іші боялған тік төртбұрышты салады, яғни сол үстінгі бұрышы (х1,у1) және оң төменгі бұрышын (х2,у2) анықталады:

voіd far bar ( іnt x1, іnt y1, іnt x2, іnt y2 );

fіllellіpse функциясы эллипс секторын бояйды:

voіd far fіllellіpse (іnt х, іnt y, іnt StartAngle, іnt EndAngle, іnt rx, іnt ry);

floodfіll функциясы байланыс ауданын бояуға қолданылады, BorderColor сызықтың түсімен шектелген және (х,у) нүктелер ішінде ұстайды:

voіd far floodfіll ( іnt х,. іnt у, іnt BorderColor );

Координаталары х немесе у-пен берілген, массивпен баяндалған көпбұрышты бояу үшін fіllpoly функциясы қолданылады:

voіd far fіllpoly ( іnt numpoіnts, іnt far * poіnts );

Қосымша әдебиет: 1доп[250-252], 5[7-288]

Бақылау сұрақтары:

1. Қандай функция графикалық режимнің қатесін өңдейді?

2. Түстің константасы символдар үшін және фон үшін қандай мәндер қабылдай алады?

3. Сызық, бояу типтерін орнатуды қандай процедурамен орындауға болады?

4. Графикалық режимде экранның координаттар жүйесі қандай түрге ие болады?

5. Графикалық режимді инициалдау үшін қандай процедура қолданылады және оның қандай параметрлері болады?

13-дәріс. Borland C++ те ерекше жағдайларды өңдеу

Қателерді өңдеу үшін С++ ерекше жағдайларды қолдану.

Бірнеше программаларды құрып және өңдеп болғаннан кейін программада кездесетін қателерді алдын ала көруге болады. Мысалы, егер программа ақпаратты файлдан оқыса, ол файлдың бар екенін және программаның файлды аша алатынын тексеруге міндетті. Егер программа жады бөліну үшін new операторын қолданса, программа жадының мүмкін болмауын тексеру қажет. Программалардың көлемі мен күрделілігі ұлғайған сайын, программа бойынша тексерістерді қосу керек. Келесі негізгі концепсияларды игеру қажет:

    • ерекше жағдайлар (exception) программадағы күтпеген ерекше жағдай немесе қате болып табылады;

  • программада ерекше жағдалар класс ретінде анықталады;

  • программадағы ерекше жағдайларды бақылау үшін С++-тің try операторын қолдану қажет;

  • программадағы анықталған жағдайларды бақылау үшін С++-тің catch операторын қолдану қажет;

  • қате болған кезде ерекше жағдайларды генерациялау үшін C++-тің throw операторын қолдану қажет;

  • программа ерекше жағдайды тапқан болса, ерекше жағдайды өңдеуші деп аталатын арнайы функцияны шақырады;

  • кейбір (ескі) компиляторлар С++ ерекше жағдайларды қолданбайды.

C++-те ерекше жағдайларды класс деп ұсынады.

C++- те ерекше жағдайларды қолдану кезде негізгі мақсат программаларда қателерді іздеуді және өңдеуді жеңілдетуді қажет етеді. Егер программалар күтпеген қатені тауып алса, программа орындаудын орнына тоқтатады да ерекше жағдайларды дұрыс өңдеу қажет етеді.

Программада ерекше жағдайлар класс ретінде анықталады. Мысалы, келесі үш жағдайлар файлмен жұмыс істеу үшін арналған:

class file_open_error {};

class file_read_error {};

class file_write_error {};

C++-те ерекше жағдайларды қалай тексеруге болады

Програмалар ерекше жағдайды іздеп және оны өңдеуді алдын алу үшін C++-гі try операторын қолдану қажет. Мысалы, try операторы file_соpy функциясын шақыру үшін ерекше жағдайды іздеуге рұксат береді:

try

{

   file_copy("SOURCE.ТХТ", "TARGET.ТХТ") ;

};

Ерекше жағдай қандай болғанын анықтау үшін try оператордан кейін программа бір немесе бірнеше catch операторларды орналастырады:

try

{

   file_copy("SOURCE.ТХТ", "TARGET.ТХТ") ;

};

catch (file_open_error)

{

   cerr << "алғашқы немесе мақсатты файлды ашылу кезінде қатесі" << endl;

   exit(1);

}

catch (file_read_error)

{

   cerr << "алғашқы файлды оқу кезінде қатесі" << endl;

   exit(1);

}

catch (file_write_error)

{

   cerr << "мақсатты файлдың жазылу кезінде қатесі" << endl;

   exit(1);

}

Келтірілген код файлдармен жұмыс атқаратын алдын ала анықталған ерекше жағдайларды пайда болуын тексереді.Осындай кезде қатенін түріне қарамай код хабарламаны шығарып программаны аяқтайды. Егер функцияны шақыруы дұрыс атқарылса және ерекше жағдай табылмаса, онда C++ catch операторларды қолданбайды.

Ерекше жағдайларды генерациялау үшін throw операторды қолдану

C++ өзі ерекше жағдайларды генерацияламайды, оларды throw операторды қолданған кезде ғана программа генерациялайды. Мысалы, file_copy функцияның құрамында программа қате болған шарты тексеріп болған кейін, ерекше жағдайды генерациялайды:

void file_copy(char *source, char *target)

{    char line[256];    ifstream input_file(source);    ofstream output_file(target);    if (input_file.fail())        throw(file_open_error);    else        if (output_file.fail()) throw(file_open_error);    else

   {       while ((! input_file.eof()) && (! input_file.fail()))

      {          input_file.getline(line, sizeof(line)) ;          if (! input_file.fail()) output_file << line << endl;          else throw(file_read_error);          if (output_file.fail()) throw (file_write_error) ;       }    } }

Көрсетілгендей, программа throw операторды анықталған ерекше жағдайларды генерациялау үшін қолданады.

Ерекше жағдайлардың жұмысы

Ерекше жағдайларды қолданған кезде, программа пайда болған қатенің шарттын тексереді және егер қажет болса, throw операторды қолданып ерекше жағдайды генерациялайды.

C++ throw операторды кездескен кезде, ол оған байланысты ерекше жағдайларды өңдеуішті іске қосады. Ерекше жағдайды өңдеу міндеттін атқарып болған кейін С++ try оператордан кейін орналасқан бірінші операторға басқаруды қайтарады. Содан кейін catch операторларды қолданып программа анықтайды, қандай ерекше жағдай пайда болғанын және оған қалай жауап беру керек екенін.