Thursday, June 9, 2016

c හා c++ ප්‍රෝග්‍රැමිං - 9


මී ළඟට අප ඉගෙන ගන්නට යන්නේ ප්‍රෝග්‍රැමිංවල ඉතාම වැදගත් මාතෘකාවක් වන ෆන්ක්ෂන් ගැනයි. ෆන්ක්ෂන් ගැන ඉගෙන ගත් පසුව සෑම සී ප්‍රෝග්‍රෑම් එකකම දක්නට ලැබෙන main() ගැනත් අපට හොඳින් වටහ ගත හැකියි. පළමුවෙන්ම පහත දැක්වෙන ප්‍රෝග්‍රෑම් එක රන් කර බලන්න. මෙම ප්‍රෝග්‍රෑම් එකේ එකම කෝඩිං කොටසක් 4 සැරයක් ලියා තිබෙනවා නේද?

/* C program without using functions */

#include <stdio.h>

int main()
     {

     int num1, num2;

     /* first run */
     printf("Enter 2 integers\n");
     scanf("%d\n%d",&num1,&num2);
     printf("The sum of 2 integers is: %d\n",num1+num2);
     /* second run */
     printf("Enter 2 integers\n");
     scanf("%d\n%d",&num1,&num2);
     printf("The sum of 2 integers is: %d\n",num1+num2);

     /* third run */
     printf("Enter 2 integers\n");
     scanf("%d\n%d",&num1,&num2);
     printf("The sum of 2 integers is: %d\n",num1+num2);

     /* fourth run */
     printf("Enter 2 integers\n");
     scanf("%d\n%d",&num1,&num2);
     printf("The sum of 2 integers is: %d\n",num1+num2);

     return 0;

     }

දැන් ඔබට අවශ්‍ය වුවොත් 4 සැරයක් වෙනුවට 100 සැරයක් හෝ 1000 එම කෝඩිං කොටස නැවත නැවත සැරයක් ලියන්නට? ඔබ සිතාවි කිසි ප්‍රශ්නයක් නැතිව එය කළ හැකියිනෙ කියා. එකම කෝඩිං කොටස තමන්ට අවශ්‍ය තරම් ටයිප් කළ හැකියි. එහෙමත් නැතිනම් copy-paste කළ හැකියි. එහෙත් මෙය ඊට වඩා කාර්යක්ෂම හා පහසුවෙන් කළ හැකි ආකාරයක්ද ප්‍රෝග්‍රැමිංවල තිබේ. ඒ තමයි ෆන්ක්ෂන් (function). ෆන්ක්ෂන් ගැන පැහැදිලි කිරීමට පෙර ඉහත ප්‍රෝග්‍රෑම් එකම ෆන්ක්ෂන් යොදා ගෙන සාදා ගන්නා අන්දම බලමු.

/* C program using functions */

#include <stdio.h>

/* function definition */
void AddNumbers()
     {
     int num1, num2;
     printf("Enter 2 integers\n");
     scanf("%d\n%d",&num1,&num2);
     printf("The sum of 2 integers is: %d\n",num1+num2);
     }

int main()
     {

     /* function calls 4 times */
     AddNumbers();
     AddNumbers();
     AddNumbers();
     AddNumbers();
     return 0;

     }

බැලූ බැල්මට එක් වෙනසක් පැහැදිලිවම පෙනේ. එනම්, ෆන්ක්ෂන් යොදා ගත් ප්‍රෝග්‍රෑම් එක අනෙකට වඩා කුඩා වේ. මෙම කුඩා බව සෝස්කෝඩ් එකේ පමණක් නොව, කම්පයිල් කළාට පසුව ලැබෙන බයිනරි ෆයිල් එකෙත් සිදු වේ. ෆන්ක්ෂන්වල ඇති ප්‍රධාන වාසියකි ප්‍රෝග්‍රෑම් කුඩාවීම. ඉහත උදාහරණවල නම් එකම කෝඩිං කොටස 4 සැරයක් පමණයි නැවත නැවත රන් වන්නේ. එහෙත් සියදහස් සැරයක් එය සිදුවන අවස්ථාවලදී ෆන්ක්ෂන් යොදා ගන්නා විට ඉන් ෆයිල් එක කුඩා වීම කැපී පෙනෙන ලෙසම සිදු වේ. තවද, ඉහත උදාහරණයේ නැවත නැවත රන් වන කෝඩිං කොටසේ තිබුණේ පේලි 3ක් (හෙවත් කමාන්ඩ් 3ක්) පමණි. එහෙත් ප්‍රායෝගිකව කමාන්ඩ් දුසිම් ගණනාවක් එලෙස නැවත නැවත රන් වන අවස්ථා තමයි හමු වන්නේ. ඒ කියන්නේ නැවත නැවත රන් වන කොටසේ ඇති කමාන්ඩ්/පේලි ගණන වැඩි වන තරමට, ෆන්ක්ෂන් යොදා ගැනීමේ වැදගත්කම තව තවත් ඉස් මතු වේ.

කුමක්ද ෆන්ක්ෂන් එකකින් ඇත්තටම සිදු වූයේ? නැවත නැවත රන් වන කෝඩිං කොටස වෙනම ගෙන, අප ඊට නමක් (ෆන්ක්ෂන් නේම් - function name) ලබා දෙනවා. ඉන්පසු ප්‍රෝග්‍රෑම් එකට එම කෝඩිං කොටස රන් කිරීමට අවශ්‍ය හැම අවස්ථාවකදීම ෆන්ක්ෂන් නේම් එක ලිවීම ප්‍රමාණවත් (සම්පූර්ණ කෝඩිං කොටසම නොලියා). බලන්න එය කොතරම් පහසුද කියා. නැවත නැවත රන් වන ප්‍රෝග්‍රැමිං කොටස වෙනම ගෙන ඊට නමක් ලබා දීම function definition (ෆන්ක්ෂන් එකක් සෑදීම) ලෙස හැඳින්වෙනවා.

ඉන්පසු එම ෆන්ක්ෂන් එක ක්‍රියාත්මක වීමට අවශ්‍ය තැන්වල එම ෆන්ක්ෂන් නේම් එක ලිවීම function calling (හෝ calling a function) හෙවත් function invoking/invocation ලෙස හැඳින්වෙනවා. ඇත්තටම සී හිදී ෆන්ක්ෂන් එකක් නිවැරදිව සාදා ගන්නා විදිය (ඒ කියන්නේ ෆන්ක්ෂන් එකක් ඩිෆයින් කරන අයුරු) ගැනත්, ෆන්ක්ෂන් එකක් කෝල් කරන විදිය ගැනත් දැනගත යුතු කරුණු කිහිපයක් ඇත. ඒ ගැන දැන් විමසා බලමු.

ඉහත උදාහරණයේ තිබූ ෆන්ක්ෂන් එක මා නැවත පහත ලියන්නම්. ෆන්ක්ෂන් එකක් කෝල් කරන විට රන් වන කෝඩිං කොටස (එනම් නැවත නැවත රන් වන කෝඩිං කොටස) { } යන සඟල වරහන් තුල ලිවිය යුතුය. එලෙස සඟල වරහන තුල ඇති කොටස function body (හෝ body of the function) කියා හැඳින්වෙනවා. ඇත්තටම ෆන්ක්ෂන් බොඩි එක තමයි ෆන්ක්ෂන් එකේ රාජකාරිය ඉටු කරන්නේ. පේලි දෙක තුනක කුඩා පේලි ගණනක සිට පේලි සියදහස් ගණනක් දක්වා විශාල ෆන්ක්ෂන් බොඩි දක්නට ලැබෙනවා.

void AddNumbers()
     {
     int num1, num2;
     printf("Enter 2 integers\n");
     scanf("%d\n%d",&num1,&num2);
     printf("The sum of 2 integers is: %d\n",num1+num2);
     }

ඇත්තටම සාමාන්‍යයෙන් ෆන්ක්ෂන් බොඩි එකක අච්චර පේලි ගණනක් (කමාන්ඩ් ගණනක්) තිබිය යුතුයි කියා නීතියක් නැත. එහෙත් එය අතිවිශාල නොවිය යුතුය. එක් පිටුවක් හෝ පිටු භාගයක් පිරෙන තරමට උපරිම පේලි ගණනක් තිබීම ඉතා හිතකරයි (හොඳ ප්‍රෝග්‍රැමිං පුරුද්දක්).
සාමාන්‍යයෙන් ෆන්ක්ෂන් බොඩි එක පිටු ගණන් පිරෙන තරමට විශාල වේ නම්, ඊට ප්‍රධාන හේතුව එක් ෆන්ක්ෂන් එකකින් විශාල රාජකාරි/කටයුතු ප්‍රමාණයක් සිදු කිරීමට උත්සහ කිරීමයි. එය හොඳ පුරුද්දක් නොවේ. එක් ෆන්ක්ෂන් එකකින් එක් රාජකාරියක් සිදු කරන්න. ඔබට ඕනෑ තරම් ෆන්ක්ෂන් ප්‍රමාණයක් ලිවිය හැකියි. ඉතිං එක් එක් රාජකාරියට වෙනම වෙනම ෆන්ක්ෂන් ලිවිය හැකියිනෙ.

තවද, එක් ෆන්ක්ෂන් එකක් තුළ රාජකාරි ගණනාවක් සිදු කර ගතහොත් ෆන්ක්ෂන්වල තිබෙන ප්‍රයෝජනවත් බවද අඩු විය හැකියි. "එක් රාජකාරියක් පමණක් කරන ෆන්ක්ෂන්" විශාල ප්‍රමාණයක් තිබීම "රාජකාරි කිහිපය බැගින් ඇතුලත් කොට ඇති ෆන්ක්ෂන්" කුඩා ප්‍රමාණයක් තිබීම යන අවස්ථා දෙකෙන් ඉතා ප්‍රයෝජනවත් වන්නේ පළමු අවස්ථාව වේ. දෙවැනි අවස්ථාව හරියට බස් කොන්දොස්තර කෙනෙකු ගාව මාරු කාසි නැතිව ලොකු මුදල් නෝට්ටු තිබෙනවා වාගේ වේවි. උදාහරණයක් ලෙස සිතමු ඔබ ගාව සාදා තිබෙනවා (ඩිෆයින් කර තිබෙනවා) යම් ෆන්ක්ෂන් එකක් ඉලක්කම් දෙකක් අඩු කිරීම හා එකතු කිරීම යන රාජකාරි දෙකම එකවර සිදු කරන. එවිට ඔබට එම ෆන්ක්ෂන් එක කෝල් කර එම ෆන්ක්ෂන් එකේ ක්‍රියාකාරිත්වය ලබා ගත හැකියි (එනම්, එකතු කිරීම හා අඩු කිරීම යන ක්‍රියාවන් දෙකම). එහෙත් දැන් ප්‍රෝග්‍රෑම් එකේ යම් අවස්ථාවක ඔබට අවශ්‍ය වුවොත් එකතු කිරීම පමණක් සිදු කිරීමට ඔබට එම ෆන්ක්ෂන් එක ප්‍රයෝජනයට ගන්නට බැහැ නේද මොකද ඉන් අඩු කිරීමත් සිදු කරන නිසා? එලෙසමයි ඔබට අඩු කිරීම පමණක් ක්‍රියාත්මක වීමට අවශ්‍ය තැන්වලදීත් එම ෆන්ක්ෂන් එක කෝල් කරන්නට බැහැ. එහෙත් ඔබ එම ෆන්ක්ෂන් එක වෙනුවට එකතු කිරීම පමණක් සිදු කරන හා අඩු කිරීම පමණක් සිදු කරන ෆන්ක්ෂන් දෙකක් ඩිෆයින් කළා නම්, අපට මේ සියලු අවස්ථාවලදී පහසුවෙනුත් කාර්යක්ෂම ලෙසත් එම ෆන්ක්ෂන් භාවිතා කළ හැකියි දැන්.

ෆන්ක්ෂන් බොඩි එක පටන් ගන්නා { ට පෙර ලියා තිබෙන කොටසත් ඉතාම වැදගත්. එම පේලියේ තමයි ෆන්ක්ෂන් නේම් (ෆන්ක්ෂන් එකේ නම) හා ඊට අදාල තවත් වැදගත් කොටස් කිහිපයක් තිබෙන්නේ. මෙම පේලිය function header කියා හැඳින්වෙනවා. ඉහත උදාහරණයේ void AddNumbers() ලෙස ඇත්තේ එම ෆන්ක්ෂන් එකේ හෙඩර් එකයි. හෙඩර් එක සෑදී තිබෙන්නේ කොටස් 3කින්ය.

එහි AddNumber වැනි ෆන්ක්ෂන් නේම් එකක් තිබෙනවා. ඔබට කැමති නමක් ලබා දිය හැකියි. මීට පෙර වේරියබල් නේම් ගැන කතා කරන විට මතකද identifier ගැනත් කතා කළා? ෆන්ක්ෂන් නේම් එකද අයිඩෙන්ටිෆයර් එකකි. එනිසා අයිඩෙන්ටිෆයර් සෑදීමේදී බලපාන රීති මීටත් වලංගු වේ. ෆන්ක්ෂන් නේම් එකක් ලිවීමේදී හොඳ පුරුදු (good programming practices) ඇත. කැමල් නොටේෂන් එක භාවිතා කරන්න; එහෙත් මෙහිදී සුලු වෙනසක් තිබෙනවා මොකද පළමු වචනයේ පළමු අකුරත් කැපිටල් කරනවා (සාමාන්‍යයෙන් පළමු වචනයේ පළමු අකුර කැමල් නොටේෂන්වලදී සිම්පල්වලින්නෙ තබන්නේ). තවද, ෆන්ක්ෂන් එකෙන් කරන රාජකාරිය පිළිබිඹු වන ආකාරයේ කෙටි නමක් ලබා දෙන්න. මෙහිදී ඉහත පැහැදිලි කළ ලෙසටම ෆන්ක්ෂන් එකෙන් කරන්නේ එක් රාජකාරියක් නම් මෙවැනි කෙටි නමක් ලබාදීම පහසු වේ; රාජකාරි කිහිපයක් කරන විට, ඉතා දිගු නම් ලිවීමට සිදු වේවි (රාජකාරි එකක් පමණක් සිදු කිරීමේ තවත් වාසියක් මෙය). ෆන්ක්ෂන් එකකින් යම් රාජකාරියක් සිදු කරන නිසා, ෆන්ක්ෂන් නේම් එක සාමාන්‍යයෙන් පටන් ගන්නේ ක්‍රියාපදයකිනි (එයත් ඉතා හොඳ පුරුද්දක් මිස රීතියක් නොවේ). ඉහත උදාහරණයේ AddNumbers යන්නෙහි Add යන ක්‍රියාපදයෙන් ආරම්භ වී තිබේ (මොකද මෙම ෆන්ක්ෂන් එකෙන් කරන්නේ සංඛ්‍යා දෙකක් එකතු කිරීම නිසා එම නම ඉතා උචිතය). ක්‍රියාපදය පමණක් මදි වගේ දැනෙනවා නම් ඊට පසුව නාමපදයක් ලිවිය හැකියි (Add ට පසුව Numbers යන්න මා ලියා ඇත ඉහත උදාහරණයේ).

ෆන්ක්ෂන් නේම් එකට ඉදිරියෙන් යම් කීවර්ඩ් එකක් ඇත. අප මීට පෙර ඉගෙන ගත් ඩේටා ටයිප් එකක් තමයි මෙහි ලියන්නේ. මෙම කොටස return type ලෙස හැඳින්වෙනවා. රිටර්න් ටයිප් එක ලෙස short, long, int, float, double, char, void වැනි කීවර්ඩ් ඔබ නිතරම දකිවී. අපේ උදාහරණයේ තිබෙන්නේ void යන්නයි. මෙම කොටසින් සිදු කරන්නේ කුමක්ද? සාමාන්‍යයෙන් දෙයාකාරයක ෆන්ක්ෂන් ඇත. එක් වර්ගයකදී ෆන්ක්ෂන් බොඩි එක තුළ යම් ක්‍රියාකාරිත්වයක් සිදු කර නිකංම ෆන්ක්ෂන් එක අවසන් වෙනවා. ඒ කියන්නේ ෆන්ක්ෂන් එකෙන් කිසිදු අගයක්/දත්තයක් පිට කරන්නේ නැහැ. දෙවැනි වර්ගයේදී අර කියූ විදියට යම් ක්‍රියාකාරිත්වයක් සිදු කර, අවසානයේදී යම් අගයක්/දත්තයක් පිට කරනවා. මේ පිට කරන දත්තය short, long, int, char, float, double ආදී ඩේටා ටයිප් එකකට අයත් විය යුතුය. කිසිදු දත්තයක් පිට කරන්නේ නැතිනම් void ලෙස ලිවිය යුතුය. ඉහතදී ගත් උදාහරණයේදී ෆන්ක්ෂන් එක තුල යම් රාජකාරියක් සිදු කළද අවසානයේ දත්තයක් පිට නොකරන නිසා void යන්න ලියා ඇත. පහත කෝඩිං බලන්න.

int AddNum(int num1, int num2)
    {
    int sum;
    sum = num1 + num2;
    return(sum);
    }

ඉහත ෆන්ක්ෂන් ඩෙෆිනිෂන් එකෙන් සිදු කරන්නේ ඊට පිටතින් ලබා දෙන සංඛ්‍යා දෙකක් එකතු කිරීමයි. එම එකතු කිරීම sum = num1 + num2; යන ස්ටේට්මන්ට් එකෙන් සිදු වෙන බව පේනවා. දැන් sum යන වේරියබල් එකේ තමයි එකතුව ගබඩා වී තිබෙන්නේ. එම දත්තය දැන් ෆන්ක්ෂන් එකේ අවසානයේදී ෆන්ක්ෂන් එකෙන් පිටතට ලබා දිය යුතුයි. එය සිදු කරන්නේ return() නම් කමාන්ඩ් එකෙන්. එම කමාන්ඩ් එකේ () යන වරහන් තුල තිබෙන්නේ පිටකළ යුතු දත්තයයි. මෙම උදාහරණයේ මෙලෙස පිට කරන්නේ int යන දත්ත වර්ගයක් නිසා (එනම් sum යනු int වර්ගයේ දත්තයකි) තමයි ෆන්ක්ෂන් හෙඩර් එකේ int AddNumber ලෙස ලියා තිබෙන්නේ. දැක්කද ෆන්ක්ෂන් හෙඩර් එක හා return ස්ටේට්මන්ට් එක අතර තිබෙන සම්බන්ධය? රිටර්න් කරන දත්තයේ දත්ත වර්ගයට ගැලපෙන දත්ත වර්ගය තමයි අනිවාර්යෙන්ම හෙඩර් එකේ රිටර්න් ටයිප් සඳහා ලියන්නේ. ඔබට අවශ්‍ය නම්, අමුතුවෙන් sum යන විචල්‍යයක් භාවිතා නොකර කෙලින්ම return(num1 + num2); කියාද ලිවිය හැකිව තිබුණා. එවිට එය පහත ආකාරයට ලිවිය යුතුයි.

int AddNum(int num1, int num2)
    {
    return(num1+num2);
    }

මෙහිදී return ස්ටේට්මන්ට් එක තුලම විචල්‍ය දෙක එකතු කිරීම සිදු කර, එහි ප්‍රතිපලය කෙලින්ම රිටර්න් කරනවා. ඇත්තටම යම් කමාන්ඩ් එකකට පසුව ඇති වරහන් තුල මෙලෙස කුඩා ගණනය කිරීම් සිදු කරන අවස්ථා නිතරම ප්‍රෝග්‍රැමිංවල හමු වෙනවා. මතක තබා ගන්න, මෙහිදී කුඩා ගණනය කිරීම් තමයි සාමාන්‍යයෙන් වරහන් තුළ සිදු කරන්නේ. ගණනය කිරීම විශාල නම්, පෙර කෝඩිං කොටසේදී මෙන්, එම ගණනය කිරීම වෙනමම සිදු කර, එහි ප්‍රතිපලය තවත් විචල්‍යයක ගබඩා කර, ඉන්පසු එම විචල්‍ය තමයි වරහන තුල ලියන්නේ. එලෙස සිදු කිරීම නිසා සෝස්කෝඩ් එක කියවා තේරුම් ගැනීමට පහසුව ලැබේ.

මේ අනුව, යම් ෆන්ක්ෂන් බොඩි එකක අවසානයට return() ස්ටේට්මන්ට් එකක් නැතිනම්, ඉන් අදහස් වන්නේ එම ෆන්ක්ෂන් එකෙන් යම් දත්තයක් පිටතට ලබා දෙන්නේ (රිටර්න් කරන්නේ) නැති බවයි. එවිට void යන කීවර්ඩ් එක ෆන්ක්ෂන් හෙඩර් එකේ තිබිය යුතුයි. සමහර ප්‍රෝග්‍රැමිං භාෂාවල නම්, මෙම දෙයාකාරයේ ෆන්ක්ෂන් සලකන්නේ වෙනස් වෙනස් ජාතියේ දෙකක් ලෙසයි. එහෙත් සීවලදී ඒ දෙවර්ගයම එකම ජාතියේ එකක් (එනම් ෆන්ක්ෂන් එකක්) ලෙස සලකනවා. මෙවිට ඒ දෙකෙහි වෙනස පෙන්වන්නේ පෙර ඉගෙන ගත් පරිදි void හෝ වෙනත් ඩේටා ටයිප් එකක් ලිවීමෙනි. සී වල ෆන්ක්ෂන් කියා ඉගෙන ගන්නා දේම වෙනත් භාෂාවලදී function, subroutine (sub), procedure, subprogram වැනි නම්වලින් හැඳින්විය හැකියි.

හෙඩර් එකේ ෆන්ක්ෂන් නේම් එකට පසුව වරහන් අනිවාර්යෙන්ම තිබිය යුතුය. සමහරවිට හිස් වරහන් තිබේවි (ඒ කියන්නේ වරහන් තුල කිසිවක් නොලියා නිකංම () ලෙස තිබේවි). තවත් අවස්ථාවල වරහන් තුල යම් යම් දේවල් තිබෙනු පෙනේවි. මෙම වරහන් කොටස parameter list (හෝ parameters) ලෙස හැඳින්වෙනවා. බොහෝ අවස්ථාවලදී ෆන්ක්ෂන් එක ක්‍රියාත්මක වීමේදී ඊට පිටතින් යම් යම් දත්ත එකක් හෝ කිහිපයක් ලබා දිය යුතුය. ෆන්ක්ෂන් එකක් කෝල් කරන කොට, එලෙස දත්ත ලබා දෙන ක්‍රමය තමයි මෙම පැරාමීටර් ලිස්ට් එක. ඉහත උදාහරණය නැවත බලමු.

int AddNum(int num1, int num2)
    {
    int sum;
    sum = num1 + num2;
    return(sum);
    }

මෙම ෆන්ක්ෂන් එකෙන් කරන්නේ සංඛ්‍යා දෙකක් එකතු කර එම එකතුව රිටර්න් කරන එකනෙ. ඉතිං එකතු කිරීමට දැන් සංඛ්‍යා දෙකක් (එනම් දත්ත දෙකක්) අවශ්‍යයි. එය ලබා ගත හැකි ආකාර කිහිපයක් තිබේ. ඉන් එක් ක්‍රමයක් තමයි පැරාමීටර් ලිස්ට් එක. මෙම AddNum යන ෆන්ක්ෂන් එක කෝල් කරන විට ඒ එක්කම මෙම සංඛ්‍යා/දත්ත දෙක ලබා දිය යුතුය (එය ලබා දෙන ආකාරය මොහොතකින් පෙන්වන්නම්). ෆන්ක්ෂන් කෝල් එක සිදු කරන මොහොතේ ලබා දුන් එම දත්ත ගබඩා කර ගන්නේ වරහන් තුල තිබෙන පැරාමීටර් ලිස්ට් එකේය. ඉහත උදාහරණයේදී අපට සංඛ්‍යා දෙකකුයි පිටතින් අවශ්‍ය වූයේ. ඉතිං එම සංඛ්‍යා දෙක දැන් පැරාමීටර් ලිස්ට් එකේ තිබෙනවා num1, num2 ලෙස. ඉන්පසු ඔබට පෙනෙන පරිදි එම අගයන් දෙක එකතු කර sum නම් තවත් විචල්‍යයකට ගබඩා කර අවසානයේ රිටර්න් කෙරෙනවා.

පැරාමීටර් ලිස්ට් එකේ තිබෙන්නේ parameters (පරාමිතීන්) වේ. පැරාමීටර් කිසිවක් නොමැති විට නිකංම () ලෙස තැබිය යුතුය. පැරාමීටර් තිබෙන විට, එම පැරාමීටර් සියල්ල () තුළ සටහන් කළ යුතුය. ඇත්තටම පැරාමීටර් එකක් යනු අමුතු දෙයක් නොවේ; පැරාමීටර් යනු වේරියබල් වේ. වේරියබල් එකකින් සිදු කරන්නේ යම් දත්තයක් ගබඩා කර තබා ගැනීමනෙ. පැරමීටරයකින් සිදු කරන්නේද එයයි. මෙහිදී පැරාමීටර් යනුවෙන් වෙනමම නමක් ලබා දී තිබෙන්නේ පහසුව තකාය මොකද පැරාමීටර් යන නම ඇසෙන විටම අපට තේරෙනවා මේ කතා කරන්නේ ෆන්ක්ෂන්වලදී වරහන් තුළ ඩෙක්ලෙයාර් කර ඇති වේරියබල් ගැන කියා. සාමාන්‍යයෙන් වේරියබල් එකක් ඩෙක්ලෙයාර් කරන විදියට (එනම්, "variable_type variable_name” ආකාරයට) වරහන තුළ ඒවා ලිවිය යුතුයි. පැරාමීටර් කිහිපයක් ඇති විට කොමා යොදා ඒවා ඉහත උදාහරණයේ පෙන්වා ඇති පරිදි ඩෙක්ලෙයාර් කරන්න. පහත දැක්වෙන්නේ විවිධාකාරයේ පැරාමීටර් සහිත ෆන්ක්ෂන් හෙඩර් කිහිපයකි.

int func1();
short fun2(int para1);
long func3(short para1, short p2);
void fn4(int abc, short p2, float fl1);

ෆන්ක්ෂන් බොඩි එක තුළදී පැරාමීටර් ලිස්ට් එකේ තිබූ පැරාමීටර්ස් (එනම් වේරියබල්) සාමාන්‍ය වේරියබල් මෙන්ම භාවිතා කළ හැකි බව ඉහතදී ඔබ දුටුවා. තවද, ෆන්ක්ෂන් එකේ රාජකාරිය සිදු කිරීමට ඊට අවශ්‍ය නම් තවත් වේරියබල්, ඔබට පුලුවන් සාමාන්‍ය පරිදිම අතිරේක වේරියබල් ෆන්ක්ෂන් බොඩි එක තුල ඩෙක්ලෙයාර් කරන්නට. ඉහත උදාහරණයේදී int sum; ලෙස අප කර ඇත්තේ එය තමයි.

දැන් අපි බලමු ෆන්ක්ෂන් එකක් කෝල් කරන විදිය. එය ඉතාම සරලයි. ෆන්ක්ෂන් එක කිසිදු පැරාමීටරයක් නොගන්නේ නම් (එනම් ෆන්ක්ෂන් නේම් එකට පසුව නිකංම () ලෙස පවතී නම්), ඔබට කරන්නට තිබෙන්නේ ෆන්ක්ෂන් නේම් එක හා () ලිවීම පමණයි. එහෙත්, යම් ෆන්ක්ෂන් එකක් පැරාමීටර් එකක් හෝ කිහිපයක් ලබා ගන්නේ නම්, ඔබ එම ෆන්ක්ෂන් එක කෝල් කරන විට, ෆන්ක්ෂන් නේම් එක ලියා වරහනක් තුළ පැරාමීටර් ගණනට සමාන දත්ත ලිවිය යුතුයි (දත්ත කිහිපයක් ඇති විට කොමා යොදා වෙන් කළ යුතුයි). පහත දැක්වෙන්නේ ඉහතදී දක්වපු එක් එක් ෆන්ක්ෂන් එකක් කෝල් කරන අයුරුය.

func1();
fun2(53);
func3(12, 42);
fn4(23, 12, 24.43);

ඉහත එක් එක් ෆන්ක්ෂන් කෝල් එක ගැන කෙටියෙන් බලමු. func1 යන්නෙහි කිසිදු දත්තයක් නැත. ඊට හේතුව එම ෆන්ක්ෂන් එක ඩිෆයින් කරපු (සාදන) මොහොතේ කිසිදු පැරාමීටරයක් නොගන්නා ලෙසයි එය සකස් කර තිබෙන්නේ. එනිසා කිසිම හේතුවක් නිසාවත් එම ෆන්ක්ෂන් කෝල් එකේ වරහන් තුළ කිසිදු දත්තයක් ලිවිය නොහැකියි. එනිසා func1(23); හෝ func2(5, 44.32); වැනි ආකාරයකට එය ලිවිය නොහැකියි. fun2 යන ෆන්ක්ෂන් එක කෝල් කරන විට, ඊට 53 යන දත්තයද ඒ සමගම ඇතුලු කෙරේ. ඊට හේතුව එම ෆන්ක්ෂන් එක ඩිෆයින් කරන මොහොතේ int වර්ගයේ දත්තයක් ලබා ගත හැකි ලෙස එය ඩිෆයින් කර තිබීමයි. එනිසා එම ෆන්ක්ෂන් කෝල් එක fun2(); හෝ fun2(234.22, 54); වැනි ආකාරයකට කිසිසේත් ලිවිය නොහැකියි. func3 යන ෆන්ක්ෂන් එක කෝල් කරන විට ඊට 12 හා 42 යන දත්ත දෙක ඇතුලු කර ඇත. එලෙසම අවසාන fn4 යන ෆන්ක්ෂන් කෝල් එකේදී 23, 12, 24.43 යන දත්ත 3ක් ඒ සමග ඇතුලු කරනු ඇත. ෆන්ක්ෂන් එක ඩිසයින් කර තිබෙන්නේ පළමුව int වර්ගයේද දෙවනුව short වර්ගයේද තෙවනුව float වර්ගයේද දත්ත වර්ග 3ක් ඇතුලු කළ යුතු ආකාරයටයි. ඉතිං එම ෆන්ක්ෂන් එක කෝල් කරන විට, ෆන්ක්ෂන් ඩෙෆිනිෂන් එකේ එම පැරාමීටර් තිබෙන අනුපිලිවෙලටම සුදුසු අගයන් ලිවිය යුතුයි ෆන්ක්ෂන් කෝල් එකේදී.

ෆන්ක්ෂන් කෝල් කරන විට තවත් කරුණක් වැදගත් වේ. එනම් කෝල් කරන ෆන්ක්ෂන් එකෙන් යම් දත්තයක් රිටර්න් කරනවාද නැද්ද යන්නයි. දැන් ඒ ගැන සොයා බලමු. උදාහරණයක් ලෙස පහත කොඩිං කොටස බලන්න. එහි කිසිදු දත්තයක් රිටර්න් කරන්නේ නැති බව ෆන්ක්ෂන් හෙඩර් එකේ void යන්න දුටු ගමන් ඔබට වැටහෙනවානෙ. ෆන්ක්ෂන් හෙඩර් එකේ void ලියා, ෆන්ක්ෂන් බොඩි එකේ අවසානයේ return කමාන්ඩ් එකක් යෙදීම තහනම් වන අතර, ෆන්ක්ෂන් හෙඩර් එකේ int, long ආදී දත්ත වර්ගයක් රිටර්න් වන බව කියා, ෆන්ක්ෂන් බොඩි එකේ ඊට ගැලපෙන return කමාන්ඩ් එකක් නොලියා සිටීමද තහනම්ය.

/* A simple function to write “hello world” */
void PrintHello()
{
printf(“Hello world\n”);
}

මෙම ෆන්ක්ෂන් එක ඉතාම සරලයි. ඉන් කරන එකම රාජකාරිය hello world කියා ස්ක්‍රීන් එකේ පෙන්වීම පමණි. කිසිදු අගයක් return කමාන්ඩ් එකක් යොදා පිටතට ලබා දෙන්නේ නැත. එනිසාම void යන කීවර්ඩ් එක යොදා තිබෙන අයුරු බලන්න. ඉහත ෆන්ක්ෂන් එක දැන් අපට ප්‍රෝග්‍රෑම් එකේ යම් තැනක සිට කෝල් කිරීමට අවශ්‍ය නම්, කරන්නට තිබෙන්නේ පහත ආකාරයට කමාන්ඩ් එක ලිවීම පමණි.

PrintHello();

පැරාමීටර්ස් නොගන්නා නිසා () යන්න තුල කිසිත් ලියන්නේ නැත. කිසිත් නැතැයි කියා () කොටස නොලියා සිටීමටද බැරිය. ඇත්තටම ඔබ මේ දක්වා උදාහරණවලදී යොදාගත් printf() යනුද ෆන්ක්ෂන් එකක් බව පෙර අවස්ථාවකදී මා පැවසුවා. printf() යනු තරමක් සංකීර්ණ ෆන්ක්ෂන් එකකි. එය ඔබ සාදපු එකක් නොව, කම්පයිලරය සමගම පැමිණෙන ෆන්ක්ෂන් එකකි (ඒ කියන්නේ කම්පයිලරය සාදපු අයමයි එය සාදා (ඩිෆයින් කර) තිබෙන්නේ). printf(“Hello World”); ආදී ලෙස ඔබ සාදපු ප්‍රෝග්‍රෑම්වල ලිව්වා නේද? ඇත්තෙන්ම එහිදී ඔබ කර තිබෙන්නේ printf යන ෆන්ක්ෂන් එක කෝල් කිරීම තමයි. එහිදී වරහන තුළ ඔබ ලියන්නේ පැරාමීටරයයි.

සටහන
ඉහත පැහැදිලි කළ විස්තරය ප්‍රායෝගිකව සිදු කර බැලීමට අවශ්‍ය නම්, එම ෆන්ක්ෂන් එකම සහිත පහත ප්‍රෝග්‍රෑම් එක රන් කර බැලිය හැකියි.

#include <stdio.h>

/* A simple function to write “hello world” */
void PrintHello()
    {

     printf("Hello World\n");

    }

int main()
     {
     PrintHello(); /* function call */
     return 0;
     }

ඉහත පෙන්නුවේ කිසිදු දත්තයක් රිටර්න් නොකරන ෆන්ක්ෂන් කෝල් කරන අයුරුය. යම් දත්තයක් රිටර්න් කරන ෆන්ක්ෂන් එකක් වුවද ඒ ආකාරයටම කෝල් කළ හැකියි. එනම්, ප්‍රෝග්‍රෑම් එකේ යම් තැනක ෆන්ක්ෂන් එකේ නම (හා පැරාමීටර්ස් තිබේ නම්, ඒවාද සමග) ලිවිය හැකියි. එහෙත් යම් දත්තයක් රිටර්න් කරන ෆන්ක්ෂන් සාමාන්‍යයෙන් කෝල් කරන්නේ එසේ නොවේ. උදාහරණයක් ලෙස පහත කෝඩිං බලන්න.

/* A simple function to multiply 2 numbers */
int MultiplyNumbers(int a, int b)
    {
    int result;
    result = a * b;
    return(result);
    }

මෙම ෆන්ක්ෂන් එක int වර්ගයේ දත්තයක් රිටර්න් කරයි. යම් ෆන්ක්ෂන් එකකින් යම් දත්තයක් රිටර්න් කරන්නේ ඇයි? එය අවශ්‍ය නිසානෙ. උදාහරණයක් ලෙස, ඉහත ෆන්ක්ෂන් එකෙන් ඊට ඇතුලු කරන ඕනෑම නිඛිල සංඛ්‍යා දෙකක ගුණිතය පිටතට ලබා දෙනවා. මෙම ෆන්ක්ෂන් එකේ රාජකාරිය එයයි. ඒ ෆන්ක්ෂන් එක කෝල් කළ විට එම රාජකාරිය සිදු කර, එහි ලැබෙන ප්‍රතිපලය තමයි ගුණිතය. උදාහරණයක් ලෙස, මෙම ෆන්ක්ෂන් එක කෝල් කරන විට ඔබ ඇතුලු කළේ 10 හා 20 යන සංඛ්‍යා දෙක නම්, ඒ දෙකේ ගුණිතය වන 200 ඉන් පිට කෙරේ. මෙම අගය සාමාන්‍යයෙන් ඔබ තවත් වේරියබල් එකක තමයි ගබඩා කර ගන්නේ. එනිසා වේරියබල් එකකට අගයක් ගබඩා කරන "ස්ටයිල් එක" තමයි මෙවිටත් යොදා ගන්නේ. එලෙස ෆන්ක්ෂන් කෝල් කරන අයුරු පහත දැක්වේ.

int result2;
result2 = MultiplyNumbers(20, 10);

ඉහත පේලි දෙක රන් වන්නේ මෙසේය. පළමුව result2 යන නමින් int වර්ගයේ වේරියබල් එකක් ඩික්ලෙයාර් කෙරේ. දෙවැනි පේලිය කොටස් දෙකක් ලෙස සලකා විස්තර කරන්නම්. එහි = ට දකුණුපස කොටස යනු ෆන්ක්ෂන් කෝල් එකයි. බලන්න ෆන්ක්ෂන් නේම් එක ලියා () තුල සුදුසු පැරාමීටර් දත්ත දෙක ලියා ඇත. එය කෝල් කරන විට, එම ෆන්ක්ෂන් එක ක්‍රියාත්මක වී එම ඇතුලු කරපු අගයන් දෙක එකිනෙකට ගුණ කර එම ගුණිතය රිටර්න් කරයි. මෙන්න මෙම අගය තමයි දැන් = ට වම්පස ඇති වේරියබල් එකේ ගබඩා වන්නේ. ඒ කියන්නේ result2 නම් වේරියබල් එකට නම්, = ට දකුණු පස පෙනෙන්නේ හරියට 200 වැනි අගයක් ලියා තිබෙනවා වගේය. ඇත්තටම එම වේරියබල් එකට වැඩක් නැහැ කොහොමද = ට දකුණු පස අගය ලැබෙන්නේ කියා. එයාට ගැලපෙන දත්තයක් කුමන හෝ ක්‍රමයකින් එතැනට ලැබෙනවා නම් එයාට වැදගත් එච්චරයි. මෙහිදී වැදගත් වන්නේ ෆන්ක්ෂන් එකේ රිටර්න් ඩේටා ටයිප් එක හා එය ගබඩා කරනා වේරියබල් එකේ ඩේටා ටයිප් එක සමාන වීමයි. (ඉහත උදාහරණයේ ෆන්ක්ෂන් එක රිටර්න් කරන්නේත් result2 නම් වේරියබල් එක ඩික්ලෙයාර් කර තිබෙන්නේත් int යන එකම වර්ගය බව පේනවා නේද?)

සටහන
ඉහත විස්තරය ප්‍රායෝගිකව කර බැලීමට පහත ප්‍රෝග්‍රෑම් එක කම්පයිල් කර රන් කර බලන්න. මෙම ප්‍රෝග්‍රෑම් එකේ ෆන්ක්ෂන් කෝලිං එක result2 = MultiplyNumbers(20, 10); වෙනුවට MultiplyNumbers(20, 10); ලෙස වෙනස් කර නැවත කම්පයිල් කර රන් කර බලන්න. ෆන්ක්ෂන් එක විසින් ගුණ කිරීම සිදු කළත්, එය කෝල් කරන විට, එය විසින් රිටර්න් කරපු දත්තය අප ලබා ගත්තේ නැත. එනිසා එහි ප්‍රතිපලය අපතේ ගොස් ඇති බව ඔබට තේරෙනවා නේද?

#include <stdio.h>

/* A simple function to multiply 2 numbers */
int MultiplyNumbers(int a, int b)
     {
     int result;
     result = a * b;
     return(result);
     }

int main()
     {
     int result2;
     result2 = MultiplyNumbers(20, 10);
     printf("the result2 has %d\n",result2); /* displays the result2 */
     return 0;
     }



සී ප්‍රෝග්‍රැමිං (C programming) ...

No comments:

Post a Comment