Pages

Thursday, December 6, 2012

Программчлалын /Си/ хэл


Програмчлалын хэл судлахад хамгийн их өргөн хэрэглэгдэж байгаа програмчлалын СИ хэлний талаарх мэдээлэл орууллаа. Си судлах гэж байгаа хэн бүхэнд хэрэгтэй мэдээлэл гэж бодож байна. Мэдээллийн эх үүсвэрийг найз Н.Цэнхэрлэнгийн материалыг ашиглав. Амжилт хүсье!

Программчлалын /Си/ хэлний үндэс
a.    Программчлалын бүтэц, толгой файлын тухай
Программчлалын бүтэц
Программ нь бэлтгэл хэсэг, дэд хэсэг болон үндсэн программаас тогтдог. Программын бэлтгэл хэсэг нь уг программын бүхий л хэсэгт ашиглагдаж болох стандарт хувьсагч, тогтмол болон функцуудын  байрлаж буй толгой файлуудыг include директивээр тодорхойлж өгдөг. Үүний дараа программын аль ч хэсэгт хэрэглэж болох глобал төрөл, тогтмол хувьсагч, хэрэглэгчийн функцуудыг тодорхойлж өгдөг. Ер нь Си хэлний хувьсагчийг программын аль ч хэсгийн эхэнд тодорхойлж өгч болдог. Си хэлний программууд нь Main() функцыг агуулж байдаг. Программ ажиллаж эхлэхэд энэ функц дотор бичигдсэн код эхлэн ажилладаг бөгөөд үүнийг үндсэн программ гэдэг. Жишээ:
Тэмдэгт мөрийг хэвлэх
/*миний эхний программ*/
#include<stdio.h>
#define greeting “Сайн байна уу?”
main()
{
printf(greeting);
}  /Программыг бичиж дуусаад Run & ctrl+F9 хослолыг сонгоно/. Юуны өмнө программын текстийг компилятор хүлээн авч хөрвүүлэлт хийнэ.хөрвүүлж дуусаад Хэрвээ алдаа гарсан байвал гарсан алдаануудын тухай мэдээллүүдийг өгөөд ажиллагаагаа зогсооно. Харин алдаагүй хөрвөж дууссан бол уг текстэд харгалзах объект файлыг  (*.OBJ өргөтгөл бүхий) дискэнд үүсгэж, ажиллагаа холбогчид шилждэг. Нэг программ хэд хэдэн хэсгээс тогтож болох бөгөөд холбогч нь тэдгээр хэсэг бүрийн объект файлуудыг нэгтгэн дискэнд биелэх файлыг (*.EXE өргөтгөлтэй ) үүсгэдэг. Энэхүү биелэх файл санах ойд ачаалсанаар уг программ ажилладаг.

Толгой файлын тухай

Өмнөх хэсгийн жишээ программын эхний мөрөнд #include<stdio.h> гэсэн мөр байгааг анзаарч байгаа байх. Энэ мөрний <stdio.h> гэдэг нь си хэлний стандарт толгой файл буюу тогтмол, төрөл, функцуудын санг агуулсан файлын нэр юм. Си хэлийг ашиглан программ бичихдээ өөр файлд тодорхойлогдсон функц, тогтмол, макро зэргийг ашиглах бүрэн боломжтой. Хэрэв ийм боломжгүй бол ялангуяа том хэмжээний программ бичиж байгаа тохиолдолд их хэмжээний тогтмол болон функцуудыг нэг файлдаа тодорхойлох нь файлын хэмжээ болон программын бүтцийн хувьд тун эмх замбараагүй болдог. Харин тогтмол макро, функцуудыг нэг файлд ялгаж торхойлоод түүнийгээ өөрийн файлдаа холбож өгвөл программын бүтэц энгийн болоод ойлгомжтой болох юм. Ийм файлыг толгой файл гэх бөгөөд файл нь “.h өргөтгөлтэй байна.   
Толгой файлыг мөн сан гэж нэрлэж болно. Жишээ нь:
/*defs.h*/
Void fun1()
{
}
/*my.c*/
#include”defs.h”
Main()
{….
Fun1();
……….} Толгой файлыг зааж өгөхдөө  #include директивийг ашиглах бөгөөд түүний ард файлыг нэрийг (“”) давхар хашилтанд тэмдгээр хашиж бичнэ. Директивийг заавал мөрийн эхлэлээс бичих ёстой. Си хэлэнд өөрийн гэсэн толгой файлууд байдаг. Энэ файлуудад Си-д нийтлэг ашиглагдах тогтмолууд, функцууд болон макронуудыг тодорхойлж өгсөн байдан. Энэхүү стандарт толгой файлуудыг тодорхойлох тохиолдолд #include директивийн ард толгой файлын нэрийг бичихдээ (“”) биш (< >)буюу өнцгөн хаалтанд хийнэ.
Жишээ нь: Математик болон логикийн функц, тогтмол, макронууд нь math.h гэсэн стандарт толгой файлд агуулагдаж байдаг. Мөн stdio.h толгой файлаас scanf(), printf() функцуудыг ашиглаж байгаа.
б. Цагаан толгой, түлхүүр үгнүүд

Си хэлний цагаан толгой
Си хэлний цагаан толгойд:
·         Латин цагаан толгойн том, жижиг үсгүүд: (A, B, ..., Z, a, b, ..., z)
·         Цифрүүд: 0, 1, 2, 3, 4 , 5, 6, 7, 8, 9
·         Тусгай тэмдгүүд:
,
{ }
|
[ ]
( )
+
-
/
%
\
;
.
:
?
=
_
!
&
*
#
~
^
·         Үл дүрслэгдэх тэмдэгтүүд: лексемүүдийг нэг нэгээс нь тусгаарлах үүрэг бүхий сул зай, табуляци, шинэ мөрөнд шилжих г.м.
Цагаан толгойн тусламжтайгаар хэлний бусад бүрдэл хэсгүүд болох тайлбар, лексем зэргийг бүтээдэг. Си хэлэнд:
·         идентификаторууд (чөлөөт нэрс)
·         албаны (нөөц) үгс
·         тогтмолууд
·         тэмдэгт мөр төрлийн тогтмолууд
·         үйлдлийн тэмдгүүд
·         тусгаарлагч тэмдгүүд
гэсэн 6 төрлийн лексем байна. Эдгээр лексемүүдийг ашиглан програмын эх кодыг бичнэ.
Түлхүүр үг
Түлхүүр үг гэдэг нь тодорхойлолгүйгээр үүргийнх нь дагуу шууд ашиглаж болох тодорхой тооны үг юм. Түлхүүр үгийг идентификатор тодорхойлоход  ашиглаж болохгүй .Си хэлэнд дараах түлхүүр үгнүүд байна.
Auto
Double
Int
Struct
Break
Else
Long
Switch
Case
Enum
Register
Typedef
Char
Extern
Return
Union
Const
Float
Short
Unsigned
Continue
For
Signed
Void
Default
Goto
Sizeof
Volatile
Do
If
Static
while



г. Стандарт ба хэрэглэгчийн идентифипатор,
 бичих дүрэм

Хэрэглэгч программдаа ашиглагдах хувьсагч, тогтмол, функц, макро зэрэгт өгсөн нэрүүдийг хэрэглэгчийн тодорхойлсон идентификатор гэдэг. Хэрэглэгчийн тодорхойлсон идентификаторт доорх шаардлагууд тавигдана. Үүнд :
·         Идентификатор нь нэг болон хэд хэдэн тэмдэгтээс тогтоно.
·         Тоо болон латин үсэг аль аль нь орж болох боловч заавал үсгээр эхэлсэн байх ёстой.
·         Зөвхөн доогуур зураас ашиглана. Харин
,
{ }
|
[ ]
( )
+
-
/
%
\
;
.
:
?
=
_
!
&
*
#
~
^
гэх мэт тэмдэгтүүд болон цэг таслал зэргийг оруулж болохгүй.
·         Түлхүүр үгтэй ижилхэн байж болохгүй
·         Кирилл үсэг оруулж болохгүй
Идентификаторт орж байгаа том, жижиг үсгүүд хоорондоо ялгаатай гэдгийг бүү март. Учир нь Си хэл том, жижиг үсгийг ялгаатай гэж үздэг. Идентификаторыг программд тодорхойлж өгөх хэрэгтэй байдаг. Жишээ нь:
 Зөв  бичигдсэн идентификаторууд :   X, y_, x2, value, _mydata, kom16, TIME, time, aa, b2c3, week_days
Буруу бичигдсэн идентификаторуудcout, 81_sales, my age, add49+89, for…

д.Өгөгдлийн төрлүүд /стандарт ба хэрэглэгчийн төрөл, тоочих төрөл,интервалын төрөл/

Програм нь бүхэл тоо болон бодит тоо гэх мэт төрөл бүрийн өгөгдлийг хадгалж боловсруулж байдаг. Хөрвүүлэгч өгөгдсөн утгыг ямар төрлийн өгөгдөл болохыг мэдэх хэрэгтэй байдаг учраас өгөгдлүүдийг төрөлжүүлэх шаардлагатай болдог. Мөн төрөл нь программчлалын хэлэнд ашиглагдаж байгаа өгөгдлийн хэмжээг тодорхойлж өгч байдаг. Өгөгдлийн хэмжээ гэдэг нь тухайн өгөгдлийн санах ойд эзлэх зайг хэлж байгаа юм. Программчлалын си хэлний төрлийг программчлалын бусад хэлний адилаар стандарт ба хэрэглэгчийн гэж хувааж болно. Стандарт төрөл гэдэг нь ямар нэгэн байдлаар тодорхойлолгүйгээр шууд хэрэглэж болохуйц төрлийг хэлнэ.  Харин хэрэглэгчийн төрөл гэдэг нь программд тодорхойлсны дараа хэрэглэдэг төрлийг хэлдэг.               
Бүхэл тоон төрөл
Төрөл
Санах ойд
эзлэх хэмжээ
Утгын муж
Нэр

Char
8
-128…127
Тэмдэгт төрөл
unsigned
char
8
0…255
unsigned
short
16
0…65535
Бүхэл тоон төрөл
Short
16
-32768…32767
Int
32
-2147483648..2147483647
Урт бүхэл тоон төрөл
unsigned int
32
0…294967295...
Long
32
-2147483648 …2147483647
unsigned long2
32
0…294967295
Жишээ нь дараах кодын хэсэгт char төрлийн  ch хувьсагчийг бүхэл тоо, тэмдэгт аль альнаар нь ашигласан байна:
char ch = ‘A’; /char төрлийн A хувьсагч/
printf(“%c тэмдэгтийн код нь %d.”\n, ch , ch );
ch = ch + 1;
printf(“%2c”, ch); 
Энд  printf функцээр тэмдэгт хувьсагчийг хэвлэхэд %c орлуулагч, бүхэл тоо болгон хэвлэхэд  %d орлуулагч тэмдэгтийг ашигласан байна.

Unsigned түлхүүр үг нь уг төрөл сөрөг утга авахгүй болохыг тодорхойлж өгдөг.
Төрөл
Санах ойд
эзлэх хэмжээ
Утгын муж
Нэр

Float
32
3.4E-38..
3.4E+38..
Дан нарийвчлалтай бодит тоо

Double
64
1.7E-308…
1.7E+308
Давхар нарийвчлалтай бодит тоо

Long double
80
3.4E-4932..
1.1E+4932

Өргөтгөсөн  нарийвчлалтай бодит тоо


Хэрэглэгч өөрийн төрлийг үүсгэх боломж байна. Үүнийг typedef түлхүүр үгийн тусламжтайгаар гүйцэтгэнэ. Шинээр төрөл үүсгэх нь Typedef<төрөл><төрлийн шинэ нэр>;  хэлбэртэй байна. Жишээ нь:
Typedef unsigned long ulong;
Typedef unsigned int uint;
Typedef unsigned double udouble;
Typedef unsigned char uchar;    
   Эндээс харахад ulong,  uint, udouble, uchar гэсэн шинэ төрлүүд үүсгэж байна. Эдгээр нь үнэн чанартаа unsigned long, unsigned int, unsigned double, unsigned char төрлүүд болно. Мөн си хэлэнд void гэсэн төрөл байдаг. 
Тоочих төрөл
Тоочих төрөл нь тодорхой тооны тогтмол утгуудын олонлог юм. Эдгээр утгууд нь оноосон нэртэй байна. Хөрвүүлэгч нь нэр болгонд харгалзах бүхэл тоон утгуудыг автоматаар 0-ээс эхлэн 1 алхмаар нэмэгдүүлэн оноодог. Си хэлэнд хязгаарлагдмал тооны тодорхой утга авах хувьсагчийг тоочих төрлөөр тодорхойлж өгч болно. Тоочих төрлийг программд тодорхойлохдоо “enum” түлхүүр үгийг ашиглана. Тоочих төрлийн утгын хязгаар short int (-32768..+32767, санах ойд 2байт эзэлнэ.) төрөлд багтах ёстой.
Бичигдэх хэлбэр:
enum [<тө-нэр>] {<тогт-нэр1>[=<дугаар1>],
<тогт-нэр2>[=<дугаар2>],…,<тогт_нэрN>[=<дугаарN>]}
[хувьсагч_нэр];

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

<тө-нэр> - Точигдох төрлийн нэр
<тогт_нэр1>, <тогт_нэр2>,…, <тогт_нэрN> - тоочсон утгууд.
Өөрөөр хэлбэл, уг тоочих төрлийн авах утгуудыг таслалаар заагласан жагсаалт.
<дугаар1>…<дугаарN> - тоочсон утгын тоон утга. Тоочсон утгыг бүхэл тоо төлөөлж болох бөгөөд төлөөлөх утгыг тухайн тоочсон утгад олгож болно. Утга олгоогүй тохиолдолд эхний элементийг төлөөлөх утгыг 0 гэж тооцох ба дараагийн элементүүд өмнөх элементээсээ дэс дараалан дугаарлагдана. Төлөөлөх утга нь бүхэл тоон төрлийнх байна. Үүнээс үндэслээд тоочигдох төрлийн нэг гэж үздэг ба түүн дээр бүхэл тоон төрөл дээр хийгдэх бүх үйлдэл хийгдэнэ.
<хувьсагч_нэр> - Зарлагдсан тоочих төрлийн хувьсагчийн нэр.
Жишээ:
enum dayname {January=1, February,. March, April, May, June, July, August, September, October, November, December} day;
Дээрх жишээний хувьд: Dayname нь тоочигдох төрлийн нэр
“January”, “February”, “Mart”, “April”… “November” тоочих төрлийн авах тогтмол утгын нэр тогтмолын нэр. Мөн тоон утгаараа January=1, February=2 буюу January+1, March=3   буюу February+1, april=4 буюу March+1 гэх мэт утгуудыг авна.

                  е.Хувьсагч тогтмолууд

Хувьсагч
Программын явцад утга нь өөрчлөгдөж болдог онцлог бүхий програмчлалын хэлний элементийг хувьсагч гэнэ. Өөрөөр хэлбэл, хувьсагч нь тогтмол утга биш, харин утгуудын тодорхой мужаас аливаа утгыг авах боломжтой элемент юм. Хувьсагч нь программд ихээхэн чухал үүрэгтэй. Өөрөөр хэлбэл, программ нь оролтоос хамааран тодорхой дүрмээр үр дүн гарах үйл ажиллагаа учраас оролт гаралтгүй программ байдаггүй. Үүнийг хувьсагчаар зохион байгуулдаг байна. Хувьсагчийн төрөл гэдэг нь түүний авч болох утгуудын мужийг хэлж байгаа юм. С хэлэнд хувьсагчийг зарлах нь
<төрөл><хувьсагч_нэр>; хэлбэртэй байна.
<төрөл> - Хувьсагчийн төрөл. Өмнө авч үзсэн бүхэл ба бодит тоон төрлүүд байхаас гадна хэрэглэгчийн тодорхойлсон төрлүүд байна.
<хувьсагч_нэр> - хувьсагчийг программд төлөөлөх идэнтификатор.
Хувьсагчийн нэрийг жижиг үсгээр бичих нь түгээмэл байдаг. Энэ нь нэг талаас түүнийг тогтмолоос ялгаж байгаа хэрэг юм.
Эдгээр стандарт төрлөөс гадна хэрэглэгч өөрийн хэрэгцээнд тохируулан шинэ төрлийн үүсгэж болдог.
Мөн хувьсагчийг утга олгон тодорхойлж болно. Энэ нь дараах хэлбэртэй байна.
<хувьсагчийн төрөл><хувьсагчийн нэр>[=<анхны утга>];
Энэхүү олгосон утга нь хувьсагчийн төрөлтэй тохирох хэрэгтэй бөгөөд хувьсагч өөр утга олготол анхнаасаа ямар утгатай байхыг зааж өгдөг. Хувьсагч тодорхойлж байгаа хэд хэдэн жишээ авч үзье.
int ivar1; /*бүхэл утга авах хувьсагч*/
int ivar2=-10; /*анхны утга олгосон бүхэл тоон хувьсагч*/
float fvar1=2.57; /*бодит тоон хувьсагч*/
unsigned int ivar3=500; /*эерэг бүхэл хувьсагч*/
char ch1, ch2=’*’, ch3; /*тэмдэгт хувьсагчууд*/

Си хэлэнд хувьсагч нь дараах онцлогуудтай. Үүнд:
·         Хувьсагчийг зарласны дараа тухайн хувьсагчийн амьдрах мужид ашиглах ёстой.
·         Нэг программ дотор ижил нэртэй хэд хэдэн хувьсагч байж болно. Гэхдээ өөр өөр үйлдлийн мужид байх ёстой. Өөрөөр хэлбэл, нэг үйлдлийн мужид ижил нэр бүхий хувьсагчууд тодорхойлж болохгүй.
·         Хувьсагчийн утгатай холбоотой гарч болох алдааг үргэлж тооцож байх нь зүйтэй.
·         Шаардлагагүй тохиолдолд том хэмжээний утгын мужтай хувьсагч тодорхойлох нь программыг их нүсэр, болхи болгодог.
Программ дотор хувьсагч тодорхойлогдоно гэдэг нь санах ойн нэг эсвэл дараалсан хэд хэдэн үүрийг уг хувьсагчид зориулан нөөцлөн авч, тэр нүднийхээ хаягийг хувьсагчид сануулж өгдөг байна. Уг хувьсагчтай ажиллана гэдэг нь тэрхүү нөөцөлсөн нүдэнд байгаа өгөгдөлтэй ажиллана гэсэн үг юм. Харин уг хувьсагчид хэдэн нүдийг нөөцлөх вэ гэдэг нь тэрхүү хувьсагчийн төрлөөс хамаардаг. Тухайлбал, char төрөл 1 байт, short төрөл 2 байт, long, int болон float төрөл 4 байт, double төрөл 8, long double төрөл 10 байт тус тус эзэлдэг болохыг өмнөх хүснэгтээс харж болно.
Тогтмол
Тогтмол гэдэг нь программын биелэлтийн хугацаанд утгаа өөрчлөлгүй хадгалж байдаг элементийг хэлнэ. Шууд бодоход программын явцад өөрчлөгдөхгүй юм бол тийм идентификатор тодорхойлох шаардлагагүй мэт санагдаж болох юм. Гэхдээ тогтмол утга тун чухал нэгэн үүрэгтэй бөгөөд үүнийг дараа жишээн дээр тайлбарлаж үзэх болно.
Тогтмолыг тодорхойлохдоо const гэсэн нөөц үгийг ашигладаг. Си хэлэнд тогтмол хэмжигдэхүүнийг дараах ерөнхий хэлбэрээр зарлана. Үүнд:
const <төрөл><нэр>=<илэрхийлэл>;
const Түлхүүр үг
<төрөл> - Өгөдлийн төрөл
<нэр> - Хэрэглэгчийн тодорхойлж өгсөн нэр. Ямар ч программчлалын системд тогтмолын нэрийг том үсгээр бичдэг заншил байдаг.
<илэрхийлэл> - тогтмолын төрөлтэй ижил төрлийн үр дүн өгөх илэрхийлэл.
Const нөөц үгийг ашиглан тогтмолыг тодорхойлоход тогтмолын нэр ба олгож байгаа илэрхийллийн хооронд тэнцүүгийн тэмдэг тавьж өгдөг. Жишээ нь:
const int MONT=12;
const int DEGREE=-30;
const double PI=3.1412;
const char NAME[ ]=”Болд”;
const char QUESTION[ ]=”Сайн уу?”;

Мөн тогтмолыг тодорхойлохдоо define директивийг3 ашиглаж болдог.
#define <тогтмолын нэр><илэрхийлэл>
Тогтмол утга тодорхойлж байгаа хэдэн жишээ үзье.
#define MONTH 12 /*эерэг бүхэл тогтмол*/
#define DEGREE -30 /*сөрөг бүхэл тогтмол*/
#define PI 3.1412 /*бутархай тогтмол*/
#define NAME “Болд” /*тэмдэгт мөр тогтмол*/
#define QUESTION “Сайн уу?” /*тэмдэгт мөр тогтмол*/

Бичлэгийн хувьд ижил боловч компиляторын хувьд энэ хоёр нь маш их ялгаатай тодорхойлолтууд юм. Учир нь const нөөц үгийг ашиглан ьодорхойлсон тогтмол нь дрограмын явцад огт өөрчлөгдөхгүй боловч хувьсагч шиг программын туршид санах ойд нэг болон хэд хэдэн байтыг эзлэн оршсоор байдаг. Мөн санамсаргүйгээр алдаа гарах магадлалыг багасгах шаардлагатай үед const хэмжигдэхүүний утгыг шинэ утгаар солих боломжтой байдаг. Гэтэл #define директивээр тодорхойлсон тогтмол утга нь өгөгдлийн сегмент4эд ямар нэгэн зай эзлэн оршихгүй бөгөөд программ хөрвүүлэх үед уг тогтмолыг ашиглаж байгаа газар бүрт тогтмолын утгыг нь шууд орлуулан боловсруулдаг. Жишээн дээр тайлбарлая.
a=pi * 2
гэсэн команд байг. Хэрэв pi тогтмолыг const нөөц үгээр тодорхойлсон бол компилятор   pi–г яг л хувьсагч шиг хөрвүүлнэ. Өөрөөр хэлбэл, энэ команд биелэхийн тулд уг тогтмолд зориулан санах ойгоос өгөгдлийг уншин авч илэрхийллийг тооцоолох болно.
Харин #definе директивээр тодорхойлсон бол pi гэсэн тогтмолд зориулсан санах ой гэж хаана ч байхгүй юм. Харин программ дотор дээрх командын оронд ердөө л
a=3.1415 * 2
гэсэн команд болгон хөрвүүлдэг байна.
Санах ойд хадгалагдаж байгаа программын кодуудыг төв процессор нэг бүрчлэн уншиж, командуудыг дэс дараалан биелүүлдэг. Гэхдээ санах ойд байгаа өгөгдлийг программын код, хувьсангч, тогтмол аль нь болохыг процессор огт мэдэхгүй бөгөөд хэрэв программыг оновчгүй зохион байгуулбал процессор буруу команд биелүүлэн, системийг гацахад хүргэж болзошгүй юм.
2.            С хэлний операторууд
Операторын тухай
ü  Биелэгдэх оператор (executable statement)
ü  Үл биелэгдэх оператор (non-executable statement)
гэж ангилдаг байна. Ингэж ангилахын учрыг олохын тулд :
-“Түүний нэр Баяр. Тэр 20 настай.” гэсэн хоёр өгүүлбэрийг авч үзье. Эдгээр өгүүлбэрүүд хэн нэгний нэр ба насны талаарх мэдээллийг бусдад өгч, таниулах үүрэгтэй байна. Түүнээс биш бусдыг ямар нэг үйлдэл хийхийг заагаагүй ажээ. Тэгвэл “Түүнийг нэрээр нь дууд. Түүний насыг асуу.” гэсэн хоёр өгүүлбэрийг авч үзье. Эдгээр өгүүлбэрүүд бол харин тус тусдаа шууд үйлдэл хийхийг заасан байна. Түүнээс биш хэн нэгний нэр ба насны талаарх мэдээллийг өгөөгүй байна. Үүний адилаар, компьютерээр шууд ямар нэг үйлдэл хийлгэх үүрэгтэй операторыг биелэгдэх оператор гээд харин программын тухай мэдээллийг хөрвүүлэгчид өгөх үүрэгтэй операторыг үл биелэгдэх оператор гээд байгаа юм.
Хөрвүүлэгч нь үл биелэгдэх операторуудын тусламжтайгаар программын бүтэц, зохион байгуулалт, боловсруулах өгөгдлүүдийн талаарх мэдээллийг олж аваад түүндээ тулгуурлан биелэгдэх операторуудыг машины код руу хөрвүүлнэ. Ө.х. машины код нь зөвхөн биелэгдэх операторуудын “орчуулга” байдаг байна. Учир нь үл биелэгдэх операторууд хөрвүүлэлтийн шатанд үүргээ гүйцэтгээд “хаягддаг” ажээ. Гэхдээ өгөгдлүүд хаягдахгүй гэдгийг санах хэрэгтэй.
Тэгэхээр зөвхөн биелэгдэх операторууд л харгалзах машины командуудтай байдаг гэж ойлгож болох нь ээ. Ингэхдээ нэг биелэгдэх операторт нэг буюу түүнээс олон машины команд харгалзсан байдаг.
Си хэлний биелэгдэх операторууд нь:
ü  утга оноох оператор
ü  оролт, гаралтын операторууд
ü  функц дуудах оператор
ü  нөхцөл шалгах оператор буюу Салаалалт бүтэц
ü  давталтын оператор буюу Давталт бүтэц
ü  сонголтын оператор буюу Сонголт бүтэц
ü  шилжүүлэх операторууд
ü  нийлмэл оператор буюу блок
г.м. болно. Харин үл биелэгдэх операторын тухайд бол, ийм оператор нь зарлах, таниулах г.м. үүрэгтэй гэснийг санаж байгаад:
ü     өгөгдөл зарлах
ü     функцын толгой хэсэг
ü     функцын прототип тодорхойлох
г.м.-ийг хамааруулж болно. Түүнчлэн препроцессорын директивийг ч бас хамааруулж үзэж болох талтай.
Эдгээр операторууд нь бүгд урьдчилан тодорхойлогдсон загварын дагуу бичигдэх бөгөөд түүнийх нь дагуу хөрвүүлэгч тэдгээрийг “танин мэднэ”. Хэрэв зохих загварыг баримтлаагүй байвал хөрвүүлэгч алдаа өгөх болно.
a.    Утга олгох оператор
Утга ойлгох операторыг Си хэлэнд “=” (тэнцүүгийн тэмдэг) – ээр гүйцэтгэдэг болохыг өмнөх олон жишээнүүдээс харж болно. Утга олох операторын үндсэн үүрэг нь хувьсагч болон тогтмолд илэрхийллийн утгыг онооход оршино. Жишээ нь:
double d=1; int i=1;
d=d + i; i=d + i;
Мөн Си хэлэнд бусад программчлалын хэлний нэгэн адилаар арифметик, логик, харьцуулах, нэмэгдүүлэх ба хорогдуулах, битийн гэх мэт үйлдлүүдийг ашиглаж болно.
Тухайлбал, арифметик *(үржих), /(хуваах), +(нэмэх), -(хасах), гэсэн үйлдлүүдийг хэрэглэнэ. Мөн %(үлдэгдэл олох) үйлдэл байдаг. Энэ % оператор нь зөвхөн бүхэл тоонуудын хооронд дээр хийгддэг үйлдэл юм. Жишээлбэл:
int i=10, j=3, n;
double x=2. 0, y;
y=x * I; /*y=20.0*/
n=i / j;    /*i-г j-дхуваахад гарах бүхэл хэсэг*/
n=i % j;  /*i-г j-д хуваахад гарах үлдэгдэл*/
Дээрх үйлдлүүдийн үр дүн нь:
y=20.0
n=3 ()
n=1 ()
b.    Нөхцөл шалгах оператор
Нөхцөл шалгах оператор нь идентификаторын утгаас хамаарч ялгаатай үйлдэл хийдэг оператор юм.
Нөхцөл шалгах оператор нь дараах хоёр хэлбэртэй байна. Үүнд:
1.    if (<логик нөхцөл>) <үйлдэл>;
2.    if (<логик нөхцөл>) <үйлдэл1>;
else <үйлдэл2>;
Эхний хэлбэрийг нөхцөл шалгах операторын хураангуй хэлбэр, хоёрдугаар хэлбэрийг дэлгэрэнгүй хэлбэр гэнэ.
<логик нөхцөл>- д шалгах нөхцөл байна. Энэ нь энгийн нөхцөл байхаас гадна нийлмэл нөхцөл байж болдог. Нийлмэл нөхцөлүүд логик холбоос болох && (and, ба), // (or, буюу)-уудаар холбогдсон байх ёстой. Мөн ! (not, үгүйсгэл) операторыг ашигласан логик нөхцөл байж болно.
Нөхцөл шалгах операторын хураангуй хэлбэрт шалгаж байгаа логик нөхцөл биелж байвал <үйлдэл> хийгдэж биелэхгүй бол нөхцөл шалгах операторын дараагийн мөр биелэн программ үргэлжлэх болно. Харин дэлгэрэнгүй хэлбэрийн хувьд шалгаж байгаа <логик нөхцөл> биелж байвал <үйлдэл1> хийгдэх ба биелэхгүй бол <үйлдэл2> биелэх болно. <үйлдэл>, <үйлдэл1>, <үйлдэл2> -т хоёр юмуу түүнээс олон үйлдэл хийж байгаа бол үйлдлүүдийг Си хэлний нэгтгэх оператор { } –оор хашиж өгнө.
Жич: Ер нь Си хэлний нөхцөл шалгах үйлдэл нь тухайн илэрхийлэл 0-оос ялгаатай бол нөхцөл биелж байна, 0-тэй тэнцүү бол нөхцөл биелэхгүй байна гэж тооцдог. Иймээс         if (a!=0) гэсэн нөхцөл шалгах үйлдэл нь if (a) гэсэн нөхцөл шалгах үйлдэл ижил юм.
Жишээлбэл: өгөгдсөн x тоо, 0-тэй тэнцүү эсэхийг тогтооход нөхцөл шалгах операторыг ашиглахдаа дараах хэлбэрээр бичиж болно.
if (x) printf (“х тоо 0-тэй тэнцүү”);
  else printf (“х тоо 0-тэй тэнцүү биш”);

c.    Сонголтын оператор
Сонголтын оператор нь нөхцөл шалгах оператортой төстэй. Гэхдээ зөвхөн бүхэл төрлийн илэрхийллийн үр дүнгийн утгаас хамаарч хэд хэдэн үйлдлээс аль нэгийг сонгон биелүүлэхэд энэ операторыг хэрэглэнэ.
Сонголтын оператор мөн хураангуй болон дэлгэрэнгүй гэсэн хоёр хэлбэртэй байна. Үүнд:
a.
switch (<илэрхийлэл>) {
case <утга1>: <үйлдэл1>; break;
case <утга2>: <үйлдэл2>; break;
case <утга3>: <үйлдэл3>; break;
… …
case <утгаN>: <үйлдэлN>;
}
b.
switch (<илэрхийлэл>) {
case <утга1>: <үйлдэл1>; break;
case <утга2>: <үйлдэл2>; break;
case <утга3>: <үйлдэл3>; break;
… …
case <утгаN>: <үйлдэлN>; break;
default: <үйлдэл>;
}
Энд switch, case, default, break нь сонголтын операторын түлхүүр үгүүд. <илэрхийлэл>- бүхэл тоон эсвэл тэмдэгт төрлийн үр дүнтэй байх илэрхийлэл.
<утга1>, <утга2>, ... , <утгаN> нь илэрхийллийн утгаас хамаарч биелэгдэх үйлдэл. Эдгээр нь хоорондоо ялгаатай утгууд байх ёстой. Хэрэв эдгээр утгуудаас нэг нь <илэрхийлэл>- ийн үр дүн болж чадахгүй бол default-ийн ард байгаа <үйлдэл> биелэх болно. Харин default байхгүй бол сонголтын операторын дараагийн үйлдэл биелэн программ үргэлжлэх болно.
<үйлдэл1>, <үйлдэл2>, ... , <үйлдэлN>-д хоёр болон түүнээс дээш үйлдэл хийж байгаа бол тэдгээрийг Си хэлний Нэгтгэх оператор { }-оор хашиж өгнө. Мөн Си хэлэнд сонголтын үйлдлүүдийн ард break операторыг бичихгүй бол тухайн биелсэн үйлдлээс хойш орших бүх case операторын хойно орших үйлдлүүдийг биелүүлэх болно. Иймээс break оператор тухайн үйлдэл биелсний дараа switch операторын үйл ажиллагааг дуусгах үүрэгтэй хэрэглэдэг юм.
d.    Давталтын операторууд
Программчлалын аль ч хэлэнд нэг үйлдлийн хэд хэдэн удаа давтан гүйцэтгэх үйлдэлтэй бодлого нилээд элбэг тохиолддог. Үүнийг давталтын операторын тусламжтайгаар гүйцэтгэнэ. Давталтын операторын нөхцөлт ба параметрт оператор гэж хувааж болно. Нөхцөлт давталтыг эхэндээ нөхцөлтэй, төгсгөлдөө нөхцөлтэй гэж хуваан үздэг.
                                          i.    Эхэндээ нөхцөлтэй давталтын оператор
while (<логик нөхцөл>)
<үйлдэл>;
Энэ дэвталтын оператор нь <логик нөхцөл> биелж байх үед доторх <үйлдэл>-ийг гүйцэтгэж, харин <логик нөхцөл> бищлэхээр болимогц давталтын үйл ажиллагааг дуусдаг. Энэ давталтын операторыг давталтад хийгдэх үйлдэл хэдэн удаа хийгдэх нь тодорхойгүй үед хэрэглэнэ. Өөрөөр хэлбэл ямар нөхцөл




биелж байх үед давталт хийх нь тодорхой боловч давталт хичнээн удаа хийгдэх нь мэдэгдэхгүй үед ашигладаг.
Харин давталт доторх <үйлдэл>-д хоёр болон түүнээс олон үйлдэл хийх аваас тэдгээр үйлдлүүдийг Си хэлний нэгтгэх оператор { }-д хийж өгдөг.
<логик нөхцөл> нийлмэл байж болно. Энэ үед логик нөхцөлүүд &&, // холбоосуудаар холбогдсон байна. Мөн ! операторыг ашигласан логик илэрхийллийг ашиглаж болно.
Жишээ 7.4.1-ээс 20 хүртэлх тоог хэвлэх
#include <stdio.h>
int c;
int main ( ) {
/* 1-ээс 10 хүртэлх тоог хэвлэх*/
c=1;
while (c <=10)
{
print (“% d”, c);
c++;
}
return 0;
}
Программын үр дүн:
1 2 3 4 5 6 7 8 9 10
Энэ программ доторх давталтыг for давталтын оператороор хийх нь илүү тохиромжтой юм. Учир нь эхлэх утга, алхам болон хүрэх утга мэдэгдэж байна.
                                        ii.    Төгсгөлдөө нөхцөлтэй давталт
do {
<үйлдэл>
} while (<логик нөхцөл>);
Энэ давталтын оператор нь мөн л <логик нөхцөл> биелж байх үед давталт доторх <үйлдэл>-ийг гүйцэтгэж, харин нөхцөл биелэхээ болимогц давталтаас гарч давталтын операторын дараагийн үйлдэлд программын удирдлага шилждэг. Энэхүү оператор нь мөн л давталтыг хийх нөхцөл мэдэгдэж байгаа боловч давтан гүйцэтгэх үйлдлийн тоо тодорхойгүй байгаа үед ашигладаг. Уг давталтын эхэндээ нөхцөлтэй давталтаас ялгарах онцлог нь давталтад хийгдэж байгаа <үйлдэл> ядаж нэг удаа заавал хийгддэгт оршино. Учир нь эхлээд давталт доторх үйлдлээ хийсний дараа <логик нөхцөл>-өө шалгадаг. Нөхцөл биелж байвал <үйлдэл>-ийг гүйцэтгэсний дараа <логик нөхцөл>-ийг шалгах гэх мэтээр ажиллана. <логик нөхцөл> нийлмэл байж болох бөгөөд &&, // логик холбоосуудаар холбогдсон, мөн логик нөхцөл ! (үгүйсгэл) операторыг хэрэглэсэн байж болно.
Уг операторын дотор нэгээс олон үйлдэл хийж байгаа бол тэдгээрийг нэгтгэх операторт хийх ёстой. Гэхдээ ямар ч үед нэгтгэх операторыг хэрэглэх нь тохиромжтой байдаг.


Жишээ 7.7. Өгөгдсөн хоёр тооны ХИЕХ-ийг олох бодлогыг төгсгөлдөө нөхцөлтэй давталтын оператор ашиглан бодъё.
#include <stdio.h>
main ( ) {
      int r,m,n;
      printf (“n=”); scanf (“%d”,&n)
      printf (“m=”); scanf (“%d”,&m)
      do {
      if (n>m) n=n-m;
      else if (n<m) m=m-n;
      } while (n-m);
      printf (“ХИЕХ нь”<<m<<end1;
      }
      Программын үр дүн:
      n=50
      m=10
      ХИЕХ нь 10
Энэхүү бодолтод нөхцөлөө төгсгөлдөө шалгаж байгаа учраас n, m тоонууд тэнцүү байхад ялгаврыг олох үйлдлээс сэргийлж нөхцөл шалгах үйлдлийг 2 удаа ашигласан байна. Энэ нь уг давталтын эхэндээ нөхдөлтэй давталтаас ялгарах онцлогийг харуулж байна.
                                       iii.    Параметр давталт ( for )
for (<анхны утга ойлголт>; <логик нөхцөл>; <утгын өөрчлөлт>) <үйлдэл>;
параметр давталтын хаалтад гурван илэрхийлэл бичигдэх бөгөөд тэдгээр
нь хоорондоо цэгтэй таслал ( ; ) –аар тусгаарлагдсан байна.
for давталтын операторын <анхны утга олголт> хэсэгт давталтад хэрэглэгдэх параметрт анхны утга олгодог. Энэ хэсэгт хоёр болон түүнээс олон хувьсагчид анхны утга олгосон байж болно. Тэр тохиолдолд уг үйлдлүүдийн хооронд таслал ( , ) –аар зааглаж бичнэ. Мөн энэ хэсэгт нэг ч үйлдэл хийгээгүй байж ч болдог.
<логик нөхцөл> хэсэгт давталтын параметр хувьсагчийн хангаж байх энгийн болон нийлмэл логик нөхцөл байх ба логик нөхцөл нийлмэл бол && <and>, // (or) гэсэн холбоосуудаар холбогдсон, мөн ! (үгүйсгэл)-ийг ашигласан байж болно. Ерөнхийдөө логик илэрхийллийн утга үнэн буюу 0-ээс ялгаатай бол давталт хийгдэнэ. Мөн энэ хэсэг хоосон байх тохиолдол байдаг.
<утгын өөрчлөлт> хэсэгт давталтад хэрэглэж байгаа хувьсагчийн утгын өөрчлөлтийн үйлдлийг бичнэ. Параметр хувьсагчийн утга нэмэгдэж эсвэл хорогдож өөрчлөгдөх ёстой. Энэ хэсэгт хоёр үйлдлүүдийг таслалаар ялгаж өгнө. Мөн энэ хэсэг хоосон байж болдог.
for давталтын оператор дотор хийгдэх <үйлдэл> нэгээс олон үйлдлээс тогтож байгаа бол тэдгээрийг Си хэлний нэгтгэх операторт хийж өгнө.
Давталтын операторуудын хэрэглэ
                                       iv.    break оператор
Программд break оператор нь нөхцөл шалгах, сонголтын болон давталтын оператуудтай хамт хэрэглэгддэг. Өөрөөр хэлбэл, break оператор нь зөвхөн do8 for8 while8 switch операторуудын дотор хэрэглэддэг. Энэ операторын үүрэг нь дээрх операторуудын биелэлтийг тасалж программын удирдлагыг дараагийн операторт шилжүүлэхэд оршино. Хэрэв эдгээр операторуудын гадна бичвэл компилятор түүнийг алдаанд тооцох болно.
Жишээ 8.1. Доорх жишээнд break операторыг хэрхэн ашиглахыг харуулав.
#include <stdio.h>
char s [ ] = “Энэ бол жишээ. Энд хоёр өгүүлбэр байна”;
main ( ) {
      int c;
      printf (“\ n Тэмдэгт мөрийн утга: % s”, s);
      for (c=0; s[ c ]!=’ \ 0’; c++) {
      if (s [ c ] = = ‘.’)
      {
      s [ c+1 ] = ‘\0’;
      break;
      }
}
printf (“\n Мөрийн өөрчлөгдсөн утга: % s\n”, s);
return 0;
}
Программын үр дүн:
Тэмдэгт мөрийн утга: Энэ бол жишээ. Энд хоёр өгүүлбэр байна.
Мөрийн өөрчлөгдсөн утга: Энэ бол жишээ.
                                        v.    continue оператор (үргэлжлүүлэх)
continue оператор нь do, for, while циклийн операторуудтай хамтарч ажиллана. Дээрх циклийн операторууд дотор continue бичигдсэн бол уг операторын дараагийн үйлдлүүд биелэгдэхгүй. do, while циклийн операторт continue ашиглах үед continue-гийн дараагийн алхам илэрхийллийг бодохоос эхэлнэ.
Жишээлбэл:
int x;
printf (“1-ээс 10 хүртэлх тэгш тооны нийлбэр \n”);
for (x=1; x<=10; x++) {
      if (x % 2!=0) /*сондгой тоо*/
      continue; /*давталтын эхэнд удирдлага шилжих*/
      print (“\n % d”, x);
}
Энэ жишээнд хэрэв x тоо сондгой тоо бол программын удирдлага continue оператороор for давталтын эхлэл рүү шилжиж байна.
                                       vi.    goto оператор
Бичигдэх хэлбэр нь:
goto <тэмдэгт>;
..............
<тэмдэгт>:<оператор>
goto оператор нь <тэмдэг>-ээр эхэлсэн мөр рүү программын удирдлагыг шилжүүлнэ. Энэ операторыг ашиглахдаа дараах хоёр шаардлагыг харгалзан үзэх хэрэгтэй. Үүнд:
Ø  <тэмдэг> болохоор хэрэглэж байгаа идентификатор нь тухайн функцийн бусад идентификатороос ялгаатай байх ёстой.
Ø  goto оператор нь өөр функцээс удирдлага шилжүүлж чадахгүй.
<тэмдэг>-ээр эхэлсэн оператор нь goto оператор биелсний дараа гүйцэтгэгдэх болно. goto операторын ард ганц <тэмдэг> бичигдэх бөгөөд мөн <тэмдэг>-ээр эхэлсэн олон мөр байвал алдаа өгдөг. goto операторыг давталтаас гарах, нөхцөл шалгах болон сонголтын оператор дотор хэрэглэж болно.


                                     vii.    return оператор
return оператор нь программыг төгсгөх буюу функцийн утгыг буцаадаг. Хэрэглэгдэх хэлбэр нь :
return [<төгсгөх утга>];
эсвэл
return [<буцах утга>];
Энэ операторын ард 0 гэж өгөхөд энэ мөрийг биелүүлснээр программ энгийнээр төгсдөг. Хэрэв функц утга буцаахгуй (void төрлийн бол) бол return операторыг бичихгүй байж болох ба бичсэн тохиолдолд буцах утга бичдэггүй. Өөрөөр хэлбэл:
return;
хэлбэртэйгээр бичих хэрэгтэй болдог. Энэ операторын хэрэглээ нь хэрэглэгчийн функцийг үзэх үед тодорхой болно.

3.            Стандарт функц процедурууд
a.    Программын оролт, гаралт, console, stdio.h сан , оролт гаралтын функцууд, тусгай тэмдэгтүүд, хэвшүүлэгч тэмдэгтүүд
Дэлгэц ба гар нь компьютерт мэдээллийг оруулах гаргах үндсэн төхөөрөмжүүд бөгөөд тэдгээрийг стандарт оролт гаралт гэж хэлдэг. Программын үр дүнг дэлгэц дээр хэвлэн харуулахын тулд стандарт оролт гаралтын сангийн scanf, printf функцийг ашиглана. Си программд стандарт оролт гаралтыг санг stdio.h гэж нэрлэдэг.
Тухайлбал: int term=15;
                        Printf(“%d*2=%d”,term,term*2);
гэсэн программын хэсэг нь дэлгэц дээр 15*2=30 гэсэн мэдээллийг хэвлэх болно. Энд %d тэмдэгтийг оруулагч тэмдэгт гэх ба функцын эхний параметрт бичигдсэн үг нь орлуулагч тэмдэгтийг эс тооцвол нэг бүрчлэн хэвлэгдэнэ. Гэхдээ энд орлуулагч тэмдэгтийг ашигласан, учраас % санийн утга нь эхний %d-ийн байранд 2*term-ийн утга нь дараагын %d-ийн байранд орлуулагдан хэвлэгдэх болно.
 Printf функц /гаралтын/
            Мэдээллийг хэвлэх printf функцийн бичигдэх ерөнхий хэлбэр нь дараах байдалтай       
printf(“format”,expression1,expression2,..);
Энд format нь юуг яаж хэвлэхийг заах бол expression1, expression2 нь орлуулагч тэмдэгтийн оронд ямар элементүүд хэвлэгдэхийг заана.
                 Puts функц
Puts функц нь өгөгдсөн текст мөрийг стандарт гаралт руу хэвлэнэ. Энэ функц нь стандарт оролт гаралт stdio.h сан дотор байрладаг. Puts функц нь текст мөрийг хэвлэхдээ шинэ мөрийн тэмдэгтийг оруулж хэвлэдэг. ‘\n’


Функцийн бичигдэх ерөнхий хэлбэр нь: puts(“текст мөр”); гэсэн хэлбэрт байна.
scanf/ Өгөгдлийг оруулах функц/
Стандарт сангийн scanf функцын тусламжтайгаар өгөдлийг оруулах бөгөөд энэ функц нь printf-тэй ижил зарчимаар ажилладаг. Scanf функц нь өгөгдлийг хялбар оруулах боломж олгодог.
             Scanf функцын бичигдэх ерөнхий хэлбэр нь:
scanf(”оруулагч тэмдэгт”,&хувьсагчийн нэр);  &-ampersand
Хэвлэгдэх тусгай тэмдэгтүүд
Курсор гэдэг нь компьютерийн дэлгэц дээр оролтын байрлалыг харуулах заагуур юм. Си хэл нь курсорын байрлалыг удирдах тусгай тэмдэгтүүдтэй байдаг бөгөөд тэдгээрийг escape тэмдэгтүүд гэж нэрлэдэг.
Escape тэмдэгтүүд нь урвуу налуу зураасаар             (\) бусад тэмдэгтхрсүүдээс ялгагдана.
            \b         курсорыг нэг тэмдэгтээр буцаах
            \f          шинэ хуудасны эхлэлд шилжих
            \n         дараагын шинэ мөрт шилжих
            \r          тухайн мөрийн эхэнд шилжих
            \t          догол мөр үүсгэх

хэвшүүлэгч  тэмдэгтүүд:
            %d      бүхэл тоо
            %i        бүхэл тоо
            %c       тэмдэг
            %s       тэмдэгт мөр /\0-ээр төгссөн тэмдэгтүүдийн дараалал/
            %f       бодит тоо
            %g      бодит тоо
Хувьсагчийн нэрний өмнө &-ийн тэмдгийг заавал бичиж хаягийг заах хэрэгтэй.
scanf функцээр заасан хувьсагчийн утгыг өөрчлөх боломжийг олгодог.
·         Printf( ) функцууд нь дараах хувилбарууд өргөн хэрэглэгдэнэ. Үүнд :
 int cprintf(const char *format[,argument,….]); - MSDOS-ын орчинд тодорхой загвартайгаар хэвлэх үед хэрэглэх ба conio.h санд  тодорхойлогдсон байдаг.
int fprintf(FILE*stream, const char *format[, argument,…] );-мэдээллийг файлд бичих
int sprintf(char*buffer, const char*format[,argument,….]); -‘\0’ –ээр төгссөн тэмдэгт мөрийг буферт бичих.
Printf( ), fprintf( ), sprint( ) гаргах функцуудын параметр дэхь format хэлбэршүүлэх мөр нь дараах хэлбэртэй байна. %[флаг][хэвлэх_өргөн][.бутархай_o_m][ h ][ I ][ L ]
·         int scanf(char*format[,address, …]); - MSDOS-ын орчинд тодорхой загвартайгаар мэдээллийг хүлээн авах. Мөн conio.h санд орших бөгөөд cprintf( ) функцын адилаар conio.h сангийн өмнө өгүүлсэн болон бусад функцуудээр загвараа тогтооно.
int fscanf (FILE*stream, const char *format[, address,…] ); - файлаас мэдээлэл унших
int sscanf (const char*buffer, const char*format [, address,…]); буферээс мэдээлэл унших
scanf( ), fscanf( ), sscanf( ), оролтын функцуудын параметр дэхь format хэлбэршүүлэх мөр нь дараах хэлбэртэй байна. . %[*][мэдээллийн_өргөн][ h ][ I ][ L ]
4.            Тэмдэгт мөр төрөлтэй ажиллах
Тэмдэгт мөр нь ASCII тэмдэгтүүдийн дараалал юм. Тэмдэгт мөрийн бичвэр мэдээлэл боловсруулахад ашиглана. Тэмдэгт мөрийг char нөөц үгээр зарладаг. Үүнд:
            char <тэмдэгт_мөрийн_нэр>[<тэмдэгтийн_тоо>];
Си хэлний тэмдэгт мөр NULL (ASCII 0) тэмдэгтээр төгсдөг. Тэмдэгт мөрийн урт 65535-аас хэтрэхгүй. Тэмдэгт мөрийг char төрлийн заагчаар зохион байгуулж болно. Хэлбэр нь:
 
char *(тэмдэгт_мөрийн_нэр);
Тэмдэгт мөртэй string.h сангийн функцуудыг ашиглан ажилладаг.
Жишээ нь:
 char s[10] ;
 Мөр төрлийн хувьсагч санах ойд 256 байт эзэлдэг. Мөрийн тэмдэгтийн тоог (үүнийг мөрийн урт гэдэг.) хязгаарлан өгч зарлаж болно.
 Жишээ нь:
 char a[69], b[13];
 Эдгээр мөр төрлийн урт санах ойд харгалзан 69, 13 байт эзэлнэ. үүнийг sizeof() функцын тусламжтай үзэж болно.
 Мөн тогтмолоор зарлаж болно.
 #define cons 10
 const char c[] = “text”;
 Си хэлний тэмдэгт мөр ASCII0 тэмдэгтээр төгссөн байх ёстой. Хэрэв тэмдэгт мөр ASCII0 тэмдэгтээр төгсөөгүй бол мөрийг хэвэлэхэд санах ойн үүрэнд байрлах замбараагүй олон тэмдэгтийг хэвлэх болно. С хэлэнд тэмдэгт мөр 65535 байт урььай байж болно. Тэмдэгт мэрд тогтмол улга ологох, эсвэл стандарт оруулах төхөөрөмжөөс утга олгох үед түүний төгсгөлд автоматаар ASCII0 тэмдэгт бичигдэх болно.
 Жишээ нь:
 char s[20]=”Ulaanbaatar”;
 Нэгэнт тэмдэгт мөр маань шугаман массив хэлбэртэйгээр зохион байгууллагддаг болохоор түүний элементүүдэд  индекслэн хандаж болно. Жишээ нь: нь S тэмдэгт мөрийн эхний элемент S[0] буюу утга нь ‘U’ байна.
 Мөр төрлийн хувьсагчид утга олгохдоо утгыг заавал апострфоор хааж өгнө.
 Жишээ нь:
 #include <stdio.h>
 #include <conio.h>
 #define cons 10
 const char c[] = “text”;
 main()
 { const char MSG[]=”input word :”; char a[50];
 printf(“%s\n”,c);
 printf(“%s”,MSG); scanf(“%s”,&a);
 printf(“%s”,a);
 getch();
 return 0;}
 Тэмдэгт мөртэй string.h сангийн функцуудыг ашиглан ажилладаг. Тухайлбал
 Заагч төрөл
 Заагч гэдэг нь хувьсагчийн санах ойн хаягийг авдаг. ӨХ санах ойн хаягаар дамжуулан уг хувьсагчид хандаж байгаа хэрэг юм. Заагч нь санах ойн heap мужид оршино. Заагчийг си хэлэнд зарлахдаа хувьсагчийн өмнө од тавьдаг. Заагчийг өх heap ойг програмын явцад үүсгэж мөн устгаж болно. Харин статик хувьсагчийн хувьд энэ нь боломжгүй юм. Хувьсагчийн заагч нь хувьсагчийг, хаягын заагч нь санах ойн хаягийг заана.
 int  *i, *j, *l;
 char *ch;
 float *a;
 Заагчийг ингэж  зарласан үед
 *i- нь тухайн заагчийн агуулж байгаа утга.
 i- г санах ойд байрлаж байгаа хаяг
 Энгийн статик хувьсагчийн хувьд & амтерсантийн тэмдгийг ашиглан санах ойд байрлуулж болно.
 Тодорхойгүй төрлийн заагч буюу (void *) төрлийн хаягийн заагч нь бусад заагчаасаа & тэмдэг ашиглаж хаягыг авдгаараа ялгаатай.
 х нь int төрлийн хувьсагч, p нь заагч төрлийн хувьсагч байг.
 p=&x; үйлдэл нь x-ийн хаягийг p-д олгоно. Харин &(x+1); &3 үйлдлүүд байж болохгүй.
 Учир үйлдэл нь (*) одоор заагчийн утгыг авна. у нь int төрлийн хувьсагч, p нь заагч төрлийн хувьсагч байг.
 p=&x;
 y=*p;
 y=x; //үйлдэлтэй тэнцүү байна.
 Заагчийг илэрхийлэлд ашиглаж болно. Унар (*) ба (&) үйлдлүүд нь бусад арифметик үйлдлүүдээсээ өмнө хийгддэг.  Хэрэв p заагч нь x-ийг зааж байвал *p=0; үйлдэл нь x хувьсагчид тэгийг онооно гэсэн үг юм. Заагч нь доор дурдсан шууд хаяглалуудтай байна.
 Жишээ нь:
 int i, *p;   //i,p-г зарлах
 p=&i; // i- хувьсагчийн хаягийг авна.
 *p=10; // p-ийн үүрэнд 10-г олгоно.
 i=*p; // i-д 10-ийг олгоно.
 Дам хаяглал
 Жишээ нь:
 int i=2; // i-д 2-г олгох
 int *p=&i; // p-ийн үүрэнд i-ийн хаягийг олгоно.
 int **p1=&p; // **p1=2;
 Хягаар дамжих
 int i;
 void *p=&i; // санах ой дахь хаягийг заана.
 Нэг заагчийг өөр заагчид олгох боломжтой.
 Жишээ нь:
 main()
 { int max=5678, *pok1, *pok2;
 pok1=&max; // max-ын хаягыг pok1-д олгоно.
 pok2=pok1; // pok2-д pok1-ийг олгох.
 printf(“%d\n”,*pok1);
 printf(“%d\n”,*pok2);
 }

 Заагчийг харьцуулах
 Заагч нь нэг объектыг зааж байх тохиолдолд хоёр заагчийг хооронд нь харьцуулж болно.
 Жишээ нь:
 main()
 { int x=2, y=1;  // x,y нь int төрөлтэй анхны утга нь 2, 1
 int *p1, *p2;
 p1=&x;
 p2=&y;
 if(p1!=p2) printf(“p1, p2 тэнцүү биш”);
 }
 Заагч хувьсагчийг ашиглан тэмдэгт мөр болон массив бүтцийг зохион байгуулахад тохиромжтой. Мөн хэрэглэгчийн функц дотор глобал хувьсагчийг хувьсах байдлаар ашиглахад хэрэглэж болдог. Заагч хувьсагчийг ашиглан дараах функцуудыг ашиглан зай нөөцөлж мөн устгаж болно. .
 1. sizeof(<төрөл>) эсвэл sizeof(<илэрхийлэл >) төрөл илэрхийлэлийн утгийг тогтооно. Буцах утга нь int байна.
 2. malloc, realloc, calloc эдгээр функцуудын тусламжтайгаар өгөгдсөн хэмжээтэй санах сойг heap мужид нөөцлөнө.
 а. void * (<төрөлгүй заагч>)calloc(<төрөл>)

Тэмдэгт мөрийг хуулах.
1. char *strcpy(char *dest, const char *src);   Үүрэг: src тэмдэгт мөрийн утгыг dest тэмдэгт мөрд хуулна. Буцаах утга: dest заагчийн зааж байгаа санах ойн хаягийг буцаана. Алдаа гарсан бол NULL утга буцаана.
Бодлого-1. Өгөгдсөн тэмдэгт мөрийг өөр тэмдэгт мөрүүд рүү хуул.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
char source[]="Computer Information Tehnologe." ;
main()
{ char dest1[80];
  char *dest2, *dest3;
printf("\nAnkh ugugdsun mur: %s", source);
  strcpy(dest1, source);                    /* dest1 ruu source -iin utgiig huulna */
printf("\n\n Huulagdsan mur 1: %s", dest1);
  dest2=(char *) malloc(strlen(source)+1);            /* dest2 -d source -iin hemjeegeer sanah oi huvaarilna */
  strcpy(dest2, source);                    /* dest2 ruu source -iin utgiig huulna */
printf("\n\n Huulagdsan mur 2: %s", dest2);
  getch();
  return 0;
}


2. char *strcpy(char *dest, const char *src, size_t maxlen);           Үүрэг: src тэмдэгт мөрийн эхний n ширхэг тэмдэгтийг dest тэмдэгт мөрд хуулна. Буцаах утга: хуулагдсан мөрийн байрлаж байгаа dest -ийн хаягийг буцаана. Хуулалтын төгсгөлд dest тэмдэгт мөрийн төгсгөлд NULL (ASCII 0) тэмдэгтийг бичнэ.


Тэмдэгт мөрийн урт.
3. size_t strlen(const char *s);    Үүрэг: s тэмдэгт мөрийн уртыг буцаана.
Тэмдэгт мөрийг залгах.
4. char *strcat(char *dest, const char *src);    Үүрэг: dest тэмдэгт мөр дээр src тэмдэгт мөрийг залгана. Буцаах утга: dest тэмдэгт мөрийн хаягийг буцаана. Үр дүн strlen(dest)+strlen(src) урттай байна.
5. char *strncat(char *dest, const char *src, size_t maxlen);          Үүрэг: dest тэмдэгт мөр дээр src тэмдэгт мөрийн эхний maxlen ширхэг тэмдэгтийг залгаж төгсгөлд нь NULL тэмдэгт хийнэ. Буцаах утга: dest тэмдэгт мөрийн эхлэх хаягийг буцаана. Үр дүн strlen(dest)+maxlen урттай байна.
Тэмдэгт мөрд хайх.
6. char *strchr(char *s, int c);       Үүрэг: s тэмдэгт мөрийн эхнээс c тэмдэгтийг хайж, олдвол түүний хаягийг, олдохгүй бол NULL утга буцаана.
Бодлого-2. Өгөгдсөн тэмдэгт мөрөөс өгөгдсөн тэмдэгтийг хай.
#include <stdio.h>
#include <string.h>
#include <conio.h>
main()
{ char *loc, buf[80];
  int ch;
  printf("Temdegt muruu oruul : "); gets(buf);                                            /* ulaanbaatar */
  printf("\nTemdegt muruus haih temdegtee oruul : ");    /* b */
  ch=getchar(); loc=strchr(buf, ch);
  if (loc==NULL) printf("\nTemdegt murd %c temdegt baihgui. ",ch);
                        else { printf("\nTemdegt muriin %d-r bairlald %c temdegt baina.",       loc-buf, ch);
          printf("\n\nButsaasan mur : %s\n", loc);
                               }
  getch();
  return 0;
}
7. char *strstr(char *s1, const char *s2);          Үүрэг: s1 тэмдэгт мөрөөс s2 тэмдэгт мөрийг хайж, олдвол түүний хаягийг, олдохгүй бол NULL утга буцаана.

Тэмдэгт мөрийг харьцуулах.
8. int *strcmp(const char *s1, const char *s1);           Үүрэг: s1, s2 тэмдэгт мөрүүдийг эхний тэмдэгтээс нь эхлэн харьцуулж, s1<s2 бол сөрөг, s1>s2 бол эерэг, s1==s2 бол 0 утга буцаана.
Бодлого-3. Өгөгдсөн тэмдэгт мөрийг палиндром эсэхийг тогтоо.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
char *hurvuul(const char *s)
{ char *tmp;
  int n=strlen(s);
  tmp=malloc(n)+1;
  for (int i=n-1; i>=0; i--) tmp[n-i-1]=s[i];
  tmp[n]=NULL
}
main()
{ char s[100], t[100];
  printf("Temdegt muruu oruul : "); scanf("%s",s);            /* naran */
  strcpy(t, hurvuul(s));
  if (strcmp(t,s)==0) printf("\nPalindrom : %s = %s \n", t, s);
                        else printf("\nPalindrom bish : %s <> %s \n", t, s);
  getch();
  return 0;
}
 Ýëåìåíòèéã íýìýõ áîëîí óñòãàõ ¿éëë¿¿ä íü îðîé ãýæ íýðëýãäýõ íýã òàëààñàà õèéãääýã òîãòöûã ñòåê ãýíý. Стектэй ажиллах стекийн оройд заадаг ерөнхий заагч-top, стект элэемэнт нэмэх ба устгах хэрэглэх нэмэлт заагч-p тус тус хэрэглэнэ. 


5. Хэрэглэгчийн функц
Хэрэглэгчийн функц нь програмын биеэ даасан нэг хэсэг бөгөөд нэг нэртэй хоорондоо уялдаа холбоо бүхий үйлдлүүдийн дараалал юм. Хэрэглэгчийн функц нь програмын зохион байгуулалтыг сайжруулж өгдөг. Тухайлбал, програмд нэг хэсэг үйлдэл олон дахин хэрэглэгдэж байвал тэдгээрийг бүлэглэн нэр өгч функц болгон бичээд шаардлагатай хэсэгт нэрээр нь дуудан ашигладаг.
Функцийн зарлах хэлбэр:
<буцах утгын төрөл> <функцийн нэр>(<параметрүүд>)
{
<үйлдэлүүд>;
return <буцах утга>;
}
·         <буцах утгын төрөл> гэдэгт функц ажилласны дараа функцийг дуудсан газарт утга болгон буцаах утгын төрөл байна. Функцийн буцах утгын төрөлд үндсэн төрлүүд байхаас гадна заагч, бүтэц, тэмдэгт мөр байж болно. Мөн утга буцаадаггүй функц байж болох ба энэ үед буцах утгын төрөл нь void байна.
·         <функцийн нэр>-д латин үсэг эсвэл латин үсгээр эхэлсэн цифр оролцсон үг байж болно.
·         <параметрүүд> гэдэгт функцэд дамжих хувьсагчийг эсвэл утгыг төлөөлөх хувьсагчууд төрлийн хамтаар зарлагдсан байх ёстой.
·         Функц нь биеэ даасан үйлдэлүүдийн багц учраас түүн дотор үйлдэл хийгдэнэ.
·         <буцах утга> гэдэгт функцийн буцах утгын төрөлд тохирох хувьсагч эсвэл тогтмол утга байна. Си хэлэнд буцах утгыг return нөөц үгийн тусламжтайгаар буцаана.

Бодлого1. n элементээс k-р зохиосон хэсэглэлийн тоог ол.
Бодлогыг бодохын тулд n!, k!, (n-k)!-ийг тус тус бодох шаардлагатай. Иймд факториал бодох функц зохиож ашиглая.
#include<stdio.h>
#include<conio.h>
long int fac(int x)
{int i;
 long int s=1;
 for(i=1;i<=x;i++)s*=i;
 return s;
}
void main()
{int n,k,m;
printf("n ba k toog oruul");scanf("%d%d",&n,&k);
m=fac(n)/(fac(n-k)*fac(k));
printf("%d-s %d-r zohioson heseglel ni:%d",n,k,m);
getch();
}

Бодлого2. Өгөгдсөн тооны хөрвөсөн тоог буцаах функц ыүхий програм бич.
#include<stdio.h>
#include<conio.h>
typedef unsigned long ulong;
ulong urvuu(ulong x)
{ulong y;
 while(x!=0){y=y*10+x%10;
             x=x/10;}
 return y;
}
void main()
{ulong n;
printf("n toog oruulna uu?"); scanf("%d",&n);
printf("ugugdsun toonii hurvusun too ni:%d",urvuu(n));
getch();
}
Бодлого3. Өгөгдсөн 2 натурал тооны аль нь олон цифртэйг ол.
#include<stdio.h>
#include<conio.h>
int tsifr(long int y)
{int s=0;
 long int x=y;
 while(x!=0){s=s+1;
             x=x/10;}
 printf("\n%d toonii tsifriin too ni:%d",y,s);
 return s;
}
void main()
{long int n,m;
 int a,b;
printf("\n2 toog oruulna uu?"); scanf("%d%d",&n,&m);
a=tsifr(n); b=tsifr(m);
if(a==b)printf("\n2 too tentsuu toonii tsifrtei");
if(a>b)printf("\n%d too olon tsifrtei",n);
else printf("\n%d too olon tsifrtei",m);
getch();
}
Бодлого4. 2 тооны ХИЕХ-ийг олох функц зохиогоод 4 тооны ХИЕХ-ийг ол.
#include<stdio.h>
#include<conio.h>
int hieh(long int y,long int x)
{int s;
 while(x!=0 && y!=0){if(x>=y)x=x%y;
                     else y=y%x;}
 s=x+y;
 return s;
}
void main()
{long int a,b,c,d;
 int m;
printf("\n4 toog oruulna uu?"); scanf("%d%d%d%d",&a,&b,&c,&d);
m=hieh(hieh(hieh(a,b),c),d);
printf("\nHIEH ni:%d",m);
getch();
}
.
а. Утга буцаахгүй функц
Хэрэглэгчийн зохиосон функцыг утга буцаахгүй байхаар зохион байгуулж болох ийс хэлбэрийн функц дараах хэлбэртэй байна. Үүнд:
void функц_нэр(параметрүүд){
<функц_код>;
return;
}
void түлхүүр үг нь функц утга буцаахгүй болохыг илэрхийлэх бөгөөд ийм функцын код утга буцаадаггүй учраас return түлхүүр үгийг агуулаагүй эсвэл return ардаа утга аваагүй хоосон бичигдэнэ.
  б.Локаль ба глобал хувьсагч, хувьсагчийн амьдрах муж
Си хэлэнд хувьсагчийг тодорхойлохдоо програмын эхэнд (толгой файлуудыг хавсаргасны дараа) эсвэл функцын эхэнд тодорхойлж өгдөг.  Програмын эхэнд торхойлсон хувьсагчууд нь main() функц ажиллаж эхлэх үед үүсэх ба програмын аль ч хэсэгт дуудан ашиглаж болохоос гадна хамгийн сүүлд олгосон утга хадгалагдаж байдаг. Ийм хувьсагчийг глобал хувьсагч гэнэ. Харин функц дотор тодорхойлогдсон хувьсагчийг дотоод буюу локаль хувьсагч гэнэ. Ийм хувьсагч нь тухайн функц дуудагдан ажиллах үед санах ойд үүсэх бөгөөд тухайн функц дотор ашиглагдаж, функц үйл ажиллагаагаа дуусгах үед санах ойгоос устдаг.
Жишээ нь.:
Ulong horovson(ulong l)
{ulong n=0; /локаль хувьсагч/
}
Int togs(int k){
Int i=1,s=0;/локаль хувьсагчууд/
}

б.auto хувьсагч
Функц дотор  тодорхойлогдсон хувьсагч нь auto хувьсагч юм. Хэдийгээр ийм хувьсагчийн өмнө auto түлхүүр үгийг тавиагүй байсан ч  түүнийг auto хувьсагч хэмээн компилятор тодорхойлдог. Өөрөөр хэлбэл функц дотор тодорхойлогдсон auto хувьсагч нь локаль хувьсагч бөгөөд ийм хувьсагчийн функцийг гадна хэрэглэх боломжгүй байдаг. Auto хувьсагчийг  Си хэлний дурын дэд блок дотор тодорхойлж болох бөгөөд тухайн блок эхлэх үед үүсэж, блок дотроо хэрэглэгдээд, блок төгсөхөд санах ойгоос устдаг.
Auto  хувьсагчийн хэрэглээн харуулсан жишээ:
#include<stdio.h>
main(){
int t,n;
scanf (“%d”,&n);
for(t=1;t<n;t++) {
printf(“\n\n”);
auto int r=5; /*for давталтын доторх авто хувьсагч/
printf(“%5i&10i\n”,t,r++);
}
printf(“%i”,r); /Алдаа r хувьсагч зарлагдаагүй. for-ийн гадна  /
return 0;

в.register хувьсагч
Програмын хувьсагчууд компьютерийн шуурхай санах ойд хадгалагдана. Харин register хувьсагч нь компьютерийн төв процессорын регистрт хадгалагдах ба ийм хувьсагчтай програм  санах ойд хадгалснаас илүү хурдан ацилладаг. Бусад талаараа register хувьсагч auto хувьсагчтай адилхан. Өөрөөр хэлбэл зөвхөн тодорхойлогдсон муждаа л ашиглагдах локаль хувьсагч байдлаар хэрэглэгдэнэ.
Register хувьсагчийн хэрэглээг харуулсан жишээ
#include<stdio.h>
main(){
 register int r=5;
printf(“i%10i\n”,*p);
int *p=&r; /* register хувьсагчийн хаягийг р заагчид олгох/
printf(“5i\n”,*p);
scanf(“*%d”);
return0;
}

г.static хувьсагч
Статик хэмээх үг нь тухайн зүйл тогтонги, тогтвортой гэдгийг илэрхийлж байдаг. Энэ утгаараа статик хувьсагч нь тухайн орчинд хэрэглэгдэх боловч олгосон газар хадгалсан байснаараа байдаг.
static хувьсагчийн хэрэглээг харуулсан жишээ
#include<stdio.h>
Main(){
Int n,t;
Scabf(“%d”,&n);
For(t=1;t<n;t++)}
Printf(“\n\n”);
Static int r=5; /for давталтын доторх статик хувьсагч/
Printf(“%5i%10i\n”,t,r++);
Return 0;
} Энэ жишээнд  static хувьсагч r давталтад санах ойд нэг л удаа үүсдэгээрээ static хувьсагчаас ялгаатай. Өөрөөр хэлбэл r хувьсагч for давталтыг эхлэх үед нэг удаа санах ойд үүсэх болно.
д.extern хувьсагч
Бүх функц дотор хэрглэхээр зарлагдсан хувьсагчийг гадаад (глобал) хувьсагч гэдэг. Гадаад хувьсагчийг функц дотор зарлаж болох бөгөөд түүнийг зарлахдаа extern түлхүүр үгээр тодорхойлж өгдөг. Жишээ нь:

int i;/бүх функц дотор хэрэглэндэх хувьсагчууд/
char c;
double d;
main(){
extern int I; /дээр тодорхойлогдсон хувьсагчуудыг функц/
extern char c;
extern double d;
}

е.рекурсив функц
Хэрэв алгоритм нь дараах тодорхойлолтыг хангаж байвал рекурсивээр тодорхойлогдсон алгоритм гэнэ.
§  Тодорхойлогдсон параметрийг тооцоолох эсвэл хэд хэдэн төгсгөх нөхцөл
§  Одоогийн тооцоологдох утга нь өмнөх алхамд тооцоологдсон утгуудаар тодорхойлогдох боломжтой рекурсивийн алхам байх
Хамгийн сүүлийн алхам нь түүний төгсгөх нөхцөл байна. Рекурсив алгоритм рекурсив функцеер зохион байгуулагдана. Рекурсив функцийг хэрэглэглэх зарим бодлогыг бодох ажлыг асар их хөнгөвчилдөг. Рекурсив функц өөрөө өөрийгөө дуудах бүрдээ програмын стект-т параметрийн тухайн утгыг хадгалж байдаг. Функцэд тодорхойлогдсон төгсөх нөхцөл биелэх үед стект хадгалсан утгуудаа сүүлд орсон нь эхэлж гарах зарчмаар суллана.төгсгөх нөхцөлийг буруу хийснээс рекурсив төгсгөлгүй давтагдаж програмын стек дүүрэх явдал гарч болно. Функц өөрийгөө эргэн дуудаж байх юм бол үүнийг рекурсив функц гэж нэрлэдэг. Рекурсивийг хэрэглэх нь зарим бодлогыг бодох ажлыг асар их хөнгөвчилдөг. Рекурсив функцийг зохион байгуулахдаа түүнийг төгсгөх нөхцөлийг нарийн тодорхойлж өгөх хэрэгтэй. 
Бодлого1. x-ийн k зэрэгтийг олдог рекурсив функц зохиогоод 1n+2n+...+nn гэсэн нийлбэрийг ол.
#include<stdio.h>
#include<conio.h>
long int zereg(int x,int k)
{
 if(k==0) return 1;
 else return x*zereg(x,k-1);
}
void main()
{int i,n;
 long int s;
printf("n toog oruul");scanf("%d",&n);
for(i=1;i<=n;i++) {printf("%d+",zereg(i,n));s=s+zereg(i,n);}
printf("=%d",s);
getch();
}

}

6.Өгөгдлийн нийлмэл бүтэцтэй төрөл:
6.1. Өгөгдлийн энгийн ба нийлмэл төрлийн ялгаа, Массив, түүн дээр хийгдэх үйлдлүүд. Динамик массив зохион байгуулах бодлогод ашиглах

Ижил төрлийн элементүүдийн төгсгөлөг тооны цуглуулгыг массив гэдэг. Массивыг дотор нь:
v  шугаман массив
v  тэгш өнцөгт массив
v  олон хэмжээст массив гэж 3 хувааж болно. Массивыг С++ хэлэнд:
Ø  Статик
Ø  Динамикаар зохион байгуулж болно. 
1.    Шугаман массив: Шугаман массивыг зарим үед нэг хэмжээст массив, вектор гэх зэргээр нэрлэнэ. Шугаман массив нь дараах хэлбэрээр зарлагдана. Үүнд: <төрөл><массивын нэр>[<элементийн тоо>];
Энд:  <төрөл> массивын элементүүдийн төрөл байх ба си хэлний стандарт өгөгдлийн төрлүүдээс гадна хэрэглэгчийн тодорхойлсон төрөл ч байж болно. <массивын нэр> массивыг програмд төлөөлөх идентификатор <элементийн тоо> массивын элементийн тоо. Массивын элементийн тоог массивын хэмжээ гэдэг. Массивыг зарлахдаа бодлогын зорилгыг хангахуйцаар хүрэлцээтэй хэмжээтэйгээр зарладаг бөгөөд <элементийн тоо1>*<төрлийн санах ойд эзлэх хэмжээ> нь өгөгдлийн сегментийн хэмжээнээс хэтрэхгүй байх ёстой. Жишээ нь:
int a[100],b[20];
Float c[50],l[2];
                        Long l[10],t[5];
                        Char p[20];
Массивын элементэд утга олгох үйлдэл:
a[0]=100; /* а массивын эхний элементэд 100 утга олгох */
a[1]=102; /* а массивын 2дугаар элементэд 102 утга олгох */
a[99]=80; /* а массивын сүүлийн элементэд 80 утга олгох */
с[9]=8.95; /* с массивын 10дугаар элементэд 8.95 утга олгох */
с[44]=0.001; /* с массивын 45 дугаар элементэд 0.001 утга олгох */
a[4]=p[2];
массивын элементийн утга авах үйлдэл:
int t=a[1], u=b[6];
float r=c[9], r1=c[10], t=l[3];
a[4]=p[2];
Мөн массивыг зарлах үед элементүүдэд утга олгож болно.
int IntegerArray[5]={10,20,30,40,50}; эсвэл int IntegerArray[]={10,20,30,40,50};
Массивт утга олгохдоо санамсаргүйгээр утга олгож болно. Үүнийг stdlib.h сангийн rand() функцийн тусламжтайгаар хийж болно. Дараах хэлбэртэй байна.
#include<stdlib.h>
int rand();
Санамсаргүй тоо үүсгэн 0-32767 хүртлэх бүхэл тоон утгаас санамсаргүйгээр нэг тоо сонгон авч буцаадаг ба ямагт үр дүнтэй байна.
Мөн массив төрлийг тодорхойлж болох бөгөөд массив төрлийг дараах хэлбэртэйгээр тодорхойлдог.
typedef int <төрөл><массив_төрөл_нэр>[<элементийн тоо>];
 <массив_төрөл_нэр>_<элементийн тоо> элементтэй массивыг тодорхойлох төрөл
typedef int massiv[100];
massiv t; /*t бүхэл төрлийн 100 элементтэй массив хувьсагч*/
2.    Тэгш өнцөгт массив
Дараах хэлбэртэйгээр зарлагдана. 
<төрөл><массивын нэр>[<элементийн тоо1>][<элементийн тоо2>];
<төрөл> массивын элементүүдийн төрөл байх ба си хэлний стандарт өгөгдлийн төрлүүдээс гадна хэрэглэгчийн тодорхойлсон төрөл ч байж болно.
<массивын нэр> массивыг програмд төлөөлөх идентификатор
<элементийн тоо1> тэгш өнцөгт  массивын мөрийн элементийн тоо
<элементийн тоо1> тэгш өнцөгт  массивын баганын элементийн тоо.
<элементийн тоо1>*< элементийн тоо2><төрлийн санах ойд эзлэх хэмжээ> нь үр дүн өгөгдлийн сегментийн хэмжээнээс хэтрэхгүй байх ёстой.
int a[100][100], r[20][5];
float f[3][3], t[8][4], w[2][90];
char c[7][9];
Тэгш өнцөгт массивын элементтэй ажиллахдаа мөр болон баганы индекс тус бүрийг [ ] хаалтанд бичиж ханддаг. Тэгш өгцөгт массивын элементэд хандахдаа 2 индекс хэрэглэх ба эхний индекс нь мөрийн дугаарыг, хоёрдугаар индекс нь тухайн мөрийн хэддүгээр элемент болохыг өөрөөр хэлбэл баганын дугаарыг заадаг. Мөр баганын индекслэлд хоёудаа 0-ээс эхэлнэ. Шугаман массивын адилаар тэгш өнцөгт массивын элементэд утга олгох, утга авах гэсэн 2 хэлбэрийн хандалт байна. жишээ нь: a[0][0]=9; /* а массивын хамгийн эхний элементэд 9-ийг олгох*/
a[99][99]=800; /* а массивын хамгийн сүүлийн элементэд 9-ийг олгох*/
a[0][99]=4; /* эхний мөрийн хамгийн сүүлийн элементэд 4-ийг олгох*/
c[1][1]=’A’;
int e=a[0][0]+c[1][1];
float fv=f[2][2];
Хэрэв тэгш өнцөгт массивын мөр баганын элементийн тоо тэнцүү бол түүнийг квадрат массив гэнэ.
Массив ба заагч.
Заагч нь өөрийн төрөлтэй ижил төрөлтэй массивийг зааж чаддаг бөгөөд си хэлэнд массив заагч хоёр нь хоорондоо нарийн холбоотой. Ер нь массив бол заагч юм.
Динамик шугаман массив: 
Динамик массив нь заагчийн тусламжтай зохион байгуулагдах бөгөөд програмын явцад хэрэгцээтэй хэмжээтэй массивыг ашиглах боломжыг олгодог. Түүний зарлалт дараах хэлбэртэй байна.
<заагчийн нэр>=(<заагчийн төрөл>*)malloc(<хэмжээ>);
<заагчийн нэр> - өмнө зарлагдсан заагчийн нэр болох идентификатор
<заагчийн төрөл>- заагчийн төрөл.Энгийн болон хэрэглэгчийн тодорхойлсон төрөл
<хэмжээ>- санах ойд хуваарилах хэмжээ буюу массивын элементийн тоо

Динамик массивыг хэрэглэж дуусаад санах ойгоос чөлөөлнө. Үүндээ free() функцийг ашиглана. Мөн дахин санах ойд хуваарилан ашиглаж болно. Жишээ нь:
A[N] массивын эхний i ширхэг элементийн арифметик дунджийг агуулсан B[N] массив үүсгэх бодлогыг динамик массив ашиглан бодов.
#include<stdio.h>
#include<stdlib.h>
main() {
int *a,*b,i,n,s=0;
printf(“n=”);scanf(“%i,&n”);
a=(int*)malloc(n);   /*динамик а массивыг санах ойд хуваарилах*/
b=(int*)malloc(n); /*динамик b массивыг санах ойд хуваарилах*/
for(i=0; i<n; i++) {
a[i]=rand()%1000;
printf(“%i”,a[i]);         }
printf(“\n”);
for(i=0; i<n; i++) {
s+=a[i];
b[i]=s/(i+1);               }
for(i=0; i<n; i++)
printf(“%i”,b[i]);
printf(“\n”);
}  


6.2. Бүтэц төрөл, нэгтгэх оператор, бүтэц төрлийг тодорхойлох, бүтэц төрлийн массивын тухай, бит талбар бүтэц төрлийн аргументтэй функц
 Програм бичнэ гэдэг нь тодорхой даалгаврыг задлан шинжилж, програмчлах шаардлагуудаа тодруулан түүнд зориулсан өгөгдлийн хийсвэр төрөл болон түүн дээр хийгдэх үйлдлүүдийг тодорхойлсоны үндсэн дээр хийгддэг системтэй үйл ажиллагаа юм. Тэгвэл си хэлэнд өгөгдлийн хийсвэр төрлийг бүтцээр зохион байгуулах болно. Бүтэц гэдэг нь төгсгөлөг тооны ижил болон ялгаатай төрөл бүхий элементүүдийг нэгтгэн зарласан өгөгдлийн нийлмэл бүтэцтэй төрөл юм. Бүтэц төрлийг дараах хэлбэртэйгээр тодорхойлно.
struct<бүтцийн нэр> {
<талбарууд>;
} <бүтэц төрлийн хувьсагч>;
<бүтцийн нэр>- бүтцийн нэр болох идентификатор. Бүтцийн нэрийг том үсгээр бүр тодруулбал Т үсгээр эхлэн бичдэг. Энэ нь type буюу төрөл гэсэн үгийн эхний үсэг юм. Гэхдээ энэ нь дүрэм биш юм.
<талбарууд>- бүтцийн гишүүдийг талбар гэдэг. Талбар нь хувьсагчууд бөгөөд стандарт болон хэрэглэгчийн тодорхойлсон төрөл болон нэрээр тодорхойлогдоно.
<бүтэц төрлийн хувьсагч>- бүтэц төрлийн хувьсагч болох идентификатор.
Жишээ нь: struct Tcircle{
                        int x,y,r;
                        } t;
Энэ зарлалтын хувьд Tcircle бүтцийн нэр, x,y,r нь бүхэл төрлийн талбарууд юм. t нь бүтэц төрлийн хувьсагч.
Бүтцийн талбартай ажиллах утга олгох, утгыг унших гэсэн үйлдлүүд байна.
Бүтэц төрлийн массив
Бүтэц төрлийн массив нь дараах хэлбэртэйгээр зарлагдана.
<бүтцийн нэр><массивын нэр> [<элемэнтийн тоо>];
Жишээ нь:   struct Tcircle m[10],q[50][20];
Бүтэц төрлийн массивт хандахдаа массивын индексийн хаалтын ард тэг тавин талбарын нэрийг бичиж хандана. Жишээлбэл:
m[0].x=50; m[0].y=9;  m[0].r=0;
q[49][10].x=m[0].x ;   q[49][9].y=m[0].y  ;    q[49][29].r=4 ;
int p=q[49][9] ;
Бүтэц төрлийн массивд зарлах үедээ утга олгож болно. Жишээлбэл:
struct Tcircle p[2]={{1,2,3},{4,5,6}};
Жишээ: Оюутны нэр, хичээлийн нэр, A,B,C,D оноонууд, үсэгт үнэлгээ, үнэлгээний оноо гэсэн талбарууд бүхий N бичлэгтэй  массив өгөгдөв. Тухайн хичээлээр авбал зохих кредит болон массивын оюутны нэр,хичээлийн нэр, A,B,C,D оноонууд гэсэн талбаруудын утгууд гараас өгөгдөнө. Оюутны үнэлэх журмыг ашиглан рейтингийн оноо ба үсэгт үнэлгээ, талбаруудын утгуудыг бодож ол.


#include<stdio.h>
const int N=1;
struct Tstudent{
int id;
char name[20];
int a,b,c,d,p,uo;
char uu;            }
main() {
int i;
Tstudent s[N];
for(i=0; i<N; i++) {
s[i].id=i+1;
printf(“Name:”); scanf(“%s”,s[i].name);
printf(“A=”); scanf(“%s”,&s[i].a);
printf(“B=”); scanf(“%s”, &s[i].b);
printf(“C=”); scanf(“%s”, &s[i].c);
printf(“D=”); scanf(“%s”, &s[i].d);
s[i].p=(s[i].a+3*s[i].b+2*s[i].c+4*s[i].d)/10;
if(s[i].p>=90) {s[i].uo=4;  s[i].uu=’A’;}else
if(s[i].p>=80) {s[i].uo=3;  s[i].uu=’B’;}else
if(s[i].p>=70) {s[i].uo=2;  s[i].uu=’C’;}else
if(s[i].p>=60) {s[i].uo=1;  s[i].uu=’D’;}else {s[i]}.uo=0; s[i].uu=’F’;}  }
for(i=0; i<N; i++) {
printf(“%d%s%d%d%d%d%d%d%c”,s[i].id, s[i].name, s[i].a, s[i].b, s[i].c, s[i].d, s[i].p, s[i].uo, s[i].uu,”\n”);
}           }
Бит талбар
Зарим үед их хэмжээний санах ойг огт хэрэглэгдэхгүй өнгөрөөх тохиолдолд байдгийг бүтцийн хувьд залруулах боломжыг си хэлний бит талбар олгодог. Бит талбарын тусламжтай талбарын авах утгаас  хамааруулан тухайн талбарын санах ойд эзлэх хэмжээг нарийн тогтоож өгч болдог. Жишээлбэл дараах бүтцийг авч үзье.
struct Tlight {
int color;
Char onoff ;
};
Энэхүү төрөл нь гэрлийн өнгө ба түүний ассан хэсгийг тодорхойлдог гэе. Тэгвэл ассан эсэхийг тодорхойлох onoff талбар ассан бол 1, асаагүй бол 0 гэсэн хоёр утга л авах болно. Мөн гэрлийн өнгө улаан,ногоон, шар өнгө байдаг гэвэл 0,1,2 гэсэн 3 утга авдаг гэе. Ингэснээр санах ойд color-ын утгыг хадгалахад 2бит, onoff-ын утгыг хадгалахад 1бит л хангалттай юм. Үүнийг бит талбарын тусламжтайгаар шийдэж болох бөгөөд  дараах хэлбэртэй болно.
struct Tlight {
int color:2 ;
Char onoff:1 ;
};

Бит төрлийн аргументтэй функц
Функцийн аргументэд бүтэц төрлийн хувьсагч, массив, заагч ашиглаж болно. Жишээ болгон өмнө нь авч үзэж байсан жишээг хэрэглэгчийн функцтэйгээр зохион байгуулж үзүүллээ.
Жишээ: Бүтэц аргументтэй функцийн хэрэглээг харуулав.
#include<stdio.h>
#define N=20
typedef struct Tstudent{
int id;
char name[20];
int a,b,c,d,p,uo;
char uu;            };
void input(struct TStudent s[ ], int n ){
int i;
for(i=0; i<n; i++) {
s[i].id=i+1;
printf(“Name:”); scanf(“%s”,s[i].name);
printf(“A=”); scanf(“%s”,&s[i].a);
printf(“B=”); scanf(“%s”, &s[i].b);
printf(“C=”); scanf(“%s”, &s[i].c);
printf(“D=”); scanf(“%s”, &s[i].d);
s[i].p=(s[i].a+3*s[i].b+2*s[i].c+4*s[i].d)/10;
if(s[i].p>=90) {s[i].uo=4;  s[i].uu=’A’;}else
if(s[i].p>=80) {s[i].uo=3;  s[i].uu=’B’;}else
if(s[i].p>=70) {s[i].uo=2;  s[i].uu=’C’;}else
if(s[i].p>=60) {s[i].uo=1;  s[i].uu=’D’;}else {s[i]}.uo=0; s[i].uu=’F’;}  }   }
void print(struct TStudent s[ ], int n){
int i;
for(i=0; i<n; i++) {
printf(“%d%s%d%d%d%d%d%d%c\n”,s[i].id, s[i].name, s[i].a, s[i].b, s[i].c, s[i].d, s[i].p, s[i].uo, s[i].uu,”\n”);
}          
printf(“\n\n”);           }
void sort(struct TStudent s[ ], int n) {
struct TStudent t;
int i, j;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(s[i].p>2s[j].p)  {
t=s[i];
s[i]=s[j];
s[j]=t;
}             }
Main()  {
struct TStudent s[N];
input(s,N);
printf(“оруулсан массив:\n”);
print(s,N);
sort(s,N);
printf(“эрэмбэлэгдсэн массив:\n”);
print(s,N);
}
Энэ жишээ програмын sort() функцийн эхний параметр нь бүтэц төрлийн массив байна. энэ параметр нь хувьсагчын параметр болж чадна. Учир нь массив бол заагч байдаг билээ.
7. Файлтай ажиллах
 Файл/File/ гэдэг мэдээллийн сан/архив гэсэн утгатай англи үг юм. Файл гэдэг нь гадаад зөөгч дээр мэдээлэл хадгалах зорилгоор үүссэн тодорхой нэрлэгдсэн байр юм. Гадаад зөөгч гэдэгт: уян, хатуу, компакт, Zip, jaz, гэх мэт диск ба соронзон тууз мэдээлэл болон програм хадгалах бүхий л зүйл орно. Файлын нэг онцлог шинж бол түүний хэмжээ/урт/ тодорхой биш байдаг явдал юм.
7.1. Файлын оролт, гаралт.
Файл. Мэдээллийг хадгалах үндсэн нэгжийг файл гэдэг. Програмчлалд файлыг хоёр талаас нь авч үздэг.
1. Мэдээллийн диск дээрх нэрлэгдсэн мужийг физик файл гэдэг. Гарнаас мэдээлэл оруулахад удаан, дэлгэсэнд гаргасан мэдээлэл хадгалагддаггүй зэрэг нь мэдээллийг диск дээр хадгалах шаардлагыг бий болгоно. Мэдээллийг диск дээр нэг удаа хадгалаад дараа нь дахин дахин уншиж ашиглах, засварлах боломжтой. Мэдээллийг диск дээр файл хэлбэрээр хадгална. Мэдээллийг дискэд гаргах(Output), дискнээс оруулах(Input) процессийг урсгал(stream) гэдэг.
2. Програмд хэрэглэгдэж байгаа файлын төрлийн хувьсагч буюу физик файлын програм дахь тодорхойлолтыг (төлөөлөгчийг) логик файл гэдэг. Програмд логик файл нь ямар нэг төрөлтэй (эсвэл төрөлгүй) файлын төрлийн хувьсагч байдлаар тодорхойлогддог.
Физик файлын бүтэц
Физик файлын бүтэц энгийн байтуудын дараалал байдалтайгаар хадгалагддаг.
Байт
Байт
Байт
   .   .   .
Байт
Байт
EOF
Логик файлын бүтэц
Логик файлын бүтэц-ийг физик файлын бүтцийг харах хэв загвар гэж үзэж болно. Програмчлалын хэлэнд энэ хэв загвар нь файлын агуулгад хандах өгөгдлийн төрөл болдог. Файлын элементийн тоо нь тухайн агшинд тодорхойгүй байдаг ба үүнийг тодорхойлохдоо файлын төгсгөлд EoF буюу ASCII 26 кодтой тэмдэгтийг бичиж өгдөг. Файлын элементийн тоог програмын явцад өөрчилж болно.
Си хэлэнд оролт гаралтын функцуудыг stdio.h толгой файлд тодорхойлсон байдаг. Файлыг: 1.Текст файл 2.Бинар файл гэж хоёр ангилна. Тэмдэгт өгөгдөл агуулсан файлыг текст файл, бусад төрлийн файлыг бинар файл гэж нэрлэнэ. Текст файлыг ямар нэг editor ашиглан үүсгээд, нэр өргөтгөлийг нь өгөөд хадгалж болно. Текст файл нь тэмдэгтүүдийн мөрийг агуулах ба дэс дараалсан хандалттай файл юм. Түүний мөрийн төгсгөлд ‘\n’ тэмдэг, файлын төгсгөлд ASCII 26 кодтой Ctrl+z тэмдэгт байрлана. Бинар файл нь шууд хандалттай файл юм. Иймд файлыг хандах аргаар нь:
1.    Дэс дараалсан хандалттай
2.    Шууд хандалттай гэж 2 ангилдаг. Хандах гэдэг нь мэдээллийг унших, бичих процесс юм. Файлын эхнээс байт байтаар хандахыг дэс дараалсан, шаардлагатай элементэд шууд хандахыг шууд хандах гэдэг.
Файлд хандахад 1.Файлын нэр буюу физик файлын нэр, 2.Файлын төрлийн хувьсагчийн нэр буюу логик файлын нэр хэрэглэгдэнэ. Файлын төрлийн хувьсагчийн нэрийг файлаас барих бариул(handle) гэдэг. Програмаас файлыг нээмэгц нээсэн функц нь уг файлын дотоод нэрийг буцаана. Уг дотоод нэрийг ашиглан файлд бичих, файлаас унших, файлыг хаах гэх мэт үйлдлийг хийнэ. Дотоод нэр нь файлын хэмжээ(байт), байрлал(хаана байгаа) зэрэг мэдээллийг агуулна. Дотоод нэр нь файл төрлийн хувьсагч байна. Жишээ нь: FILE *f, *fhandle гэх мэт.
Файлтай ажиллахад 1.Файл нээх, 2.Фsайлаас мэдээлэл унших, 3.Файлд мэдээлэл бичих, 4.Файл хаах гэсэн дөрвөн үйлдэл хийнэ. Си хэлэнд файлтай ажиллах ихэнх функц f үсгээр эхэлсэн байдаг.
Файл нээх. Файлыг fopen функцаар нээнэ. Энэ функц нь FILE* төрлийн заагч буюу нээгдсэн файлын дугаарыг буцаадаг. Файл амжилттай нээгдсэн бол тэгээс ялгаатай утга буцаана.
<файлын_логик_нэр>=fopen(<файлын_физик_нэр>,<нээх_горим>); 
Үүнд: <файлын_физик_нэр> - файлын нэр болох тэмдэгт төрлийн заагч, нээх горим дорх хандах горим юм. Үүнд: Файлыг нээх горим:
Горим
Зорилго
“r”
Байгаа файлыг уншихаар нээнэ. 
“w”
Бичихээр шинэ файл нээх. (Ижил нэртэй файл байвал устгаад)
“a”
Файлын  төгсгөлд мэдээлэл нэмж бичихээр нээх. Хэрвээ файл байхгүй бол шинээр нээнэ.
“r+”
Өмнө байгаа файлыг унших ба нэмж бичихээр нээх.
“w+”
Файлыг унших ба нэмж бичихээр нээх. Ижил нэртэй файл байвал мэдээлэл нь устана.
“a+”
Файлын  төгсгөлд мэдээлэл нэмж бичих уншихаар нээх. Файл байхгүй бол шинээр нээнэ.
“rb”
Бинар файлыг уншихаар нээх. (Шууд хандалттай файл)
“wb”
Бинар файлыг бичихээр нээх. (Шууд хандалттай файл)
“ab”
Бинар файлд мэдээлэл нэмж бичихээр нээх. (Шууд хандалттай файл)
Жишээ: f=fopen("score.txt","r"); энэ нь score.txt файлыг уншихаар нээнэ.
Хэрэв байхгүй файлыг нээхээр оролдвол fopen функц макро NULL утгыг буцаадаг. Үүнийг ашиглан нээх үйлдэл амжилттай болсон эсэхийг хянана. Энэ үед perror функц ашиглан ямар алдаа гарч байгааг мэдэж болно. Хэрэв алдаа гарвал програмын биелэлтийг exit функцээр зогсооно. Жишээ нь:
  FILE *f;
  if ((f=fopen("score.txt","r"))==NULL)
     { perror(“score.txt fopen");
       exit(1);     /* stdlib.h санд байдаг функц */
     }
Энэ жишээнд score.txt файлыг цаашид f функц төлөөлнө.
Файл хаах. Файлыг fclose функцаар хаана. fclose(<файлын_логик_нэр>);
Энэ функц файл амжилттай хаагдвал тэг утга, үгүй бол тэг биш EOF утга буцаана. EOF нь End of File – файлын төгсгөлийг заасан тогтмол. Жишээ нь:
  if (fclose(f)==EOF)
     { perror(“score.txt fclose");
       exit(1);     /* stdlib.h санд байдаг функц */
     }
Файлтай ажиллахдаа дээрх хоёр үйлдлийг заавал хийх хэрэгтэй.


Унших ба бичих үйлдэл. Тэмдэгт өгөгдөл агуулсан файлыг текст файл гэдэг. Текст файлд тэмдэгтээр эсвэл тэмдэгт мөрөөр хандан ажиллаж болдог. Текст файл нь тэмдэгтүүдийн мөрийг агуулах ба мөрийн төгсгөлд мөр шилжүүлэх ‘\n’ тэмдэгт, файлын төгсгөлд ASCII 26 кодтой тэмдэгт байрлана. Эсвэл Ctrl+z байна. Текст файл бол дэс дараалсан хандалттай файл юм. Текст файлыг ямар нэг editor ашиглан үүсгээд, нэр өргөтгөлийг нь өгөөд хадгалж болно.
Байтуудын дарааллыг агуулсан файлыг бинар файл гэж нэрлэнэ. Бинар файл нь шууд хандалттай файл юм.
Текст файл stream-аас char-тэмдэгт эсвэл buffer-тэмдэгт мөр унших, эсвэл түүнд бичих функцууд:
fgetc(FILE *stream) - Файлаас нэг тэмдэгт уншиж, амжилттай бол уншсан тэмдэгтийг үгүй бол EOF утга буцаана.
getc(FILE *stream) - Файлаас мөн адил нэг тэмдэгт уншина
fgets(buffer, n byte, FILE *stream) - Файлаас n урттай(byte) мөр эсвэл мөр шилжих тэмдэгт хүртлэх мөрийг уншиж buffer-буфер луу бичнэ. Тэмдэгт мөрийн төгсгөлд ASCII 0 тэмдэгтийг бичдэг. Амжилттай ажилласан бол бичсэн тэмдэгт мөрийн хаягийг, алдаа гарсан эсвэл файлын төгсгөлд хүрсэн бол NULL утга буцаана.
fputc(char, FILE *stream) - Файлд нэг тэмдэгт(char)-ийг бичнэ. Функц амжилттай бол char тэмдэгтийг үгүй бол EOF утга буцаана.
putc(char, FILE *stream) - Файлд мөн адил нэг тэмдэгт бичнэ
fputs(buffer, FILE *stream) - Файлд buffer-буферийн мөрийг бичнэ. Амжилттай ажилласан бол сөрөг биш бүхэл тоо, алдаа гарсан бол EOF утга буцаана.
Текст файлд формат хэлбэрээр бичих ба файлаас формат хэлбэрээр унших функцууд:
fprintf(FILE *stream, const char *format[, argument, . . . ]); - stream файлд format-д заасан хэлбэр бүхий мэдээллийг бичнэ. format-мөрөнд бичих мэдээллийн хэвшүүлэлтийг өгөх ба энэ нь printf() функцынхтай адил (номын хуудас 22-23) байна. Функц амжилттай биелэсэн бол файлд бичсэн байтын тоо, алдаа гарсан бол EOF утга буцаана. Жишээлбэл double төрлийн d утгыг файлд таслалаас өмнө 8 орны зайтай, таслалаас хойш 2 орны нарийвчлалтай бичнэ гэвэл: fprintf(pr, “%8.2t”,d); гэж өгнө.
fscanf(FILE *stream, const char *format[, argument, . . . ]); - stream файлаас format-д заасан хэлбэр бүхий мэдээллийг уншина. format-мөрөнд унших мэдээллийн хэвшүүлэлтийг өгөх ба энэ нь scanf() функцынхтай адил байна. Функц амжилттай биелэсэн бол файлаас уншсан байтын тоо, алдаа гарсан бол EOF утга буцаана.



Жишээ 1. score.txt файлд хадгалагдсан оюутны онооны дундажийг хэвлэ.
// file1.cpp
// score.txt filed hadgalagdsan onoony dundajiig hevle
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{ FILE *fhandle;
  if ((fhandle=fopen("score.txt","r"))==NULL)
     { perror("score.txt fopen");
                         exit(1);
     }
  int score,too=0,sum=0;
  while (!feof(fhandle)&&!ferror(fhandle))
                          { fscanf(fhandle,"%d",&score) ;
                            sum+=score;
                            too++;
                          }
  printf("dundaj:%d\n",sum/too);
  if (fclose(fhandle)==EOF)
     { perror("score.txt(fclose)");
                         exit(1);
     }
  getch();
}


Дээрх жишээнд файлаас мэдээллийг уншихад хоёр зүйл тохиолдож болно. Уншиж байгаад файлын төгсгөлд хүрэх үүнийг feof() функцаар, алдаа гарах үүнийг ferror() функцаар тус тус хянана. Эдгээр функц нь тэг эсвэл тэг биш утга буцаана.
Файлтай ажиллах функцуудын ангилал:
  1. Нээх, хаах: fopen, freopen, fdopen, fflush, flushall, fileno, fclose, fcloseall
  2. Мэдээлэл унших, бичих: feof, fgetc, fgetchar, fgets, fprintf, fputc, fputs
  3. Файлын заагч(курсор)-ийг удирдах: fgetpos, fseek, fsetpos, ftell, rewind
  4. Ажиллаж байх үеийн алдааг хянах: clearerr, ferror, perror, strerror,
  5. Файл устгах, нэр өөрчлөх, бусад: remove, rename, rmtmp, tempnam, tmpfile, tmpnam



Текст файлтай ажиллах функцууд-ыг хэрэглэх жишээнүүд:
Жишээ 2. “name.dat” файлд байгаа овог нэр, “phone.dat” файлд байгаа утасны дугаарыг нэгтгэн “report.dat” файлыг үүсгэх.


// FILECLOS.CPP
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <errno.h>
int main (int argc, char *argv[])
{   FILE *p[3];
    char buff[256], phone[255], name[50];
    char *file[] = {"name.dat","phone.dat","report.dat"};
    char *mod[] = {"r","r","w"};
    int i = 0;
            //  open 3 files. 2 for reading, 1 for writing
    for ( ; i < 3; i++ )
        { if ( (p[i] = fopen (file[i],mod[i])) == NULL )
             { sprintf(buff,"Cann't open %s for \%s\. err: %d",
               file[i],mod[i],errno);
               fprintf(stderr,"%s\n",buff);
               if ( i > 0 )        //  close all opened files
               fcloseall();
               exit(EXIT_FAILURE);
             }
        }
    i = 1;
    while ( fscanf(p[0],"%s%s",buff,name) == 2 &&
            fscanf(p[1],"%s",phone) == 1 )
                         { fprintf(p[2],"%d:%s %s:%s\n",i++,
                                       buff,name,phone);
                         }
            //  close all opened files
    fcloseall();
            //  open report.dat for reading
    if ( (p[0] = fopen (file[2],mod[0])) == NULL )
       { sprintf(buff,"Cann't open %s for \%s\. err: %d",
         file[2],mod[0],errno);
         fprintf(stderr,"%s\n",buff);
         exit(EXIT_FAILURE);
       }
    while ( (fgets (buff,254,p[0])) != NULL )
          { fprintf(stdout,"%s",buff); }
    fclose(p[0]);
    getch();
    return 0;
}

Жишээ 3. fgetc, fputc, puts, feof, rewind функцын хэрглээ.
// FEOF.CPP
#include <stdio.h>
#include <conio.h>
int main (int argc, char *argv[])
{  FILE *fp;
   int c;
   fp = fopen("test.txt","r");
            /* print `EOF' character */
   while ( !feof(fp) )
         { c = fgetc(fp);
           fputc(c, stdout);
           //  or fputc( c=fgetc(fp), stdout );
         }
   puts("\n");    //  puts new lines
   rewind(fp); // zaagchiig ehend ni avaachna
   /* mutch better */
   while ( !feof(fp) )
         { c = fgetc(fp);
           if ( feof(fp) )
           break;
           fputc(c, stdout);
         }
   getch();
   return

Дараалсан хандалттай файл
Файлтай ажиллахдаа эхлээд нээж, ажиллаж дууссаны дараа хаах, мөн дискенд хадгалагдах үйлдлийг заавал хийдэг. Текст файлд тэмдэгтээр эсвэл тэмдэгт мөрөөр хандан ажиллаж болдог. Текст файл нь мөр мөрөөрөө файлд бичигдсэн байдаг. Энэ нь дараах хэлбэртэй байна.
Шууд хандалттай файл
Төрөлт файлын бүх элементүүд   нэг төрлийн байх ба ийм файлын элементийн төрөл нь файлын төрлөөс бусад ямар ч төрөл байж болдог.



Бинар файлтай ажиллах функцууд:
Бинар файлын текст файлаас ялгаатай нь editor ашиглан үүсгэх боломжгүй. Бинар файлтай зөвхөн fwrite, fread функц ашиглан ажиллана.
Бичигдэх хэлбэр нь:
size_t  fread(buffer, хэмжээ, тоо, file-handle) – бинар файлаас мэдээлэл унших
size_t  fwrite(buffer, хэмжээ, тоо, file-handle) – бинар файлд мэдээлэл бичих
Бинар файлын агуулгыг feof функцаар хянаж унших нь тохиромжгүй. Үүний оронд буцах утга size_t утгаар хянах нь илүү тохиромжтой. Жишээ 6. Бинар файлд мэдээлэл бичээд түүнийгээ уншиж дэлгэцэнд хэвлэх програм:
// FREAD1.CPP
#include <stdio.h>
#include <conio.h>
struct mystruct
{ int i;
  char ch;
};
int main(void)
{ FILE *stream;
  struct mystruct s,s1;
if ((stream = fopen("TEST.$$$", "wb")) == NULL)
/* open file TEST.$$$ */
     { fprintf(stderr, "Cannot open output file.\n");
       return 1;
     }
  s.i = 0;
  s.ch = 'A';
fwrite(&s, sizeof(s), 1, stream);
          /* write struct s to file */
  s.i = 1;
  s.ch = 'B';
fwrite(&s, sizeof(s), 1, stream);
/* write struct s to file */
  fclose(stream); /* close file */
  stream=fopen("TEST.$$$", "rb");
  fread(&s1, sizeof(s), 1, stream);
  printf("%d %c\n",s1.i,s1.ch);
  fread(&s1, sizeof(s), 1, stream);
  printf("%d %c\n",s1.i,s1.ch);
  fclose(stream); /* close file */
  getch();
  return 0;
}

8. Санах ой
Програм нь хоосон орчинд ажиллахгүй, компьютерийн санах ойд ажиллана. Санах ойн хаяг хадгалах хувьсагчийг заагч гэнэ. Заагчийн утга нь санах ойн ямар нэг хаяг байна. Заагч хувьсагчийг зарлахдаа түүний нэрний өмнө од(*) тавина.
int thing; /* ердийн хувьсагч */
int *thing_ptr; /* заагч хувьсагч */
Заагчийн үйлдлүүд
Заагчтай хамт хэрэглэгддэг үйлдлүүдийг дараах хүснэгтэд үзүүлэв.
Үйлдэл
Тайлбар
*
Заагчаар дамжин зааж байгаа утгыг унших
&
Обьектын санах ой дахь хаягыг тодорхойлох
Дээрх үйлдлүүдийг зарим тохиолдолд эндүүрдэг учраас дараах хүснэгтэнд тайлбар хийв.
Заавар
Тайлбар
thing
Ердийн хувьсагч
&thing
thing  хувьсагчийн хаяг
thing_ptr
Заагч хувьсагч
*thing_ptr
Зааж байгаа утга(бүхэл тоо)

Заагч үйлдлүүдийн зарим хэрэглээг жишээ болгон харая
            int thing; /* бүхэл тоон хувьсагч зарлах*/
            thing = 4;

int *thing_ptr;  /* заагч хувьсагч зарлах*/
thing_ptr = &thing;  /*заагч хувьсагчруу заах */
*thing_ptr = 5; /* “thing ”утгыг 5 болгох*/
&thing илэрхийлэл нь thing хувьсагчийн хаягыг өгнө. Дараа нь уг хаягыг заагч thing_ptr заагч хувьсагчид оноож байна.
Заагчийн төрөл
Заагч хувьсагч нь бусад хувьсагчийн адил өгөгдлийн төрөлтэй байх ба энэ нь тухайн заагчаар зааж байгаа үүрэн дэх өгөгдлийн төрлийг илэрхийлнэ. Энд заагч нь ямар нэгэн төрлийн өгөгдлийн үүр биш, харин санах ойн хаягийг заадаг гэдгийг ойлгох хэрэгтэй. Зааж байгаа хаягаас хойш ямар хэмжээтэй өгөгдөл байна вэ? гэдгийг мэдэхийн тулд заагчийн төрлийг ашигладаг.
8.3Динамик санах ой
Програм бичиж байх үед заримдаа ямар хэмжээтэй өгөгдөл боловсруулах нь тодорхой бус байдаг.Зарим програм ажиллаж байх үед өгөгдлимйн хэмжээ өөрчлөгдөх хэрэг болдог. Эдгээр тохиолдлуудад нөөцийг тохиромжтой ашиглахын үүднээс програма ажиллаж байх үед санах ойг хувиарлах, чөлөөлөх хэрэг гарна. Энэ бол динамик санах ойн менежмент юм.     


Санах ойг динамикаар удирдахад дараах стандарт функцуудыг ашигладаг:

·         malloc(), calloc() функцууд нт санах ой хувиарлахад
·         free() функц нь хувиарласан санах ойг чөлөөлөхөд эдгээр функцууд нь бүгд stdlib.h толгой файлд агуулагдана

9.Препроцессорын директив

Препроцессорын директив нь програмын компиляцын үйл ажиллагааны хамгийн эхний шатанд хийгддэг. Препроцессорын директив # (фунтын) тэмдгээр эхэлдэг. Препроцессорын директивийг цаашид  директив гэж нэрлэж явна. Си хэлэнд олон директив байдаг. Тэдгээрээс  дурьдвал:
1.    #include директив
#include директив нь програмын кодын эхэнд бичигддэг. Энэ директивийн үүрэг нь дискен дээрх текст файлыг тухайн програмын текстэд хавсаргана. Ингэснээр хавсаргасан файлд орших төрөл, тогтмол, функц зэргийг ашиглах боломж бүрддэг. Файл хавсаргахдаа дараах 2 хэлбэрийн аль нэгээр бичдэг.
#include<filename>
#include “filename” өнгөц хаалт (<>) болон давхар (“”) нь хэрэглэгээрээ бяцхан ялгаатай. Тухайлбал, (<>) хаалтанд хийсэн бол Си хэлний  IDE-д (Си 3.1 хувилбарт Option-directories-include мөрөнд заасан зам, Си 5.0 хувилбарт Option- project-directories- include мөрөнд заасан зам) заасан замаас хавсаргах файлыг болно. Харин давхар (“”) –д хийсэн  бол эхлээд хавсаргах файлыг эхлээд идэвхитэй хавтсанд хайж, байхгүй бол өнцгөн хаалтын адилаар IDE-д засан замд хайх болно. Өмнө бид #include директивийг файл буюу Си хэлний стандарт санг програмд хавсаргах байдлаар бичмсэн програм бүрдээ хэрэглэж байсан. Жишээ нь:
#include<stdio.h>
#include<math.h>
#include”stdlib.h” Мөн Си  хэлний нэг програмыг нөгөөд хавсаргах ашиглах боломжийг энэ директив олгодог.
2.    # define директив буюу макро
Энэ директив нь нилээд өргөн боломжийг програм зохиогчид өгдөг. Уг директивийг анх хэрэглэхэд нилээд хачин зүйл шиг санагдаж магадгүй. # define директив програмын эхний хэсэгт  #include директивээр тодорхойлогдсон програмын элементийг “Макро тодорхойлолт” буюу “Макро” гэдэг. Жишээ нь:
 #define AGELIMIT 35  гэвэл програм ажиллах үед програмд байгаа бүх AGELIMIT үг 35  гэсэн тоогоор солигдоно. Энэ жишээний AGELIMIT болон 35-ыг #define директивийн аргумент гэнэ. #define директивийн эхний аргумент нь програм дахь тухайн утгаар солигдох нэр бөгөөд харин дараагийн аргумент нь тогтмол утга
 (тоон  болон тэмдэгт мөр тогтмол), илэрхийлэл зэрэг байж болно.
#define BIG 512
Int myArray[BIG]; энэ жишээний дээрх массив програм ажиллахад int myArray [512];
Болж хөрвүүлэгдэнэ.


3.    #ifdef, #ifndef директивүүд
#ifdef директив нь #if defined, #ifndef директив нь if !defined-тай ижил бөгөөд харгалзан идентификатор,  эсвэл макрог өмнө нь тодорхойлогдсон, тодорхойлогдоогүй эсэхийг шалгана. #ednif директивтэй хамтран хэрэглэгдэнэ.
 #ifdef, #ifndef директивүүдийн хэрэглээг харуулсан жишээ
#include<tsdio.h>
Void W(){
#ifdef YEAR
Printf(“YAER өмнө тодорхойлогдсон.\n”);
#endif
#ifndef YEAR
Printf(“YAER өмнө тодорхойлогдооогүй.\n”);
#define YEAR 2002;
Printf(“Одоо YEAR тодорхойлогдсон.\n);
#endif
}
Main(){
W();
Printf(“%d\n” YEAR);
}

4.    #undef ,#if, #elif, #else, #endif директивүүд
Эдгээр директивүүд нь томоохон модуль програмчлалын үед хэрэглэгдэх ба илүү уян хатан бөгөөд ажиллах бүрдээ өөр ажиллах бүрдээ өөр үр дүн өгөх програм бичиж болдог.
#undef <аргумент>
<аргумент> өмнө тодорхойлсон макрогийн нэр
#undef директив нь аргументэд өгсөн нэр бүхий хамгийн сүүлд тодорхойлсон (#define директивээр) макро тодорхойлолтыг хүчингүй болгоно. Жишээ нь:
#define BIG 3 /* BIG-ийг тодорхойлох*/
#define HUGE 3 /* HUGE-ийг тодорхойлох*/
#define BIG  /* Одоо BIG-ийг тодорхойлохгүй болсон*/
#define HUGE 10 /* HUGE-ийг 10 утгатайгаар дахин тодорхойлох*/
#define HUGE /* Одоо HUGE 5 утгатай болсон*/
#define HUGE /* Одоо HUGE 5 тодорхойлолтгүй болсон*/
Дээрх жишээнд сүүлийн мөрийн өмнөх мөрд сүүлд тодорхойлогдсон HUGE –ийг тодорхойлолтыг эхлээд хүчингүй болгоно. Ингэснээр  HUGE –ийн өмнөх тодорхойлолт #define HUGE 5 үлдэх болно. Хамгийн сүүлийн мөр нь энэ тодорхойлолтын хүчингүй болгож байна.
#if<илэрхийлэл1>
<илэрхийлэл1 үнэн үед хийшдэх үйлдлүүд>
#elif<илэрхийлэл2>
<илэрхийлэл1 худал ба  илэрхийлэл2 үнэн үед хийгдэх үйлдлүүд>
#elif<илэрхийлэл3>
<илэрхийлэл1  ба  илэрхийлэл2  2уулаа худал илэрхийлэл3 үнэн үед хийгдэх үйлдлүүд>
#else <бүх илэрхийллүүд худал үед хийгдэх үйлдлүүд>

10. Стандарт сангууд

1.    math.h сангийн функцуудын хэрэглээ
<math.h> толгой файлд математикийн функцууд ба макронууд тодорхойлогдсон байдаг Макро:
HUGE_VAL
Функц:  Тригонометрийн функцууд
1. acos
double acos(double x);
x-ийн arc cosine утгыг радианаар буцаана.
x-ийн утга нь [-1, +1] завсарт өгөгдөнө. Буцах утга нь [0, pi] завсарт байна.
#include <math.h>
               #include <stdio.h>
               #include <stdlib.h>
 
               void main() 
               { 
                  double d; 
                  double result; 
 
                  printf("Enter a double:"); 
                  scanf("%lg", &d); 
                  result = acos(d); 
                  printf("\nacos(%lg) = %lg\n", d, result); 
               }
Програмын үр дүн:
Enter a double:. 45
acos(0.45) = 1.10403


2. asin
double asin(double x);
x-ийн arc sine утгыг радианаар буцаана. 
x-ийн утга нь [-1, +1] завсарт өгөгдөнө. Буцах утга нь [-p/2, +p/2] завсарт байна.
3. atan
double atan(double x);
x-ийн arc tangens утгыг радианаар буцаана.
x-ийн дурын утганд [-p/2, +p/2] завсарт байх утга буцаана.
4. atan2
double atan2(doubly y, double x);
[-p/2, +p/2] завсарт tan-1(y/x) функцийн утгыг тооцоолж буцаана.
5. cos
double cos(double x);
x-ийн косинус функцийн утгыг тооцоолж буцаана.
Буцах утгын муж нь [-1, +1] байна.
6. cosh
double cosh(double x);
x-ийн гиперболлог косинус функцийн утгыг тооцоолж буцаана.
Аргумент болон буцах утгын муж байхгүй.
7. sin
double sin(double x);
x-ийн синус функцийн утгыг тооцоолж буцаана.
Буцах утгын муж нь [-1, +1] байна.
8. sinh
double sinh(double x);
x-ийн гиперболлог синус функцийн утгыг тооцоолж буцаана.
Аргумент болон буцах утгын муж байхгүй.
9. tan
double tan(double x);
x-ийн тангенс функцийн утгыг тооцоолж буцаана.
Аргумент болон буцах утгын муж байхгүй.
10. tanh
double tanh(double x);
x-ийн гиперболлог тангенс функцийн утгыг тооцоолж буцаана.
Буцах утгын муж нь [-1, +1] байна.
Exponential, Logarithmic ба зэрэг дэвшүүлэх функцууд
1. exp
double exp(double x);
ex функцийн утгыг тооцоолж буцаана.
2. frexp
double frexp(double x, int *exponent);
x тоог мантисс ба эрэмбэд задална.
3. ldexp
double ldexp(double x, int n);
x тоог 2-ийн n зэрэгтээр үржүүлсэн утгыг буцаана.  x*2^n
4. log
double log(double x);
e суурьтай натурал логарифм x-ийн утгыг буцаана.  
5. log10
double log10(double x);
10 суурьтай логарифм log10(x)-ийн утгыг буцаана.


6. modf
double modf(double x, double *i);
x тоог бүхэл ба бутархай хэсгээр задалж, бүхэл хэсгийг i-д оноож, бутархай хэсгийг үр дүн болгон буцаана.
#include <stdlib.h>
               #include <stdio.h>
               #include <math.h> 
 
               void main()
               { 
                  double d, frac, intr; 
 
                  printf("Enter a double: ");
                  scanf("%lg", &d); 
                  frac = modf (d, &intr);
                  printf("\nFor %g, the fractional part is 
                                 %g,\nand the integral part is " 
                                 "%g.\n", d, frac, intr); 
               } 
7. pow
double pow(double x, double y);
x-ийн y зэрэгтийг тооцоолж буцаана.
Хэрэв y нь бутархай бол x нь сөрөг байж болохгүй. y нь 0 эсвэл 0-ээс бага бол x нь 0 байж болохгүй.  
#include <stdlib.h>
               #include <stdio.h>
               #include <math.h>
               void main()
               {
                  double d1, d2;
                  printf("Enter two doubles: ");
                  scanf("%lg %lg", &d1, &d2);
                  printf("\npow(%g, %g)=%g\n", d1, d2,
                                   pow (d1, d2));
               }
Output
Enter two doubles: 2 16
pow(2, 16)= 65536
8. sqrt
double sqrt(double x);
x тооны квадрат язгуурыг олж буцаана.  
#include <stdlib.h>
               #include <stdio.h>
               #include <math.h>
 
               int main()
               { 
                  double d; 
 
                  printf("Enter a double: "); 
                  scanf("%lg", &d); 
                  printf("\nsqrt(%g)=%g\n", d, sqrt(d)); 
 
                  return 0;
               } 

Output

Enter a double: 81
sqrt(81)= 9



Бусад математикийн функцууд
1. ceil
double ceil(double x);
x-ээс багагүй хамгийн бага бүхэл тоог олж буцаана. .
2. fabs    double fabs(double x);
x тооны абсолют утгыг буцаана.
3. floor
double floor(double x);
x-ээс ихгүй хамгийн их бүхэл утгыг буцаана.


4. fmod
double fmod(double x, double y);
x тоог y тоонд хуваахад гарах үлдэгдэлийг буцаана.
#include <stdio.h>
               #include <stdlib.h>
               #include <math.h>
               void main()
               {
                  double d1, d2, r;
                  printf("Enter two doubles: ");
                  scanf("%lg %lg", &d1, &d2);
                  r = fmod(d1, d2);
                  printf("fmod(%g, %g)=%g\n", d1, d2, r);
               }
Output
Enter two doubles: 16 7
fmod (16, 7)=2
2.    ctype.h сангийн функцууд

ctype.h сангийн функцууд нь тэмдэгтийг шалгах, хөрвүүлэх үйлдэлд хэрэглэгддэг. ASCII тэмдэгтийн хүснэгт нь 8 бит байдаг бөгөөд хэвлэгдэх тэмдэгтүүдэд 0x20 (хоосон зай) -аас 0x7E (дундуур зураас) –хүртэл тэмдэгтүүд, харин удирдах тэмдэгтүүдэд  0 (NUL) -аас 0x1F (US), ба 0x7F (DEL) хүртэлх ASCII код бүхий тэмдэгтүүд байдаг. Функцууд: isalnum();
            isalpha();       iscntrl();         isdigit();         isgraph();     
islower();       isprint();        ispunct();      isspace();     
isupper();      isxdigit();       tolower();      toupper();

Эдгээр функцууд нь int төрлийн аргументтай байх ба unsigned char төрлийн утга авч, int төрлийн утга буцаана.

is... Функцууд
Эдгээр функцууд нь өгөгдсөн тэмдэгтийг шалгаад нөхцөлийг хангаж байвал 0 биш утга, хангахгүй бол 0 утгыг буцаана.  
int isalnum(int character); өгөгдсөн тэмдэгт латин үсэг юмуу цифр байвал үнэн утга буцаана.
int isalpha(int character); өгөгдсөн тэмдэгт латин үсэг байвал үнэн утга буцаана.
int iscntrl(int character); өгөгдсөн тэмдэгт удирдах тэмдэгт бол үнэн утга буцаана.
int isdigit(int character); өгөгдсөн тэмдэгт цифр эсэхийг шалгана.
int isgraph(int
character); сул зайнаас бусад хэвлэгдэх тэмдэгт бол үнэн утга буцаана.
int islower(int character); латин жижиг үсэг бол үнэн утга буцаана.
int isprint(int
character); сул зай болон хэвлэгдэх тэмдэгт бол үнэн утга буцаана.
int ispunct(int character); сул зай, латин үсэг, цифрээс бусад хэвлэгдэх тэмдэгт бол үнэн утга буцаана.
int isspace(int character); сул зай, шинэ мөрөнд шилжих, таб зэрэг тэмдэгтүүд бол үнэн утга буцаана.
int isupper(int character); латин том үсэг бол үнэн утга буцаана.
int isxdigit(int character); 16тын тооллын системийн тоо бол үнэн утга буцаана
is функцуудыг хэрэглэх
Дасгал 1. ASCII тэмдэгтүүдээс аравтын тоог гарга.
#include <ctype.h>   /* bya2_5_01.c */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
char *binary(int a)
{ char *b,t=7;
  b=(char*)malloc(9);
  strcpy(b,"00000000");
  while (a) { b[t]=(char)(a % 2 + '0');
              a/=2; t--;
            }
  b[8]=NULL;
  return &b[0];
}
main()
{ int i;
  printf (" Aravtyn tsifruud:\n\n", i);
  printf("   Dec  Hex   Binary    Char \n");
  for (i=0;i<256;i++)
      if (isdigit(i) != 0)
          printf("%5d%5X%12s%5c\n",i,i,binary(i),i);
  getch();
}
Дасгал 2. ASCII тэмдэгтүүдээс латин том үсгийг гарга.
#include <ctype.h>   /* bya2_5_01.c */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
char *binary(int a)
{ char *b,t=7;
  b=(char*)malloc(9);
  strcpy(b,"00000000");
  while (a) { b[t]=(char)(a % 2 + '0');
              a/=2; t--;
            }
  b[8]=NULL;
  return &b[0];
}
main()
{ int i;
  printf (" Latin tom usguud:\n\n", i);
  printf("   Dec  Hex   Binary     Char ");
  printf("   Dec  Hex   Binary     Char \n");
  for (i=0;i<256;i++)
      if (isupper(i) != 0)
          if (i%2!=0) printf("%5d%5X%12s%5c   ",i,i,binary(i),i);
              else printf("%5d%5X%12s%5c\n",i,i,binary(i),i);
  getch();
}
Дасгал 3. ASCII тэмдэгтүүдээс латин жижиг үсгийг гарга.
#include <ctype.h>   /* bya2_5_03.c */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
main()
{ int i;
  printf (" Latin jijig usguud:\n\n", i);
  printf("   Dec  Hex   Binary     Char ");
  printf("   Dec  Hex   Binary     Char \n");
  for (i=0;i<256;i++)
      if (islower(i) != 0)
          if (i%2!=0) printf("%5d%5X%12s%5c   ",i,i,binary(i),i);
              else printf("%5d%5X%12s%5c\n",i,i,binary(i),i);
  getch();
}
Дасгал 4. ASCII тэмдэгтүүдээс бусад тэмдэгтүүдийг гарга.
#include <ctype.h>   /* bya2_5_04.c */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
main()
{ int i;
  printf (" Latin useg tsifrees busad temdegtuud:\n\n", i);
  printf("   Dec  Hex   Binary     Char ");
  printf("   Dec  Hex   Binary     Char \n");
  for (i=0;i<256;i++)
      if (ispunct(i) != 0)
          if (i%2!=0) printf("%5d%5X%12s%5c   ",i,i,binary(i),i);
              else printf("%5d%5X%12s%5c\n",i,i,binary(i),i);
  getch();
}

to... функцууд
Эдгээр функцууд нь тэмдэгтийг хувиргах функцууд байна.
int tolower(int character); латин том үсгийг латин жижиг үсэг болгох
int toupper(int character); латин жижиг үсгийг латин том үсэг болгох
to функцийн хэрэглээ
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
void main()    /* mzb2_07d2.c */
{   char *str =
      "Moral indignation is jealousy with a halo. - H. G. Wells";
   char *p;
   printf("Original string: \"%s\"\n", str);
   printf("After tolower:   \"");
   for (p = str; *p; p++) printf("%c", tolower (* p));
   printf("\"\n");
   printf("After toupper:   \"");
   for (p = str; *p; p++) printf("% c", toupper (* p));
   printf ("\"\n");
   getch();
}
3.    <assert.h>
Assert макро нь програмын оношилгоонд хэрэглэгдэнэ.
void assert (int expretion)
Хэрэв expretion 0 бол assert (expretion) биелэхэд assert() макро стандарт гаргах байгууламжид дараах мэдээллийг хэвлэнэ. Assertion failed: expretion, filefilname, line nnn Дараа нь abort() функцийг дуудаж гүйцэтгэл тасарна. Эх файлын нэр ба мөрийн дугаарыг _FILE_and_LINE_ процессорын макрогоос авдаг. <assert.h> толгой файлыг хавсаргасан үед NDEBUG тодорхойлогдсон бол, assert макро хэрэгсэхгүй болдог.
Жишээ болгон дараах програмыг авч үзье
Assert() функцийн хэрэглээг харуулсан жишээ
#include<stdio.h>
#include<assert.h>
main() {
int x;
printf(“\Бүхэл тоо оруулна уу:\”);
scanf(“%d”,&x);
assert(x>=0);
printf(“Оруулсан тоо %d.\n”,x);
return(0); }
Бүхэл тоо оруулна уу:10
Оруулсан тоо 10.
Бүхэл тоо оруулна уу: -1
Аssertion  failed: x,filelist19_3.c, line 8
Abromal program termination
Энэ жишээнд -1 утгыг оруулахад assert(x>=0) нь 0 утга авч системийн алдааны мэдээлэл өгч програм энгийн бишээр тасарч байна.
4.    stdlib.h сангийн функцууд
stdlib толгой файл нь тоон хөрвүүлэлтийн болон санах ойн хуваарилалтын функцууд агуулагддаг.
макро:
NULL                                     EXIT_FAILURE       EXIT_SUCCESS     RAND_MAX             MB_CUR_MAX
функцууд:
abort();          abs();                         atexit();          atof();                         atoi();                         atol();
bsearch();     calloc();         div();               exit();              free();                         getenv();
labs();            ldiv();              malloc();        mblen();         mbstowcs();             mbtowc();
qsort();          rand();            realloc();        srand();         strtod();         strtol();
strtoul();        system();       wcstombs();             wctomb();
Тэмдэгт мөртэй ажиллах функцууд
1. atof
double atof(const char *str); s тэмдэгт мөрд агуулагдаж байгаа цифрүүдийн дарааллыг double төрлийн утгад хөрвүүлж буцаана.
2. atoi
int atoi(const char *str); s тэмдэгт мөрд агуулагдаж байгаа цифрүүдийн дарааллыг int төрлийн утгад хөрвүүлж буцаана.
3. atol
long int atol(const char *str); s тэмдэгт мөрд агуулагдаж байгаа цифрүүдийн дарааллыг long төрлийн утгад хөрвүүлэн буцаана.
4. strtod
double strtod(const char *str, char **endptr); s тэмдэгт мөрд агуулагдаж байгаа цифрүүдийн дарааллыг double төрлийн утгад хөрвүүлнэ. Сул зай, таб, enter зэрэг тэмдэгтүүдийг тооцдоггүй. Хөрвүүлж болохгүй сүүлийн элементүүдийг *endp заагч агуулна.
5. strtol
long int strtol(const char *str, char **endptr, int base);
s тэмдэгт мөрд агуулагдаж байгаа цифрүүдийн дарааллын long төрлийн утга хөрвүүлэх боломжтой эхний утгуудыг хөрвүүлнэ.
Сул зай, таб, enter зэрэг тэмдэгтүүдийг тооцдоггүй. Хөрвүүлж болохгүй сүүлийн элементүүдийг *endp заагч агуулна. Хэрэв base нь 0 бол 10-тын тооллын системд хөрвүүлэлтийг хийнэ.
6. strtoul
unsigned long int strtoul(const char *str, char **endptr, int base);
Энэ нь s-ийг unsigned long утга руу хөрвүүлдэг.
Сул зай, таб, enter зэрэг тэмдэгтүүдийг тооцдоггүй. Эхний хөрвүүлэгдэхгүй тэмдэгт гарах үед хөрвүүлэлтийг зогсооно.  
Санах ойтой ажиллах функцууд
1. calloc
void *calloc(size_t nitems, size_t size);             хэрэгцээтэй санах ойг хуваарилан эхлэх хаягийг буцаана. Хэрэв санах ой авч чадахгүй бол null утга буцаана.
2. free
void free(void *ptr);             энэ функц нь calloc, malloc, болон realloc функцуудын тусламжтайгаар хуваарилагдсан *p заагчийн зааж байгаа санах ойг чөлөөлнө.  
3. malloc
void *malloc(size_t size);              санах ойд size хэмжээтэй санах ойг хуваарилж хаягийг буцаана. Хэрэв  санах ойг нөөцөлж чадахгүй бол NULL утга буцаана.
4. realloc
void *realloc(void *ptr, size_t size);
энэ функц нь *p заагчаар хаяглагдсан хэмжээ бүхий санах ойн мужийг  size хэмжээтэйгээр шинээр хуваарилна. Санах ойн хуваарилагдсан шинэ мужийн эхлэх хаягийг буцаана. Хэрэв санах ой хуваарилж чадахгүй бол NULL утга буцаана. Хуучин мужийн агуулгыг хэвээр үлдэнэ.
Environment Functions
1. abort
void abort(void);     програмын ажиллагааг таслана.
2. atexit
int atexit(void (*func)(void));
програм энгийнээр тасрах үед функцуудийг бүртгэн авна. Хэрэв 0 биш утга буцсан бол бүртгэл хийгдээгүй гэсэн үг.
3. exit
void exit(int status);            програмын хэвийн ажиллагааг таслана.
4. getenv
char *getenv(const char *name);           name хувьсагчид тохирох орчны хувьсагчийн утгыг буцаана.
5. system
int system(const char *string);    s тэмдэгт мөрийг хөрвүүлэлтийн орчинд дамжуулна.
Хайх болон эрэмбэлэх функцууд
1. bsearch
void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *));
энэ функц нь хоертын хайлтыг гүйцэтгэх ба массиваас key утгыг хайна. Compar функцийн тусламжтайгаар хайж буй элементийн утгаас массивын элементийн утга  утга бага байх үед сөрөг, тэнцүү үед 0, их үед эерэг утга буцаж байх естой. Хэрэв хайж байгаа утга массивт байгаа бол элементийн заагч, байхгүй өол NULL утга буцаана.
bsearch функцыг хэрэглэх
#include <stdio.h>    /* mzb2_07d3.c */
#include <stdlib.h>
#include <conio.h>
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
int array[] = { 15,117,232,332,456,567,678,789};
#ifdef __cplusplus
extern "C"
#endif
int intcmp (const void *p1, const void *p2)
{ return (*(int *) p1 -*(int *) p2); }
void main()
{   int *pointer;
    int key = 567;
    pointer = (int *) bsearch (&key, array,
                  SIZE(array), sizeof(int), intcmp);
    if (pointer)
       printf ("[% d] is in array \n", key);
    else
       printf ("[% d] is not in array \n", key);
    getch();
}
2. qsort
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*));
массивын элементүүдийг эрэмбэлнэ. Массивын элементүүд нь compar функцийн тусламжтайгаар өсөхөөр эрэмбэлэгдэнэ.
Си хэлний <stdlib.h> толгой файлын rand() функцийг ашиглахад 0..32767 завсраас санамсаргүй тоо буцаадаг.
Жишээ-3. Шугаман массивын элементүүдийг буурахаар эрэмбэлж хэвлэ.
#include <stdio.h>
#include <stdlib.h>
main()
{ int a[100],i,j,m,n;
  printf("n="); scanf("%i",&n);
  for (i=0;i<n;i++) a[i]=rand()%500;
  printf("\n Oruulsan massiv:\n");
  for (i=0;i<n;i++) printf("%  i",a[i]);
  printf("\n");
  for (i=0;i<n-1;i++)
      for (j=i+1;j<n;j++)
          if (a[i]>a[j])
             { m=a[i];a[i]=a[j];a[j]=m; }
  printf("\n Erembelegdsen massiv:\n");
  for (i=0;i<n;i++) printf("%  i",a[i]);
  printf("\n");
  getch();
  return 0;
}
11.Хэрэглэгчийн Header үүсгэх
·         Модуль буюу проект үүсгэх шаардлага
·         .h өргөтгөлтэй текст файл
·         .h өргөтгөлтэй функцуудын файл
·         Хэрэглэгчийн толгой файлыг програмд ашиглах
Олон дахин хэрэглэглэх функцуудээр header файл үүсгээд, түүнийгээ програмдаа хавсарган ашиглах нь илүү тохиромжтой байдаг. Хэрэглэгчийн header файл үүсгэх нь дараах алхамуудтай. Үүнд:
1.     Хэрэглэгчийн толгой файлд тодорхойлогдох функцуудын тодорхойлолт буюу функцуудын толгой (prototype) –г агуулсан .h өргөтгөлтэй текст файл үүсгэх. Хэрэглэгчийн толгой файлын код дараах байдалтай байна.
#ifndef  <идентификатор>
#define  <идентификатор>
      //тогтмол
      //төрөл
      //функцийн толгой /prototype/
#endif
2.     Тодорхойлсон функцуудын кодыг агуулсан .cpp файл үүсгэх, энэ нь өмнө үүсгэх .h өргөтгөлтэй файлтай ижил нэртэй байх ёстой. Энд үүсгэх файл нь зөвхөн функцуудын кодыг агуулсан байх болно. Энэ програмын кодонд main() функц тодорхойлогдож болохгүй.
3.     Уг толгой файлыг програмд хавсарган бодлогод ашиглах
Програмд хавсаргахдаа #include директивийг ашиглана.   #include “file1.h”
Бодлого:
  1. Натурал n тоо өгөгдсөн. Энэ тооны эхний ба эцсийн цифрүүдийн ялгаврыг ол.
  2. Натурал n тоо өгөгдсөн. Энэ тооны эхний ба эцсийн цифрүүдийн байрыг соль.
  3. Натурал n тоо өгөгдсөн. Хэрэв бололцоотой бол k гэсэн цифрийг энэ тооны өмнө хойно нь залган бич.
  4. Өгөгдсөн натурал тооны аравтын бичиглэл дэх хамгийн том цифрийг ол.
  5. натурал n тоо өгөгдсөн. Энэ тооны цифрүүдээс зохиож болох хамгийн их утгатай тоог гарган авахаар цифрүүдийнх нь байрыг сэлгэ.
Эдгээр бодлогуудын алийг нь ч бодоход өгөгдсөн натурал тооны цифрүүдийн тоог буцаах функц болон натурал тоог зэрэг дэвшүүлэх функц зайлшгүй шаардлагатай болох ба эдгээр функцуудыг агуулсан хэрэглэгчийн header файл үүсгэе.

#include "my.h"

 int digits(int n)
 { int k=0;
while(n!=0)
{k=k+1;
n=n/10;}
 return k; }
long power(long a, long n)
 { int i; long st=1;
for(i=1;i<=n;i++)st=st*a; return st; }
Бодолт:
my.h текст файл

#ifndef MyHeader
#define MyHeader
 int digits(int n);
long power(long a, long n);
 #endif
Тодорхойлсон функцуудын кодуудыг агуулсан my.c файл: Уг толгой файлыг програмд хавсарган бодлогод ашиглах: /bod1.c файл/
#include <stdio.h>
#include "my.h"
 main()
 { int n,k,k1,s,t;
 printf("olon orontoi natural n toog oruulna uu?n");
scanf("%d",&n);
t=digits(n);
 k=n%10;
k1=n/power(10,t-1);
 printf("%d toonii negjiin ornii tsifr ni: %dn", n, k)
; printf("ahlah ornii tsifr ni: %dn", k1); i
f(k>=k1)s=k-k1; else s=k1-k; printf
("ehnii ba etssinn tsifruudiin yalgavar ni: %dn", s);
 return 0; }

Програмаа биелэх файлд хөрвүүлэхдээ DOS-ийн командын мөрд
 bcc  bod1.c  my.c  
гэж өгөхөд bod1.exe файл үүсэх болно. 
#include <stdio.h
 #include "my.h"
main() { int n,k,k1,s,t;
printf("olon orontoi natural n toog oruulna uu?n");
scanf("%d",&n);
 t=digits(n);
 k=n%10;
 k1=n/power(10,t-1);
s=k*power(10,t-1)+n%power(10,t-1)/10*10+k1;
 printf("ehnii ba etssiin tsifriig colison ni: %dn", s);
return 0;
 }