Басылым №1 09. 2015ж беттің і


Дәріс №10. Деректердің күрделі типтері: массивтер



бет4/5
Дата07.07.2016
өлшемі1.38 Mb.
#183441
1   2   3   4   5

Дәріс №10. Деректердің күрделі типтері: массивтер


  1. Массив дегеніміз не? Массив қызметтері және сипатталуы.

  2. Массивтің инициялизациялануы.

  3. Массив элементтерімен жұмыс жасау.

  4. Символдық массивтер.

  5. Көп өлшемді массивтер.


Массив дегеніміз не? Массив қызметтері және сипатталуы.

Массив дегеніміз - бір атпен аталған, әртүрлі индекстелген бір типті элементтер жиынтығы.

Қасиеттері:

Массивтің қасиеттерін анықтайтын 4 негізгі принципі бар:

-массивте элементтер деп аталатын мәндер сақталады;

-массивтің барлық элементтері бір типті болуы керек;

-жадыда массивтің барлық элементі тізбектеліп орналасады және бірінші элемент адрестің нөлдік индексін білдіреді;

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



Mассивтің сипатталуы:

<элементтің типі> <массив аты> [<элементтер саны>];

Мысалы, int a[12]; {12 элементтен тұратын массив}

char s[20]; {20 элементтен тұратын массив}

#define KOL 10 {}

int [KOL];
Массивтің инициялизациялануы.
Массивті инициялизациялау 3 тәсілмен анықталады:

- массивті құру барысында;

- массивті құру барысында бастапқы тұрақтыларды көрсету;

- программаның орындалу барысында;

- құру барысында массивтің бастапқы мәндері берілмесе, онда автоматты түрде массив 0-мен толтырылады (NULL).

Мысалдар:

int a[3]={-1,0,1};

char buk [ ]={‘A’,’.’,’*’,’-‘,’!’,’i’,’u’};

float x[4]={0,1.5,7.55,-3.3E1,0,1.1457890,-1.1};

Массив элементінің саны мәндер санына сәйкес келмесе (3-ші мысал) көпшілік компиляторда қате хабарланады, ал кейбірі автоматты түрде өлшемін үлкейтеді немесе жетпесе (мән) 0-мен толықтырылады. 2-ші мысалда массивтің элементтер саны мәндері санына қарай анықталады.


Массив элементтерімен жұмыс жасау.
Массив элементтерін қолдану үшін квадрат жақшада бүтін мәнді индекс көрсетіледі. Мұндағы индекс массивтің базалық адресіне қарағанда элементтің орнынының ығысу адресін анықтайды. С/С++ машиналық-бағытталған тіл болғандықтан массивтің бірінші элементті 0-ші индекстен басталып нөмірленеді, себебі массивтің бірінші элементті оның базалық адресінің басынада орналасады да бірінші элементтің адресін алу үшін ешқандай ығысу жасалудың қажеті жоқ. Мысалы, 5-ші элементтің адресін алу үшін базалық адрестен бастап, 4 элементке ығысу орындалуы тиіс. Массивпен жұмыс жасауда алдымен массив сипатталады. Мұнда квадрат жақшада оның элементтерінің саны көрсетіледі, ол өз кезегінде жадыдан бөлінетін ұяшықтар санын анықтайды.

Мысалы:


Int imas[6];

Сипатталуына сәйкес анықталған массивтің элементтерінің саны -6 және элементтері 0-ден 5-ке дейін индекстелгендіктен мынадай қолданылу жолы дұрыс болмайды:

Imas[6]=3667;

Массив элементін қолданғанда индекс ретінде үш түрлі мән беруге болады:



  • Сандық тұрақты.

  • Айнымалы.

  • Өрнек.

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

Қолданылу мысалдары:

#define K 8

int imas[k]; /*8 элементтерен тұратын массив сипаты */

int w=6; /* w бүтін типті айнымалысының сипаты*/

imas[3]; /*массивтің 4-ші элементті */

imas[w]; /* массивтің 7-ші элементі */

imas[k-6]; /*массивтің 3-ші элементі */ Индекс массивтің жадыдан қанша байт орын алатынынан тәуелсіз тікелей реттік нөмініне сілтейді.



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

Символдық массивті енгізу және инициализациялау мысалдарына программа келтірейік:

#include

main ()


{

char pan[12], razm[5];

static char opr[11]=”информация”;

razm[0]=’б’;

razm[1]=’а’;

razm[2]=’й’;

razm[3]=’т’;

razm[4]=\o’;

printf(“\n информатика сөзін енгізіңіз:“);

scanf(“%s”, pan);

printf(“\n %s \n”, pan);

printf(“\n %s \n”, razm);

printf(“\n %s \n”, opr);
}

Көріп отырғанымыздай символық массивке енгізілетін жолдық мәннің ұзындықтары бірге арттырылып алынып отыр. Ол орын жолдың соңы таңбасына арналады. Инициализациялау барысында ол таңб арнайы қойылады.


Көп өлшемді массивтер
Бір типті элементтер жиынтығын өңдеуде олардың жадыда санына қарай және элементтерін қолдану моделіне қарай анықтап сипаттау мүмкіндігі бар. Соған байланысты массивтің өлшемі анықталады деп есептеледі. Демек, индекстерінің көрсетілуіне қарай бір өлшемді, екі өлшемді т.с.с. массивтерді анықтауға болады. Екі немесе одан да көп өлшемді массивтеркөп өлшемді массивтер деп аталады. Сәйкес өлшемде сипттау үшін квадрат жақшаларда олардың өлшемдері көрсетіледі. Мысалы, екі өлшемді массив екі квадрат жақшамен анықталып төмендегідей сипатталады:

float massiv[3][4];

Мұндағы massiv массив атауы, ал массивтің 12 элементі бар, массив 0-ден 2-ге дейін индекстелетін 3 жолдан және 0-ден 3-ке дейін индекстелетін 4 бағаннан тұрады.

Практикада массив өлшемі көбінесе үш өлшемдіден аспайды. Массивті екі өлшемді түрде сипаттағанмен ол ЭЕМ жадысында тізбектелген бірдей типті мәндер тізбегі ретінде орналатырылады да, массивтің алғашқы элементінің орынының адресі-базалық адресі массив атуына беріледі. Жалпы массив атауы - өз бетінше көрсеткіш болып табылады.

С/С++ тілдерінде практикада математикалық матрица түрінде анықталатын есептерді қарастырғанда көп өлшемді массив құру міндетті емес. Оны бір өлшемді массив түрінде ұйымдастыруға болады. Ал, элементтерін ретімен қолдану үшін оның реттік нөмірін сәйкес анықтау формуласын дәл анықтаса жеткілікті. Себебі компьютерде көп өлшемді массив түрінде сипатталғаныменбірдей элементтер тізбегі басқарылады.

Мысалы, a[3,4] массивінің a[і,j] –ші элементін қолдану ретін қарастырайық. Ол үшін 12 элементтен тұратын бір өлшемді массивті төмендегідей сипаттайық:

Float a[12];

Ал, a[і,j] –ші элементін мына түрде өрнектеледі - a[i*4+j].

Мысалы, 2 жолы мен 3 бағанының қиылысуындағы элементті қолдану үшін оның a[1][2] индекстерімен анықталатыны белгілі. Ал жоғарыдағы a[i*3+j] өрнегіне қоятын болсақ a[1*4+2]=a[6] болады. Бұдан екінші жолдың 3-ші элементті тізбекте 7-ші екендігін, ал оны қолдану үшін массивтің базалық адресіне қарағанда 6 элементке жылжу қажеттігін аңғару қиын емес.
Дәріс №10.Өзін-өзі тексеру сұрақтары немесе тестер


  1. Массив атауы айнымалы ма?

  2. Массивтің нөлден бастап нөмірленуі неден тәуелді?

  3. Көп өлшемді массивтің бір өлшемді массив ретінде басқарылуына мән беріңіз.


Дәріс №11. Деректердің күрделі типтері: массивтер


  1. Массив дегеніміз не? Массив қызметтері және сипатталуы.

  2. Массивтің инициялизациялануы.

  3. Массив элементтерімен жұмыс жасау.

  4. Символдық массивтер.

  5. Көп өлшемді массивтер.


Массив дегеніміз не? Массив қызметтері және сипатталуы.

Массив дегеніміз - бір атпен аталған, әртүрлі индекстелген бір типті элементтер жиынтығы.

Қасиеттері:

Массивтің қасиеттерін анықтайтын 4 негізгі принципі бар:

-массивте элементтер деп аталатын мәндер сақталады;

-массивтің барлық элементтері бір типті болуы керек;

-жадыда массивтің барлық элементі тізбектеліп орналасады және бірінші элемент адрестің нөлдік индексін білдіреді;

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



Mассивтің сипатталуы:

<элементтің типі> <массив аты> [<элементтер саны>];

Мысалы, int a[12]; {12 элементтен тұратын массив}

char s[20]; {20 элементтен тұратын массив}

#define KOL 10 {}

int [KOL];
Массивтің инициялизациялануы.
Массивті инициялизациялау 3 тәсілмен анықталады:

- массивті құру барысында;

- массивті құру барысында бастапқы тұрақтыларды көрсету;

- програманың орындалу барысында;

- құру барысында массивтің бастапқы мәндері берілмесе, онда автоматты түрде массив 0-мен толтырылады (NULL).

Мысалдар:

int a[3]={-1,0,1};

char buk [ ]={‘A’,’.’,’*’,’-‘,’!’,’i’,’u’};

float x[4]={0,1.5,7.55,-3.3E1,0,1.1457890,-1.1};

Массив элементінің саны мәндер санына сәйкес келмесе (3-ші мысал) көпшілік компиляторда қате хабарланады, ал кейбірі автоматты түрде өлшемін үлкейтеді немесе жетпесе (мән) 0-мен толықтырылады. 2-ші мысалда массивтің элементтер саны мәндері санына қарай анықталады.


Массив элементтерімен жұмыс жасау.
Массив элементтерін қолдану үшін квадрат жақшада бүтін мәнді индекс көрсетіледі. Мұндағы индекс массивтің базалық адресіне қарағанда элементтің орнынының ығысу адресін анықтайды. С/С++ машиналық-бағытталған тіл болғандықтан массивтің бірінші элементті 0-ші индекстен басталып нөмірленеді, себебі массивтің бірінші элементті оның базалық адресінің басынада орналасады да бірінші элементтің адресін алу үшін ешқандай ығысу жасалудың қажеті жоқ. Мысалы, 5-ші элементтің адресін алу үшін базалық адрестен бастап, 4 элементке ығысу орындалуы тиіс. Массивпен жұмыс жасауда алдымен массив сипатталады. Мұнда квадрат жақшада оның элементтерінің саны көрсетіледі, ол өз кезегінде жадыдан бөлінетін ұяшықтар санын анықтайды.

Мысалы:


Int imas[6];

Сипатталуына сәйкес анықталған массивтің элементтерінің саны -6 және элементтері 0-ден 5-ке дейін индекстелгендіктен мынадай қолданылу жолы дұрыс болмайды:

Imas[6]=3667;

Массив элементін қолданғанда индекс ретінде үш түрлі мән беруге болады:



  • Сандық тұрақты.

  • Айнымалы.

  • Өрнек.

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

Қолданылу мысалдары:

#define K 8

int imas[k]; /*8 элементтерен тұратын массив сипаты */

int w=6; /* w бүтін типті айнымалысының сипаты*/

imas[3]; /*массивтің 4-ші элементті */

imas[w]; /* массивтің 7-ші элементі */

imas[k-6]; /*массивтің 3-ші элементі */ Индекс массивтің жадыдан қанша байт орын алатынынан тәуелсіз тікелей реттік нөмініне сілтейді.



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

Символдық массивті енгізу және инициализациялау мысалдарына программа келтірейік:

#include

main ()


{

char pan[12], razm[5];

static char opr[11]=”информация”;

razm[0]=’б’;

razm[1]=’а’;

razm[2]=’й’;

razm[3]=’т’;

razm[4]=\o’;

printf(“\n информатика сөзін енгізіңіз:“);

scanf(“%s”, pan);

printf(“\n %s \n”, pan);

printf(“\n %s \n”, razm);

printf(“\n %s \n”, opr);
}

Көріп отырғанымыздай символық массивке енгізілетін жолдық мәннің ұзындықтары бірге арттырылып алынып отыр. Ол орын жолдың соңы таңбасына арналады. Инициализациялау барысында ол таңб арнайы қойылады.


Көп өлшемді массивтер
Бір типті элементтер жиынтығын өңдеуде олардың жадыда санына қарай және элементтерін қолдану моделіне қарай анықтап сипаттау мүмкіндігі бар. Соған байланысты массивтің өлшемі анықталады деп есептеледі. Демек, индекстерінің көрсетілуіне қарай бір өлшемді, екі өлшемді т.с.с. массивтерді анықтауға болады. Екі немесе одан да көп өлшемді массивтеркөп өлшемді массивтер деп аталады. Сәйкес өлшемде сипттау үшін квадрат жақшаларда олардың өлшемдері көрсетіледі. Мысалы, екі өлшемді массив екі квадрат жақшамен анықталып төмендегідей сипатталады:

float massiv[3][4];

Мұндағы massiv массив атауы, ал массивтің 12 элементі бар, массив 0-ден 2-ге дейін индекстелетін 3 жолдан және 0-ден 3-ке дейін индекстелетін 4 бағаннан тұрады.

Практикада массив өлшемі көбінесе үш өлшемдіден аспайды. Массивті екі өлшемді түрде сипаттағанмен ол ЭЕМ жадысында тізбектелген бірдей типті мәндер тізбегі ретінде орналатырылады да, массивтің алғашқы элементінің орынының адресі-базалық адресі массив атуына беріледі. Жалпы массив атауы - өз бетінше көрсеткіш болып табылады.

С/С++ тілдерінде практикада математикалық матрица түрінде анықталатын есептерді қарастырғанда көп өлшемді массив құру міндетті емес. Оны бір өлшемді массив түрінде ұйымдастыруға болады. Ал, элементтерін ретімен қолдану үшін оның реттік нөмірін сәйкес анықтау формуласын дәл анықтаса жеткілікті. Себебі компьютерде көп өлшемді массив түрінде сипатталғаныменбірдей элементтер тізбегі басқарылады.

Мысалы, a[3,4] массивінің a[і,j] –ші элементін қолдану ретін қарастырайық. Ол үшін 12 элементтен тұратын бір өлшемді массивті төмендегідей сипаттайық:

Float a[12];

Ал, a[і,j] –ші элементін мына түрде өрнектеледі - a[i*4+j].

Мысалы, 2 жолы мен 3 бағанының қиылысуындағы элементті қолдану үшін оның a[1][2] индекстерімен анықталатыны белгілі. Ал жоғарыдағы a[i*3+j] өрнегіне қоятын болсақ a[1*4+2]=a[6] болады. Бұдан екінші жолдың 3-ші элементті тізбекте 7-ші екендігін, ал оны қолдану үшін массивтің базалық адресіне қарағанда 6 элементке жылжу қажеттігін аңғару қиын емес.
Дәріс №11.Өзін-өзі тексеру сұрақтары немесе тестер


  1. Массив атауы айнымалы ма?

  2. Массивтің нөлден бастап нөмірленуі неден тәуелді?

  3. Көп өлшемді массивтің бір өлшемді массив ретінде басқарылуына мән беріңіз.


Дәріс №12. Деректердің құрылымы (структурасы)


  1. Структуралар түсінігі

  2. Структуралар мен функциялар

  3. Структуралар массиві

  4. Структураларға көрсеткіш

1 Структуралар түсінігі

Структура – бір атпен біріктірілген бір немесе бірнеше әр түрлі типті айнымалылар тобы. Структура struct қызметші сөзімен құрылады. Структураның жалпы құрылымы төмендегідей:

struct тег {

тип1 иден1;

тип2 иден2;

… …

типN иденN;



};

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

Сипатталған структура негізінде айнымалы құру үшін

struct <тег> <айнымалы>

С++ тілінде struct қызметші сөзін көрсетпесе де болады:

<тег> <айнымалы>

Айнымалыны структураны құру кезінде де анықтауға болады:

struct тег {

тип1 иден1;

тип2 иден2;

… …


типN иденN;

} <айнымалы>;

Егер структура типті басқа айнымалылар құрылмайтын болса, структура тегінкөрсетпеуге болады. Мұндай структура атаусыз (безымянный) деп аталады:

struct {


тип1 иден1;

тип2 иден2;

… …

типN иденN;



} <айнымалылар тізімі>;

Сипаттау мысалы:

Struct strtype {

Char fam[25];

Char gor[20];

Int god;


Float zarp;

};

Мұнда strtype атты структура құрылды. Осы структура арқылы айнымалы төмендегідей сипатталады:



Struct rab strtype;

Немесе былайша да сипаттауға болады:

Struct strtype {

Char fam[25];

Char gor[20];

Int god;


Float zarp;

} rab;


Структуралар іштестірілген де болуы мүмкін:

struct тег1 {

тип1 иден1;

тип2 иден2;

тип3 иден3;

};

struct тег2 {



тип1 иден1;

тип2 иден2;

struct тег1 иден3;

};

Қолданылу мысалы:



struct adr {

char ul[20];

int dom;

int kb;


}

struct adam {

char fam[25];

struct adr;

}
Сәйкесінше айнымалыны сипаттау мысалы:

struct adam sotr;

ал, қолданылу мысалы:

sotr.adr.dom=5;

Коріп отырғанымыздай структура элементтерін нүкте операторының көмегімен алуға болады, форматы мынадай:

<айнымалы>.<элемент>

Структура элементтері циклда енгізілгенде _flusshall() –функциясы кіріс легіндегі жаңа жол символын өшіруге, яғни буферді тазалауға қолданылады. Жаңа жол символы scanf( ) функциясын қолданғанда қойылады. Ал, gets( ) функциясы бұл таңбаға дейінгі символдарды ғана оқиды.


&&&

$$$002-012-002$3.2.12.2 Стуктуралар мен функциялар

Кейбір жағдайларда структураны функция денесінде қолдану қажеттігі туындайды. Ондай жағдайда функция прототипінде структураны функция параметрі ретінде беру керек (С++ тілінде struct қызметші сөзін көрсету міндетті емес):

// С және С++ тілдерінде



<функция типі> <функция аты> (struct <тег> <айнымалы>)

// Тек қана С++ тілінде



<функция типі> <функция аты> (<тег> <айнымалы>)

Структура элементтерінің тұрақты тізімін беруге немесе инициализациялауға болады.

Struct adam sotr={“Романов”, “Айболова”,34,50}

Функцияға структура типті объектіні беру тәсілдері үш түрлі:



  • Компоненттерін жеке-жеке беру.

  • Структураны толығымен беру.

  • Структураға көрсеткішті беру.

Компоненттерін жеке беру мысалы:

Struct adr funrpr(char r[20], int k, int d)

{

Struct adr f;



f.ul=r;

f.dom=d;


f.kb=k;

return f;

}
Структуралар массиві
Структуралар массивін сипаттау структура типті айнымалыны сипаттауға ұқсас. Мысалы, struct <тег> <айнымалы-массив>.

Сипаттау ретін төмендегі мысалдан нақты аңғаруға тырысыңыз:

#define N 10

struct mas {

char group[8];

int count;

int otest;

} stud[N];

Немесе бірге тағайындау арқылы төмендегідей де сипатталады:

#define N 3

struct mas {

char group[8];

int count;

int otest;

} stud[N] = {“MKO4”,23,2,

“IKO3”,19,3,

“IKO2”, 23,2

}

Мұндай массивтер өлшемі компиляциялау барысында анықталады. Оның структура элементтерінің өлшемі мен массив элементтерінің санының көбейтіндісіне тең.


Структураларға көрсеткіш
Көрсеткіш келесі түрде сипатталуы мүмкін:

struct <тег> *<айнымалы>

Бұндай жағдайда структуралық айнымалының кез-келген элементін мына әдістердің бірімен алуға болады:

(*<айнымалы>).<элемент> немесе <айнымалы> –> <элемент>

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

Сипаттау мысалдары:

Struct strtype *p;

Мұндағы р айнымалысы strtype типті структураға көрсеткіш деп аталады. Ал, *р – структураның өзі, оның элементтері (*p).dom, (*p).god түрінде қолданылады.

Көрсеткішті пайдалану жолдары:

Struct strtype sotrudn, *p;

P=&sotrudn;

Printf(“sotrudn info: %s \t %i \t %6.2f \n”, (*p).fam, (*p).god, (*p).zarp);

Мұнда (*р).fam бейнесінде жақша міндетті түрде болуы тиіс, себебі нүкте (.) операторының приоритеті * операторының приоритетінен жоғары. Структураларға көрсеткіштер жиі қолданылады. Сондықтан оның элементтерін қолдану барысында ыңғайлы болатын қысқаша жазу формасы қарастырылған. Оның түрі мынадай:

P - ><структура элементі>

Жоғарыдағы мысалдағы шығару жолы осы жазу формасын қолданып төмендегідей жазылады:

Printf(“sotrudn info: %s \t %i \t %6.2f \n”, p->fam, p->.god, p->zarp);

Нүкте және -> операторларының орындалу реті солдан оңға қарай және приоритеттері басқа операторлардан жоғары. Қолдану барысында осы қасиетін мұқият ескеру қажет.

Әртүрлі уақытта әрүрлі типті және әртүрлі өлшемді обьектілерді сақтай алатын айнымалы –біріктіру деп аталады. Өлшемдеріне және реттеуге қатысты талаптарды компилияция орындайды. Жадының бір аймағында әртүрлі мәндерді сақтауға мүмкіндіктері бар.

Біріктіру синтаксисі структура синтаксисі секілді:

Union unprim {

Int iman;

Float fman;

Char *sman;

} mainun;

Си тілінде мәндер типіне жаңа атау беруге болатын құрал - typedef құралы бар.
Дәріс №12.Өзін-өзі тексеру сұрақтары


  1. Структуралар не үшін құрылады?

  2. Структуралар элементтері қандай типті бола алады?

  3. Структуралар элементтерін енгізу-шығаруда басқару элементтерінің қойылу реттері қандай?

  4. typedef құралы не үшін қолданылады?


Дәріс №13. Файлдар



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

Ал, файлға көрсеткіш файл туралы информациялардан тұратын құрылымға (жазбаға) сілтейді. Мұндағы информация мынадай сұрақтарының жауабынан тұрады:

 буфер адресі,

 буфердегі ағымды литердің күйі,

 файлдан оқуға немесе жазуға ашық па?,

 файлдың соңғы таңбасы кездесті ме?

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

FILE * fp;

FILE * fopen (char * name, char * m);

Мұндағы: fp – FILE типіндегі көрсеткіш, ал fopen FILE – ге көрсеткішті қайтарады. Fopen функциясы мына түрде қолданылады:

fp = fopen (name, m);

Мұндағы: name – файлдың атын меншіктейтін жол; ал, m – файлды қолдану режимі; яғни бұл да жол, қолданушы файлды қалай қолданатынын білдіреді, төмендегідей мәндердің бірін иелене алады:

" r " – (read) оқу режимі;

" w "- ( write) жазу;

" a "- ( apprnd) толықтыру;

Кейбір жүйеде тексттік және бинарлық файлдар болып жіктеледі, бұл жағдайда режим жолына "в" (binary – бинарлық) немесе “t”(тексттік) таңбасы тіркеледі. Файлмен жұмыс жасау барысында қате кездессе, онда fopen функциясы NULL мәнін қайтарады.

Мысалы, FILE*fin, * fout;

fin=fopen (“PRIMER.dat”,”’r”);

fout=fopen (“RESULT.dat”, “w”);

1-ші жолда 2:fin,fout – файл көрсеткіші құрылады, ал төменгі жолдарда сәйкесінше оқуға және жазуға арналған файлдар ашылады.

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

- текстік;

- екілік;

Текстік режимде ашу үшін режимді көрсеткенде қасына «t» символын тіркеу арқылы жүзеге асады;

Режимдер кестесі:


Режим

Сипаты

а

а+

r



r+

w

w+



Файл мәндерімен толықтырылуы үшін ашылады. Егер файл

жоқ болса, ол құрылады. Жаңа мән соңына тіркеледі;

Жоғарыдағы секілді, тек оқұға да болады;

Файлды тек оқу үшін ашады, файл жоқ болса, ашылмайды;

Файлды оқуға да, жазуға да болады;

Жаңа файл ашады, бұрын бар болса, мәнін өшіреді.

Жаңа файлды мән жазуға да, одан оқуға да мүмкіндік

береді. Файл болса, мәні тазартылады.



R+,w+,a+ режимдерін қолдануда, яғни оған оқуды және жазуды бір уақытта орындалу барысында файл көрсеткішінің Fsetpos(), fseek(), немесе rewind()файлдары көмегімен ағымды позицияларын модификациялау керек. Программа жұмысы аяқталғанда Си-де автоматты түрде барлық ашық файлдар жабылады, ал файлды жабу үшін fclose(fin) қолданылады.

С++ тілінде:

Файлмен мәлімет алмасу мақсатында ifstream және ofstream кластарын қолданған тиімді. Ол үшін < fstream. h > тақырыптық файлы ашылуы тиіс. Мұнда, сәйкесінше, ifstream класының объектісі myof және ostream класының mygf лектері құрылып көрсетілген файлмен байланысады.

Мысалы,

Ifstream myof(“prim.in”,ios::in);



Ofstream mygf(“prim.out”,ios::out);

 Бір объектімен тізбектеп бірнеше лекті байланыстыру қажет болса, онда ол төмендегідей ретпен орындалады:

Ifstream myof;

. . .


myof(“prim.in”);

. . .


myof.close();

myof.open (“prim2.in”);

. . .

myof.close();



 Файлмен мәлімет алмасу мүмкіндігінің режимін өзгерту – файлдық объектінің сипатындағы екінші аргументін өзгерту арқылы жүзеге асады.

Мысалы, Ofsetream myof ( “prim.in”,ios::app | ios::nocreate); - мұндағы файл бар болса ғана myof объектісі құрылып, байланыс орнатылады, себебі ios::nocreate аргументі берілген, яғни файл болмаса, объект құрылмайтынын білдіреді. Ал, ios::app аргументі файлға шығарылатын мәндер файлдың соңына қосылатынын анықтайды.

Флаг-аргументтер биттік | - «немесе» амалының көмегімен біріктіріліп анықтала алады.

Файлдық лекті анықтау барысында қолданылатын аргументтерді анықтайтын флагтар төмендегідей:



флаг

Мағынасы

ios::in

Файл оқуға ашылады

ios::out

Файл жазуға ашылады

ios::ate

Объект құрылған соң, ағымды көрсеткіш файлдың

соңына орнатылады



ios::app

Мәндер файлдың соңына жазылады

ios::trunc

Егер файл бар болса, ол тазартылады

ios::nocreate

Файл болмаса, онда объект құрылмайды

ios::noreplace

Файл бар болса, онда объект құрылмайды

ios::binary

Файл екілік режимде ашылады (қалыпты жағдайда

тексттік режим)



feоf (FILE * fp) – функциясы файлдың соңын анықтайды.

Файлды жабу үшін:



Int fclose(FILE *fp) функциясы қолданылады, яғни файлдық көрсеткішпен орнатылған байланысты үзеді.

 Файлмен мәлімет алмасу үшін fstream класының объектісі де қолданылады: Fstream io(“update.dat”, ios::in|ios::app); - бұл жағдайда көрсетілген файл мәліметті оқуға және жазуға ашылады.

Seekg() файлдан оқу ал, seekp() файлға жазу барысында функциялары файлдың ағымды позициясының маркерін басқаруға қолданылады.

Мысалы, io.seekg(5, ios::cur) – оқу барысында маркерді ағымды орынынан 5 байтқа жылжыту;

io.seekg(-7, ios::end)- маркерді соңынан бастап 7 байтқа жылжыту керектігін білдіреді.

Аргументтер:



Io::cur – ағымды орынынан; Io::beg – файл басынан;

Io::end - файл соңынан жылжытылатынын білдіреді.

Файлдың лектік күйін анықтау функциялары:




Функция

Түсініктеме

eof()

Файл соңын кездестірсе, 0-дік емес мән қайтарады

fail()

Лекте қате кездессе 0- ден өзге мән қайтарады

bad()

Енгізу-шығару барысында мағыналы қате кетсе, нөлден өзге

мән қайтарады, онда лекпен жұмыс тоқтатылғаны дұрыс. Лек

күйінің биттік мәндері анықталмаса, 0-ге тең емес мән береді.


rdstate()

Мына тұрақтылардың бірін, яғнм лектің ағымды күйін

анықтайтын мәнді қайтарады:

Ios::goodbit - қате жоқ

Ios::eofbit – файл соңына жетті

Ios::failbit – форматтау немесе түрлендіру қатесі

Ios::badbit - маңызды қате



clear()

0-ге тең болса тазарту


Файлдық енгізу-шығару.
Файлдан оқығанда Pascal-дағы секілді,

fprinf(fin,’формат’, <айнымалы>);

fscanf(fin,'формат', <айнымалы>);

fseek() функциясы:

Жалпы форматы:



Int fseek (FILE *str, long offset, int orig)

М, fseek (f, K, r)

Fseek функциясы f Көрсеткіші арқылы берілген файлдағы ағымды көрсеткішті К байтқа жылжытады. Жылжыту:

- файлдың басынан (r=0)

- ағымды көрсеткіш тұрған (r=1)

- файлдың аяғынан (r=1) басталуы мүмкін.

Си- де r-дің мәні ретінде көрсету үшін қолданылатын 3 const қарастырылған:

SEEK_SET (файл басынан жылжу)

SEEK_CUR(ағымдағы позициядан бастау)

SEEK_END(файл соңынан)

Fseek() функциясы қызметі сәтті аяқталса 0-ді, әйтпесе EOF мәнін қайтарады.

 Ftell()-функциясы файл басынан бастап ығысқан шамамен анықталады, яғни long типті мән қайтарады, ағымды көрсеткіштің рынын анықтайды.

long ftell(FILE*str)

Ftell(f)


 Rewind функциясы ағымды көрсеткішті файлдың басынан орындайды.

rewind(FILE*str);

rewind(f) мынаған сәйкес мәнді қайтарады;

fseek(f, ol, seek_set);

Мысалы:

# include



void main()

FILE *pf; “tect.dat”-да=”ABCD”

Char c;

Long l; {С тілінде 64 кб-өлшенді файлдармен жұмыс жасауға



болады, сондықтан L-long типті. }

pf=fopen (“test.dat”, “r+t”);

c=f getc (pf); {“A”-ны алады}

putchar (c);{“A”-ны экранға шығару}

с=f getc(pf);{“B”-ны оқу}

putchar (c);{“B”-ны экранға шығару}

l=ftell(pf);{ағымы көрсеткіш мәнін меншіктейді,в-оқылғандықтан,L=2}

C= f getc(pf); {c-ны оқып экранға шығару}

putchar(c);

fseek (pf,l,o);{ағымды көрсеткіш”Д”-да тұрған жерінен “С”-ны көрсетуге көшеді,себебі функция басынан 2 бт жылжиды }

с=f getc(pf);

putchar(c); {экранға ''C''-ны экранға шығарады }

fseek (pf,l,o);{ағымды көрсеткіш қайтадан “С''-ға сілтейді,енді оның орнына “Е” файлға жазылады}

fputc (‘E’,pf);

fseek (pf,l,o); {ағымды көрсеткіш файл басына l=2 байтқа байланысты жылжиды,

яғни “E”-ні көрсетеді}

с=f getc(pf); {экранға “Е''-ні шығарады}

putchar (c);

rewind (pf); {ағымды көрсеткіш файл басына көшіріледі.}

c=f getc (pf);

putchar (C);{С-ға файлдан «А» оқылады, экранға шығарады}

нәтижесінде:ABCCEA

get c () –берілген потоктан бір символды оқиды.
&&&

$$$002-013-100$Дәріс №13.Өзін-өзі тексеру сұрақтары


1.Файл дегеніміз не?

2.Файлдық лекті сәйкестендіруді қалай түсінесіз?

3.Файл бойымен жылжу, ағымдық көрсеткішті басқару функциялары қандай?
Дәріс №014. Графика


  • Графикалық режимде жұмыс жасау туралы.

  • Графикалық жүйені инициализациялау.

  • Қателерді өңдеу. Режимдердің ауысуы.


Графикалық режимде жұмыс жасау туралы
Дербес компьютер экраны текстік және графиктік режимдердің бірінде жұмыс істейді. Графикалық режимде жұмыстың қалай жүргізілетінін қарастырайық.

Қазіргі ДК-де, негізінен, растрлық дисплейлер қолданылады. Олардағы бейненің ең кіші элементі болып нүкте – pixel (ағылш., picture element) табылады. Дисплейдің мүмкіндігі – бұл көлденең және тік орналасқан пикселдер саны (стандартты разрешение – 640*480 нүкте). Дисплейде бейнеленетін сурет орталық процессор жадысының бейнежады (видеопамять) деп аталатын арнайы облысында кодталып сақталады. Мәліметтер периодты түрде осы облыстан оқылып, бейнесигналдарға түрлендіріледі де экранда бейнеленеді. Сурет кодтарын бейнесигналдарға түрлендіруді арнайы электрондық схема-бейнеадаптер (видеоадаптер) жүзеге асырады. Ең кең тараған адаптерлер VGA және SVGA. C++ тілінде бейнежадының дербес бөліктеріне енуге, түстерді басқаруға, әр түрлі формада графикалық бейнелер тұрғызуға, текстік хабарламалар шығаруға, курсорды басқаруға мүмкіндік беретін көптеген функциялардын тұратын графикалық кітапхана бар. Бұл функциялардың нақты бейнеадаптерлермен жұмысқа баптау қажетті графикалық драйверді қосу арқылы қол жеткізіледі. Драйвер – бұл ДК-дің құрылғыларын басқаруға арналған арнайы программа. Адаптерлердің барлық түрлері үшін графикалық драйверлер Borland International фирмасымен құрастырылған. Олар BGI (Borland Graphics Interface) кеңеймесімен жеке файлдарда орналасқан. Графикалық драйверді қосу үшін арнайы initgraph() функциясы қолданылады.

Көптеген графикалық функциялар ағымдағы позиция көрсеткіші деген ұғымды қолданады. Ол таңдалған пикселді білдіреді және екі бүтін сан арқылы сипатталады: экранның горизонталь және вертикаль координаттары. Нумерация солдан оңға және жоғарыдан төмен қарай жүргізіледі (нольден бастап).

Мысалы, EGA үшін 640*480 режимінде экран бұрышы мен оның центрінің координаттары мынадай болады




Графикалық жүйені инициализациялау.
1. Драйверді және графикалық режимді таңдау detectgraph (&gd, &gm) функция арқылы орындалады.

2. Драйверді жүктеу, графикалық жүйені инициализациялауды initgraph (&gd, &gm, "BGI-файлдың жолы") функциясы атқарады, мұндағы gd және gm айнымалылары қажет драйвер мен

графикалық режимнің номерлері. Егер ВGI-файлдар ағымдағы директорияда орналасса, онда initgraph()функциясының үшінші параметрі ретінде бос жолды беруге болады initgraph (&gd, &gm, " ");

Графикамен жұмыс жаса барысында мына әрекеттер тізбегі арқылы графиктік режимді орнату жолдары жазылады:

#include

#include

#include

void main ( )

{ int gd, gm, error;

detectgraph (&gd, &gm);

initgraph (&gd, &gm,” ”);

error=graphresult ( );

if (error !=grOk )

{ puts ("ошибка графики");

puts (grapherrormsg (error));

exit (1);

}

……………………………. // Программа денесі



closegraph ( );

exit (0) ;

}

Қателерді өңдеу. Режимдердің ауысуы.

1.Графикамен жұмыс жасағанда қате жағдайларды өңдеу үшін graphresult ( ); функциясы қолданылады. Ол соңғы қолданылып отырған графикалық функцияның аяқталу кодын қайтарады. Қате болмаса, «0» қайтарылады. Әр түрлі қателер типі үшін өздерінің аяқталу коды қарастырылған:




Тұрақтылар

Қате коды

Хабарлама

GrOK

0

Қате жоқ

GrNoInitGraph

-1

Графика инициализацияланбаған

GrNoLoadMcm

-5

Драйверді жүктеуге жадының

жеткіліксіздігі



GrFontNotFound

-8

Шрифт файлы табылмаған

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

2. Режимдерді ауыстыру. Дисплейлік адаптердің текстік режиміне уақытша ауысу үшін мына функция қолданылады:

restorecrtmode ();

Қайтадан графикалық режимге ауысу setgraphmode (gm) функциясымен жүзеге асырылады.

Ағымдағы драйвер үшін графикалық режимнің максимал мәнінің номерін getmaxmode ()

функциясы арқылы анықтауға болады.

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

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


BLACK

0

Қара

DARKGRAY

8

Қара сұр

BLUE

1

Көк

LIGHTBLUE

9

Ашық көк

GREEN

2

Жасыл

LIGHTGREEN

10

Ашық жасыл

GRAY

3

Сұр

LIGHTCYAN

11

Ашық бирюза

RED

4

Қызыл

LIGHTRED

12

Ашық қызыл

MAGENTA

5

Қызғылт (таңқурай)

LIGHTMAGENT

A


13

Ашық қызғылт (ашық таңқурай)

BROWN

6

Қоңыр

YELLOW

14

сары

LIGHTGRA

Y


7

Ашық сұр

WHITE

15

ақ

Графиктік мәліметтер нақты бір бейнелер арқылы берілетіні мәлім. Тілде бейнелерді тұрғызуға арналған арнайы функциялар қолданылады.


Дәріс №015.Өзін-өзі тексеру сұрақтары
1. Растрлық графика дегеніміз не?

2. Растрлық және векторлық графика айырмашылығы неде?


Дәріс №15. ОБЪЕКТІЛІ-БАҒЫТТАЛҒАН ПРОГРАММАЛАУ (ОБП)


  • Объектілі-бағытталған программалау негізі.

  • Кластар иерархиясы.

  • Объект қасиеттері: инкапсуляция, тұқым қуалау, полиформизм.

  • Конструкторлар мен деструкторлар.

Объектілі-бағытталған программалау негізі.

{Дәріс конспекті)

ОБП элементтері 70-ші жылдарда Симула тілінде модельдеуде қолданылды. Қазірде кең құлаш жайған программалау технологиясына айналып отыр. ОБП негізгі мақсаты – программа құруда деңгейін көтеру. С++ тіліндегіі ОБП негізін қалаушы – Бьярне Страуструн, 80-жылдары Bell Labs компаниясында өңдеген.

С++ тілі объектілермен жұмыс жасауға бағытталған, ал С тілі – структуралық программалауға бағытталған. С++тілінде объект класы тұрақтылар мен айнымалылардан және оларға қолданылатын амалдардан тұрады. ОБП -ды қолданудың негізгі үш ерекшелігі бар:

1. Программа коды ықшамдалады және құрылымы жақсарады.

2. Программаға программалық бағыттарды қосу және алып тастау жеңіл орындалады (программаны модернизациялау жеңіл, яғни онда бар кластың ұрпақ класын құру арқылы жүзеге асырылады).

3. Тиімді құрылған класты кітапханалық файлдар сақтап, оны қажетінше қолдану мүмкіндігі бар. ОБП-да объектілердің байланысы мен өзара әрекеттестігінің схемасын сипаттау арқылы есеп пен оның шешімі қарастырылады.
Кластар иерархиясы.
С++-тегі класс структураның кеңейтілген түрі және объект құруға арналған. С++-тегі класс шаблон секілді, оның негізінде объектілер құрылады. Кез-келген кластың бірнеше ішкі кластары болуы мүмкін. Кластар иерархиясы құрылады, баба класы жалпы сипаттаға әдістерден тұрады. Кластың құрамын арнайы кілттік сөздердің көмегімен реттеуге болады. Олар: public - «ашық», «көрінетін» бөлігі private - «тасаланған» бөлігі («жабық») protected - «қорғалған» бөлігі. «Көрінетін» бөлігіндегі сипатталған әдістер класты қолданатын кез-келген программадан шақырылады, яғни кластың интерфейсін құрайды. «Тасаланған» бөлігіндегі элементтер тек өзінің әдістерінде қолданылады, ал«қорғалған» бөлігіндегі элементтер өз әдістері мен ұрпақ кластарда қолданылады
Объект қасиеттері: инкапсуляция, тұқым қуалау, полиформизм.
Объект – класс экземпляры. Объектінің қасиеттері бар. Оның күйі, оның белгілерінің мәндері арқылы беріледі. Объектінің негізгі қасиеті – инкапсуляция.

Инкапсуляция дегеніміз – бір структурада мәліметтермен қатар оларды өңдеуге арналған функциялардың берілуі (әдістердің).

Тұқым қуалау қасиеті деп баба класынан ұрпақтарына мәліметтер мен әдістердің берілуін атайды.

Егер кластың атрибуттары бір баба кластан берілсе, онда жалғыздық (одиночный) тұқым қуалау деп атайды.

Полиморфизм

Полиморфизм класс иерархиясымен байланысты, иерархиядағы бірнеше класқа бірдей хабарлама беру мүмкіндігінің болуы, яғни қандай кластың қайсысы келген хабарды өңдеу құқығын алатынын анықтау – полиморфизм деп аталады. Бір иерархиядағы әртүрлі класта болатын және бір атпен аталған және virtual қызметші сөзімен сипатталған әдіс виртуальді әдіс деп табылады.

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

Конструктор ролі виртуальді әдісті дұрыс адрестер кестесімен байланыстыру.

Программаны компиляциялау барысында виртуальді функциялар адресі белгісіз, ал виртуальді кесте ұяшықтары белгілі болады да программа орындалу барысында сол ұяшықтарға адрестер жазылады.

Кластың сипатталуы:

class < Аты > {

< тип 1 > < айн 1 >

< тип 2> < айн 2 >
public:

әдіс 1


әдіс 2
әдіс n;

};

<сипаттаушы> <кл. аты> [:базалық тізім] {элементтер тізімі}

Мұндағы - <сипаттаушы> – class, struct, union қызметші сөздернің бірі. Класс аты – идентификатор;

< базалық тізім > -қасиеттері тұқым қуалауға тиісті базалық класс немесе кластар тізімі болады;

{элементтер тізімі} – осы кластың өзіне тән элементтер тізімі беріледі. С++ тілінде класты құрғанда элементтерді бермей-ақ сипаттауға болады,

u class Sorun.

Бұларды класс аттарына сілтеме жасау үшін қолданады, ал объектімен нақтыжұмыс жасауда толық анықталуы тиіс. Автоматты түрде кластың барлық элементтері «жабық» деп есептеледі және олар тек осы класс функцияларында қолданылады. Ал, оларды «ашық» түрдесипаттау үшін public, protected, private қызметші сөздерінің бірін қолдану керек.

Қарапайым класс мысалы:

# include <

# include

class obj_type

{

double data;



public:

void set_v(double ang);

double get_sin(void);

}

obj;



void obj_type :: set_v(double ang) {

data = ang;

}

double obj_type :: get_sin(vold) {



return (sin(0.01*data);

«Комплекс сандар» класын құрайық: Комплекс сандар мен матрицаларын анықтайық:

#include

#include


{exit( ); }

class Complex

{ float Re;

float Im;

public:

void sum (complex, complex);



void Minus (complex, complex);

void Mult (complex, complex);

void Div (complex, complex);

void Get ( );

void Put ( );

};

void complex :: Minus(complex X, complex Y)



{

Re = x.Re – y.Re;

Im = x.Im – Y.Im;

}

Void Complex :: Mult (complex X, complex Y)



{

Re = x.Re*Y.Re – x.Im*Y.Im;

Im = x.Re – Y.Im+x.Im*Y.Re;

}

void Complex :: Div (complex X, complex Y)



{

if (Y.Re\\y.Im)) {

Cout << “0-ге бөлінгендік”;

exit(12); }

Re = x.Re*Y.Re – x.Im*Y.Im;

Im = x.Re* Y.Im + x.Im* Y.Re;

}

void Complex :: Get ( ) {



cont << «Комплекс санның нақты бөлігін енгіз:»;

cin >>Re


cout << «Комплекс санның жорамал бөлігін енгіз»;

cin>>Im


}

void main ( ) {

complex a, b, c;

a. Get ( );

b. Get ( );

c. Sum (a, b);

c. Put ( );

}

Конструкторлар мен деструкторлар.


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

Деструктор – бұл да айрықша функция, жойылатын объект алып тұрған динамикалық жадыны босату қызметін атқарады. Деструктордың да аты класс атымен бірдей, тек алдында ~ (тильда) жазылады. Деструктор – класс объектісіне сілтейтін көрсеткіш арқылы анықталған delete операторы кездескенде шақырылады. Деструктордың конструктордан айырмашылығы ешқандай аргументтен тәуелді емес. Егер деструктор айқын түрде анықталмаса, компилятор класс үшін стандартты деструктор бөледі. Класс деструкторы мен конструкторы С++ тілінде динамикалық жадыны үлестіру және босату үшін сәйкесінше Nen, delete қолданылады.

# include

# include

class string

char * Q string;

int strieng;

public


string (char*);(конструктор)

~ string ( ); }(деструктор)

string ::string (char*init str) {

Q string = new (Q string, init str);

if (!Q string) cont << «Жады жетіспейді»;

strieng:=streen (Q string);

}

string :: ~ string ( );



{

cout << «Жол»

delete Q string;

Q string = (Char *) 0;

cout << “Босатылды \n”; }

void main ( ) {

string First («Алғашқы жол»); First - конструкторды шақыру}

{

string second («Екінші жол»); Second - үшін конструктор шақыру }


Дәріс №15.Өзін-өзі тексеру сұрақтары
ОБП дегеніміз не?

Класс экземпляры дегеніміз не?



Әдістерді қайта анықтаудың қандай тәсілдері бар?


Достарыңызбен бөлісу:
1   2   3   4   5




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет