Funktsioonide näited C-programmeerimisel koos näidetega

Lang L: none (table-of-contents):

Anonim

Osutajad annavad C-funktsioonidele palju võimalusi, mille piiramiseks on meil piiratud ühe väärtuse tagastamine. Osuti parameetrite abil saavad meie funktsioonid nüüd tegelikke andmeid töödelda, mitte andmete koopiat.

Muutujate tegelike väärtuste muutmiseks edastab kutsuv lause aadressid funktsiooni osuti parameetritele.

Selles õpetuses saate teada

  • Funktsioonid Näidikud
  • Funktsioonid massiivi parameetritega
  • Massiivi tagastavad funktsioonid
  • Funktsioonide osutajad
  • Funktsioonide osutite massiiv
  • Tühiste osutite kasutamine
  • Funktsioonide osutajad argumentidena

Funktsioonid Näidikud

Näiteks vahetab järgmine programm kaks väärtust kahest:

void swap (int *a, int *b);int main() {int m = 25;int n = 100;printf("m is %d, n is %d\n", m, n);swap(&m, &n);printf("m is %d, n is %d\n", m, n);return 0;}void swap (int *a, int *b) {int temp;temp = *a;*a = *b;*b = temp;}}

Väljund:

m is 25, n is 100m is 100, n is 25

Programm vahetab tegelike muutujate väärtused, kuna funktsioon pääseb neile aadresside abil aadresside abil. Siin arutleme programmi protsessi üle:

  1. Deklareerime kahe muutuja väärtuse vahetamise eest vastutava funktsiooni, mis võtab parameetritena kaks täisarvu osutit ja tagastab mis tahes väärtuse, kui seda kutsutakse.
  2. Põhifunktsioonis deklareerime ja lähtestame kaks täisarvu muutujat ('m' ja 'n'), seejärel trükime vastavalt nende väärtused.
  3. Kutsume funktsiooni swap (), edastades kahe muutuja aadressi argumentidena, kasutades sümbolit ampersand. Pärast seda trükime muutujate uued vahetatud väärtused.
  4. Siin määratleme funktsiooni swap () sisu, mis võtab parameetritena kaks täisarvu muutuja aadressi, ja deklareerime ajutise täisarvu muutuja, mida kasutatakse kolmanda salvestuskastina, et salvestada üks väärtusemuutujatest, mis pannakse teise muutujasse.
  5. Salvestage ajutises muutujas esimese muutuja, millele osutab täht a, sisu.
  6. Salvestage teine ​​muutuja, millele osutab b, esimesele muutujale, mille tähistab a
  7. Värskendage teist muutujat (osutab b) esimese ajutisse muutujasse salvestatud muutuja väärtuse järgi.

Funktsioonid massiivi parameetritega

C-s ei saa me väärtust massiivi funktsioonile edastada. Kui massiivi nimi on osuti (aadress), siis edastame massiivi nime lihtsalt funktsioonile, mis tähendab, et osuti edastatakse massiivile.

Näiteks kaalume järgmist programmi:

int add_array (int *a, int num_elements);int main() {int Tab[5] = {100, 220, 37, 16, 98};printf("Total summation is %d\n", add_array(Tab, 5));return 0;}int add_array (int *p, int size) {int total = 0;int k;for (k = 0; k < size; k++) {total += p[k]; /* it is equivalent to total +=*p ;p++; */}return (total);}

Väljund:

 Total summation is 471

Siin selgitame programmi koodi selle üksikasjadega

  1. Deklareerime ja määratleme funktsiooni add_array (), mis võtab parameetritena massiivi aadressi (osuti) koos elementide numbriga ja tagastab nende elementide kogunenud summa. Kursorit kasutatakse massiivi elementide itereerimiseks (kasutades p [k] tähistust) ja me koondame summeerimise lokaalsesse muutujasse, mis tagastatakse pärast kogu elemendi massiivi itereerimist.
  2. Deklareerime ja lähtestame viie täisarvulise elemendiga täisarvu massiivi. Trükime summaarse summa, edastades massiivi nime (mis toimib aadressina) ja massiivi suuruse funktsioonile add_array () kui argument.

Massiivi tagastavad funktsioonid

C-s võime osuti massiivile tagastada, nagu järgmises programmis:

#include int * build_array();int main() {int *a;a = build_array(); /* get first 5 even numbers */for (k = 0; k < 5; k++)printf("%d\n", a[k]);return 0;}int * build_array() {static int Tab[5]={1,2,3,4,5};return (Tab);}

Väljund:

12345

Ja siin arutame programmi üksikasju

  1. Määratleme ja kuulutame välja funktsiooni, mis tagastab täisarvu sisaldava massiivi aadressi ja ei võtnud ühtegi argumenti.
  2. Deklareerime täisnäidiku, mis võtab vastu kogu funktsiooni kutsumise järel ehitatud massiivi, ja trükime selle sisu, korrates kogu viie elemendi massiivi.

Pange tähele, et funktsiooni tagastatud massiivi aadressi salvestamiseks on määratletud osuti, mitte massiiv. Pange tähele ka seda, et kui funktsioonilt tagastatakse kohalik muutuja, peame selle funktsioonis staatiliseks kuulutama.

Funktsioonide osutajad

Kuna teame definitsiooni järgi, et osutid osutavad aadressi mis tahes mälukohas, võivad nad osutada ka käivitatava koodi alguses mälu funktsioonidena.

Funktsioonikurss deklareeritakse tähega *, selle deklaratsiooni üldine lause on:

return_type (*function_name)(arguments)

Peate meeles pidama, et sulgud (* function_name) ümber on olulised, kuna ilma nendeta arvab kompilaator, et funktsiooni_name tagastab point_i return_type.

Pärast funktsiooniosuti määratlemist peame selle määrama funktsioonile. Näiteks deklareerib järgmine programm tavalise funktsiooni, määratleb funktsiooni kursori, määrab funktsiooni kursori tavalisele funktsioonile ja kutsub seejärel funktsiooni kursori kaudu:

#include void Hi_function (int times); /* function */int main() {void (*function_ptr)(int); /* function pointer Declaration */function_ptr = Hi_function; /* pointer assignment */function_ptr (3); /* function call */return 0;}void Hi_function (int times) {int k;for (k = 0; k < times; k++) printf("Hi\n");} 

Väljund:

HiHiHi

  1. Määratleme ja kuulutame välja standardfunktsiooni, mis prindib Hi-teksti k korda, mis on näidatud parameetrite aegadega, kui funktsiooni kutsutakse
  2. Määratleme kursori funktsiooni (koos selle erideklaratsiooniga), mis võtab täisarvu parameetri ja ei tagasta midagi.
  3. Initsialiseerime oma kursori funktsiooni funktsiooniga Hi_function, mis tähendab, et osuti osutab funktsioonile Hi_function ().
  4. Selle asemel, et standardfunktsioon kutsuks funktsiooni nime argumentidega lindistades, kutsume vaid kursori funktsiooni, edastades argumentidena numbri 3 ja see on kõik!

Pidage meeles, et funktsiooni nimi osutab käivitatava koodi algusaadressile nagu massiivi nimi, mis osutab selle esimesele elemendile. Seetõttu on õiged sellised juhised nagu function_ptr = & Hi_function ja (* funptr) (3).

MÄRKUS. Funktsiooni määramise ja funktsioonikõne ajal pole oluline sisestada aadressioperaatorit ja indirection-operaatorit *.

Funktsioonide osutite massiiv

Funktsioonide osutite massiiv võib otsuse tegemiseks mängida lülitit või if-lauset, nagu järgmises programmis:

#include int sum(int num1, int num2);int sub(int num1, int num2);int mult(int num1, int num2);int div(int num1, int num2);int main(){ int x, y, choice, result;int (*ope[4])(int, int);ope[0] = sum;ope[1] = sub;ope[2] = mult;ope[3] = div;printf("Enter two integer numbers: ");scanf("%d%d", &x, &y);printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");scanf("%d", &choice);result = ope[choice](x, y);printf("%d", result);return 0;}int sum(int x, int y) {return(x + y);}int sub(int x, int y) {return(x - y);}int mult(int x, int y) {return(x * y);}int div(int x, int y) {if (y != 0) return (x / y); else return 0;}
Enter two integer numbers: 13 48Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2624

Siin arutame programmi üksikasju:

  1. Deklareerime ja määratleme neli funktsiooni, mis võtavad kaks täisarvu argumenti ja tagastavad täisarvu. Need funktsioonid liidavad, lahutavad, korrutavad ja jagavad kaks argumenti selle kohta, millist funktsiooni kasutaja kutsub.
  2. Deklareerime vastavalt operandide, operatsiooni tüübi ja tulemuse käsitsemiseks 4 täisarvu. Samuti kuulutame välja nelja funktsiooniosuti massiivi. Iga massiivi elemendi funktsioonikursor võtab kaks täisarvu parameetrit ja tagastab täisarvu.
  3. Määrame ja initsialiseerime iga massiivi elemendi juba deklareeritud funktsiooniga. Näiteks kolmas element, mis on kolmas funktsioonikursor, osutab korrutamisfunktsioonile.
  4. Operandid ja operatsiooni tüüp otsime klaviatuurilt sisestatud kasutajalt.
  5. Kutsusime argumentidega sobiva massiivi elemendi (Function pointer) ja salvestame vastava funktsiooni loodud tulemuse.

Käsk int (* ope [4]) (int, int); määratleb funktsiooninäidikute massiivi. Igal massiivi elemendil peavad olema samad parameetrid ja tagastustüüp.

Väite tulemus = ope [valik] (x, y); käivitab vastava funktsiooni vastavalt kasutaja tehtud valikule. Kaks sisestatud täisarvu on funktsioonile edastatud argumendid.

Tühiste osutite kasutamine

Tühjendusnäppe kasutatakse funktsioonide deklaratsioonide ajal. Mis tahes tüübi tagastamiseks kasutame void * return tüüpi lube. Kui eeldame, et meie parameetrid funktsioonile üleminekul ei muutu, kuulutame selle constiks.

Näiteks:

 void * cube (const void *); 

Mõelge järgmisele programmile:

#include void* cube (const void* num);int main() {int x, cube_int;x = 4;cube_int = cube (&x);printf("%d cubed is %d\n", x, cube_int);return 0;}void* cube (const void *num) {int result;result = (*(int *)num) * (*(int *)num) * (*(int *)num);return result;}

Tulemus:

 4 cubed is 64 

Siin arutame programmi üksikasju:

  1. Määratleme ja kuulutame välja funktsiooni, mis tagastab täisarvu ja võtab muutumatu muutuja aadressi ilma kindla andmetüübita. Arvutame nummerdiga viidatud sisumuutuja (x) kuupväärtuse ja kuna see on tühine osuti, peame selle tippima täisarvu andmetüüpi, kasutades konkreetset tähistust (* datatüüp), ja naaseme kuubi väärtus.
  2. Deklareerime operandi ja tulemuse muutujaks. Samuti lähtestame oma operandi väärtusega "4."
  3. Kutsume kuubi funktsiooni, edastades operandi aadressi, ja käsitleme tulemuse muutuja naasvat väärtust

Funktsioonide osutajad argumentidena

Teine võimalus funktsiooni osutit ära kasutada, edastades selle argumendina teisele funktsioonile, mida mõnikord nimetatakse "tagasihelistamisfunktsiooniks", kuna vastuvõttev funktsioon "kutsub seda tagasi".

Päisefailis stdlib.h kasutab funktsioon Quicksort "qsort ()" seda tehnikat, mis on massiivi sorteerimiseks mõeldud algoritm.

void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
  • void * base: voidi osutus massiivile.
  • size_t num: massiivi elemendi number.
  • size_t width Elemendi suurus.
  • int (* võrdle (const void *, const void *): funktsioonikursor, mis koosneb kahest argumendist ja tagastab 0, kui argumentidel on sama väärtus, <0, kui arg1 tuleb arg2 ees, ja> 0, kui arg1 tuleb arg2 järel.

Järgmine programm sorteerib funktsiooni qsort () abil täisarvude massiivi väiksest suureni:

#include #include int compare (const void *, const void *);int main() {int arr[5] = {52, 14, 50, 48, 13};int num, width, i;num = sizeof(arr)/sizeof(arr[0]);width = sizeof(arr[0]);qsort((void *)arr, num, width, compare);for (i = 0; i < 5; i++)printf("%d ", arr[ i ]);return 0;}int compare (const void *elem1, const void *elem2) {if ((*(int *)elem1) == (*(int *)elem2)) return 0;else if ((*(int *)elem1) < (*(int *)elem2)) return -1;else return 1;}

Tulemus:

 13 14 48 50 52 

Siin arutame programmi üksikasju:

  1. Määratleme kahest argumendist koosneva funktsiooni võrdlus ja tagastab 0, kui argumentidel on sama väärtus, <0, kui arg1 tuleb enne arg2, ja> 0, kui arg1 tuleb pärast arg2. Parameetrid on tühise osuturi tüüp, mis on valatud sobivale massiivi andmetüübile (täisarv)
  2. Defineerime ja lähtestame täisarvu massiivi Massiivi suurus salvestatakse muutujasse num ja iga massiivi elemendi suurus salvestatakse laiuse muutujasse, kasutades eelnevalt määratud operaator sizeof ().
  3. Kutsume funktsiooni qsort ja edastame massiivi nime, suuruse, laiuse ja võrdlusfunktsiooni, mille kasutaja on eelnevalt määranud, et sorteerida massiiv kasvavas järjekorras. Võrdlus viiakse läbi, võttes igas iteratsioonis kaks massiivi elementi kuni kogu massiivini sorteeritakse.
  4. Me printime massiivi elemendid, et olla kindel, et meie massiiv on korralikult sorteeritud, korrates kogu massiivi silmuseks.