Си хэлний үндсэн ойлголтууд

Сэдвүүд:

·         Товч түүх

·         Мөн чанар

·         Эхлэл

·         Цагаан толгой

·         Тайлбар

·         Идентификатор (Чөлөөт нэр)

·         Албаны (нөөц) үгс

·         Тогтмолууд

·         Тэмдэгт мөр төрлийн тогтмол

·         Өгөгдлийн төрөл (Data type)

·         Хувьсагч ба тогтмол

·         Үйлдлийн тэмдгүүд

·         Тусгаарлагч тэмдгүүд

·         Илэрхийлэл

Товч түүх

Програмчлалын Си хэлийг 1972 онд Bell Laboratories (АНУ) компанийн ажилтан Деннис Ритчи (Dennis M. Ritchie) UNIX үйлдлийн системийг боловсруулж байх явцдаа зохиожээ. Си хэл нь системийн програмчлалын хэрэгсэл мэтээр бүтээгдсэн байна. Өөрийн онцлог, давуу талуудын ачаар энэ хэл богино хугацааны дотор хэрэглээний болон системийн програмчлалын хамгийн түгээмэл хэл болж чадсан юм. Тиймээс хэдийгээр сургалтын зориулалттай биш боловч компьютерын ухааны боловсролд өргөн хэрэглэгддэг. Си хэлний хөрвүүлэгчид орчин үеийн бараг бүх төрлийн компьютер дээр, UNIX/Linux, MS-DOS, MAC OS, OS/2, Windows, Solaris г.м. үйлдлийн системүүдэд ажиллаж байна.

Си хэл анхнаасаа л цомхон хүрээнд зориулагдсан “ажлын багаж” мэтээр зохиогдсон тул 1989 оныг хүртэл ямар нэгэн стандарт хэлбэрт (албан ёсны хувилбар) ороогүй байжээ. Тийм учраас Си хэлний янз бүрийн хөрвүүлэгч програмыг боловсруулагчид Б.Керниган, Д.Ритчи нарын “Програмчлалын Си хэл” (“The C Programming Language”, 1st Edition, Brian Kernighan & Dennis Ritchie, 1978) номыг албан бус стандарт лавлах болгон хэрэглэдэг байв. Энэ номын дагуух хувилбарыг ном, сурах бичигт “K&R C” гэж тэмдэглэж заншсан. Иймэрхүү байдалтай байж байгаад 1989 онд ANSI C хэмээх стандарт гарчээ. 1990 онд Олон Улсын Стандартчилалын Холбоо (ISO) ANSI C стандартыг үл ялиг өөрчлөөд ISO C олон улсын стандартыг баталжээ. Үүнээс хойно C99 хэмээх стандарт гарсан. Гэхдээ өнөөдөр дэлхий нийтээр ANSI C стандартыг илүү өргөн хэрэглэж байна. Энэ стандартын үндсэн эх сурвалжаар мөнөөх Б.Керниган, Д.Ритчи нарын “Програмчлалын Си хэл” (“The C Programming Language”, 2nd Edition, Brian Kernighan & Dennis Ritchie, 1988) номын 2 дахь хэвлэлийг тооцдог.

Бид хичээлээ ANSI C стандартыг баримтлан өрнүүлэх болно. Харин програм бичихдээ, MS-DOS үйлдлийн системд зориулсан хөрвүүлэгч бүхий Turbo C++ 3.0 програмчлалын орчинд ажиллах болно.

Мөн чанар

Дээд төвшний програмчлалын Си хэл нь агуулгын хувьд тун цомхон хэл. Учир нь цөөн тооны хэдэн машины командаар хэлний үндсэн элементүүдийг цогцлуулж чадсан юм. Түүнчлэн Си дээр, яг л ассемблерын хэл шиг доод төвшний програм бичих бүрэн боломжтой байдаг. Тиймээс Си хэлийг заримдаа дээд төвшний ассемблерын хэл, эсвэл универсал ассемблерын хэл гэнэ. Заримдаа дунд төвшний програмчлалын хэл гэнэ. Си хэлийг ашиглан бичдэг програм хангамжууд гэвэл:

·         Үйлдлийн системүүд

·         Хөрвүүлэгчүүд

·         Ассемблерууд

·         Текст эдиторууд

·         Сүлжээний драйверууд

·         Өгөгдлийн сангууд

·         Интерпретаторууд

·         Утилитууд

·         Хэрэглээний програмууд

г.м. болно.

Эхлэл

Програмчлалын шинэ хэл судалж эхлэхдээ дараах асуултуудад хариулт авсан байх ёстой. Эдгээр нь:

1.       Хэлний цагаан толгой ямар вэ? Түүний лексемүүдийг яаж бичих вэ?

2.       Өгөгдлийн ямар төрлүүд байдаг вэ? Тэдгээрийг яаж тодорхойлдог (бичдэг) вэ?

3.       Өгөгдлүүд дээр ямар үйлдлүүдийг гүйцэтгэх боломжтой вэ? Яаж илэрхийлэл бичих вэ? Тэдгээр нь хэрхэн биелдэг вэ?

4.       Програмын бүтэц ямар байдаг вэ? Операторууд, тодорхойлолтууд ямар дарааллаар бичигддэг вэ?

5.       Програмын биелэлтийн үр дүнг яаж гаргах (хэрэглэгчид үзүүлэх) вэ?

6.       Утга оноох, нөхцөлт, шилжилтийн операторууд яаж бичигдэх вэ?

7.       Програмд өгөгдлийг яаж оруулах вэ?

8.       Давталтын ямар ямар бүтцүүд байна вэ?

9.       Функц, процедурыг яаж тодорхойлдог вэ?

г.м. Ингэснээр цаашид програм бичихэд чухал хэрэг болно.

Цагаан толгой

Си хэлний цагаан толгойд:

·         Латин цагаан толгойн том, жижиг үсгүүд: (A, B, ..., Z, a, b, ..., z)

·         Цифрүүд: 0, 1, 2, 3, 4 , 5, 6, 7, 8, 9

·         Тусгай тэмдгүүд:

,

{ }

|

[ ]

( )

+

-

/

%

\

;

.

:

?

< 

=

> 

_

!

&

*

#

~

^

·         Үл дүрслэгдэх тэмдэгтүүд: лексемүүдийг нэг нэгээс нь тусгаарлах үүрэг бүхий сул зай, табуляци, шинэ мөрөнд шилжих г.м.

Цагаан толгойн тусламжтайгаар хэлний бусад бүрдэл хэсгүүд болох тайлбар, лексем зэргийг бүтээдэг. Си хэлэнд:

·         идентификаторууд (чөлөөт нэрс)

·         албаны (нөөц) үгс

·         тогтмолууд

·         тэмдэгт мөр төрлийн тогтмолууд

·         үйлдлийн тэмдгүүд

·         тусгаарлагч тэмдгүүд

гэсэн 6 төрлийн лексем байна. Эдгээр лексемүүдийг ашиглан програмын эх кодыг бичнэ.

Тайлбар

Эх код дотор, зүүн гар талаасаа /*, баруун гар талаасаа */ тэмдгүүдээр хашигдсан текстийг тайлбар (comment) гэнэ. Тайлбарыг кирилл үсгээр хийж болно. Ж.нь:

 /* Энэ бол тайлбар */

Си хэлэнд нэг тайлбарыг өөр тайлбар дотор хийж болохгүй. Тухайлбал:

/* Энэ бол тайлбар 1 /* Энэ бол тайлбар 2 */ Энэ бол тайлбар 3 */

гэсэн бичиглэл байж болохгүй. “Энэ бол тайлбар 3” гэсэн текстийг тайлбар гэж үзэхгүй.

Хөрвүүлэгч нь тайлбарыг хөрвүүлэх оролдлого хийхгүй. Хөрвүүлэлтийн явцад бүх тайлбарыг хоосон зайгаар солино. Учир нь тайлбар бол хөрвүүлэгчид бус хүнд зориулагдсан.

Идентификатор (Чөлөөт нэр)

Үсэг юм уу доогуур зураас “_”-аар эхлэсэн, үсэг, цифр, доогуур зураасуудын дарааллыг идентификатор гэнэ. Ж.нь:

X, y_, x2, value, _mydata, kom16, TIME, time, aa, b2c3, week_days

Том, жижиг үсгүүд ялгаатай утгыг илэрхийлнэ. Тиймээс ж.нь TIME болон time нь ялгаатай нэрнүүд байна.

Идентификатор нь дурын урттай байж болох ч Turbo C++ хөрвүүлэгч эхний 32 тэмдэгтийг л тооцдог.

Албаны (нөөц) үгс

Си хэлэнд урьдаас тодорхойлогдож нөөцлөгдсөн учраас програм зохиогч хүн чөлөөт нэр болгон ашиглах боломжгүй тийм идентификаторуудыг албаны үгс гэнэ. Албаны үгс нь өгөгдлийн төрөл, санах ойн ангиллууд, өгөгдлийн хэлбэрүүд, модификаторууд, хуурмаг хувьсагчууд (регистрийн хувьсагчууд), операторууд г.м.-ийг тодорхойлно.

Си хэлэнд өөрт нь:

auto

break

case

char

const

continue

default

do

double

else

enum

extern

float

for

goto

If

Int

long

register

return

short

signed

sizeof

static

Struct

switch

typedef

union

unsigned

void

volatile

while

гэсэн нөөц үгнүүд тодорхойлогдсон байдаг.

Үүнээс гадна Си хэлний янз бүрийн хөрвүүлэгч, стандарт сан боловсруулагчдын дунд тогтсон нэг тохиролцоо бий. Энэ нь, нэг юм уу хоёр доогуур зураас “_”-аар эхлэсэн индентификаторыг нөөц үг гэж тооцох явдал юм. Тиймээс ийм идентификаторыг эх кодонд чөлөөт нэр болгон ашиглах нь зохимжгүй.

Тогтмолууд

Өөрчлөгдөх боломжгүй утгыг тогтмол гэнэ. Си хэлэнд:

·         тэмдэгт төрлийн тогтмол

·         бүхэл тоо

·         бодит тоо

·         тоочсон төрлийн тогтмол

·         тэг-заагч (null-pointer)

гэсэн үндсэн 5 төрлийн тогтмол тодорхойлогдсон байдаг. Тэг-заагчаас бусад төрлийн тогтмолыг арифметик буюу тоон тогтмолууд гэдэг.

Тэмдэгт тогтмол

ASCII-тэмдэгттэй ажиллахын тулд тэмдэгт тогтмолыг хэрэглэнэ. Тэмдэгт тогтмол гэдэг нь ASCII-тэмдэгт, энэ тэмдэгтийг хоёр талаас нь хашсан дан хашилт (апостроф) зэргээс тогтох лексем юм. Ж.нь:

‘A’        ‘a’         ‘B’        ‘b’         ‘8’         ‘0’         ‘+’        ‘;’

г.м. нь тэмдэгт тогтмолууд болно.

Хашилтуудын хооронд, гаралтын төхөөрөмжид дүрслэгдэх боломжтой дурын ASCII-тэмдэгтийг бичиж болно. Харин удирдах кодыг (өмнөх лекцийг хар) илэрхийлэхийн тулд хэд хэдэн дүрслэгдэгч ASCII-тэмдэгтийн комбинацийг ашигладаг. Ингэхдээ комбинаци болгон гэдрэг налуу зураас ‘\’-аар (backslash) эхлэх ёстой. Ямар ямар удирдах кодыг хэрхэн бичихийг харуулваас:

·         ‘\n’ – курсорыг шинэ мөрөнд шилжүүлэх

·         ‘\t’ – хэвтээ табуляци

·         ‘\r’ – курсорыг одоо байрлах мөрийнх нь эхэнд аваачих

·         ‘\\’ – гэдрэг налуу зураас \

·         ‘\’’ – дан хашилт

·         ‘\”’ – давхар хашилт

·         ‘\0’ – тэгийн тэмдэг

·         ‘\a’ – дуут сигнал

·         ‘\b’ – курсорыг зүүн гар тийш нэг байр (нэг тэмдэгтээр) шилжүүлэх

·         “\f’ – хуудас шилжүүлэх

·         ‘\v’ – босоо табуляци

·         ‘\?’ – асуултын тэмдэг.

Дээрх тэмдэгт тогтмолууд бүгд хоёр буюу түүнээс олон тэмдэгтээр бичигдсэн боловч бүгд харгалзан нэг нэг удирдах кодыг илэрхийлнэ гэдгийг дахин хэлье.

Тэмдэгт тогтмолыг бүхэл тоон төрөлд хамааруулж үздэг байна. Тиймээс илэрхийлэлд бүхэл тоон өгөгдөл мэтээр оролцож болдог.

Бүхэл тоо

Си хэлэнд:

·         10-тын (Decimal)

·         16-тын (Hexadecimal)

·         8-тын (Octal)

гэсэн 3 төрлийн бүхэл тоон тогтмол тодорхойлогдсон байдаг.

10-тын тогтмолыг стандарт хэлбэрээр бичнэ. Ж.нь:

44        684      0          1024

г.м.

Харин 8-тын тогтмолыг 0-ээр эхлүүлж бичнэ. Ж.нь:

016 (= 1410)                045 (= 3710)

г.м.

16-тын тогтмолыг бичихдээ урд талд нь 0x юм уу 0X гэсэн угтваруудыг залгана. Ж.нь:

0x16 (= 2210)               0XFF (= 25510)

г.м.

Бодит тоо

Бодит тоон тогтмолыг дараах хэсгүүдээс бүтээнэ. Бүхэл хэсгийг 10-тын тогтмолоор, бутархайн таслалыг цэгээр, бутархай хэсгийг мөн 10-тын тогтмолоор бичнэ. Хэрэв тоог 10-ын зэрэгт хэлбэрээр (мантисс + зэрэг) бичих бол зэргийн суурийгeюм ууEүсгээр, зэрэг илтгэгчийг 10-тын тогтмолоор дүрсэлнэ. Бүхэл юм уу бутархай хэсгийн аль нэг нь 0 байвал бичихгүй орхиж болно, гэхдээ хоёуланг нь зэрэг орхиж болохгүй. Ж.нь:

44.       3.14159           44e0                0.314159E1                 0.0

г.м.

Өгөгдлийн төрөл ба тоон тогтмолууд. Хязгаарын утгууд

Програмд зарлагдсан тогтмол болгон санах ойд ямар нэг зай эзэлнэ. Энэ зай ямар хэмжээтэй байх вэ, энд агуулагдах код юуг дүрсэлсэн бэ гэдгийг өгөгдлийн төрөл гэсэн ойлголтоор тодорхойлдог.

Тэмдэгт төрлийн тогтмолд хөрвүүлэгч санах ойд 1 байтын зай олгоно.

Харин бүхэл тоон тогтмол ямар утгын мужид байгаагаас шалтгаалан хөрвүүлэгч өөр өөр зайг санах ойд олгоно. Тухайлбал [0, 32767] завсарт орших тогтмолд 2 байт өгөх бол [32768, 4294967295] завсрын тогтмолд 4 байт өгнө.

Бодит тоон тогтмолд хөрвүүлэгч санах ойд 8 байтын зайг олгодог. Ө.х. давхар (double) нарийвчлалаар дүрсэлнэ. Тиймээс ж.нь 3.141592653589763 болон 3.14 гэсэн тогтмолууд ижилхэн 8 байт эзэлдэг. Гэхдээ програм зохиогч нь бодит тооны санах ойд эзлэх хэмжээг хөрвүүлэгчийн сонголтоос өөрөөр олгоё гэвэл тоог бичихдээ ард нь F (эсвэл f), L (эсвэл l) гэсэн дагаварыг залгах боломжтой. Ж.нь 3.14159F гэвэл 4 байт, 3.14L гэвэл 10 байт болдог.

Тэг-заагч

Тэг-заагч нь цорын ганц тоон бус тогтмол юм. Үүний тухай хойно дэлгэрэнгүй үзнэ.

Тоочсон төрлийн тогтмол

Тоочсон төрлийн тогтмолууд гэдэг нь:

enum тоочсон_төрлийн_нэр { тогтмолуудын_нэр(с)ийн_жагсаалт } ;

хэмээх загвараар бичигдсэн тогтмолуудыг хэлнэ. Энд:

·         enum – тоочсон төрлийг илэрхийлэх албаны үг

·         тоочсон_төрлийн_нэр – заавал байх албагүй чөлөөт идентификатор

·         тогтмолуудын_нэр(с)ийн_жагсаалт – нэг нэгээсээ таслалаар тусгаарлагдан цувж бичигдсэн тогтмолуудын нэрс. Заримдаа: тогтмолын_нэр=тогтмолын_утга гэсэн загвараар бичигдсэн байж болно.

Ж.нь:

enum { ONE = 1, TWO, THREE, FOUR } ;

enum DAY { SUN, MON, TUE, WED, THU, FRI, SAT } ;

enum BOOLEAN { NO, YES } ;

г.м. Хэрэв нэрсийн жагсаалт дунд ‘=’ орсон элемент байхгүй бол тогтмолуудыг зүүн талаасаа 0-ээр эхлээд 1-ээр нэмэгдсэн утгатай гэж үздэг. Тиймээс NO=0, YES=1, SUN=0, FRI=5 байна. Бас TWO=2, THREE=3, FOUR=4 байна.

Тэмдэгт мөр төрлийн тогтмол

Эх код дотор, давхар хашилтанд бичигдсэн ASCII-тэмдэгтүүдийн дарааллыг тэмдэгт мөр төрлийн тогтмол (мөр-тогтмол) гэнэ. Ж.нь:

Ene bol temdegt mur!

эсвэл:

“Bid programchlaliin C kheliig uzej baina”

г.м.

Тэмдэгтүүдийн дунд удирдах кодууд орсон байж болно. Удирдах кодыг бичихдээ  өмнө дурдсанчлан ‘\’-аар эхлүүлэх ёстой. Ж.нь:

“\n Ene text \n delgetsen deer \n 3 murund dooshoo tsuvarch garna”

Мөр төрлийн тогтмолыг хөрвүүлэгч санах ойд яаж хадгалдаг вэ? Тэмдэгт болгон (удирдах код ч гэсэн) 1 байт эзэлж, бүх тэмдэгтүүд дараалсан нүднүүдэд цуварч байрладаг байна. Харин хамгийн сүүлийн тэмдэгтийн ард хөрвүүлэгч өөрөө ‘\0’ гэсэн тэмдэгтийг залгадаг. Тиймээс мөр-тогтмолын санах ойд эзлэх байтын тоо нь мөрийн тэмдэгтийн тооноос 1-ээр их байдаг ажээ. Ж.нь:

“Ene mur sanax oid 34 byte ezelne.”

гэсэн тэмдэгт мөрийн санах ой дахь дүрслэл:

E

n

E

 

m

u

r

 

s

a

n

a

x

 

o

i

d

 

3

4

 

b

y

t

e

 

e

z

e

L

n

e

.

\0

болно.

Эндээс ж.нь F’ гэсэн тэмдэгт тогтмол ба F гэсэн тэмдэгт мөрийн ялгаа харагдана. Юу гэвээс ‘F’ нь санах ойд 1 байт болох бол “F” нь 2 байт болох юм.

Хэрэв хоёр мөр-тогтмолын дунд сул зай эсвэл табуляци байвал хөрвүүлэгч тэдгээрийг нэг бүхэл мөр-тогтмол мэтээр ойлгоно. Ж.нь:

“Namriin nalgar” “ shar udruud”

гэсэн тэмдэгт мөрүүд нь:

“Namriin nalgar shar udruud”

гэсэн ганц мөр-тогтмол болох юм.

Яг үүний адилаар, эх кодын хэд хэдэн дараалсан мөрөнд цуварч байрласан тэмдэгт мөрүүд мөн нэг бүхэл мөр-тогтмол мэтээр ойлгогдоно. Ж.нь:

“Ikh Mongol uls ”

“baiguulagdsanii ”

“800 jiliin ”

“oi”

гэсэн дараалал бол:

Ikh Mongol uls baiguulagdsanii 800 jiliin oi”

гэсэн ганц мөр-тогтмол болох юм.

Өгөгдлийн төрөл (Data type)

Програмд ашиглагдаж буй өгөгдөл болгон ямар нэг утгатай байна (тоон, тэмдэгт г.м.). Хөрвүүлсний дараа өгөгдөл нь санах ойд тодорхой зай (нүд эсвэл нүднүүд) эзэлнэ. Тэр зайнд нь өгөгдлийн утга 2-тын кодоор хадгалагдана.

Харин өгөгдлийг санах ойд ямар зай эзлүүлэх, тэр зайнд өгөгдлийн утгыг ямар аргаар кодлох вэ зэргийг хөрвүүлэгчид “зааж” өгдөг програмчлалын хэлний ойлголтыг өгөгдлийн төрөл гэдэг байна. Тэгвэл өгөгдөл санах ойд ямар зай эзлэх, түүний утгыг яаж кодлох зэрэг нь өгөгдөл ямар утга авч байна вэ гэдгээс шалтгаалдаг. Тиймээс өгөгдлийн төрөл гэдэг нь үнэн хэрэгтээ түүний авах боломжтой утгын олонлог юм. Өгөгдлийн төрөл нь албаны үгээр илэрхийлэгдэнэ.

Өгөгдлийн төрөл нь өгөгдлийг зарлах (data declaration) гэсэн ойлголттой нягт холбоотой. Өгөгдлийг зарлана гэдэг нь тухайн өгөгдөлтэй хэрхэн харьцахыг хөрвүүлэгчид “зааварласан” бичиглэл үйлдэж байгаа хэрэг. Мэдээж өгөгдлийг ашиглаж эхлэхээсээ өмнө ингэж зарлах ёстой нь ойлгомжтой байх. Адил төрлийн өгөгдлүүдийг зарлахдаа дараах загварыг баримталж бичнэ:

өгөгдлийн_төрөл өгөгдлүүдийн_нэр(с) ;

Энд:

·         өгөгдлийн_төрөл - өгөгдлийн төрлийг заасан албаны үг

·         өгөгдлүүдийн_нэр(с) – өгөгдлүүдийг нэрлэхийн тулд програм зохиогчийн сонгож авсан чөлөөт индентификаторуудыг таслалаар тусгаарлан цувуулж бичсэн жагсаалт.

Өгөгдлийг зарласан бичиглэлийн төгсгөлд цэгтэй таслал “;” тавьж буйг анхаараарай.

Си хэлэнд дараах үндсэн өгөгдлийн төрлүүд тодорхойлогдсон байдаг.

Бүхэл тооны хувьд:

Өгөгдлийн төрөл

Санах ойд эзлэх зай байтаар

Утгын муж

Тайлбар

unsigned char

1

0 .. 255

 

signed char

1

-128 .. 127

signed гэсэн үгийг бичихгүй байж болно

Enum

2

-32768 .. 32767

 

unsigned int

2

0 .. 65535

 

signed int

2

-32768 .. 32767

signed гэсэн үгийг бичихгүй байж болно

Unsigned short

2

0 .. 65535

 

signed short

2

-32768 .. 32767

signed гэсэн үгийг бичихгүй байж болно

unsigned long

4

0 .. 4294967295

 

signed long

4

-2147483648 .. 2147483647

signed гэсэн үгийг бичихгүй байж болно

гэсэн төрлүүд тодорхойлогдсон байна.

Signed гэсэн төрлүүд бол тэмдэгтэй бүхэл тоог илэрхийлэх бөгөөд хамгийн ахлах битийг тэмдгийн бит болгон авдгаараа unsigned төрлөөсөө ялгаатай. Тэмдэгтэй ба тэмдэггүй бүхэл төрлүүдийн ялгаа дараах жишээн дээр тод харагдана. k=16 гэсэн өгөгдөл int (буюу signed int) төрөл байг. Тэгвэл –k=-16 болно. Харин k=16 гэсэн өгөгдөл unsigned int төрөл байсан бол –k=65520 болно. Учир нь энэ тохиолдолд:

-k = 2N - |k|

гэсэн хувиргалтыг хийн 65520 гэсэн утгыг гаргаж байгаа юм. Энд N – unsigned төрлийг дүрслэх битийн тоо, тухайн тохиолдолд N=16.

Эх код дотор, unsigned гэж зарлагдаагүй ямар ч бүхэл өгөгдлийг хөрвүүлэгч автоматаар signed төрлийнх гэж тооцох болно. Тийм учраас тэмдэгтэй бүхэл өгөгдлийг зарлахын тулд char, int, short, long үгнүүдийг бичихдээ signed гэсэн угтварыг орхиж болно. Харин зарлахдаа зөвхөн signed эсвэл unsigned гэж бичээд char, int, short, long үгнүүдийг орхисон бол signed нь signed int, unsigned нь unsigned int төрөлтэй эквивалент байх болно.

Бүхэл өгөгдлийг зарлаж буй зарим нэг жишээ:

char symbol, cc;                              /*энд symbol ба cc гэсэн char төрлийн өгөгдлүүд зарлав*/

unsigned char code;                       /*энд code гэсэн unsigned char төрлийн өгөгдөл зарлав*/

int number, row;                              /*энд number, row гэсэн unsigned char төрлийн өгөгдлүүд зарлав*/

unsigned long long_num;                /*энд long_num гэсэн unsigned long төрлийн өгөгдөл зарлав*/

г.м.

Бодит тооны хувьд:

Өгөгдлийн төрөл

Санах ойд эзлэх зай байтаар

Абсолют утгын муж

Тайлбар

float

4

3.4E-38 .. 3.4E+38

Дан нарийвчлал

double

8

1.7E-308  .. 1.7E+308

Давхар нарийвчлал

long double

10

3.4E-4932 .. 1.1E+4932

Дээд нарийвчлал

гэсэн төрлүүд тодорхойлогдсон байна. Өмнөх лекцэд дурдсанчлан бодит тоо санах ойд мантисс ба зэрэг бүхий хөвөгч цэгтэй хэлбэрээр хадгалагддаг.

Бодит тоон өгөгдөл зарлаж буй жишээнүүд:

float x, X, cc3, pot_8;         /*энд x, X, cc3, pot_8 гэсэн float төрлийн өгөгдлүүд зарлав*/

double e, stop, B4;              /*энд e, stop, B4 гэсэн double төрлийн өгөгдлүүд зарлав*/

г.м.

Хувьсагч ба тогтмол

Хувьсагч

Зарлагдсан өгөгдлийн утга програм биелэх явцад өөрчлөгдөх боломжтой байж болно. Эсвэл өөрчлөгдөх боломжгүй байж болно. Утга нь өөрчлөгдөх боломжтой өгөгдлийг хувьсагч (variable) гэдэг. Хувьсагч өгөгдлүүдийг зарлахдаа:

өгөгдлийн_төрөл хувьсагчуудын_нэр(с) ;

гэсэн загварын дагуу бичнэ. Энд:

·         хувьсагчуудын_нэр(с) - хувьсагчуудыг нэрлэхийн тулд програм зохиогчийн сонгож авсан чөлөөт индентификаторуудыг таслалаар тусгаарлан цувуулж бичсэн жагсаалт.

Хувьсагчийг зарлах загвар нь өгөгдлийг зарлах загвартай адилхан болох нь харагдаж байна. Ж.нь:

int x, y, z;                            /*x, y, z нь int төрлийн хувьсагчууд*/

float a, b, c;                        /* a, b, c нь float төрлийн хувьсагчууд*/

double e, f;                          /* e, f нь double төрлийн хувьсагчууд*/

unsigned char i, j;               /* i, j нь unsigned char төрлийн хувьсагчууд*/

г.м.

Хувьсагчийг зарласны дараагаар тухайн хувьсагч тодорхойгүй утгатай болдог. Ө.х. дөнгөж зарлагдсан хувьсагч автоматаар 0 гэсэн утгыг авна гэж бодож болохгүй. Яагаад ингэдэг вэ?

Хувьсагч гэдэг ойлголт түүний нэр ба төрөл гэсэн хоёр хэсгээс бүрдэж байна. Түүнийг аль нэг төрлөөр зарласны дараа хувьсагч санах ойгоос тодорхой мужийг эзэлж, энэ муж хувьсагчийн нэрээр нэрлэгдэнэ. Гэтэл энэ мужийн нүднүүд нэрлэгдэхээсээ заавал хоосон байх албагүй. Ж.нь өмнө нь ажиллаж байсан програмын өгөгдлүүдийн үлдэгдэл энд агуулагдаж болно.

Тийм учраас хувьсагчид анхны утга оноох буюу хувьсагчийг идэвхжүүлэх (variable initialization) хэрэгтэй. Хувьсагчийг идэвхжүүлэхдээ:

өгөгдлийн_төрөл хувьсагчийн_нэр = анхны_утга ;

гэсэн загварын дагуу бичнэ. Ө.х. хувьсагчийг зарлах, идэвхжүүлэх үйлдэл хамт хийгддэг. Ингэснээр, хувьсагч санах ойд зай эзлэнгүүт тэр зайн нүднүүдэд анхны утга байрлах юм.

Хувьсагчийг зарлан, идэвхжүүлж буй жишээ:

float pi = 3.1415, cc = 1.23 ;

unsigned int year = 1997 ;

char useg = ‘A’ ;

Тогтмол

Нэр бүхий хувьсагч өгөгдөл зарладгийн адилаар мөн нэр бүхий тогтмол өгөгдлийг зарлаж (тодорхойлж) болно. Тогтмол өгөгдлийг хэд хэдэн янзаар зарлах боломжтой.

Эхний боломжтой бид “Тогтмолууд” сэдвийн “Тоочсон төрлийн тогтмол” хэсэгт танилцсан. Энэ бол enum нөөц үгийг ашиглах явдал юм.

Хоёр дахь боломж бол:

const өгөгдлийн_төрөл ТОГТМОЛЫН_НЭР = тогтмолын утга ;

гэсэн загварын дагуу бичиж зарлах арга юм. Энд:

·         const – тогтмол өгөгдөл зарлахад хэрэглэх албаны үг

·         өгөгдлийн_төрөл – тогтмолын төрлийг заасан албаны үг

·         ТОГТМОЛЫН_НЭР – тогтмолыг нэрлэхийн тулд програм зохиогчийн сонгож авсан чөлөөт идентификатор

·         тогтмолын утга – тогтмолын төрөлд нийцэх ямар нэг утга.

Ж.нь:

const double E = 2.718282 ;

const long M = 99999999 ;

const F = 765 ;

г.м. Хамгийн сүүлийн тохиолдолд F тогтмолыг зарлахдаа өгөгдлийн төрлийг заагаагүй байна. Тиймээс автоматаар int төрөлтэй гэж үзэх болно.

Гурав дахь боломж бол:

#define ТОГТМОЛЫН_НЭР  тогтмолын_утга

гэсэн загварын дагуу бичиж зарлах арга юм. Ийм бичиглэлийг макротодорхойлолт (macrodefinition) гэнэ. Макротодорхойлолтын төгсгөлд цэгтэй таслал “;” байхгүй болохыг анхаараарай. Энд:

·         #define – препроцессорын директив (удирдамж) хэмээн нэрлэгдэх команд.

Ж.нь:

#define EULER 2.718282

#define NEXT ‘Z’

г.м.

Макротодорхойлолт гэж юу вэ? Товчоор хэлбэл, энэ нь нэг илэрхийллийг өөр нэг илэрхийлэл буюу үгээр орлуулах явдал юм. Онцлог нь, орлуулах процесс хөрвүүлэлтээс өмнө хийгдэнэ. Үүнийг препроцессор буюу бэлтгэгч хэмээх програмаар гүйцэтгэдэг. Препроцессор нь хөрвүүлэгчийн тусгай бүрдэл хэсэг юм. Тухайлбал:

#define NEXT ‘Z’

гэсэн макротодорхойлолтын үр дүнд препроцессор нь, энэ тодорхойлолтоос доош орших текстэнд агуулагдах бүх ‘Z’  гэсэн тэмдэгт тогтмолыг NEXT гэсэн үгээр орлуулах болно.

Макротодорхойлолтын тухай бид хойно дэлгэрэнгүй үзнэ.

Макротодорхойлолтоор тогтмол зарлахдаа өгөгдлийн төрлийг яг зааж бичихгүй байна. Тогтмолын төрөл түүний авч байгаа утгаар тодорхойлогдох болно. Тиймээс ж.нь

#define NEXT ‘Z’

тодорхойлолт бол:

const char NEXT = ‘Z’ ;

гэсэнтэй эквивалент юм.

Үйлдлийн тэмдгүүд

Илэрхийлэл бүтээж утгыг нь олохдоо үйлдлүүдийг ашигладаг. Үйлдлүүдийг үйлдлийн тэмдгүүдээр (operation marks) төлөөлүүлнэ. Үйлдлийн тэмдгүүд нь хэлний цагаан толгойн тэмдэгтүүд байдаг.

Эдгээрээс, “[ ]”, “( )”, “?:” гэснээс бусад бүх үйлдлийн тэмдгүүдийг бие даасан лексем гэж үздэг. Илэрхийллийн төрөл, бүтцээс хамааран нэг ийм лексем өөр өөр үйлдлийг төлөөлж болно. Ө.х. нэг тэмдэг өөр өөр илэрхийлэлд өөр өөр үүрэгтэй оролцож болно. Тухайлбал & тэмдэг заримдаа битүүд дээр хийх AND үйлдлийг төлөөлдөг бол заримдаа өгөгдлийн санах ой дахь хаягийг олох үйлдэл байх жишээтэй. Түүнчлэн – тэмдэг гэхэд заримдаа тооны тэмдгийг өөрчлөх үйлдлийг, заримдаа хоёр тоог хооронд нь хасах үйлдлийг төлөөлдөг байх жишээтэй.

Илэрхийлэлд оролцож буй үйлдлүүд тодорхой дарааллын дагуу хийгдэнэ. Ө.х. аль нэг үйлдэл хамгийн түрүүнд, дараа нь өөр нэг үйлдэл, тэгээд өөр нэг үйлдэл г.м. Үүнийг үйлдлийн эрэмбэ гэдэг. I эрэмбийн үйлдлүүд хамгийн өндөр эрхтэй, ө.х. хамгийн түрүүнд хийгдэнэ. Дараа нь II эрэмбэ, III эрэмбэ г.м. Адил эрэмбийн үйлдлүүд ижил эрхтэй. Тиймээс илэрхийлэлд нэг эрэмбийн олон үйлдэл орсон тохиолдолд хамгийн зүүнээсээ (эсвэл баруунаасаа) эхлэн хийгдэнэ. Зүүнээс (→) үү баруунаас (←) уу гэдэг нь илэрхийллийн төрөл, бүтцээс хамаарна.

Дараах хүснэгтэд үйлдлийн тэмдгүүд, тэдгээрийн эрэмбийг буурах дарааллаар харуулав:

Эрэмбэ

Үйлдлүүд

Биелэгдэх чиглэл
(→, ←)

Тайлбар

I

( )   [ ]   ->   .

 

II

!   ~   +   -   ++   --   &   *   (өгөгдлийн_төрөл)   sizeof

 

III

*   /   %

Мультипликатив үйлдлүүд

IV

+   -

Аддитив үйлдлүүд

V

<<   >>

Бит шилжүүлэх үйлдлүүд

VI

<   <=   >=   >

Жиших үйлдлүүд

VII

==   !=

Жиших үйлдлүүд

VIII

&

Битүүд дээр хийх “AND” үйлдэл

IX

^

Битүүд дээр хийх “XOR” үйлдэл

X

|

Битүүд дээр хийх “OR” үйлдэл

XI

&&

ANDүйлдэл

XII

||

 ORүйлдэл

XIII

?:

Нөхцөл шалгах үйлдэл

XIV

=   *=   /=   %=   +=   -=   &=   ^=   |=   <<=   >>=

Утга оноох үйлдлүүд

XV

,

“Таслал” үйлдэл

Үйлдлүүд дангаараа илэрхийллийг бүтээхгүй. Үйлдэл хийх ёстой өгөгдлүүд мөн илэрхийлэлд байх ёстой. Энэ өгөгдлүүдийг операндууд (operands) гэдэг. Тэгвэл хэдэн операндтай ажиллах вэ гэдгээр нь үйлдлүүдийг унар (дан гишүүнт) ба бинар (хоёр гишүүнт) үйлдлүүд гэж ангилдаг байна.

Унар үйлдэл нь ганц операнд дээр хийгдэх бөгөөд операндынхаа өмнө (эсвэл ар) талд бичигдэнэ:

унар_үйлдэл операнд

Өмнөх хүснэгтэд үзүүлсэн II эрэмбийн үйлдлүүдийн нэгээс бусад нь бүгд унар юм:

·         &   - операндын санах ой дахь хаягийг авах

·         *    - операндын зааж буй санах ойн хаягаар хандалт хийх. Энэ үйлдлийн операнд нь санах ойн хаяг байх ёстой.

·         -    - арифметик (тоон) операндын тэмдгийг солих үүрэгтэй унар хасах. Ж.нь -2.

·         +   - унар нэмэх. Ж.нь +2.

·         ~   - бүхэл тоон операндын 2-тын кодын бүх битийг инверслэх. Ж.нь ~8=247.

·         !    - операндын логик үгүйсгэл (NOT). Ж.нь !1=0, !0=1, !5=0, !(-2)=0.

·         ++ - операндын утгыг 1-ээр нэмэгдүүлэх. Префикс ба постфикс гэсэн 2 хэлбэртэй. Префикс хэлбэр нь операндынхаа өмнө бичигдэх бөгөөд операндын утгыг ашиглалгүйгээр 1-ээр ихэсгэнэ: ++операнд. Постфикс хэлбэр нь операндынхаа ард бичигдэх бөгөөд операндын утгыг ашиглаад 1-ээр ихэсгэнэ: операнд++. Операнд нь хувьсагч өгөгдөл байх ёстой. Тиймээс ++5, 84++, ++(j+k) г.м. бичиглэл байж болохгүй.

·         --   - операндын утгыг 1-ээр багасгах. Мөн префикс, постфикс хэлбэрүүдтэй. Тавигдах шаардлага ++-ийн адил.

·         (өгөгдлийн_төрөл)    - төрөл илээр хувиргах үйлдэл. Операндын өгөгдлийн төрлийг заасан өгөгдлийн төрөлд хувиргана. Бичих хэлбэр нь:

(өгөгдлийн_төрөл) операнд

Ж.нь (long)8 гэсэн хувиргалтын үр дүн 4 байт, (char)8 гэвэл 1 байт болно г.м. Эдгээр хувиргалтаар бүхэл тоонуудын утга өөрчлөгдөхгүй, харин санах ойд эзлэх хэмжээ нь өөрчлөгдөж байгаа. Гэтэл (long double)6, (float)4 гэсэн хувиргалтуудаар бүхэл тоонуудын санах ойд эзлэх хэмжээ төдийгүй кодлогдох хэлбэр нь өөрчлөгдөнө. Ө.х. мантисс, зэрэг гэсэн хэсгүүд гарч ирэх жишээтэй. Ийм учраас арифметик өгөгдлүүдийн төрлийг хувиргах үйлдлийг болгоомжтой хийх хэрэгтэй. Ж.нь хэт том бүхэл тоог бодит төрөлд (float г.м.) хувиргах үед мантиссын нарийвчлал алдагдаж болзошгүй. Эсрэгээр, бодит тоог бүхэл төрөлд хувиргах үед бүхэл өгөгдлийн утгын мужаас хэтрэх байдал үүсч болзошгүй.

·         sizeof      - операнд юм уу өгөгдлийн төрлийн санах ойд эзлэх хэмжээг байтаар олох. Ж.нь sizeof(12), sizeof(unsigned char).

Бинар үйлдэл нь хоёр операнд дээр хийгдэх бөгөөд тэдгээрийнхээ дунд бичигдэнэ:

операнд1 бинар_үйлдэл операнд2

 II болон XIII эрэмбийн үйлдлүүдээс бусад бүх эрэмбэ бинар үйлдлийнх байна. Дэлгэрэнгүй танилцъя.

Аддитив үйлдлүүд (IV эрэмбэ):

·         +   - бинар нэмэх. Арифметик юм уу заагч операндуудыг хооронд нь нэмэх үүрэгтэй.

·         -    - бинар хасах. Арифметик юм уу заагч операндуудыг хооронд нь хасах үрэгтэй.

Мультипликатив үйлдлүүд (III эрэмбэ):

·         *    - арифметик операндуудыг үржих

·         /     - арифметик операндуудыг хуваах. Хэрэв операндууд нь бүхэл тоо байвал хариу нь мөн бүхэл болж нарийвчлагдана. Ж.нь 20/3=6.

·         %  - бүхэл операндуудыг хувааж үлдэгдлийг нь олох. Операндууд эерэг бол үлдэгдэл мөн эерэг байна. Турбо Си хөрвүүлэгчийн хувьд, хуваагдагч операнд сөрөг л бол үлдэгдэл дандаа сөрөг байна. Ж.нь 13%4=1, (-13)%4=-1, 13%(-4)=1, (-13)%(-4)=-1.

Бит шилжүүлэх үйлдлүүд (V эрэмбэ):

·         << - зүүн гар талдаа бичигдсэн бүхэл операндын хоёртын кодын битүүдийг баруун гар талдаа бичигдсэн бүхэл операндын утгаар зүүн тийш шилжүүлэх. Ж.нь 4<<2=16. Зүүн тийш N битээр шилжүүлнэ гэдэг 2N-ээр үржсэнтэй эквивалент байна.

·         >> - зүүн гар талдаа бичигдсэн бүхэл операндын 2-тын кодын битүүдийг баруун гар талдаа бичигдсэн бүхэл операндын утгаар баруун тийш шилжүүлэх. Ж.нь 5>>1=2. Баруун тийш N битээр шилжүүлнэ гэдэг 2N-д бүхлээр хуваасантай эквивалент байна.

Битүүд дээр хийх логик үйлдлүүд (VIII-X эрэмбэ):

·         &   - бүхэл операндуудын 2-тын кодын битүүдийг логик үржих (бит конъюнкци). Ж.нь 6&5=4.

·         !    - бүхэл операндуудын 2-тын кодын битүүдийг логик нэмэх (бит дизъюнкци). Ж.нь 6|5=7.

·         ^    - бүхэл операндуудын 2-тын кодын битүүдийг XOR үйлдээр хувиргах (бит XOR). Ж.нь 6^5=3.

Жиших үйлдлүүд (VI-VII эрэмбэ):

·         <   - зүүн талын операнд баруун талын операндаас бага эсэх

·         >   - зүүн талын операнд баруун талын операндаас их эсэх

·         <= - зүүн талын операнд баруун талын операндаас бага буюу тэнцүү эсэх

·         >= - зүүн талын операнд баруун талын операндаас их буюу тэнцүү эсэх

·         == - зүүн талын операнд баруун талын операндтай тэнцүү эсэх

·         !=  - зүүн талын операнд баруун талын операндтай тэнцүү биш эсэх

Жиших үйлдэлд оролцож буй операндууд арифметик төрлийнх юм уу заагч байх ёстой. Жишилтийн үр дүн 0 (худал) эсвэл 1 (үнэн) байна. Ж.нь (x<B==A<x) гэсэн илэрхийллийг x нь A, B-ийн хооронд оршино, A<B гэсэн нөхцөлтэй бодвол эхлээд x<B ба A<x гэсэн үйлдлүүд хийгдээд, гарсан үр дүнгүүдэд == үйлдэл хийгдэнэ. Эцсийн хариу 1 байна. Түүнчлэн 3<5=1, 3>5=0, 3==5=0, 3!=5=1 г.м.

Логик үйлдлүүд (XI-XII эрэмбэ):

·         &&            - арифметик операндууд юм уу нөхцлүүдийг логик үржих (конъюнкци)

·         ||    - арифметик операндууд юм уу нөхцлүүдийг логик нэмэх (дизъюнкци)

Логик .үйлдлийн үр дүн 0 (худал) эсвэл 1 (үнэн) байна. Ж.нь 3+4>5&&3+5>4&&4+5>3=1, 3!=5||3==5=1 байна.

Утга оноох үйлдлүүд (XIV эрэмбэ):

·         =   - баруун талын операнд буюу илэрхийллийн утгыг зүүн талын операндад оноох. Ж.нь P=10.3-2*x.

·         *=  - үржвэрийг оноох. Зүүн талын операндыг баруун талын операндаар үржүүлээд гарах утгыг зүүн талын операндад оноох. Ж.нь P*=2 гэдэг нь P=P*2 гэсэнтэй эквивалент.

·         /=  - ноогдворыг оноох. Зүүн талын операндыг баруун талын операндад хуваагаад гарах бүхэл хэсгийг зүүн талын операндад оноох. Ж.нь P/=2.2-x гэдэг нь P=P/(2.2-x) гэсэнтэй эквивалент.

·         %= - үлдэгдлийг оноох. Зүүн талын операндыг баруун талын операндад хуваагаад гарах үлдэгдлийг зүүн талын операндад оноох. Ж.нь N%=3 гэдэг нь N=N%3 гэсэнтэй эквивалент.

·         += - нийлбэрийг оноох. Зүүн талын операнд дээр баруун талын операндыг нэмээд гарах утгыг зүүн талын операндад оноох. Ж.нь A+=B гэдэг нь A=A+B гэсэнтэй эквивалент.

·         -=  - ялгаврыг оноох. Зүүн талын операндаас баруун талын операндыг хасаад гарах утгыг зүүн талын операндад оноох. Ж.нь A-=B+1.5 гэдэг нь A=A-(B+1.5) гэсэнтэй эквивалент.

·         <<= - зүүн шилжүүлээд оноох. Зүүн талын операндын 2-тын кодыг баруун талын операндын утгаар зүүн тийш шилжүүлээд гарах утгыг зүүн талын операндад оноох. Ж.нь a<<=4 гэдэг нь a=a<<4 гэсэнтэй эквивалент.

·         <<= - баруун шилжүүлээд оноох. Зүүн талын операндын 2-тын кодыг баруун талын операндын утгаар баруун тийш шилжүүлээд гарах утгыг зүүн талын операндад оноох. Ж.нь a>>=4 гэдэг нь a=a>>4 гэсэнтэй эквивалент.

·         &= - бит конъюнкцийг оноох. Ж.нь k&=44 гэдэг нь k=k&44 гэсэнтэй эквивалент.

·         |=   - бит дизъюнкцийг оноох. Ж.нь a|=b гэдэг нь a=a&b гэсэнтэй эквивалент.

·         ^=  - бит XOR-ыг оноох. Ж.нь z^=x+y гэдэг нь z=z^(x+y) гэсэнтэй эквивалент.

Таслалын тэмдэг-үйлдэл (XV эрэмбэ):

Өөр хоорондоо таслалаар тусгаарлагдан бичигдсэн хэд хэдэн илэрхийлэл зүүн гар талаасаа эхлэн дэс дараагаар бодогддог. Харин эцсийн үр дүн болж хамгийн баруун талын илэрхийллийн утга гарна. Ж.нь (x=3, 3*x) гэсэн илэрхийллийн утга 9 болно. Харин x нь 3 байна.

Унар, бинараас гадна тернар үйлдэл гэж байдаг. Энэ нь гурван операндтай ажиллагч үйлдэл юм. Манай тохиолдолд ганц тернар үйлдэл бий.

Нөхцөл шалгах үйлдэл (XIII эрэмбэ):

Энэ үйлдэл ? ба : гэсэн тэмдгүүдээс тогтоно. Үйлдлийг бичих загвар нь:

илэрхийлэл1 ? илэрхийлэл2 : илэрхийлэл3

гэсэн хэлбэртэй. Тайлбарлавал: хэрэв илэрхийлэл1 үнэн байвал илэрхийлэл2-ыг бодох, үгүй бол илэрхийлэл3-ыг бод гэсэн үг. Ж.нь x-ийн модулийг олох үйлдлийг ингэж бичиж болно:

x<0 ? –x : x ;

Тусгаарлагч тэмдгүүд

Дараах тэмдгүүдийг тусгаарлагч тэмдгүүд (punctuation marks эсвэл separators) хэмээх лексем болгон авдаг байна. Үүнд:

[ ]         ( )         { }         ,           ;           :                   *           =          #

Тусгаарлагч тэмдгүүд ямар үүрэгтэй вэ? Нэрнээс нь л ойлгомжтой байгаа байх. Тусгаарлагч тэмдгүүд нь програмын текстэн доторх аль нэг объектыг өөр нэг объектоос ялгаж зааглахад хэрэглэгдэнэ.Эдгээрийн заримтай танилцъя.

[ ] - Дөрвөлжин хаалт

Нэг буюу олон хэмжээст массивын (массивын тухай хойно үзнэ) индексийг бичихдээ, мөн массивын элементэд хандахдаа үүнийг ашиглана. Ж.нь:

int A[5];                              /* Бүхэл төрлийн 5 элементтэй нэг хэмжээст A массив */

int e[3][2];                          /* Бүхэл төрлийн 3x2 хэмжээтэй хоёр хэмжээст x массив (матриц) */

e[0][0] = A[2] = 4; /* e массивын эхний, A массивын 3 дахь элементэд 4 гэсэн утга оноох */

( ) - Дугуй хаалт

Хэд хэдэн үүргийг гүйцэтгэж болно.

1.       Нөхцөл шалгах if операторын (энэ операторын тухай хойно үзнэ) операндыг (нөхцлийг) тусгаарлаж харуулна (агуулна). Ж.нь:

if (x<0) x = -x;  /* х гэсэн арифметик хувьсагчийн абсолют утгыг олох */

2.       Функц (функцын тухай хойно дэлгэрэнгүй үзнэ) зарлах, функцын эх загвар дүрслэхэд заавал оролцож, формал параметрууд юм уу параметруудын загварыг тусгаарлаж харуулна. Ж.нь:

float F(float x, int k)    /* функц зарлаж байгаа нь */

{ функцын_бие }

float F(float, int);         /* функцын эх загвар дүрсэлж байгаа нь */

3.       Функцын заагчийг (заагчийн тухай хойно дэлгэрэнгүй үзнэ) тодорхойлоход заавал оролцоно. Ж.нь:

int (*pfunc) ( ); /* pfunc гэсэн функцын заагч тодорхойлж байгаа нь */

4.       Илэрхийллийг дэд хэсгүүд буюу операндаар бүлэглэж, үйлдлийн дарааллыг тодорхойлно. Ж.нь:

y = (a + b) / c;   /* нэмэх үйлдлийг түрүүлж хийлгэнэ */

5.       Давталтын (давталтын тухай хойно дэлгэрэнгүй үзнэ) операторуудын зайлшгүй бүрдэл хэсгүүд болж оролцоно. Ж.нь:

for (i=0, j=1; i<j; i+=2, j++) давталтын_бие;            /* параметрт давталт */

while (i<j) давталтын_бие;                                       /* “байхад” нөхцөлт давталт */

do давталтын_бие while (k>0);                                /* “байхад” нөхцөлт давталт */

6.       Өгөгдлийн төрлийг илээр хувиргах үйлдэлд оролцоно. Ж.нь:

long I = 12L;    /* long төрлийн бүхэл хувьсагч зарлан идэвхжүүлэх */

float brig;          /* float төрлийн бодит хувьсагч зарлах */

brig = (float) i; /* бүхэл хувьсагчийн төрлийг илээр өөрчлөн бодит болгоод бодит хувьсагчид оноох */

7.       Энэ лекцийн “Хувьсагч ба тогтмол” хэсэгт, #define хэмээх командын тусламжтайгаар нэр бүхий тогтмолыг зарлах боломжийг дурдсан билээ. Үүнийг макротодорхойлолт хэмээн нэрлэдэг болохыг мөн дурдсан байгаа. Тэгвэл ерөнхий тохиолдолд дугуй хаалт ашиглан илүү боловсронгуй макротодорхойлолт хийж болно. Ж.нь:

#define R(x,y) sqrt((x)*(x) + (y)*(y))    /* sqrt(x^2+y^2) илэрхийллийг R(x,y)-ээр орлуулах */

{ } - Нуман хаалт

Нийлмэл оператор эсвэл програмын тодорхой бүрдэл хэсгийн (блок) эхлэл, төгсгөлийг ялгаж харуулахад үүнийг ашиглана. Тухайлбал нөхцөл шалгах if операторт нуман хаалт ашигласан жишээ:

if (d > x)

{      /* нийлмэл операторын эхлэл */

d--;

x++;

}     /* нийлмэл операторын төгсгөл */

Функцын биеийн эхлэл, төгсгөлийг нуман хаалтаар тэмдэглэсэн жишээ:

float absx (float x)

{      /* функцын биеийн эхлэл */

return x > 0.0 ? x : -x;

}     /* функцын биеийн төгсгөл */

Төгсгөлийн нуман хаалтны ард цэгтэй таслал тавихгүй болохыг анхаараарай.

, - Таслал

Энэ лекцийн “Үйлдлийн тэмдгүүд” хэсэгт, таслалын тэмдэг нь үйлдэл төлөөлдөг болохыг дурдсан байгаа. Тэгвэл бас тусгаарлагч тэмдгийн үүрэг гүйцэтгэдэг байна. Тухайлбал адил төрлийн өгөгдлүүд (хувьсагчууд) зарлахад ийм үүргээр оролцоно. Ж.нь:

int i, n;

float x, y, z, p1, p2;

; - Цэгтэй таслал

Си хэл дээр бичсэн програмын текстийн оператор болгон, тодорхойлолт (зарлалт) болгон цэгтэй таслал ‘;’-аар төгсч байх ёстой. Ард нь ‘;’ тавьсан илэрхийлэл болгоныг оператор гэж үзнэ. Ж.нь:

int i;            /* бүхэл төрлийн i хувьсагч тодорхойлох (зарлах) */

i++;             /* i хувьсагчийн утгыг нэгээр ихэсгэх илэрхийлэл-оператор */

F(z, 4);        /* F функцыг дуудах илэрхийлэл-оператор */

Илэрхийлэл

Тогтмолууд, хувьсагчууд, үйлдлийн болон тусгаарлагч тэмдгүүдийн тусламжтайгаар илэрхийллийг бүтээнэ. Илэрхийлэл болгон нэг буюу хэд хэдэн операнд, үйлдлийн тэмдгүүд, тусгаарлагч тэмдгээс (ихэвчлэн дугуй хаалт) тогтоно. Илэрхийллийн гол үүрэг бол ямар нэг утга олох явдал. Ямар утга олж буйгаар нь илэрхийллийн төрөл тодорхойлогдоно.

Арифметик илэрхийлэл

Хэрэв илэрхийллийн утга бүхэл юм уу бодит тоо байвал ийм илэрхийллийг арифметик илэрхийлэл гэдэг.

Арифметик илэрхийлэлд дараах үйлдлүүд оролцсон байж болно:

·         +   - нэмэх (эсвэл унар нэмэх)

·         -    - хасах  (эсвэл унар хасах)

·         *    - үржүүлэх

·         /     - хуваах

·         %  - үлдэгдэл олох (ө.х. нэг бүхэл тоог нөгөөд хуваахад гарах үлдэгдлийг олох)

Харин эдгээр үйлдэлд оролцож буй операндууд нь:

·         арифметик тогтмолууд

·         арифметик хувьсагчууд

·         дугуй хаалтанд орсон илэрхийллүүд

байж болно.

Ж.нь хоёр операнд (бинар үйлдэл) бүхий арифметик илэрхийллүүд:

a+b      12.3-x              3.14159*Z        k/3       16%1               (x-y)*(x+y)

г.м.

Тухайн үйлдлийн төрөл, онцлогоос шалтгаалж, үйлдэлд оролцогч операндууд заавал нэгэн ижил төрлийнх байх ёстой эсвэл тийм байх албагүй байж болно. Тэгвэл, заавал нэг төрлийнх байх ёстой байтал өөр өөр төрлийн операндууд бичигдсэн байвал яах вэ?

Зарим үйлдэл ийм байдлыг зөвшөөрч болох юм. Энэ тохиолдолд операндуудын төрлийг автоматаар нэгэн ижил болгох (data type conversion) процессыг хөрвүүлэгч хийдэг. Ингэхдээ тодорхой дүрмийг баримтлах бөгөөд энэ дүрэм Си хэлэнд өөрт нь тодорхойлогдсон байдаг. Энэ дүрмийг дурдвал (бинар үйлдлийн хувьд):

1.       int ба long-оос бусад бүх бүхэл төрөл өөрөөсөө багагүй урттай (санах ойд эзлэх зай) бүхэл төрөлд хувирна. Дараа нь хоёр операнд доорх заалтуудын дагуу нэг ижил төрөлд хувирах ёстой.

2.       Хэрэв аль нэг операнд long double төрөл байвал нөгөө нь мөн long double болно.

1.       Хэрэв II заалт биелэхгүй, харин аль нэг операнд double байвал нөгөө нь мөн double болно.

2.       Хэрэв II-III заалт биелэхгүй, харин аль нэг операнд float байвал нөгөө нь мөн float болно.

3.       Хэрэв II-IV заалт биелэхгүй (хоёр операнд хоёулаа бүхэл), харин аль нэг операнд unsigned long int байвал нөгөө нь мөн unsigned long int болно.

4.       Хэрэв II-V заалт биелэхгүй, харин аль нэг операнд long байвал нөгөө нь мөн long болно.

5.       Хэрэв II-VI заалт биелэхгүй, харин аль нэг операнд unsigned байвал нөгөө нь мөн unsigned болно.

6.       Хэрэв II-VII заалт биелэхгүй байвал хоёр операнд хоёулаа int болно.

Ж.нь 5+3 илэрхийллийг авч үзье. Энд VIII заалт хэрэгжих тул хариу нь 8 гэсэн бүхэл тоо байна. Тэгвэл 5.0+3 илэрхийллийн хувьд III заалт хэрэгжих бөгөөд хариу нь 8.0 байна. Үүний адилаар 5-3=2 байх бол 5-3.0=2.0 байна. Мөн 5*3=18, 5.0*3.0=18.0 байна. 5/2 гэсэн хуваах үйлдлийг авч үзье. VIII заалт хэрэгжих учраас хариу нь 2 гэсэн бүхэл тоо байна. Уг нь 5/2=2.5 байдаг шүү дээ. Тиймээс зөв хариу авахын тулд 5.0/2 эсвэл 5/2.0 гэж бичих хэрэгтэй юм.

Гэтэл зарим үйлдлийн операндууд нь бүгд нэг төрөлтэй байхыг шаардаад зогсохгүй өөр  төрлийн операнд бичихийг үл зөвшөөрдөг. Тухайлбал үлдэгдэл олох % үйлдлийн операндууд бүгд бүхэл төрлийнх байх ёстой. Учир нь үлдэгдэл гэдэг ямагт бүхэл тоо байдаг. Тиймээс ж.нь 5%2, 6%4 г.м. байж болох бол 5.0%2, 6%4.0 г.м. байж болохгүй бөгөөд хөрвүүлэгч алдаа өгнө. Ө.х. энд төрөл хувиргах процесс автоматаар хийгдэхгүй.

Эндээс дараах дүгнэлтийг хийж болох байна. Юу гэвээс, үйлдлийн хариу бүхэл төрлийнх байхын тулд операндууд нь бүгд бүхэл төрлийнх байх ёстой. Харин үйлдлийн хариу бодит төрлийнх байхын тулд операндуудын аль нэг нь л бодит төрлийнх байхад хангалттай.

Үйлдлийн операндууд нь арифметик тогтмолууд байгаа тохиолдлыг сая бид үзлээ. Хэрэв операндууд нь нэр бүхий хувьсагч, нэр бүхий тогтмол эсвэл илэрхийлэл байвал яах вэ? Энэ тохиолдолд өгөгдлийн төрлийг илээр хувиргах үйлдлийг хийх хэрэгтэй. “Үйлдлийн тэмдгүүд” хэсэгт бид төрөл хувиргах (өгөгдлийн_төрөл) үйлдэлтэй танилцсан билээ. Түүнийг хийнэ. Ж.нь дараах жишээг харцгаая:

int n=5, k=2;

double d;

int m;

d = (double) n / (double) k;

m = n / k;

Энэ жишээнд, n/k үйлдлийн хариуг 2.5 гаргахын тулд (d=2.5) n, k-ийн төрлүүдийг илээр бодит болгон хувиргаж байна:

d = (double) n / (double) k;

 Мэдээж зөвхөн n-ийн эсвэл зөвхөн k-ийн төрлийг хувиргахад мөн л хангалттай байсан:

d = (double) n / k;      d = n / (double) k;

Харин n, k-ийн төрлүүдийг илээр бодит болгож хувиргаагүй тохиолдолд 2 гарах болно (m=2).

Утга оноох үйлдэл

Утга оноох = үйлдэл нь арифметик илэрхийлэлд оролцож болох бас нэг үйлдэл юм. Энэ нь бинар үйлдэл учраас хоёр операндтай ажиллана. Баруун талын операнд нь утга (илэрхийлэл), зүүн талын операнд нь энэ утгыг авах хэмжигдхүүн (хувьсагч) юм. Ж.нь z-ийг хувьсагчийн нэр гэвэл:

z = 2.3 + 5.1

гэсэн бичиглэл нь 7.4 гэсэн утга бүхий илэрхийлэл болно. Түүнчлэн энэ утга z хувьсагчид утга болж оноогдоно. Гэхдээ зөвхөн энэ илэрхийллийн төгсгөлд цэгтэй таслал ; тавигдсан тохиолдолд уг илэрхийлэл утга оноох оператор болж хувирна. Ө.х.

z = 2.3 + 5.1;

гэсэн илэрхийлэл бол z хувьсагчид 7.4 гэсэн утгыг оноох оператор юм.

Утга оноох операторын зүүн болон баруун талын операндуудын төрөл ялгаатай байж болно. Энэ тохиолдолд дээр дурдсан төрөл автоматаар хувиргах дүрэм үйлчлэхгүй. Зүүн талын операнд ямар төрөлтэй байна, тэр төрөл рүү баруун талын операндын төрлийг хувиргадаг. Жишээ болгож саяны операторыг дахин авч үзье:

z = 2.3 + 5.1;

Энд, баруун талын операнд нь бодит төрөлтэй байна. Гэхдээ z хувьсагчийг бүхэл гэж зарласан уу, бодит гэж зарласан уу гэдгээс түүний авах утга хамаарна. Ж.нь:

double z;     /* z нь бодит төрлийн хувьсагч */

z = 2.3 + 5.1;

гэсэн бол z нь 7.4 гэсэн бодит утгыг авна. Учир нь хоёр операндын төрлүүд адил байна. Гэтэл:

int z;            /* z нь бүхэл төрлийн хувьсагч */

z = 2.3 + 5.1;

гэсэн бол z нь 7 гэсэн бүхэл утгыг авна. Учир нь баруун талын 7.4 гэсэн операндыг зүүн талын операндын төрөл рүү хувиргаж байна. Мэдээж бодит тоог бүхэл тоонд шилжүүлэхэд бутархай хэсэг хаягдаж таарна.

Нөхцөлт ба логик илэрхийллүүд

Жиших үйлдлүүд оролцсон илэрхийллийг нөхцөлт илэрхийлэл гэнэ. Үнэн хэрэгтээ энэ нь жиших үйлдлээр холбогдсон арифметик илэрхийллүүдийн цогц юм. Жиших үйлдлүүд нь:

·         == - тэнцүү

·         !=  - тэнцүү биш

·         <   - бага

·         <= - бага буюу тэнцүү (ихгүй)

·         >   - их

·         >= - их буюу тэнцүү (багагүй)

Ж.нь:

a – b > 6.3              /* a-b гэсэн арифметик илэрхийллийн утга 6.3-аас их эсэх*/

(x - 4) * 3 == 12     /* (x-4)*3 гэсэн арифметик илэрхийллийн утга 12-той тэнцэх эсэх*/

6 <= 44                   /* 6 нь 44-өөс ихгүй эсэх * /

г.м.

Си хэлэнд бие даасан логик өгөгдлийн төрөл гэж байхгүй учраас нөхцөлт илэрхийллийн буцаах “үнэн”, эсвэл “худал” гэсэн утгыг харгалзан 1, 0-ээр илэрхийлдэг. Тиймээс 6 <= 44 гэсэн нөхцлийн утга 1 байна.

Логик үйлдлүүд оролцсон илэрхийллийг логик илэрхийлэл гэнэ. Логик илэрхийлэл нь нөхцөлт илэрхийлэл, мөн арифметик илэрхийллүүдээс тогтож болно. Логик үйлдлүүд нь:

·         !    - үгүйсгэл (логик NOT)

·         &&            - конъюнкци (логик AND)

·         ||    - дизъюнкци (логик OR)

Ж.нь:

a+b>c && a+c>b && b+c>a

4&&2

!=5

г.м.

Логик илэрхийллийн утга 1 (“үнэн”) эсвэл 0 (“худал”) байна. Ж.нь && үйлдлийн хувьд аль нэг операнд 0 байвал эцсийн хариу 0 болно. Тиймээс конъюнкцийг логик үржилт гэдэг. Харин || үйлдлийн хувьд аль нэг операнд 0-ээс ялгаатай байвал эцсийн хариу 1 болно. Тиймээс дизъюнкцийг логик нэмэлт гэдэг. Үгүйсгэлийн хувьд операнд нь 0-ээс ялгаатай байвал хариу нь 0, эсрэг тохиолдолд 1 байна.