ফাংশন
এই অধ্যায়ে আমরা মজার বিষয়, ফাংশন নিয়ে আলোচনা করব। আগের অধ্যায়ে লুপ নিয়ে আলোচনা করেছিলাম। না পড়ে থাকলে পড়ে আসতে পারেন। এখন প্রশ্ন ফাংশন কি? আগে ফাংশন নিয়ে মজার এই লেখাটি পড়ে আসতে পারেন। এরপরেও আমি কিছু বিষয় নিয়ে আলোচনা করছি ফাংশন জিনিসটা কি সেটি উপলব্ধি করার জন্য। ফাংশন কে ধরে নেই আমরা জাদুর বাক্স হিসেবে। এই জাদুর বাক্সে প্রয়োজনীয় ইনপুট দিলে আমাদের কাঙ্ক্ষিত আউটপুট দেয়। এইরকম একটি জাদুর বাক্স ধরে নেই রাইস কুকার। আশাকরছি সবাই এর সাথে পরিচিত। একটি রাইস কুকারে পরিষ্কার চাল ও পরিমাণমত পানি দিয়ে বিদ্যুৎ এর মাধ্যমে তাপ দিলে আমরা পেয়ে যাই গরম ভাত। তাহলে এই জাদুর বাক্স/রাইস কুকার টি ইনপুট হিসেবে নিচ্ছে চাল, পানি এবং বিদ্যুৎ আর আমাদের আউটপুট দিচ্ছে গরম ভাত। এখন এভাবে লিখতে পারি আমরা, ভাত = রাইস_কুকার(চাল, পানি, বিদ্যুৎ)। এখানে রাইস_কুকার ফাংশন। আরেকটি জাদুর বাক্সের উদাহরণ দেখতে পারি এবং সেটি হচ্ছে কফি মেকার। এখানেও একইভাবে এই জাদুর বাক্সটি ইনপুট নিচ্ছে পানি, কফি, চিনি এবং বিদ্যুৎ আর আউটপুট হিসেবে দিচ্ছে গরম গরম কফি। এটি তাহলে লিখতে পারি এভাবে, কফি = কফি_মেকার(পানি, কফির গুঁড়ো, চিনি, বিদ্যুৎ)। আশাকরছি এখন ফাংশনের ধারণা অনেকটাই পরিষ্কার হয়ে গেছে আপনার।
ফাংশনের বিষয় ত এখন বুঝা গেল, কিন্তু প্রোগ্রামিংয়ে কীভাবে কি? আমরা প্রথমদিকে দুইটি নাম্বার যোগ করার প্রোগ্রাম করেছিলাম। সেই কাজ এখন আমরা main ফাংশনে না করে আলাদা অন্য একটি ফাংশনে করব। প্রোগ্রামটি দেখে নেই তাহলে আগে।
#include <iostream>
using namespace std;
int func(int a, int b){ // function int sum = a + b; return sum; }
int main() { int n, m;
cout << "Enter two values: "; cin >> n >> m;
int ans = func(n, m); // calling the function cout << "Sum = " << ans << endl;
return 0; } Code: 5.0 |
প্রোগ্রামটিতে আমরা মেইন ফাংশনের আগে একটি func নামের ফাংশন বানিয়ে রেখেছি। এটি দুইটি নাম্বার ইনপুট নিয়ে তাদের যোগ করে সেই যোগফল কে রিটার্ন করে দিবে। কিন্তু শুধু জাদুর বাক্স বানিয়ে রাখলেই ত হবে না তাকে ইনপুট দিয়ে কাজ ও করাতে হবে আর ইনপুট দিয়ে কাজ করানোকে প্রোগ্রামিংয়ে বলে কল করা মানে ফাংশন কল করা func(n, m)। যেটি আমরা মেইন ফাংশনের ভিতরে করেছি। এরপর রিটার্ন করা ভ্যালুটি ans নামক ভেরিয়েবলে রেখে দিচ্ছে। আচ্ছা, এখন int func(int a, int b) এখানে হয়ত বুঝতে সমস্যা হতে পারে অনেকেরই। int func() লিখার কারণ হচ্ছে আমরা যে ভ্যালুটি রিটার্ন করে নিব সেটি ত তথ্য/ডাটা, আর ডাটা নিতে হলে ত মাধ্যম ছাড়া নেওয়া সম্ভব না আর যেহেতু যোগফল পূর্ণসংখ্যা তাই এখানে int। অন্য ডাটা টাইপের দরকার হলে তখন অন্য ডাটা টাইপ অবশ্যই ব্যবহার করতে হবে। এরপরে আসে ফাংশনের ভিতরে আবার ভেরিয়েবল ডিক্লেয়ার করে নেওয়ার বিষয়টি। আমরা মেইন ফাংশন থেকে যে ভ্যালু দুইটি পাস করতেছি func(n, m) সেই ভ্যালু দুইটিই কিন্তু যাচ্ছে। তাদের মাধ্যম বা ভেরিয়েবল কিন্তু যাচ্ছে না। তাই ভ্যালু দুইটি রাখার জন্য আবার ভেরিয়েবল ডিক্লেয়ার করে নিতে হচ্ছে। আমি যে ফাংশনের নাম func দিয়েছি, এটি কি তার সঠিক অর্থ প্রকাশ করছে? নাম যদি আমি sum/add দিতাম তাহলে, কিছুটা অর্থ প্রকাশ পেত এটি কি কাজের ফাংশন। আপনারা অবশ্যই ভেরিয়েবল এবং ফাংশনের অর্থপূর্ণ নাম ব্যবহার করবেন আশাকরছি।
এখন একটি প্রশ্ন, এটি ত মেইন ফাংশনেই আরো অনেক কম কষ্ট করে করা যায় তাহলে শুধু শুধু ফাংশন ব্যবহার করতে যাব কেন? বা, আরো পরিষ্কার করে বললে ফাংশনের প্রয়োজন ত আসলে বুঝা যাচ্ছে না। এই প্রশ্নটি প্রথম প্রথম ফাংশন শিখতে গিয়ে আমার মনেও এসেছিলো এবং ক্যাম্পাসে জুনিয়রদের ক্লাস নেওয়ার সময় ও তাদের থেকে এই প্রশ্ন পেয়েছি তাই চেষ্টা করেছি ভালো একটি উদাহরণ খুঝে বের করতে। কিন্তু আসলে বিগিনার লেভেলে ঐরকম ভালো উদাহরণ টা বুঝাতে যাওয়া কঠিন, কারণ ফাংশনের প্রয়োজন আসলে একটু অ্যাডভান্সড লেভেলে ভালো বুঝা যায়। তাই আসলে এর প্রয়োজন পরিষ্কার না হলেও ধারণা অবশ্যই রাখতে হবে। সবসময় সবকিছুর কারণ না পাওয়া গেলেও তার ব্যবহার শিখলে আসলে পরে কারণ পাওয়া যায়। এরপরেও একটি উদাহরণ দিয়ে চেষ্টা করছি আমি, ফাংশন আমাদের কীভাবে উপকার করতে পারে।
তিনটি নাম্বার থেকে সবথেকে বড় নাম্বারটি বের করার প্রোগ্রামটি যদি আমরা দেখি তাহলে সেখানে আমাদের বড় নাম্বারটি বের করার জন্য বেশকিছু কন্ডিশন চেক করতে হয়েছিলো এবং নাম্বারগুলোর বিন্যাস ও বের করতে হয়েছিলো। এখন যদি আমি দুইটি নাম্বার থেকে বড়টি বের করার জন্য একটি ফাংশন যদি আগেই লিখে রাখি তাহলে একটু কাজ ও চিন্তা করার জন্য সময় বেঁচে যেতে পারে। কীভাবে? প্রথম দুইটি নাম্বার থেকে বড়টি বের করে তার সাথে যদি আপনি তৃতীয় নাম্বারটির তুলনা করেন তাহলেই কিন্তু সহজে বড় নাম্বারটি বের করা যাচ্ছে। এটি ফাংশনে না করেও আগের থেকে কাজ কমানো যায় কিন্তু ফাংশনে করলে সবথেকে সহজ তা আপনারা একটু ভেবে বের করার চেষ্টা করতে পারেন।
#include <iostream>
using namespace std;
int MAX(int a, int b){ int mx; if (a > b){ mx = a; } else { mx = b; } return mx; }
int main() { int a, b, c;
cout << "Enter three values: "; cin >> a >> b >> c;
int max_num; max_num = MAX(a, b); max_num = MAX(max_num, c);
// you can also find the max this way // max_num = MAX(a, MAX(b, c));
cout << "Maximum Number: " << max_num << endl;
return 0; } Code: 5.1 |
প্রোগ্রামটি যদি দেখেন, আমরা MAX নামের একটি ফাংশন তৈরি করে রেখেছি আগেই যার কাজ দুইটি নাম্বার থেকে বড় টি বের করে দেওয়া। এখন মেইন ফাংশনে প্রথমে আমরা a এবং b থেকে বড় নাম্বারটি বের করে নিলাম ফাংশন কল করে, এরপর c এর সাথে তাকে চেক করলাম আবার ফাংশন কল করে। a এবং b কে আর দরকার হলো না কারণ তাদের থেকে বড়টি আমরা পেয়েছি, এখন হয়ত সেই বড়টিই বড় হবে অথবা c বড় হবে। এরপরেও কনফিউশন থাকলে এইটুকু ত আশাকরছি বুঝতে পারছেন, একই ধরণের কাজ বারবার মেইন ফাংশনের ভিতরে না করে সেই কাজটি ফাংশনে করে রাখলে এরপর বারবার শুধু ভিন্ন ইনপুট দিয়ে কল করেই আমরা কাজ ও কোডের সাইজ অনেক কমিয়ে ফেলতে পারছি। এরপরেও বারবার পড়ে নিন। আসলে কোন বিষয় না বুঝলে তা বারবার পড়ার বিকল্প নেই। আর বেশি বেশি ফাংশন ব্যবহার করাটা একটা ভালো প্র্যাক্টিস। মেইন ফাংশনের ভিতরেই সব লিখতে যাওয়া একটা বাজে অভ্যাস হিসেবেই দেখে সবাই এর কারণ, আপনার কোড যখন অন্যকেও পড়ে বুঝতে যাবে তখন প্রয়োজনীয় জায়গাতে ফাংশন থাকলে বুঝতে অনেক সুবিধা হবে।
এতদিন আমরা শুধু ফাংশনের ভিতরে ভেরিয়েবল ডিক্লেয়ার করে কাজ করেছি। ফাংশনের ভিতরে যে ভেরিয়েবল ডিক্লেয়ার করা হয় তাকে লোকাল ভেরিয়েবল বলে আর এই ভেরিয়েবল শুধু ঐ ফাংশনেই কাজ করতে পারে। আর ফাংশনের বাইরে যে ভেরিয়েবল ডিক্লেয়ার করা হয় তাকে বলে গ্লোবাল ভেরিয়েবল। গ্লোবাল ভেরিয়েবলের ক্ষমতা বেশি কারণ এটি যেকোন ফাংশনে গিয়েই কাজ করতে পারে কিন্তু লোকাল ভেরিয়েবল তা পারে না। এখন আমরা দুইটি নাম্বার যোগের প্রোগ্রামটিই আবার করব তবে গ্লোবাল ভেরিয়েবল ব্যবহার করে।
#include <iostream>
using namespace std;
int a, b, sum;
void add(){ sum = a + b; }
int main() { cout << "Enter two values: "; cin >> a >> b;
add(); cout << sum << endl;
return 0; } Code: 5.2 |
এখানে আমরা গ্লোবালি তিনটা ভেরিয়েবল ডিক্লেয়ার করে নিয়েছি। এতে আমাদের অতিরিক্ত ভেরিয়েবল লাগছে না এবং ফাংশন কল করার সময় কোন ভ্যালু পাস ও করতে হচ্ছে না। তবে, উল্লেখ্য বিষয় এখানে ফাংশনের টাইপ হচ্ছে void। void একটি ডাটা টাইপ, এর কাজ কোন কিছুই ধারণ করে না মানে আমাদের কোনকিছু রিটার্ন করার দরকার নেই। একটু ভেবে দেখলে বুঝতে পারবেন এই প্রোগ্রামে আমাদের আসলে ফাংশনের মাধ্যমে কোনকিছু রিটার্ন করার দরকার নেই তাই এই টাইপের অবতারণা।
আমি যদি void টাইপের ফাংশনে কিছু পাস করতে চাই বা, এরকম প্রয়োজন হলো যে কিছু ভ্যালু আমাকে মেইন ফাংশন থেকে নিয়েই করতে হবে, তাহলে কি করতে পারব? নিচের প্রোগ্রামটি রান করে দেখুন।
#include <iostream>
using namespace std;
int sum;
void add(int n, int m){ sum = n + m; }
int main() { int a, b;
cout << "Enter two values: "; cin >> a >> b;
add(a, b);
cout << sum << endl;
return 0; } Code: 5.3 |
বলেছিলাম লোকাল ভেরিয়েবল অন্য ফাংশনে কাজ করতে পারে না। আসলেই করে কিনা সেটিও দেখে নেই। অবশ্যই রান করে দেখবেন। প্রোগ্রাম যতই সহজ মনে হোক এই সিরিজে প্রতিটা প্রোগ্রাম অবশ্যই রান করে দেখতে হবে এবং সম্ভব হলে বারবার। আর যে কাজগুলো নিজে নিজে করতে বলা হচ্ছে তাও অবশ্যই চেষ্টা করতে হবে। প্রোগ্রামারদের প্রোগ্রামিংয়ের বেলায় একটু খুতখুতে স্বভাবের হতে হয়। একটি বিষয় যত ছোটই হোক সেটি কোনভাবেই এড়িয়ে যাওয়া যাবে না। কারণ, ঐ ছোট বিষয়টিই হয়ত কোনসময় অনেক বড় সমস্যা হয়ে দাঁড়াবে।
#include <iostream>
using namespace std;
int sum;
void add(){ sum = a + b; }
int main() { int a, b;
cout << "Enter two values: "; cin >> a >> b;
add();
cout << sum << endl;
return 0; } Code: 5.4 |
a is not declared in this scope
b is not declared in this scope
Build message এ এই দুটি লাইন আসলে দুটি ইরোর বুঝাচ্ছে এই প্রোগ্রামের। মানে ফাংশনের ভিতরে ব্যবহার করা a এবং b ডিক্লেয়ার করা হয় নি। আসলে আমরা করেছি কিন্তু সেই দুটি অন্য ফাংশনের লোকাল ভেরিয়েবল।
ফাংশনের টাইপ আমাদের প্রয়োজনমত দিয়ে নিতে হবে কিন্তু এখন পর্যন্ত আমরা শুধু int আর void নিয়েই দেখেছি। অন্য ডাটা টাইপ ব্যবহার করে আমরা একটি প্রোগ্রাম দেখে নেই যেটি একটি ভাগ করার প্রোগ্রাম।
#include <iostream>
using namespace std;
double div(double a, double b){ return a / b; }
int main() { double n, m;
cout << "Enter two values: "; cin >> n >> m;
double ans = div(n, m);
cout << ans << endl;
return 0; } Code: 5.5 |
এবার মজার একটি কাজ করব আমরা। আপনাকে একটি character ইনপুট নিতে হবে। character টি হয়ত a-z এর মাঝে থেকে হবে নয়ত, A-Z এর মাঝে থেকে হবে। কাজটি হচ্ছে small letter হলে capital letter করতে হবে আবার capital letter হলে small letter করতে হবে। এটি কীভাবে সম্ভব? অনেকভাবেই সম্ভব। তবে আমরা করব সবথেকে সহজ উপায়ে। আপনি যদি ASCII ভ্যালু দেখে থাকেন তাহলে দেখবেন a = 97, b = 98, c = 99.... z = 122 এবং A = 65, B = 66, C = 67.... Z = 90। এখন যদি আপনি A এর সাথে 32 যোগ করেন তাহলে হবে 97 মানে a। A + 32 = 65 + 32 = 97। তাহলে capital letter এর A এর সাথে 32 যোগ করলেই পাওয়া যাচ্ছে small letter এর a। এখন small letter থেকে capital কীভাবে করবেন তা নিশ্চয়ই বলে দিতে হবে না।
#include <iostream>
using namespace std;
char convert(char ch){ if (ch >= 'A' && ch <= 'Z'){ ch = ch + 32; } else { ch = ch - 32; } return ch; }
int main() { char ch;
cout << "Enter the character: "; cin >> ch;
char ans = convert(ch);
cout << ans << endl;
return 0; } Code: 5.6 |
এখানে ফাংশনে কন্ডিশন দিয়ে দেখেছি ইনপুট নেওয়া character টি capital letter কিনা। capital letter হলে 32 যোগ করে দিব আর নাহলে অবশ্যই character টি small letter তখন শুধু character টি থেকে 32 বিয়োগ করে দিব। এবং কনভার্ট করা character টি রিটার্ন করে দিয়েছি।
এখন আমরা নতুন আরেকটি ডাটা টাইপ শিখব, সেটি হচ্ছে বুলিয়ান ডাটা টাইপ। এর বৈশিষ্ট্য হচ্ছে এটি শুধু true অথবা false রাখতে পারে বা, 0 অথবা 1। একটি সাধারণ প্রোগ্রাম দেখে নেই।
#include <iostream>
using namespace std;
int main() { bool flag = true;
if (flag == true){ cout << "true" << endl; } else { cout << "false" << endl; }
return 0; } Code: 5.7 |
আপনি flag ভেরিয়েবলে false রেখেও দেখতে পারেন। ভেরিয়েবলটির নাম flag দেওয়ার কারণ বুলিয়ান টাইপ অনেক সময় flag হিসেবে কাজ করে থাকে। অর্থপূর্ণ নাম আর কি।
এই অধ্যায়ে ফাংশন নিয়ে বিস্তারিত আলোচনা করিনি। বাকি কিছু বিষয় আমরা অ্যারে আর স্ট্রিং অধ্যায় পড়ার সময় দেখে নিব। পরের অধ্যায়ে আমরা অ্যারে নিয়ে আলোচনা করব।
No comments