Функције у програмирању на језику Ц.


увод

Претпоставимо да морамо да напишемо програм за унос два броја и извршимо аритметичку операцију коју корисник тражи. Корисник може тражити било коју од аритметичких операција попут сабирања, одузимања, множења или дељења. Како ћемо написати програм? Написаћемо један Ц програм са главном функцијом, где ћемо прихватити два броја и операцију коју треба извршити. У зависности од операције коју је корисник унео, имаћемо услов ако ћемо бројеве сабирати / одузимати / множити / делити. Ово су директни кораци за овај једноставан захтев. Замислите да се ове операције са два броја повећавају на сабирање више бројева или низа бројева. Тада ће се повећати и код унутар сваке изјаве „ако“. То значи како се захтев мења или постаје сложен, код се такође повећава и постаје сложен. То заузврат смањује и читљивост кода. Шта ће се догодити ако извршимо овај скуп операција унутар именованог блока и позовемо овај блок кад год је то потребно? Повећава читљивост кода, као и омогућава кориснику да га лако разуме.

На пример, исте аритметичке операције за низ бројева креирају се у различитим функцијама као што су сабирање (), одузимање (), множење () и дељење () и у главној функцији ако ове функције позовемо у изјави „ако“ у тада код изгледа једноставније и лакше за разумевање. Логика која се користи за ове операције овде је мање важна. Ако морамо да знамо логику, онда можемо да проверимо одговарајућу функцију. Претпоставимо да постоји неки додатни захтев приликом дељења да се провери да ли је делилац нула. Тада не треба да прелазимо целу главну функцију док не добијемо код операције дељења. Уместо тога можемо директно преузети функцију Дивисион () и додати нови скуп кода за проверу нуле. Тако стварање функције такође олакшава додавање нових захтева. Отуда се у функцијама Ц увелико користи.

У Ц је све написано унутар функције. Сам програм започиње од главне () функције. Као што и само име говори, то је главна функција у било ком програму, од које започиње извршење кода. Остали захтеви корисника се затим деле на више функција и позивају се из главне функције. Било која друга функција такође може позвати исту или другу функцију. Укратко, Ц није комплетан без функција!

Функција може да прихвати један или више улаза, изврши неку операцију на њима, а може и не мора да врати излаз позивајућој функцији. Може се позвати из било које функције, било који број пута. То значи да је функција именовани блок кода за вишекратну употребу у програму.

Врсте функција

У Ц имамо две врсте функција.

Библиотечка функција

Функције библиотеке су уграђене функције у Ц. Најчешће коришћене функције попут добивања уноса од корисника, приказивања излаза на екрану, поређења било које две жице, копирања две вредности низа, додељивања меморије итд. Већ су кодиране у различите функције у Ц и смештен у библиотеке. Ове функције се могу позивати када и када су потребне у нашем програму.

На пример, имена морамо да уносимо са тастатуре. То значи да би програм требало да чита уносе са тастатуре и да буде у могућности да складишти у некој променљивој. Функција треба да буде довољно флексибилна да прихвати различите врсте променљивих. Сви ови захтеви су унапред обрађени и стављени у функцију која се назива сцанф ().

Неки други примери библиотечких функција су принтф (), маин (), стрцпи (), стрцмп (), стрлен (), маллоц () итд.

Ове функције библиотеке су поново категорисане на основу њихове употребе и функционалности и смештене у различите датотеке. Те датотеке су познате као датотеке заглавља. Ове датотеке се чувају са ознакама '.х' које означавају датотеке заглавља. Најчешће коришћене улазне и излазне функције смештене су у заглавну датотеку стдио.х. У овој датотеци заглавља имаћемо све маин (), сцанф, принтф, гетс, гетцхар, пут, путцхар итд. Све функције библиотеке повезане са стрингом смештене су у датотеку заглавља стринг.х.

Када напишемо програм, он неће знати одакле постоје ове уграђене функције нити одакле ће преузети те функције. Морамо их експлицитно укључити у наш код. То ће помоћи компајлеру да зна функције које ће се користити у програму, као и да избегне укључивање свих уграђених функција у наш код. То нам омогућава да укључимо само оне датотеке заглавља које су потребне за програм. Можемо користити само оне датотеке заглавља које су потребне програму. Ове датотеке заглавља додају се у наш програм употребом претпроцесорске директиве назване '#инцлуде', тј;

#include <stdio.h>
#include <string.h>
#include <math.h>

Ове директиве су постављене на почетку кода. Када компајлер компајлира код и види ове директиве, он их директно замењује њиховим одговарајућим кодом. Стога, када зовемо функције попут сцанф, принтф итд., Он зна дефиницију истих и извршава те кодове.

Кориснички дефинисана функција

То су функције које је корисник декларисао и дефинисао у складу са својим програмским захтевима. Ове функције су доступне само за тренутни програм у којем је дефинисан. Може га користити програм у коме је дефинисан као и све повезане датотеке програма. Али не може се користити као функција библиотеке у свим програмима.

Када се функција позове у блоку или било која друга функција, контрола извршења ће прећи на ћелијску функцију; извршиће изразе у функцији и вратити се у позвани блок / функцију са / без неких вредности.

Из горњег дијаграма је јасно како функционише позив функције. Понаша се као ознака, али се враћа у позивни блок када се његово извршавање заврши.

Предности функција

Повећава читљивост програма, као и смањује сложеност програма.

  • Ако постоји било који понављајући блок кода, онда ако је смештен у функцију и може се позивати где год је потребно. Програм чини једноставним и лако разумљивим.
  • У функцији користи приступ одозго надоле - то значи да прво извршава све логике функције на високом нивоу, а затим прелази на логику нижег нивоа. Да би било још прецизније, прво проблем дели на различите задатке и ствара функције за њих. Касније у функцији ствара логику за решавање тих проблема. На пример, напишите програм за извођење аритметичких операција попут сабирања / одузимања / множења / дељења бројева. Када пишемо програм, видимо само сабирање / одузимање / множење / дељење бројева и стварање одговарајуће функције. Више детаља о извођењу ових операција - што је нижи ниво операција, врши се у оквиру одговарајућих функција.
  • Можемо поново користити функције у истом програму или у другим програмима које је написао исти корисник. Можемо чак створити функције које други програми, други корисници или чак други системи могу поново користити.
  • Помаже у разумевању логике програма и доброг функционисања. Такође, олакшава отклањање грешака у функцији него отклањање грешака у пуној дужини појединачног кода. На пример, ако постоји нека грешка у функцији Дивисион (), онда можемо директно да пређемо на функцију и решимо проблем. Али ако није било такве функције и написан је пуни код, онда ћемо завршити са отклањањем грешака у целом коду. Ц нам омогућава да компајлирамо и отклонимо грешке само у функцијама, а не да компајлирамо цео програм. Ово је такође додатна предност за отклањање грешака у коду. Ово олакшава тестирање.

Изјаве о функцијама

Корисник / програмер мора да кодира кориснички дефинисану функцију и она има специфичан формат који Ц компајлер може да разуме. Као први корак у креирању функције, морамо их прогласити. То је еквивалентно стварању меморијског простора у РАМ меморији за чување функције и извршавање различитих задатака у функцији. Типична функција има углавном два дела - заглавље функције и тело функције. Заглавље функције је први ред функције који спомиње име функције, аргументе прослеђене функцији и повратни тип функције. Укратко, заглавље функције говори о структури функције.

Када креирамо функцију у програму, декларишемо функцију са заглављем. тј;

тип података име_функције (аргументи / параметри);

Овде је тип података тип података излаза функције. То може бити било који примитивни или непримитивни тип података. Може бити чак и ништавно - што указује да не враћа никакве излазе. Следеће је име функције. Обично се даје смислено име тако да видећи само име може да се разуме шта функција ради. Назив функције би требао бити јединствен за програм. Ниједна друга функција у истом програму не би требало да има исто име функције. Следећа је листа аргумената / параметара. То су променљиве са или без вредности које су функцији прослеђене из функције која позива. Функција такође може бити без икаквих аргумената. Ако проследимо аргументе, тада треба да наведемо типове података сваког од њих. Функцији можемо проследити било који број аргумената.

воид фнДисплаи (Чар цхрСтринг []); // функција са параметром низа без повратних вредности
инт фнАддитион (инт интНум1, инт интНум2); // функција са 2 целобројна аргумента са целобројним излазом
пловак фнАвераге (инт интНум []); // функција са аргументом као целобројни низ са повратном вредношћу као флоат

То су различите декларације функција у зависности од захтева, улазних параметара и њихових повратних вредности. Декларација функције се врши пре него што се дефинише и користи у коду. Обично функцију декларишемо убрзо након директива претпроцесора.

#include <stdio.h>

//Function Declaration
void fnDisplay (char chrString []); // a function with string parameter with no return values
int fnAddition (int intNum1, int intNum2); // a function with 2 integer arguments with integer output
float fnAverage (int intNum []); // a function with argument as integer array with return value as float

void main (){
// example program
}

Дефиниције функција

Тело функције је скуп кода са изразима и изразима који користе параметре који су му прослеђени. Дефинише функционалност функције. Можемо поставити дефиницију функције док пријављујемо функцију или било где у програму.

Типична дефиниција функције укључује заглавље функције праћено отвореном заградом - '{'. Унутар тела функције можемо имати декларацију за локалне променљиве функције, код за извршавање задатака и ретурн израз за враћање вредности позивајућој функцији, након чега следи заграда - '}'.

datatype function_name (arguments/parameters) {
	declaration part;
	expressions/ statements;
	return variable_name;
}

Ово је типична структура функционалног тела на језику Ц. Испод је пример програма који показује како контрола програма скаче када се позове функција. Овде се дефиниција функције налази на крају кода. Али функцију смо декларисали и пре него што главна функција започне. Када компајлер компајлира код, он види декларацију и разуме да за њу постоји дефиниција. Када позовемо функцију у главној функцији, она замењује позив функције дефиницијом функције и извршава код. Да функцију нисмо декларисали на почетку и позвали је у главној функцији, компајлер неће знати да је функција дефинисана на крају и баца грешку компилације да функција није дефинисана. Можемо чак и да поставимо дефиницију функције док се декларишемо.
#include <stdio.h>
void fnDisplay (char chrString []); // a function with string parameter with no return values

void main (){
	char chrStr [] = "Example of a Function";
	printf ("\nBefore calling the Function.....");
	fnDisplay (chrStr); // calling the function
	printf ("\nAfter calling the function.....");
}

// Function definition
void fnDisplay (char chrString []){
	printf ("\nInside the function Body......\n");
	printf ("%s", chrString);
	printf ("\nEnd of the function Body.....");
}

Функције позивања

Научили смо како се декларише функција и дефинише њена дефиниција. Сада да видимо како да позовемо функцију из друге функције. Функција се може позвати из било које функције / блока кода помињањем њеног имена. Поред тога, требало би да се подудара са дефиницијом функције - то значи да ако функција има параметре који су јој прослеђени, тада морамо параметре проследити функцији тако што ћемо их навести у заградама '()'. Тип параметара треба тачно да се подудара са типом који је декларисан у функцији. Имена променљивих која се прослеђују функцији и имена наведена у декларацији функције могу бити различита. Али број параметара и њихов тип увек треба да се подударају.

фнДисплаи (цхрСтр); // позивање функције

Овде функција прихвата један аргумент и типа је низа. Док позивамо функцију, преносимо исти тип параметра. Може се запитати зашто се само име променљиве преноси као параметар. Овде је низ низ карактера и низ делује као показивач - када је наведено име низа, он показује на први елемент низа. Стога се стринг преноси да би функционисао као било која друга нормална променљива. Више детаља о истом налази се у одељку показивача. Ако преносимо било који други тип променљиве, тада вредност преносимо на параметар функције наводећи име променљиве.

фнАддитион (интВал1, интВал2);

Овде су интВал1 и интВал2 целобројног типа и када се проследе као горе, његова имена се замењују његовом вредношћу. Стога, када је овај позив замењен његовом дефиницијом, преводилац добија вредност на интНум1 иинтНум2, респективно.

Ако функција враћа вредност, позив функције треба доделити променљивој типа повратка. У функцији фнДисплаи, тип повратка је неважећи. Стога не морамо доделити позив функције било којој променљивој. У функцији фнАддитион, враћа резултат позивајућој функцији. Отуда морамо резултат ухватити у неку променљиву истог типа. Отуда позивамо функцију као доле:

интРесулт = фнАддитион (интВал1, интВал2); // позива функцију

 

#include <stdio.h>
int fnAddition(int intNum1, int intNum2);

void main(){
	int intVal1, intVal2, intResult;

	printf("\nPlease enter first number to be added:");
	scanf("%d", &intVal1);
	printf("\nPlease enter second number to be added:"); 
	scanf("%d", &intVal2);
	intResult = fnAddition(intVal1, intVal2); //calls the function
	printf("\nSum of two number is:%d", intResult);
}
// Function definition
int fnAddition (int intNum1, int intNum2){
	return intNum1 + intNum2; // returns the sum of two numbers
}

Параметри функције

Знамо који су параметри функција. Али како пренети параметре функцији и како ће њихове вредности бити додељене функцијским параметрима у њеној дефиницији. Параметри декларисани у декларацији функције називају се формални параметри. Стварају се када се функција позове и делује као локална променљива унутар функције. Они се бришу из меморије по завршетку функције. Поново ће се креирати на неком другом меморијском месту, ако се поново позове иста функција.

int fnAddition (int intNum1, int intNum2); // intNum1 and intNum2 are formal parameters
void fnDisplay (char chrString []){//chrString[] is formal parameter
	printf ("\nInside the function Body......\n");
	printf ("%s", chrString);
	printf ("\nEnd of the function Body.....");
}

Параметри / променљиве прослеђени функцији током позива функције називају се стварним параметрима функције. Они имају стварне вредности параметара функције и у зависности од њихове вредности функција се процењује. У кодним именима стварни и формални параметри могу бити исти или различити. Разликујемо их како бисмо их разликовали.

фнДисплаи (цхрСтр); // цхрСтр је стварни параметар
интРесулт = фнАддитион (интВал1, интВал2); // интВал1 и интВал2 су стварни параметри

Постоје два начина преношења стварних параметара у функцију.

  • Прођи вредност

У овој методи, када се функција позове, стварни параметри ће имати стварне вредности које треба проценити. Када компајлер замењује позив функције својом дефиницијом, његови формални параметри се замењују вредностима. Будући да формални параметар добија вредност за њих, све промене променљиве формалног параметра неће променити вредност стварне променљиве параметра. То може утицати на функцију, али када се врати функцији која позива, стварна вредност параметра остаће непромењена.

интРесулт = фнАддитион (интВал1, интВал2); // интВал1 и интВал2 имају стварну вредност параметара

када компајлер компајлира код, он замењује горњи позив функције као доле:
Претпоставимо да је интВал1 = 10 и интВал2 = 40, онда
интРесулт = фнАддитион (10, 40);

int fnAddition (10, 40){
	return 10 + 40; // returns the sum of two numbers
}

Овде нисмо модификовали формални параметар и стога нема промена вредности унутар функције. Стога нема промена ни на стварним параметрима.

Претпоставимо да имамо још једну функцију као доле која једноставно повећава вредност параметра прослеђеног за 10. Претпоставимо да интВал има вредност 25.

интРесулт = фнИнцремент (интВал); // интВал је стварни параметар

Када се функција позове као горе, компајлер ово види као

интРесулт = фнИнцремент (25); // интВал је стварни параметар

Замењује овај позив дефиницијом функције као доле:

 

Исти ефекат стварних и формалних параметара можемо видети у доњем програму. После функције можемо приметити да се вредност стварног параметра не мења иако се у функцији мења вредност формалног параметра. Иако се формални параметар замењује прослеђеном вредношћу, он делује као локална променљива унутар функције. Његова вредност нестаје чим функција заврши.

#include <stdio.h>
int fnIncrement (intVal);

void main (){
	int intVal=25, intResult;

	printf ("\nValue of intVal before function call is %d", intVal);
	intResult = fnIncrement(intVal); //calls the function
	printf ("\nValue of intVal after function call is %d", intVal);
	printf ("\nIncremented Value is:%d", intResult);
}
// Function definition
int fnIncrement (int intNum){
	printf ("\nValue of intNum before incrementing is %d", intNum);
	intNum += 10;
	printf ("\nValue of intNum after incrementing is %d", intNum);
	return intNum;
 }

  • Прођи референцу

Овим методом прослеђујемо адресу стварне променљиве где се чува вредност коју треба проследити. То значи да се преноси референца на вредност која није стварна вредност. Стога ће и формални и стварни параметри указивати на исте меморијске локације у меморији. Тако ће све промене формалног или стварног параметра променити обе вредности. То значи да адреса на коју указују оба параметра остаје иста, али вредност у тој адреси може се променити у било коју вредност.

Размотрите исти програм повећања горе. Пропустимо параметар референцом - проследимо адресу интВал као параметар када је функција позвана. Тада формални параметар интНум такође добија адресу интВал и стога се оба сада односе на исту вредност.

#include <stdio.h>
int fnIncrement (int *intNum); // formal parameter needs to be a pointer, inorder to accept the address

void main (){
	int intVal = 25, intResult;

	printf ("\nValue and Address of intVal before function call is %d and %x", intVal, &intVal);
	intResult = fnIncrement (&intVal); //pass by reference
	printf ("\nValue and Address of intVal after function call is %d and %x", intVal, &intVal);
	printf ("\nIncremented Value and address of intResult is:%d and %x", intResult, &intResult);
}
// Function definition
int fnIncrement (int *intNum){// even though address is passed, the '*' now points to the value at the address passed
	printf ("\nValue and Address of intNum before incrementing is %d and %x", *intNum, intNum);
	*intNum += 10; // inorder to increment the value at the address passed, pointer notation needs to be used. Address of the variable remains same
	printf ("\nValue and Address of intNum after incrementing is %d and %x", *intNum, intNum);
	return *intNum; //returns the incremented value
}

У програму можемо приметити да је функција декларисана променљивом показивача. Променљива показивача показује на адресу друге променљиве. Стога, када проследимо адресу стварног параметра позиву функције, формалном параметру, интНум се креира да указује на интВал. У функцији, када повећавамо интНум за 10, требало би да увећамо вредност интНум, али не и адресу. Отуда користимо '*' пре интНум. Стога адреса на коју указује интНум остаје непромењена иако се вредност мења. Након прираста интНум и интВал имаће исту вредност и адресу. Пошто смо вратили вредност позивајућој функцији (овде имајте на уму да нисмо вратили адресу, већ вредност), интРесулт ће добити вредност на другој адреси. Претпоставимо да смо вратили адресу интНум, онда би и интРесулт указао на исту адресу.

Испод програм показује како добити интРесулт такође на истој адреси. Сви ови параметри користе показиваче за то. У овој фази може изгледати мало сложено, али биће јасно када се показивач разуме. Увек имајте на уму да * Нум означава вредност на другој локацији адресе, Нум означава адресу друге локације, а & Нум је његова адреса. Али имајте на уму како се функција декларише, позива, како се вредности преносе, враћају и приказују.

#include <stdio.h>
int *fnIncrement (int *intNum); // formal parameter needs to be a pointer, inorder to accept the address

void main () {
    int intVal = 25,*intResult;

    printf ("\nValue and Address of intVal before function call is %d and %x", intVal, &intVal);
    intResult = fnIncrement (&intVal); //pass by reference
    printf ("\nValue and Address of intVal after function call is %d and %x", intVal, &intVal);
    printf ("\nIncremented Value and address of intResult is:%d and %x", *intResult, intResult);
}
// Function definition
int *fnIncrement (int *intNum){// even though address is passed, the '*' now points to the value at the address passed
    printf ("\nValue and Address of intNum before incrementing is %d and %x", *intNum, intNum);
    *intNum += 10; // inorder to increment the value at the address passed, pointer notation needs to be used. Address of the variable remains same
    printf ("\nValue and Address of intNum after incrementing is %d and %x", *intNum, intNum);
    return intNum; //returns the incremented value
}

Ове врсте карактеристика функција углавном се користе када морамо копирати две вредности, заменити два броја итд.

Различите функције

Понекад можда не знамо број параметара који се прослеђују и њихове типове података. У таквим ситуацијама можемо да креирамо функције са опционим параметрима. Али требало би да проследимо бар један параметар са познатим типом података. Будући да функција прихвата променљиви број аргумената / параметара, функција се назива Вариадиц функција. Општа синтакса за декларисање такве функције је испод:

тип података име_функције (аргумент типа података1,…);

инт фнАддитион (инт интЦоунт, ...);

Овде '...' означава компајлер да има опционалне аргументе било које врсте и било ког броја. У функцији се опционим параметрима обраћамо помоћу макронаредби попут ва_старт, ва_лист итд. Ови макронаредбе су дефинисане у заглавној датотеци стдарг.х, а ову датотеку морамо укључити ако користимо различите функције. Први аргумент у декларацији и дефиницији функције је обавезан. Обично би овај први аргумент био број аргумената прослеђених овој функцији. Када позивамо функцију, ми одређујемо колико аргумената ћемо проследити, праћени стварном листом аргумената. Тако у време извођења, позив функције сазнаје колико аргумената му се прослеђује.

Користи неке макронаредбе које се користе за хватање прослеђених променљивих аргумената, обраду сваког аргумента итд.

  • ва_лист: Ово је променљива библиотеке која се користи за чување аргумената прослеђених варијадној функцији. Декларишемо променљиву типа ва_лист за хватање аргумената прослеђених функцији.

   ва_лист име_променљиве;
  ва_лист параметри; // прогласимо променљиву 'параметри' типа ва_лист

Ова променљива библиотеке погодна је за држање променљивих за макронаредбе које користе варијадне функције попут ва_старт, ва_енд и ва_арг.

  • ва_старт: Ово је макро који се користи за иницијализацију листе параметара променљиве променљивом декларисаном од ва_лист. Овај макро снима све параметре прослеђене функцији у тип променљиве ва_лист и показује на почетак листе аргумената. Овај макро узима два аргумента - један је променљива листе параметара типа ва_лист, а други је последњи аргумент који је први фиксни аргумент прослеђен функцији (функције прелазе листе аргумената од последњег до првог; стога се назива фиксни први аргумент последњи аргумент).

ва_старт (ва_лист арг_лист, ласт_арг);
ва_старт (параметри, интЦоунт); // Почиње приступ опционом параметру од почетка

Овде ће „параметри“ бити иницијализовани да би се листа променљивих параметара проследила позиву функције. 'интЦоунт' је последњи аргумент функције, који је овде, број аргумената прослеђених функцији.

  • ва_арг: Овај макро користи се за преузимање следећег аргумента са листе параметара.

     type va_arg(va_list arg_list, type));

Прелази сваки аргумент на листи аргумената са својим типом података као 'тип'. Нећемо знати број и тип података параметара прослеђених функцији. Стога треба да додамо неки тип података пређеним аргументима и корисник експлицитно дефинише тип за аргументе који се преузимају помоћу макроа ва_арг. Враћа аргумент који је истог 'типа' који има макро ва_арг.

интПарам = ва_арг(параметри, инт));// преузима параметре из 'параметерс' и пребацује их на тип 'инт' и додељује их променљивој 'интПарам' која је такође типа 'инт'.

  • ва_енд: Овај макро користи се за означавање краја употребе листе параметара функције. Ако се овај макро не позове, функција се неће вратити и њен резултат неће бити дефинисан. Иако макронаредба ва_енд не враћа ништа, треба да наведемо овај макронаредбу да означи крај употребе променљивих параметара функције.

    ва_енд(ва_лист арг_лист); // завршавамо употребу параметара
    ва_енд(параметри); // завршавамо употребу параметара

#include <stdarg.h>
#include <stdio.h>

// Function declaration and definition
int fnAddition (int intCount, ...){
	int intSum = 0;
	va_list parameters; // declare a variable 'parameters' of type va_list

	va_start (parameters, intCount); //Starts accessing the optional parameter from the beginning
	printf("\nNumber of parameters passed is:%d", intCount);

	printf("\nNumbers that are passed to the function are:\n");
	for (int index = 0; index < intCount; index++)
		printf("%d\t", va_arg(parameters, int));

	va_start(parameters, intCount); //Starts accessing the optional parameter from the beginning
	for (int index = 0; index < intCount; index++)
		intSum += va_arg(parameters, int);
	
	va_end(parameters); // end the use of parameters
	return intSum; //return the result
}

void main (){
	int intResult;
	intResult = fnAddition (5, 10, 20, 30, 40, 50); //calls the function 5 parameters
	printf ("\nSum the numbers is:%d", intResult);
}

Главна функција

Ово је важна функција било ког програма Ц. Било који програм мора имати ову подразумевану функцију. Ова функција је она од које започиње извршавање програма Ц. Стога не треба да декларишемо прототип функције, већ морамо да дефинишемо ову функцију. То значи да ову главну функцију треба да имамо тамо где прихватамо вредности, позивамо функције, приказујемо резултате итд. Главна функција је обично типа ретурн као инт, која се користи за указивање статуса програма компајлеру. Ако користимо његов тип повратка као инт, програм треба да има 'ретурн 0;' на крају да означи да је програм успешно састављен. Али такође можемо имати његов тип повратног стања воид - што значи да преводилац нема статус.

Ова функција може или не мора имати аргументе. Аргументи се преносе функцији када треба да ухватимо улазе кроз командну линију током извршавања програма. Ако корисник унесе унос током извршавања програма као горе сви примери, не морамо прослеђивати аргументе главној функцији.

#include <stdio.h>

int main (){
	printf ("\Example of main function without arguments");

	return 0; // indicates compiler that program is executed successfully and can exit from the program
}

Када се аргументи проследе главној функцији, она прихвата два аргумента - један број аргумената са целобројним типом, а други је низ параметара са типом цхар. Може се назвати било како, али они треба да имају исти тип података као што је објашњено.

инт главни (инт аргц, Чар * аргв []) {….}

аргц - је број параметара који се преносе функцији

* аргв [] - је показивач карактера на низ аргумената. Прихватаће аргц број параметара у свој низ.

#include <stdio.h>

int main(int argc, char *argv[]){

	printf("\nTotal Number of arguments passed is : %d", argc);
	printf("\nArguments passed through command line is : \n");
	for (int index = 0; index<argc; index++)// traverses each arguments one by one
		printf("%s\t" , argv[index]);

	return 0; // indicates compiler that program is executed successfully and can exit from the program
}

Рекурзивне функције

То су функције које се у оквиру исте функције позивају више пута. То значи да се функција назива сама од себе.

datatype fn_name (){
	….
	fn_name(); // same function is being called
	….
}


Познати пример за објашњење рекурзијске функције је факторијел броја. Факторијал броја је умножак броја и факторијела броја -1. тј;
факторијел (н) = н * факторијел (н-1)
= н * (н-1) * факторијел (н-2)
=….
= н * (н-1) * (н-2) * ... .. * 3 * 2 * факторијел (1)
= н * (н-1) * (н-2) * ... .. * 3 * 2 * 1
Овде можемо уочити образац при израчунавању факторијела броја. То јест, више пута израчунава факторијел претходног броја и множи га са тренутним бројем. То значи да, када пишемо функцију за израчунавање факторијела, не треба писати никакву фор петљу или док петља где непрекидно множимо бројеве да бисмо добили факторијел. Уместо тога, можемо више пута позивати исту функцију док не добијемо број 1. Укратко, факторска функција ће бити као доле:
int fnFactorial(int intNum){
	if (intNum < 1)
		return 1;
	else
		return (intNum * fnFactorial(intNum - 1));
}

Будући да се функција позива унутар исте функције, морамо бити опрезни да бисмо креирали рекурзивну функцију. Ако се не користи правилна наредба заустављања, може завршити у бесконачној петљи. У горњем примеру постоји услов да се провери да ли је број мањи од један. Ако је мање од један, онда не позивамо функцију тамо; уместо да врати 1 заустављањем позива функције. Али ако је број већи или једнак јединици, непрекидно позивамо функцију за број једнак интНум -1. Тако понавља функцију и зауставља се у једном тренутку.
#include <stdio.h>
int fnFactorial(int intNum);

void main(){
	int intVal;

	printf("\n Please enter the number whose factorial to be found:");
	scanf("%d", &intVal);
	printf("\n Factorial of a number %d is : %d:", intVal, fnFactorial(intVal));
}
int fnFactorial(int intNum){
	if (intNum < 1)
		return 1;
	else
		return (intNum * fnFactorial(intNum - 1));
}

Статичке функције

Претпоставимо да морамо да напишемо неке функције које су интерне у програму и не желимо да било који корисник користи ту функцију. Ове интерне функције може користити нека друга функција у истом програму, али не би требало да буду доступне другим програмима, датотекама или корисницима. На пример, претпоставимо да имамо програм у којем генеришемо разне извештаје попут извештаја о оцени ученика, годишњег извештаја факултета и неких других извештаја особља. Али сви они имају заједничко заглавље извештаја са именом колеџа, адресом, телефоном, факсом итд. Стога можемо имати функцију да сви ови подаци заглавља буду одштампани на извештају. Али функцију за приказ заглавља позваће различите функције које генеришу извештаје. Стога ова функција заглавља нема никакве везе са корисницима. Слично томе, други програми или повезани са студентима не захтевају ове функције заглавља. Укратко, не желимо да било који други програми или датотеке или корисници приступају овој функцији заглавља која је посебно креирана за заглавље извештаја. Тако ову функцију заглавља можемо сакрити од било које друге датотеке или корисника и учинити је да је користи датотека / програм у којем је написана. То се постиже употребом кључне речи 'статиц' пре декларације функције.

статички тип података име_функције (аргумент / и);
   статичка празнина дисплаиХеадер ();

Статичка функција је она којој могу приступити функције у датотеци у којој је створена. Није јавно доступан за кориснике или друге програме.

Креирајмо две датотеке - стд_стафф_репорт.ц за приказ студентских, запослених и годишњих извештаја и дисплаиХеадер.ц датотеку за приказ заглавља извештаја. Позовимо функцију дисплаиХеадер () у датотеку дисплаиХеадер из датотеке стд_стафф_репорт.ц, а да функцију не учинимо статичном. Радиће нормално као и било која друга датотека. Ако функцију учинимо статичном, позив функције из датотеке стд_стафф_репорт.ц ће избацити грешку. Ако те функције напишемо у стд_стафф_репорт.ц у датотеку дисплаиХеадер.ц и позовемо их да ће радити нормално. То значи да су статичке функције доступне само оним функцијама које се налазе у истој датотеци. Статичке функције нису доступне ниједном другом кориснику / датотеци / програму осим тамо где су написане.

// displayHeader.c
#include <stdio.h>
 static void displayHeader(){
	printf("\nDisplaying Header");
}

 
//std_staff_report.c
#include <stdio.h>
#include "displayHeader.c"// comment this line to see the affect of static
void displayStdReport(char *stdName);
void displayStaffReport(char *staffName);
void displayAnnualReport();

void main(){
	printf("\n\nStudent Report is:");
	displayStdReport("Rose");
	printf("\n\nStaff Report is:");
	displayStaffReport("Robert");
	printf("\n\nAnual Report is:");
	displayAnnualReport();

}
void displayStdReport(char *stdName){
	printf("\nInside %s Student Report Function:", stdName);
	displayHeader();
	printf("\nDisplaying %s Student Report :", stdName);

}
void displayStaffReport(char * staffName){
	printf("\nInside %s Staff Report Function:", staffName);
	displayHeader();
	printf("\nDisplaying %s Staff Report:", staffName);
}
void displayAnnualReport(){
	printf("\nInside Annual Report");
		displayHeader();
		printf("\nDisplaying Annual Report");
}

Угњежђене функције

Угњежђене функције су функције које имају једну или више функција које се позивају у њему. На пример, позив функције унутар главне функције чини главну функцију угнежђеном функцијом. Не постоји ограничење броја угнежђених функција. Већ смо видели гнежђење функција у главној функцији, рекурзивној функцији, статичкој функцији итд.

datatype function_name(arguments){
	datatype function_name1(); // declare another function
	…
	datatype function_name1(); // call the function
	….
	datatype function_name1(){ //define the function
	…
	}
}

Различите аритметичке операције изведене у оквиру главне функције пример су угнежђене функције.
#include <stdio.h>

//Function Declaration
void add(int intNum1, int intNum2);
void minus(int intNum1, int intNum2);
void divide(int intNum1, int intNum2);
void multiply(int intNum1, int intNum2);

void main(){
	// calling different functions within another function
	add(30, 60);
	minus(100, 23);
	divide(25, 5);
	multiply(400, 7);
	printf("\n End of the arithmetic Operation….");
}

void add (int intNum1, int intNum2){
	printf("\nSum of %d and %d is : %d", intNum1, intNum2, intNum1 + intNum2);
}
void minus(int intNum1, int intNum2){
	printf("\nDifference of %d and %d is : %d", intNum1, intNum2, intNum1 - intNum2);
}
void divide(int intNum1, int intNum2){
	printf("\nResult of %d / %d is : %d", intNum1, intNum2, intNum1 / intNum2);
}
void multiply(int intNum1, int intNum2){
	printf("\nResult of %d * %d is : %d", intNum1, intNum2, intNum1*intNum2);
}

резиме

  • Функција је именовани блок кода за вишекратну употребу у програму.
  • Постоје две врсте функција - библиотечке и кориснички дефинисане функције.
  • Функције библиотеке су - маин (), сцанф, гетс, гетцхар, принтф, пут, путцхар, маллоц, цаллоц, скрт, син, цос, тан, флоор, екп, толовер, тоуппер, исдигит, исалпха итд.
  • Параметри у функцију могу се преносити на два начина - прослеђивање вредности и прослеђивање референце.
  • У пролазу по вредности, вредност стварног параметра се преноси и функција не може променити вредност стварног параметра
  • У просљеђивању путем референце, адреса стварног параметра се просљеђује и све промјене вриједности формалног параметра промијениће и вриједност стварних параметара. Али адреса оба параметра остаје иста.
  • Варијадне функције су функције које прихватају променљиви број параметара било ког типа.
  • Статичке функције су функције које датотекама или програмима или корисницима нису видљиве осим датотеке у којој је написана.
  • Угњежђене функције су функције дефинисане у оквиру других функција.
  • Рекурзивна функција је она у којој се исте функције више пута позивају у њој.