субота, 20 априла, 2024
Како да...?

Увод у програмски језик C (8. део)

Аутор: Никола Харди

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

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

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

Функције могу да обухвате и код који није дословно исти. Код можемо да „параметризујемо”. То значи да при сваком позиву функције можемо да подесимо неке делове кода. Например, ако имамо функцију за испис имена, можемо да јој поставимо параметар које име желимо да буде исписано. То се постиже путем параметара или аргумената. У овом тексту нећемо правити разлику између параметара и аргумената иако она формално постоји.

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

Као и код променљивих, функција мора да буде декларисана пре него што је позовемо. Декларација функције се назива још и њеним „потписом” и састоји се од типа повратне вредности, имена потпрограма и листе параметара, завршно са знаком тачка-зарез. Уколико уз декларацију функције желимо и да је дефинишемо, то може да буде урађено тако што се изостави знак тачка-зарез и у наставку потписа се напише тело потпрограма.

Пример процедуре без параметара:

void procedure()
{
	puts("Hello world!");
}

Пример функције са два параметра:

int sum(int a, int b)
{
	int c;
	c = a + b;
	return c;
}

Примећујете да параметри имају свој тип и назив. Понашају се слично променљивим. Унутар функције могу бити декларисане додатне променљиве. Резултат функције, који се још назива и повратна вредност, „враћа” се наредбом return. Важно је рећи да се извршавањем наредбе return прекида извршавање целе функције, што је илустровано следећим примером.

Пример прекида извршавања функције наредбом return:

int min(int a, int b)
{
	if(a < b)
		return a;
	else if(b < a)
		return b;
}

Уколико је број a мањи од броја b, извршавање ће се завршити већ у другој линији ове функције, а до друге провере неће ни доћи. Занимљиво је приметити и да ова функција има грешку. Шта се догађа уколико су бројеви једнаки?

Функције имају сврху само ако их користимо, односно „позивамо”. Функције се позивају по имену, а од променљивих се разликују по томе што се у позиву функције пише и пар заграда, унутар којих су вредности параметара када је то потребно.

Пример позива фукције sum():

int zbir = sum(2, 3);

Последња ствар која је остала недоречена је да се параметри у функцију могу пренети по вредности или по адреси. Практична употреба и детаљи о разликама су ипак можда превише за један уводни курс о C-у. Најважније ствари које треба имати на уму су да, када параметре користите као у нашим примерима функција sum() и min(), тада се они преносе по вредности и практично се копирају. То значи да ако доделимо нове вредности параметрима, те вредности ће важити само унутар функције, а не и на месту где је функција позвана. Да би такве доделе биле видљиве и ван функције, користи се пренос параметара по адреси. То заправо значи да се при навођењу параметара у декларацији користе показивачи, а при позиву функције се користе адресе (показивачи или адресе променљивих).

Пример преноса параметара по адреси:

void swap(int *a, int *b)
{
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

Позив:

	int a = 5, b = 7;
	swap(&a, &b);

Требало би да овај текст покрије основне ствари о руковању потпрограмима. Уколико вам је потребна инспирација како да увежбате рад са функцијама, ево лепог проблема:

Покушајте да напишете функцију за испис елемената низа на стандардни излаз. Затим напишите функцију за сортирање низа у којој ћете позивати функцију за испис низа и посматрајте како елементи низа мењају своја места.

Уколико вас занима нешто више, или нам се поткрала нека грешка, молимо вас да нам се јавите. Срећно!

Наредни део овог серијала можете прочитати овде.

Претходни део овог серијала можете прочитати овде.