-->
Главная » Статьи » Информатика

ФУНКЦИЯНЫҢ КӨРСЕТКІШТЕРІ

ФУНКЦИЯНЫҢ КӨРСЕТКІШТЕРІ

 

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

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

Сұрыптау үш бөлімнен тұрады:

-  салыстыруға, жұп объектілердің ретін анықтайтын;

-  алмастыруға, жұп объектілердің ретін керісіншеге алмастыратын;

-  сұрыптаушы алгоритм, барлық объектілер реттелмейінше салыстыру мен алмастыруды жүзеге асырады.

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

 

#include <stdio.h>

#include <string.h>

#define MAXLINES 500               \\ жолдардың максималды саны

char *lineptr [MAXLINES];                  \\ жолдарға көрсеткіштер массив  

int readlines (char *lineptr[ ], int nlines);

void writelines (char *lineptr[ ], int nlines);

void qsort (void* lineptr[ ], int left, int right, int (*comp)(void*, void*));

int numcmp(char*,char*);                    

\\ жолдарды сұрыптау

main (int argc, char*argv[ ])

{  int nlines;                                               \\ оқылған жолдар саны

   int numeric=0;                                        \\ 1, егер сұрыптау сандық мәні бойынша

   if (argc>1 && strcmp(argv[1],”-n”)= =0)

             numeric=1;

   if(( nlines=readlines(lineptr,MAXLINES))>=0)

   {        qsort((void**) lineptr, 0, nlines-1,

(int (*)(void*,void*))(numeric?numcmp:strcmp));

writelines(lineptr,nlines);

return 0;

   }

             else

             {        printf("өте көп \n жолы енгізілген”);

                      return 1;

             }

}

  

qsort, strcmp және numcmp функциясына көңіл аударғанда олардың аттары осы функциялардың адрестері ретінде айтылады. Сондықтан & операторы массивтің атының алдына қажет болмағандықтан, олардың алдарында да керек емес (массив аты мен функция аты – бұл көрсеткіштер).

qsort функциясы тек стрингтерді ғана емес, кез-келген типтегі берілгендерді өңдейді. Прототиптен көрінгендей qsort функциясы өз аргументтері ретінде күтеді: сілтемелер массивін екі бүтін мәнді және функцияны екі аргумент – көрсеткіш ретінде. Аргументтер көрсеткіштері ретінде void* типіндегі жалпыланған көрсеткіштер берілген. Кез-келген көрсеткішті void* типіне және керісінше ақпаратты жоғалтусыз қайта қалпына келтіруге болады. Сондықтан void*аргументтерін алдын-ала түрлендіріп барып қана, біз qsort-пен жұмыс жасаймыз. Салыстыру функциясының ішінде оның аргументтері оған қажетті типке келтіріледі. Шындығында да бұл алмастыруға ешқандай да әсерін аргументтерге тигізбейді, олар тек компилятор үшін типтердің келісімділігін қамтамасыз етеді.

   \\ qsort – сұрыптайды v[left]…v[right] өз ретімен

void qsort (void*v[ ],int left,int right, int (*comp)(void*, void *))

{  int i, last;

void (swap (void *v[ ], int, int);

if (left>=right)  // егер массивтік екі элементтен кем болмасештеме жасалынбайды.

return;

swap (v, left,(left+right)/2);

last=left;

for (i=left+1; i<=right; i++)

if ((*comp)(v[i],v[left])<0)

   swap(v, ++last, i);

    swap (v, left, last);

qsort (v, left, last-1, comp);

qsort (v,last+1, right, comp);

}

qsort функциясының төртінші параметріне көңіл аударыңыз:

             int (*comp)(void*, void*)

Бұл параметр comp  функцияға көрсеткіш және екі аргументі бар көрсеткіш және int типінің нәтижесін хабарлайдыБұдан, comp функцияғакөрсеткіш болғандықтан *comp – функция боладыонда (*comp) (v[i], v[left]) өрнегі – оған көңіл бөлу(шақыру)

Екі стрингті салыстыратын numcmp, функциясының мәтініноларды сан ретінде қарастырып отырып келтірейікалдын-алаолар atof функциясының сандық мәніне аударылады.

#include <stdlib.h>

\\ numcmp: s1 мен s2-ні сан ретінде салыстырады

int numcmp (char *s1, char *s2)

{  double v1, v2;

   v1=atof(s1); v2=atof(s2);

   if (v1<v2) return –1;

   else if (v1>v2) return 1;

else return 0;

}

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

Мәселені келесі екі декларацияның айырмашылығымен мысал келтіре отырып жазайық: 

int * f();          // f int-қа көрсеткішті қайтарады.

int ( * pf)();     // pf – int-ті қайтаратын функция көрсеткіш

* префикстік операторлардың приоритеті ( ) операторының приоритетіне қарағанда төмен, сондықтан екінші жағдайда жақшаның болуы міндетті емес.

Келесі декларацияны және олардың сөздік сипаттамасын қарастырайық:

char ** argv÷ argv - көрсеткіштен көрсеткішке char-ға;

int (*array) [13] ÷ array- int-тен массив [13]-ке көрсеткіш;

void* comp ()   ÷ comp - void -қа қайтаратын көрсеткіш функциясы;

void ( * comp) ( ) ÷ comp - void-қа қайтарушы көрсеткіш функциясы;

char ( *(*f())[]()÷ f - char-ды қайтарушы функцияға көрсеткіштерден массивке [] қайтарушы көрсеткіштердің функциясы;

char ( *(*ar[3])()) [5] ÷ archar  типінен тұратын [5массивіне көрсеткішті қайтаратын функцияға [3көрсеткіштер массиві.

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

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

 Жариялануы кезінде көрсеткіш үнемі кейбір типпен байланыса алады. Жеке жағдайда бұл void типі болуы мүмкін. void-қа көрсеткішті кез-келген көрсеткішке алмастыруға болады, және керісінше.

Кез-келген тип көрсеткіштері функция көрсеткіштеріне алмасуы мүмкін және керісінше.

Арнайы кілттік near, far, huge сөздері программалауға көрсеткіштердің форматы мен өлшемдерін модификациялауға мүмкіндік береді. Компилятор таңдалған моделдің жадысында қабылданған көрсеткіштің өлшемін ескереді және адрестік мәндердің түрлендіруінің сәйкестілігін анық емес түрде жүргізуі мүмкін. Сонымен, көрсеткіштің функция аргументі ретінде берілуі, оның өлшемінің келесі екі мәндердің үлкеніне түрленуінің анық емес болуына әкеліп соғуы мүмкін:

-  жадының әрекет етуші моделі үшін көрсеткіштің қабылданған көрсеткішіне;

-  аргументтің тип өлшеміне.

Егер көрсеткіштің – аргумент типі анық көрсетілген болса, сондай-ақ near, far, huge, модификаторларымен бірге берілген функцияның прототипі (функцияның алдын-ала жариялануы) болса, онда дәл осы типке түрлендіру жүргізіледі.

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

int (*p) (long);          // long типінің мәнін тосатын және int типін

                                   // қайтаратын функцияға көрсеткіш жариялау

(*(int(*)(int))p)(0);    - көрсеткіш бойынша функцияны шақыру.

Категория: Информатика | Добавил: admin_ (17.11.2013)
Просмотров: 1611 | Теги: ФУНКЦИЯНЫҢ КӨРСЕТКІШТЕРІ с++ қазақш | Рейтинг: 0.0/0
Всего комментариев: 0

Имя *:
Email:
Код *: