অ্যারে, স্ট্রিং ও ফাংশন

সি প্রোগ্রামিং: অ্যারে (Array) ও স্ট্রিং (String) এর ব্যবহার। একমাত্রিক অ্যারে, স্ট্রিং ফাংশন (strlen, strcpy) এবং ইউজার ডিফাইন্ড ফাংশনের ধারণা।

শেখা শুরু করুন

অধ্যায় ৫: প্রোগ্রামিং ভাষা - অ্যারে, স্ট্রিং ও ফাংশন

  1. লেকচার ১৩: অ্যারে, স্ট্রিং ও ফাংশন
  2. ভেরিয়েবল বনাম অ্যারে: একটি গল্প
  3. অ্যারে (Array) কী?
  4. অ্যারে ডিক্লেয়ারেশন ও ইনডেক্সিং
  5. অ্যারেতে মান রাখা ও প্রদর্শন
  6. উদাহরণ: ৫টি সংখ্যার গড় নির্ণয়
  7. স্ট্রিং (String) কী?
  8. নাল ক্যারেক্টার (Null Character)
  9. স্ট্রিং হ্যান্ডলিং ফাংশন (string.h)
  10. ফাংশন (Function) কী?
  11. ফাংশনের প্রকারভেদ
  12. ফাংশনের গঠন (Structure)
  13. ফাংশন ব্যবহারের উদাহরণ
  14. ফাংশন ব্যবহারের সুবিধা
  15. একনজরে সম্পর্ক
  16. নিজে চেষ্টা করো
  17. সারসংক্ষেপ

লেকচার ১৩: অ্যারে, স্ট্রিং ও ফাংশন

এই লেকচার শেষে আমরা-

১। অ্যারে (Array) এর ধারণা ও গঠন ব্যাখ্যা করতে পারব।
২। মেমোরিতে অ্যারের অবস্থান এবং ইনডেক্সিং ব্যবস্থা বিশ্লেষণ করতে পারব।
৩। সি প্রোগ্রামে স্ট্রিং (String) এর ব্যবহার ও বিভিন্ন লাইব্রেরি ফাংশন প্রয়োগ করতে পারব।
৪। ইউজার ডিফাইন্ড ফাংশন তৈরি এবং ব্যবহার করতে পারব।

সবাইকে স্বাগতম! আশা করি তোমরা সবাই ভালো আছো। আজ আমরা সি প্রোগ্রামিংয়ের অত্যন্ত গুরুত্বপূর্ণ এবং মজার তিনটি বিষয় নিয়ে আলোচনা করব। আজকের লেকচার শেষে আমরা- ১। অ্যারে (Array) এর ধারণা ও গঠন ব্যাখ্যা করতে পারব, ২। মেমোরিতে অ্যারের অবস্থান এবং ইনডেক্সিং ব্যবস্থা বিশ্লেষণ করতে পারব, ৩। সি প্রোগ্রামে স্ট্রিং (String) এর ব্যবহার ও বিভিন্ন লাইব্রেরি ফাংশন প্রয়োগ করতে পারব এবং ৪। ইউজার ডিফাইন্ড ফাংশন তৈরি এবং ব্যবহার করতে পারব। এই টপিকগুলো প্রোগ্রামিংয়ের ভিত্তি মজবুত করার জন্য অপরিহার্য। চলো শুরু করা যাক!

ভেরিয়েবল বনাম অ্যারে: একটি গল্প

সমস্যা:
৫০ জন বন্ধুর নাম ও ফোন নম্বর সংরক্ষণ করতে হবে।

উপায় ১:
৫০টি আলাদা ভেরিয়েবল (name1, name2, ..., name50)

উপায় ২:
একটি মাত্র লিস্ট বা তালিকা।

প্রোগ্রামিংয়ে এই 'লিস্ট' বা তালিকাই হলো অ্যারে (Array)

চলো শুরুতেই একটা সমস্যার সমাধান করি। ধরো, তোমাকে তোমার ক্লাসের ৫০ জন বন্ধুর রোল নম্বর সেভ করে রাখতে হবে। এখন তুমি কী করবে? ৫০টি আলাদা ভেরিয়েবল ডিক্লেয়ার করবে? যেমন roll1, roll2, roll3 এভাবে roll50 পর্যন্ত? এটা কি বুদ্ধিমানের কাজ হবে? কোড লিখতে লিখতেই তো তুমি ক্লান্ত হয়ে যাবে! ঠিক এই সমস্যা সমাধানের জন্যই প্রোগ্রামিংয়ে এসেছে 'অ্যারে'। পাশের ছবিতে দেখো, বাম দিকে ভেরিয়েবলগুলো ছড়িয়ে ছিটিয়ে আছে, আর ডানদিকে অ্যারে বা ড্রয়ারে সব সুন্দর করে সাজানো। অ্যারে মানে হলো একটা লম্বা তালিকা, যেখানে একটা নাম দিয়েই আমরা অনেকগুলো ডেটা রাখতে পারি।

অ্যারে (Array) কী?

সংজ্ঞা:
একই ধরণের (Homogeneous) ডেটার সমষ্টি যা একটি সাধারণ নামে এবং ইনডেক্স (Index) দিয়ে পরিচিত।

মূল বৈশিষ্ট্য:
১. একই ডেটা টাইপ হতে হবে (সব int বা সব float)।
২. মেমোরিতে পরপর অবস্থান নেয়।
৩. নির্দিষ্ট সাইজ বা আকার থাকে।

তাহলে অ্যারে আসলে কী? সহজ কথায়, অ্যারে হলো একই ধরণের ডেটার সমষ্টি। শব্দটা খেয়াল করো- 'একই ধরণের'। মানে তুমি যদি একটা ইনটিজার অ্যারে বানাও, সেখানে শুধু পূর্ণসংখ্যাই রাখা যাবে, ভগ্নাংশ বা ক্যারেক্টার রাখা যাবে না। আর এই সবগুলোর একটা সাধারণ নাম থাকে। যেমন ধরো, এই ছবির ট্রেনের বগিগুলো। সব বগি দেখতে একই রকম, পরপর সাজানো থাকে, কিন্তু প্রতিটা বগির একটা করে নম্বর থাকে। অ্যারেও ঠিক তেমনই। মেমোরিতে এরা পরপর জায়গা দখল করে।

অ্যারে ডিক্লেয়ারেশন ও ইনডেক্সিং

সিনট্যাক্স:
Data_Type Array_Name [Array_Size];
উদাহরণ: int marks[5];

ইনডেক্সিং (Indexing):
১. শুরু হয় ০ (শূণ্য) থেকে।
২. শেষ হয় (Size - 1) এ।
৩. marks[0] হলো প্রথম উপাদান।

এখন দেখি সি প্রোগ্রামে অ্যারে কীভাবে লিখতে হয়। সিনট্যাক্সটা দেখো- প্রথমে ডেটা টাইপ, তারপর অ্যারের নাম, আর থার্ড ব্র্যাকেটের ভেতরে সাইজ। যেমন: `int marks[5];`। এর মানে হলো, আমরা 'marks' নামে ৫টি পূর্ণসংখ্যা রাখার জায়গা তৈরি করলাম। ছবিতে দেখো, মেমোরিতে ৫টি ঘর তৈরি হয়েছে। সবচেয়ে গুরুত্বপূর্ণ হলো ইনডেক্স বা অবস্থান। কম্পিউটারে গণনা শুরু হয় ০ থেকে। তাই প্রথম ঘরটি হলো `marks[0]`, আর শেষ ঘরটি হলো `marks[4]`। ৫ নম্বর ঘর কিন্তু নেই! এটা অনেকেই ভুল করে, তাই খুব সতর্ক থাকবে।

অ্যারেতে মান রাখা ও প্রদর্শন

int marks[5];
marks[0] = 80; // সরাসরি মান রাখা
marks[1] = 75;

// লুপ ব্যবহার করে ইনপুট নেওয়া
for(i=0; i<5; i++) {
    scanf("%d", &marks[i]);
}
  • লুপ ব্যবহার করে খুব সহজেই শত শত ডেটা ইনপুট নেওয়া যায়।
  • marks[i] এর মাধ্যমে প্রতিটি ঘরে এক্সেস করা হয়।

এবার চলো কোডে দেখি। আমরা দুইভাবে মান রাখতে পারি। সরাসরি `marks[0] = 80` এভাবে লিখে, অথবা লুপ ব্যবহার করে। যেহেতু অ্যারেতে অনেকগুলো ঘর থাকে, তাই বারবার `scanf` না লিখে আমরা একটা `for` লুপ চালিয়ে খুব সহজেই ইনপুট নিতে পারি। এখানে `i` এর মান ০ থেকে ৪ পর্যন্ত ঘুরবে এবং প্রতিবার `marks[i]` তে ইনপুট নিবে। মানে `marks[0]`, `marks[1]`... এভাবে। ভিডিওটা পজ করে কোডটা একটু ভালো করে দেখো।

উদাহরণ: ৫টি সংখ্যার গড় নির্ণয়

#include <stdio.h>
int main() {
    int marks[5], i;
    float sum = 0, avg;
    printf("Enter 5 marks: ");
    for(i=0; i<5; i++) {
        scanf("%d", &marks[i]);
        sum = sum + marks[i];
    }
    avg = sum / 5.0;
    printf("Average = %.2f", avg);
    return 0;
}

অ্যারের সবচেয়ে বড় সুবিধা হলো গাণিতিক কাজ। ধরো ৫টি বিষয়ের নম্বরের গড় বের করতে হবে। আমরা একটা লুপের ভেতরেই ইনপুট নিতে পারি এবং সাথে সাথে `sum` ভেরিয়েবলে যোগ করে ফেলতে পারি। লুপ শেষ হলে মোট যোগফলকে ৫ দিয়ে ভাগ করলেই গড় বা Average পেয়ে যাব। খেয়াল করো, আমরা `sum` কে `float` বা ভগ্নাংশ হিসেবে নিয়েছি যাতে গড় সঠিক আসে।

স্ট্রিং (String) কী?

সংজ্ঞা:
স্ট্রিং হলো একগুচ্ছ ক্যারেক্টার বা বর্ণের সমষ্টি। সি ভাষায় একে 'ক্যারেক্টার অ্যারে' (Character Array) বলা হয়।

উদাহরণ:
"Dhaka", "ICT", "HSC 2024"

সিনট্যাক্স:
char name[10];

ইনপুট:
gets(name); বা scanf("%s", name);

এবার আসি স্ট্রিং-এ। স্ট্রিং শুনলে নতুন কিছু মনে হতে পারে, কিন্তু আসলে এটি অ্যারে ছাড়া আর কিছুই না। যখন আমরা অনেকগুলো ক্যারেক্টার বা বর্ণ একসাথে রাখি, তখন তাকে স্ট্রিং বলে। যেমন তোমার নাম, দেশের নাম ইত্যাদি। সি ভাষায় স্ট্রিং ডিক্লেয়ার করতে হয় `char` টাইপ দিয়ে। যেমন `char name[10]`। মানে এখানে ১০টি অক্ষর রাখা যাবে। ইনপুট নেওয়ার জন্য আমরা `gets()` বা `scanf()` ব্যবহার করি।

নাল ক্যারেক্টার (Null Character)

গোপন ক্যারেক্টার: \0
স্ট্রিং এর শেষে স্বয়ংক্রিয়ভাবে একটি \0 বা নাল ক্যারেক্টার যুক্ত থাকে।

কাজ:
কম্পিউটারকে বোঝানো যে স্ট্রিংটি এখানে শেষ হয়েছে।

মেমোরি হিসাব:
"DHAKA" (৫ অক্ষর) রাখার জন্য অ্যারে সাইজ হতে হবে অন্তত

স্ট্রিং এর ক্ষেত্রে একটা খুব গুরুত্বপূর্ণ গোপন বিষয় আছে, সেটা হলো 'নাল ক্যারেক্টার' (`\0`)। ছবিতে দেখো, তুমি যখন "DHAKA" লেখো, কম্পিউটার কিন্তু এর শেষে অদৃশ্যভাবে একটা `\0` বসিয়ে দেয়। কেন? যাতে সে বুঝতে পারে নামটা এখানেই শেষ। এজন্য সবসময় মনে রাখবে, স্ট্রিং এর সাইজ আসল অক্ষরের চেয়ে অন্তত ১ বেশি হতে হবে। ৫ অক্ষরের নামের জন্য ৬ সাইজের অ্যারে লাগবে। এই নাল ক্যারেক্টার ছাড়া কম্পিউটার বুঝতেই পারবে না স্ট্রিং কোথায় শেষ হয়েছে।

স্ট্রিং হ্যান্ডলিং ফাংশন (string.h)

হেডার ফাইল: #include <string.h>

জনপ্রিয় ফাংশন:
১. strlen(str): স্ট্রিং এর দৈর্ঘ্য নির্ণয় করে।
২. strcpy(des, src): এক স্ট্রিং কপি করে অন্যটায় রাখে।
৩. strcat(str1, str2): দুটি স্ট্রিং জোড়া লাগায়।
৪. strcmp(str1, str2): দুটি স্ট্রিং তুলনা করে।

স্ট্রিং নিয়ে কাজ করার জন্য সি ভাষায় অনেকগুলো রেডিমেড টুলস বা ফাংশন আছে। এগুলো ব্যবহার করতে হলে আমাদের `<string.h>` হেডার ফাইলটি যুক্ত করতে হয়। যেমন `strlen` দিয়ে আমরা সহজেই বের করতে পারি নামের দৈর্ঘ্য কত, `strcat` দিয়ে দুটি নাম জোড়া লাগাতে পারি। আর পাসওয়ার্ড ঠিক আছে কিনা চেক করতে `strcmp` ব্যবহার করা হয়। এগুলো আমাদের কাজ অনেক সহজ করে দেয়, লুপ চালিয়ে ম্যানুয়ালি চেক করতে হয় না।

ফাংশন (Function) কী?

সংজ্ঞা:
নির্দিষ্ট কাজ করার জন্য কোডের একটি ব্লক যা বারবার ব্যবহার করা যায়।

বাস্তব উদাহরণ:
জুসার মেশিন (Juicer Machine)
- ইনপুট: ফল (Parameters)
- প্রসেস: জুস তৈরি (Function Body)
- আউটপুট: জুস (Return Value)

এবার আমরা শিখব ফাংশন সম্পর্কে। ফাংশন হলো একটি জুসার মেশিনের মতো। পাশের ছবিটি দেখো। মেশিনে তুমি ফল দাও (এটা হলো ইনপুট বা আর্গুমেন্ট), মেশিন সেটা প্রসেস করে, এবং শেষে জুস দেয় (এটা হলো আউটপুট বা রিটার্ন ভ্যালু)। প্রোগ্রামিংয়েও ফাংশন ঠিক এভাবেই কাজ করে। তুমি একে কিছু ডেটা দেবে, সে নির্দিষ্ট কাজ করে ফলাফল ফেরত দেবে।

ফাংশনের প্রকারভেদ

১. লাইব্রেরি ফাংশন (Library Function)
- কম্পাইলারে আগেই তৈরি করা থাকে।
- আমরা শুধু ব্যবহার করি।
- উদাহরণ: printf(), scanf(), sqrt(), pow()

ফাংশন মূলত দুই ধরণের। বাম দিকে দেখো, লাইব্রেরি ফাংশন - যা সি ভাষার সাথেই দেওয়া থাকে, যেমন `printf` বা `sqrt`। এগুলো তৈরি করাই আছে, আমরা জাস্ট ব্যবহার করি। আর ডান দিকে, ইউজার ডিফাইন্ড ফাংশন - যা আমরা, অর্থাৎ প্রোগ্রামাররা নিজেদের প্রয়োজনে বানাই। যেমন তুমি যদি 'যোগ' করার জন্য একটি ফাংশন বানাও, সেটা হবে ইউজার ডিফাইন্ড ফাংশন। `main()` ফাংশনটিও কিন্তু একটি ইউজার ডিফাইন্ড ফাংশন, যা আমরা লিখি।

ফাংশনের গঠন (Structure)

গঠন:

Return_Type Function_Name (Parameter_List)
{
    // Body of the function
    // Statements
    return value;
}

উদাহরণ:

int add(int a, int b) {
    return a + b;
}

একটি ফাংশন কীভাবে লিখতে হয়, চলো তার গঠন বা স্ট্রাকচারটা দেখি। ছবিতে খুব সুন্দর করে দেখানো আছে। প্রথমে থাকে `Return Type` (ফাংশন কী ধরণের মান ফেরত দেবে), তারপর ফাংশনের নাম, আর ব্র্যাকেটের ভেতর থাকে `Parameters` (যা ইনপুট হিসেবে আসবে)। সবশেষে কারলি ব্রেস `{}` এর ভেতর থাকে মূল কাজ। উদাহরণটি দেখো, এখানে `add` ফাংশন দুটি সংখ্যা নিয়ে তাদের যোগফল রিটার্ন করছে।

ফাংশন ব্যবহারের উদাহরণ

#include <stdio.h>

// ফাংশন তৈরি
int square(int x) {
    return x * x;
}

int main() {
    int result;
    result = square(5); // ফাংশন কল
    printf("Square is: %d", result);
    return 0;
}

চলো একটি পূর্ণাঙ্গ প্রোগ্রাম দেখি। এখানে `square` নামে একটি ফাংশন আছে যা কোনো সংখ্যার বর্গ বের করে। `main` ফাংশন থেকে আমরা যখন `square(5)` কল করছি, তখন ৫ সংখ্যাটি `x`-এর মধ্যে চলে যাচ্ছে। তারপর ৫ গুণ ৫ অর্থাৎ ২৫ হিসাব হয়ে `result`-এ ফিরে আসছে। ভিডিওটি পজ করে ফ্লো-টা বোঝার চেষ্টা করো। কীভাবে মান যাচ্ছে এবং ফিরে আসছে, এটা বোঝা খুব জরুরি।

ফাংশন ব্যবহারের সুবিধা

  1. রিইউজবিলিটি (Reusability): একই কোড বারবার লিখতে হয় না। একবার লিখেই বহুবার ব্যবহার করা যায়।

  2. সহজ ডিবাগিং: ভুল খুঁজে বের করা সহজ হয়। নির্দিষ্ট ফাংশনে ভুল হলে শুধু সেটাই ঠিক করলেই চলে।

  3. মডুলারিটি: বড় প্রোগ্রামকে ছোট ছোট অংশে ভাগ করা যায়।

  4. কোড পরিষ্কার থাকে: মেইন ফাংশন ছোট ও গোছানো থাকে।

এখন প্রশ্ন হলো, ফাংশন কেন ব্যবহার করব? প্রথমত, 'Reusability'। একবার একটা ফাংশন লিখে রাখলে সেটা হাজারবার ব্যবহার করা যায়। দ্বিতীয়ত, বড় কোনো সমস্যাকে ছোট ছোট ভাগে ভাগ করে সমাধান করা যায়। এতে ভুল বা Bug খুঁজে বের করা অনেক সহজ হয়ে যায়। বড় সফটওয়্যার তৈরিতে ফাংশনের কোনো বিকল্প নেই। তুমি যখন বড় প্রজেক্ট করবে, তখন দেখবে সব কাজই আলাদা আলাদা ফাংশনে ভাগ করা থাকে।

একনজরে সম্পর্ক

অ্যারে (Array): অনেকগুলো ডেটা রাখার ঝুড়ি বা কন্টেইনার।

স্ট্রিং (String): অক্ষরের (Character) বিশেষ অ্যারে।

ফাংশন (Function): সেই ডেটা প্রসেস করার মেশিন।

বাস্তবতা:
আমরা অ্যারেতে ডেটা রাখি, এবং ফাংশন দিয়ে সেই ডেটার ওপর কাজ করি।

আমরা ক্লাসের শেষ পর্যায়ে চলে এসেছি। চলো তিনটি বিষয়কে মিলিয়ে ফেলি। অ্যারে হলো আমাদের ডেটা রাখার ঝুড়ি। স্ট্রিং হলো বিশেষ ধরণের অ্যারে যা অক্ষর রাখে। আর ফাংশন হলো সেই মেশিন যা এই ডেটাগুলোকে প্রসেস করে। একটি ভালো প্রোগ্রামে এই তিনটির সমন্বয়েই কাজ হয়। ছবিতে যেমন দেখছ, ডেটা অ্যারে থেকে ফাংশনে যাচ্ছে এবং ফাংশন সেটা প্রসেস করে আউটপুট দিচ্ছে।

নিজে চেষ্টা করো

  1. ৫টি ফ্লোটিং পয়েন্ট (দশমিক) নম্বর রাখার জন্য অ্যারে ডিক্লেয়ার করো।

  2. "BANGLADESH" শব্দটির জন্য কত সাইজের ক্যারেক্টার অ্যারে প্রয়োজন? (নাল ক্যারেক্টার সহ)

  3. দুটি সংখ্যার মধ্যে বড় সংখ্যাটি বের করার জন্য একটি ফাংশন লিখ।

যাওয়ার আগে তোমাদের জন্য ছোট কিছু কাজ। ১. ৫টি ফ্লোটিং পয়েন্ট নম্বর রাখার অ্যারে কীভাবে লিখবে? ২. "BANGLADESH" রাখার জন্য অ্যারে সাইজ কত হবে? (মনে আছে তো নাল ক্যারেক্টারের কথা? গুনে দেখো কয়টা অক্ষর আছে আর এক যোগ করো)। ৩. দুটি সংখ্যার মধ্যে বড়টি বের করার ফাংশন লেখার চেষ্টা করো। এই প্রশ্নগুলো সমাধান করলে তোমাদের কনসেপ্ট একদম ক্লিয়ার হয়ে যাবে।

সারসংক্ষেপ

এই লেকচার শেষে আমরা-

১। অ্যারে (Array) দিয়ে একই ধরণের ডেটা সংরক্ষণ করতে শিখেছি।
২। স্ট্রিং ও নাল ক্যারেক্টার (\0) এর গুরুত্ব বুঝেছি।
৩। লাইব্রেরি ও ইউজার ডিফাইন্ড ফাংশনের পার্থক্য ও ব্যবহার শিখেছি।

পরবর্তী লেকচারে আমরা পয়েন্টার নিয়ে আলোচনা করব।

আজকে আমরা অনেক গুরুত্বপূর্ণ বিষয় শিখেছি - অ্যারে দিয়ে ডেটা সাজানো, স্ট্রিং দিয়ে শব্দ তৈরি এবং ফাংশন দিয়ে কাজ ভাগ করা। প্রোগ্রামিংয়ে দক্ষ হতে হলে এগুলোর প্র্যাকটিস চালিয়ে যেতে হবে। কোথাও বুঝতে সমস্যা হলে ভিডিওটি আবার দেখো। সবাই ভালো থেকো, দেখা হবে পরের লেকচারে!

লেকচার ১৩: অ্যারে, স্ট্রিং ও ফাংশন - ডেটা স্ট্রাকচার ও মডুলার প্রোগ্রামিং

পড়তে প্রায় 5 মিনিট

লেকচার ১৩-তে আমরা প্রোগ্রামিংয়ের দুটি অত্যন্ত শক্তিশালী হাতিয়ার—অ্যারে (Array) এবং ফাংশন (Function)—সম্পর্কে জেনেছি। চিন্তা করে দেখো, একটি ক্লাসে যদি ৫০ জন ছাত্র থাকে এবং তাদের প্রত্যেকের রোল নম্বর বা মার্কস সংরক্ষণ করার জন্য আমাদের ৫০টি আলাদা ভেরিয়েবল (mark1, mark2, ..., mark50) ডিক্লেয়ার করতে হয়, তবে সেটি কতটা বিরক্তিকর ও সময়সাপেক্ষ হবে! প্রোগ্রামিংয়ে এই ধরণের সমস্যা সমাধানের জন্যই অ্যারের উৎপত্তি।

আবার, একটি বড় প্রোগ্রাম লেখার সময় যদি একই কাজ (যেমন যোগ করা বা গড়ে বের করা) বারবার করতে হয়, তবে বারবার একই কোড না লিখে আমরা সেই কোডটিকে একটি আলাদা ব্লকে রেখে দিতে পারি, যাকে ফাংশন বলা হয়। এই অধ্যায়ে আমরা অ্যারে এবং ফাংশন ব্যবহার করে কীভাবে ডেটা ম্যানেজমেন্ট এবং মডুলার প্রোগ্রামিং (Modular Programming) করা যায়, তা বিস্তারিত শিখব। বোর্ড পরীক্ষায় এই অংশ থেকে লিনিয়ার সার্চ, ম্যাক্সিমাম ভ্যালু নির্ণয় এবং স্ট্রিং ম্যানিপুলেশন সংক্রান্ত প্রশ্ন প্রায়ই আসে।

অ্যারে (Array): ডেটার সুশৃঙ্খল বিন্যাস

সহজ কথায়, অ্যারে হলো একই ধরণের অনেকগুলো ভেরিয়েবলের একটি প্যাকেট বা সমষ্টি। যখন আমাদের একই ডেটা টাইপের (যেমন শুধুই পূর্ণসংখ্যা বা শুধুই ভগ্নাংশ) অনেকগুলো মান নিয়ে কাজ করতে হয়, তখন আমরা অ্যারে ব্যবহার করি।

সংজ্ঞা (Definition): একই ধরণের (Data Type) একাধিক ডেটা বা উপাদানকে যখন একটি সাধারণ নাম এবং ইনডেক্স (Index) নম্বরের মাধ্যমে মেমোরিতে পাশাপাশি সংরক্ষণ করা হয়, তখন তাকে অ্যারে (Array) বলে।

অ্যারের বৈশিষ্ট্য ও মেমোরি বিন্যাস

অ্যারের প্রধান বৈশিষ্ট্য হলো এটি মেমোরিতে পরপর (Contiguous) জায়গা দখল করে। অর্থাৎ, অ্যারের প্রথম উপাদানটি মেমোরির যে ঠিকানায় থাকে, দ্বিতীয়টি ঠিক তার পরের ঠিকানায় থাকে।

Array Memory Organization

উপরের চিত্রটি লক্ষ্য করো। এখানে marks নামের একটি ৫ সাইজের ইনটিজার অ্যারে দেখানো হয়েছে।
- ইনডেক্স (Index): অ্যারের প্রতিটি উপাদানের অবস্থান নির্দেশক সংখ্যা। এটি সবসময় ০ (শূণ্য) থেকে শুরু হয় এবং শেষ হয় (N-1) এ (যেখানে N হলো অ্যারের মোট সাইজ)।
- মেমোরি অ্যাড্রেস: যদি marks[0] এর অ্যাড্রেস ১০০০ হয় এবং ইনটিজার ২ বাইট জায়গা নেয়, তবে marks[1] এর অ্যাড্রেস হবে ১০০২।

গুরুত্বপূর্ণ (Important):
- অ্যারের সাইজ স্থির (Fixed Size)। প্রোগ্রাম রান করার সময় এটি বাড়ানো বা কমানো যায় না (একে Static Memory Allocation বলে)।
- ইনডেক্স নেগেটিভ হতে পারে না।
- অ্যারের ইনডেক্সিং ০ থেকে শুরু হয়, তাই ১০ সাইজের অ্যারের শেষ ইনডেক্স হবে ৯।

অ্যারের মেমোরি সাইজ নির্ণয়

পরীক্ষায় প্রায়ই MCQ-তে অ্যারের মোট মেমোরি সাইজ বের করতে বলা হয়। এর সূত্রটি হলো:

$$Total\_Memory = Array\_Size \times Size\_of\_Data\_Type$$
যেমন: int A[10]; (ধরি, int = ২ বাইট)
তাহলে, মোট মেমোরি = $10 \times 2 = 20$ Bytes.

অ্যারে সম্পর্কিত গুরুত্বপূর্ণ প্রোগ্রাম (Exam Focus)

লেকচারে তোমরা অ্যারের যোগফল ও গড় নির্ণয় দেখেছ। কিন্তু সৃজনশীল প্রশ্নে (CQ) সবচেয়ে বেশি আসে সর্বোচ্চ/সর্বনিম্ন সংখ্যা নির্ণয় এবং লিনিয়ার সার্চ। নিচে এই দুটি প্রোগ্রামের পূর্ণাঙ্গ কোড ও ব্যাখ্যা দেওয়া হলো।

১. অ্যারে থেকে বৃহত্তম সংখ্যা (Maximum) নির্ণয়

লজিক: আমরা প্রথমে অ্যারের ১ম সংখ্যাটিকে (arr[0]) ধরে নিব যে এটিই সবচেয়ে বড় (max)। এরপর লুপ চালিয়ে বাকি সংখ্যাগুলোর সাথে max-এর তুলনা করব। যদি কোনো সংখ্যা max-এর চেয়ে বড় হয়, তবে তাকেই নতুন max হিসেবে আপডেট করব।

উদাহরণ (Example): Maximum Value Finding

#include <stdio.h>

int main() {
    int arr[5] = {10, 45, 20, 85, 30};
    int max = arr[0]; // ১ম সংখ্যাকে বড় ধরে নিলাম
    int i;

    for(i = 1; i < 5; i++) {
        if(arr[i] > max) { // যদি বর্তমান সংখ্যা max এর চেয়ে বড় হয়
            max = arr[i];  // তবে max আপডেট হবে
        }
    }

    printf("Maximum Value is: %d", max);
    return 0;
}

আউটপুট: Maximum Value is: 85

২. লিনিয়ার সার্চ (Linear Search)

লজিক: অ্যারের শুরু থেকে শেষ পর্যন্ত প্রতিটি উপাদান চেক করে দেখা যে সেটি আমাদের কাঙ্ক্ষিত সংখ্যার (Target Value) সমান কিনা। যদি পাওয়া যায় তবে লুপ ব্রেক করে বের হয়ে আসব।

উদাহরণ (Example): Linear Search

#include <stdio.h>

int main() {
    int arr[5] = {10, 45, 20, 85, 30};
    int target = 20; // আমরা ২০ খুঁজছি
    int i, found = 0; // found একটি ফ্ল্যাগ ভেরিয়েবল

    for(i = 0; i < 5; i++) {
        if(arr[i] == target) {
            printf("Found at index: %d\n", i);
            found = 1; // পাওয়া গেছে
            break; // লুপ থেকে বের হয়ে যাও
        }
    }

    if(found == 0) {
        printf("Not Found");
    }

    return 0;
}

আউটপুট: Found at index: 2

স্ট্রিং (String): ক্যারেক্টার অ্যারে

সি প্রোগ্রামিংয়ে আলাদা কোনো "String" ডেটা টাইপ নেই। ক্যারেক্টার টাইপের অ্যারে (char array) ব্যবহার করে স্ট্রিং তৈরি করা হয়। স্ট্রিং হলো একগুচ্ছ ক্যারেক্টারের সমষ্টি যা ডাবল কোটেশন (" ") এর মধ্যে থাকে।

নাল ক্যারেক্টার (Null Character): স্ট্রিংয়ের শেষে সর্বদা একটি বিশেষ ক্যারেক্টার '\0' (ব্যাকস্ল্যাশ জিরো) থাকে, একে নাল ক্যারেক্টার বলে। এটি কম্পাইলারকে নির্দেশ দেয় যে স্ট্রিংটি এখানে শেষ হয়েছে।

স্ট্রিং ইনপুট: scanf বনাম gets

এটি শিক্ষার্থীদের একটি সাধারণ ভুলের জায়গা।
- scanf("%s", str); : এটি স্পেস (Space) পেলে ইনপুট নেওয়া বন্ধ করে দেয়। তাই "Rahim Uddin" ইনপুট দিলে এটি শুধু "Rahim" গ্রহণ করবে।
- gets(str); : এটি স্পেসসহ পুরো লাইন ইনপুট নিতে পারে। (আধুনিক কম্পাইলারে fgets ব্যবহার করতে বলা হয়, তবে HSC সিলেবাসে gets বৈধ)।

পরীক্ষার টিপস (Exam Tip):
যদি প্রশ্ন আসে "BANGLADESH" শব্দটি মেমোরিতে রাখতে কত বাইট জায়গা লাগবে?
উত্তর: ১০টি অক্ষর + ১টি নাল ক্যারেক্টার (\0) = ১১ বাইট। সবসময় ১ যোগ করতে হবে।

স্ট্রিং লাইব্রেরি ফাংশন (string.h)

স্ট্রিং ম্যানিপুলেশনের জন্য সি ভাষায় <string.h> হেডার ফাইলে কিছু বিল্ট-ইন ফাংশন আছে। এগুলো ব্যবহার করলে লুপ চালিয়ে কাজ করতে হয় না।

ফাংশন কাজ উদাহরণ
strlen(s) স্ট্রিংয়ের দৈর্ঘ্য নির্ণয় করে (নাল ক্যারেক্টার বাদে)। len = strlen(str);
strcpy(des, src) একটি স্ট্রিং কপি করে অন্যটিতে রাখে। strcpy(str2, str1);
strcat(s1, s2) দুটি স্ট্রিং জোড়া লাগায় (Concatenation)। strcat(s1, s2);
strcmp(s1, s2) দুটি স্ট্রিং তুলনা করে। সমান হলে ০ রিটার্ন করে। if(strcmp(s1, s2)==0)

ফাংশন (Function): মডুলার প্রোগ্রামিং

ফাংশন হলো একটি বড় প্রোগ্রামের ক্ষুদ্র অংশ যা একটি নির্দিষ্ট কাজ সম্পাদন করে। জুসার মেশিনে যেমন ফল দিলে জুস বের হয়, তেমনি ফাংশনে ইনপুট (প্যারামিটার) দিলে প্রসেস হয়ে আউটপুট (রিটার্ন ভ্যালু) পাওয়া যায়।

সংজ্ঞা (Definition): ফাংশন হলো কিছু নির্দেশাবলি বা কোডের সমষ্টি যা একটি নির্দিষ্ট কাজ সম্পন্ন করার জন্য তৈরি করা হয় এবং প্রয়োজনে মূল প্রোগ্রাম থেকে কল (Call) করা যায়।

ফাংশনের প্রকারভেদ
  1. লাইব্রেরি ফাংশন (Library Function): আগে থেকেই তৈরি করা, যেমন printf(), scanf(), sqrt()
  2. ইউজার ডিফাইন্ড ফাংশন (User-Defined Function): ব্যবহারকারী নিজের প্রয়োজনমতো তৈরি করে।
ফাংশনের গঠন ও কলিং প্রসেস

একটি ইউজার ডিফাইন্ড ফাংশনের প্রধান ৩টি অংশ থাকে:
1. ফাংশন প্রোটোটাইপ (Prototype): ফাংশনের নাম ও প্যারামিটার ঘোষণা (সেমিকোলন থাকে)।
2. ফাংশন ডেফিনিশন (Definition): মূল কোড বা বডি।
3. ফাংশন কল (Call): ব্যবহার করার নির্দেশ।

Function Call Flowchart

উদাহরণ: দুটি সংখ্যার যোগফল নির্ণয়ের ফাংশন

#include <stdio.h>

// 1. Function Prototype
int add(int a, int b);

int main() {
    int result;
    // 3. Function Call
    result = add(10, 20); 
    printf("Sum is: %d", result);
    return 0;
}

// 2. Function Definition
int add(int a, int b) {
    int sum = a + b;
    return sum; // Return Value
}
লোকাল বনাম গ্লোবাল ভেরিয়েবল
  • লোকাল ভেরিয়েবল: কোনো ফাংশনের ভেতরে ডিক্লেয়ার করা ভেরিয়েবল। এটি শুধু ওই ফাংশনেই কাজ করে।
  • গ্লোবাল ভেরিয়েবল: সব ফাংশনের বাইরে (উপরে) ডিক্লেয়ার করা হয়। এটি পুরো প্রোগ্রামের যেকোনো জায়গা থেকে ব্যবহার করা যায়।

পরীক্ষার প্রস্তুতি ও টিপস

সৃজনশীল প্রশ্নের টিপস (CQ Tips):
- উদ্দীপকে যদি "তালিকা", "সিরিজ" বা "অনেকগুলো ডেটা" নিয়ে কাজ করার কথা বলা হয়, তবে বুঝবে এটি অ্যারের প্রশ্ন।
- যদি বলা হয় "একই কাজ বারবার করার জন্য একটি সাব-প্রোগ্রাম তৈরি করো", তবে সেটি ফাংশন বা সাব-রুটিন নির্দেশ করছে।
- কোড লেখার সময় অ্যারের সাইজ এবং লুপের লিমিট ঠিক আছে কিনা খেয়াল রাখবে (যেমন: সাইজ ৫ হলে লুপ চলবে ০ থেকে ৪ পর্যন্ত)।

সংক্ষিপ্ত সারাংশ (Quick Revision):
- Array: সমজাতীয় ডেটার সমষ্টি, ইনডেক্স ০ থেকে শুরু।
- String: ক্যারেক্টার অ্যারে, শেষে \0 থাকে।
- Function: কোড পুনরায় ব্যবহার (Code Reusability) নিশ্চিত করে।
- Header Files: স্ট্রিং ফাংশনের জন্য <string.h> এবং গাণিতিক ফাংশনের জন্য <math.h> ব্যবহার করতে হয়।

পরিভাষা (Glossary)

পরিভাষা (Term) সংজ্ঞা (Definition)
Array Index অ্যারের প্রতিটি উপাদানের অবস্থান নির্দেশক সংখ্যা, যা ০ থেকে শুরু হয়।
Null Character স্ট্রিং-এর সমাপ্তি নির্দেশক বিশেষ ক্যারেক্টার (\0)।
Prototype কম্পাইলারকে ফাংশনের নাম ও প্যারামিটার সম্পর্কে আগাম তথ্য দেওয়ার ঘোষণা।
Argument ফাংশন কল করার সময় যে মান পাঠানো হয় (Actual Parameter)।
Parameter ফাংশন ডেফিনিশনে যে ভেরিয়েবল মান গ্রহণ করে (Formal Parameter)।
Buffer Overflow অ্যারের নির্ধারিত সাইজের চেয়ে বেশি ডেটা রাখার চেষ্টা করলে যে এরর হয়।

অনুশীলনের প্রশ্ন

সৃজনশীল প্রশ্ন

সৃজনশীল প্রশ্ন ১

আইসিটি শিক্ষক ক্লাসে ৫০ জন ছাত্রের গণিত পরীক্ষার নম্বর সংরক্ষণ এবং গড় নির্ণয় করার জন্য একটি সি প্রোগ্রাম লেখার কথা ভাবছিলেন। তিনি প্রথমে ৫০টি ভিন্ন ভেরিয়েবল (যেমন: $m1, m2, ..., m50$) ডিক্লেয়ার করার কথা চিন্তা করলেন, কিন্তু পরে বুঝলেন এটি অত্যন্ত কষ্টসাধ্য ও সময়সাপেক্ষ। তাই তিনি ভিন্ন একটি ডেটা স্ট্রাকচার ব্যবহার করার সিদ্ধান্ত নিলেন যেখানে একই ধরণের ডেটা একটি নামের অধীনে সংরক্ষণ করা যায়।

ক) অ্যারে (Array) কী?
খ) স্ট্রিং-কে কেন ক্যারেক্টার অ্যারে বলা হয়? ব্যাখ্যা কর।
গ) উদ্দীপকের শিক্ষকের সমস্যাটি সমাধানের জন্য অ্যারে ব্যবহার করে একটি সি প্রোগ্রাম লেখ যা ৫০ জন ছাত্রের নম্বর ইনপুট নিয়ে গড় বের করবে।
ঘ) উদ্দীপকে উল্লিখিত ৫০টি আলাদা ভেরিয়েবল ব্যবহার এবং শিক্ষকের গৃহীত সিদ্ধান্তের মধ্যে মেমোরি ব্যবস্থাপনা ও কোড দক্ষতার ক্ষেত্রে কোনটি অধিক সুবিধাজনক? বিশ্লেষণপূর্বক মতামত দাও।

উত্তর

(ক) একই ধরণের ডেটা গুচ্ছকে একটি সাধারণ নামের অধীনে মেমোরিতে পর্যায়ক্রমে সাজিয়ে রাখাকে অ্যারে (Array) বলে।

(খ) সি ভাষায় স্ট্রিং হলো একগুচ্ছ ক্যারেক্টারের সমষ্টি যা মেমোরিতে পরপর সংরক্ষিত থাকে এবং যার শেষে একটি নাল ক্যারেক্টার ('\0') থাকে। মূলত ক্যারেক্টার টাইপের অ্যারে ব্যবহার করেই স্ট্রিং তৈরি ও সংরক্ষণ করা হয় বলে স্ট্রিংকে ক্যারেক্টার অ্যারে বলা হয়।

(গ) উদ্দীপকের সমস্যাটি সমাধানের জন্য অ্যারে ব্যবহার করে সি প্রোগ্রাম নিচে দেওয়া হলো:

#include <stdio.h>

int main() {
    int marks[50], i;
    float sum = 0, average;

    // ৫০ জন ছাত্রের নম্বর ইনপুট নেওয়া
    printf("Enter marks for 50 students:\n");
    for(i = 0; i < 50; i++) {
        scanf("%d", &marks[i]);
        sum = sum + marks[i]; // যোগফল নির্ণয়
    }

    average = sum / 50; // গড় নির্ণয়

    printf("Average marks = %.2f\n", average);

    return 0;
}

(ঘ) উদ্দীপকে ৫০টি আলাদা ভেরিয়েবল ব্যবহারের পরিবর্তে অ্যারে ব্যবহারের সিদ্ধান্তটি মেমোরি ব্যবস্থাপনা ও কোড দক্ষতার ক্ষেত্রে অনেক বেশি সুবিধাজনক। নিচে এর বিশ্লেষণ দেওয়া হলো:

  1. কোড ব্যবস্থাপনা ও সরলতা: ৫০টি ভেরিয়েবল (m1 থেকে m50) ডিক্লেয়ার করা এবং প্রতিটির জন্য আলাদা scanf বা printf লেখা অত্যন্ত কষ্টসাধ্য ও কোডের আকার অনেক বড় করে ফেলে। পক্ষান্তরে, অ্যারে ব্যবহার করে int marks[50]; ঘোষণা করলেই ৫০টি জায়গা তৈরি হয়ে যায় এবং লুপ ব্যবহার করে মাত্র কয়েক লাইনে ইনপুট ও প্রসেসিং করা সম্ভব হয়।

  2. মেমোরি এক্সেস: আলাদা ভেরিয়েবলগুলো মেমোরির বিভিন্ন জায়গায় ছড়িয়ে ছিটিয়ে থাকতে পারে, কিন্তু অ্যারে মেমোরিতে পর্যায়ক্রমিক (contiguous) লোকেশন দখল করে। ফলে ইনডেক্স ব্যবহার করে খুব দ্রুত যেকোনো ডেটা এক্সেস করা যায়।

  3. প্রোগ্রাম পরিবর্তনযোগ্যতা: যদি ছাত্র সংখ্যা ৫০ এর পরিবর্তে ১০০ হয়, তবে সাধারণ ভেরিয়েবল পদ্ধতিতে আরও ৫০টি নতুন ভেরিয়েবল লিখতে হবে। কিন্তু অ্যারে পদ্ধতিতে শুধুমাত্র সাইজ পরিবর্তন করলেই চলে।

সুতরাং, কোডের দৈর্ঘ্য কমানো, জটিলতা পরিহার করা এবং ডেটা প্রসেসিং সহজ করার জন্য শিক্ষকের অ্যারে ব্যবহারের সিদ্ধান্তটিই যৌক্তিক ও অধিক সুবিধাজনক।


সৃজনশীল প্রশ্ন ২

নিহাল সি প্রোগ্রামিং শিখছে। সে তার নিজের নাম ইনপুট হিসেবে নিল। তারপর একটি লাইব্রেরি ফাংশন ব্যবহার করে দেখল তার নামে কতগুলো অক্ষর আছে। এরপর সে লুপ ব্যবহার করে তার নামটিকে উল্টো করে (Reverse) প্রিন্ট করল। তার বন্ধু বলল, "তুমি লাইব্রেরি ফাংশন ব্যবহার না করেও অক্ষরের সংখ্যা বের করতে পারতে।"

ক) নাল ক্যারেক্টার ('\0') কী?
খ) scanf ফাংশন দিয়ে কি স্পেসসহ (Space) পুরো নাম ইনপুট নেওয়া যায়? ব্যাখ্যা কর।
গ) নিহাল যেভাবে তার নাম উল্টো করে প্রিন্ট করেছে, সেই কাজটি করার জন্য একটি সি প্রোগ্রাম লেখ।
ঘ) নিহালের বন্ধুর উক্তিটির যথার্থতা মূল্যায়ন কর এবং লাইব্রেরি ফাংশন ও ইউজার ডিফাইনড ফাংশনের মধ্যে তুলনা কর।

উত্তর

(ক) নাল ক্যারেক্টার ('\0') হলো একটি বিশেষ ক্যারেক্টার যা স্ট্রিং-এর সমাপ্তি নির্দেশ করতে ব্যবহৃত হয়। এর আসকি (ASCII) মান হলো ০।

(খ) না, সাধারণ scanf("%s", name); ব্যবহার করে স্পেসসহ পুরো নাম ইনপুট নেওয়া যায় না। কারণ scanf ফাংশন হোয়াইট স্পেস (স্পেস, ট্যাব, নিউলাইন) পেলেই ইনপুট নেওয়া বন্ধ করে দেয়। স্পেসসহ স্ট্রিং ইনপুট নেওয়ার জন্য gets() ফাংশন অথবা scanf("%[^\n]", name); ফরম্যাট স্পেসিফায়ার ব্যবহার করতে হয়।

(গ) নিহালের কাজটি (নাম উল্টো করে প্রিন্ট করা) করার জন্য সি প্রোগ্রাম নিচে দেওয়া হলো:

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

int main() {
    char name[100];
    int len, i;

    printf("Enter your name: ");
    gets(name); // নাম ইনপুট নেওয়া

    len = strlen(name); // লাইব্রেরি ফাংশন দিয়ে দৈর্ঘ্য নির্ণয়

    printf("Reversed name: ");
    // শেষের অক্ষর থেকে শুরু করে প্রথম অক্ষর পর্যন্ত লুপ
    for(i = len - 1; i >= 0; i--) {
        printf("%c", name[i]);
    }

    return 0;
}

(ঘ) নিহালের বন্ধুর উক্তিটি যথার্থ। লাইব্রেরি ফাংশন strlen() ব্যবহার না করেও লুপ চালিয়ে নাল ক্যারেক্টার (\0) পর্যন্ত গুনে স্ট্রিংয়ের দৈর্ঘ্য বের করা সম্ভব।

লাইব্রেরি ফাংশন ও ইউজার ডিফাইনড ফাংশনের তুলনা ও বিশ্লেষণ:

  1. সহজলভ্যতা: লাইব্রেরি ফাংশন (যেমন strlen, strcpy) কম্পাইলারের সাথে আগেই তৈরি করা থাকে, তাই এগুলো ব্যবহার করা সহজ এবং সময় বাঁচায়। অন্যদিকে, ইউজার ডিফাইনড ফাংশন ব্যবহারকারীকে নিজের প্রয়োজন মতো তৈরি করতে হয়।

  2. নির্ভুলতা ও দক্ষতা: লাইব্রেরি ফাংশনগুলো সাধারণত অপ্টিমাইজড এবং বাগ-মুক্ত হয়। নতুন করে কোড লিখলে (ইউজার ডিফাইনড) সেখানে ভুল হওয়ার সম্ভাবনা থাকে।

  3. কাস্টমাইজেশন: লাইব্রেরি ফাংশন নির্দিষ্ট কিছু কাজই করতে পারে। কিন্তু ইউজার ডিফাইনড ফাংশন দিয়ে আমরা যেকোনো জটিল লজিক বা কাস্টম কাজ বাস্তবায়ন করতে পারি।

নিহালের ক্ষেত্রে, যেহেতু সে শিখছে, তাই ম্যানুয়ালি লুপ চালিয়ে দৈর্ঘ্য বের করা তার লজিক ডেভেলপমেন্টের জন্য ভালো, তবে প্রফেশনাল কোডিংয়ে লাইব্রেরি ফাংশন ব্যবহার করাই শ্রেয়।


সৃজনশীল প্রশ্ন ৩

দৃশ্যপট-১: আবির একটি সি প্রোগ্রাম লিখল যা দুটি পূর্ণ সংখ্যার যোগফল নির্ণয় করে।
দৃশ্যপট-২: পরবর্তীতে সে এমন একটি প্রোগ্রাম লিখতে চাইল যেখানে add(), sub(), mul() নামে আলাদা অংশ থাকবে এবং মূল প্রোগ্রাম (main) থেকে প্রয়োজন অনুযায়ী সেগুলোকে কল করা হবে।

ক) ফাংশন প্রোটোটাইপ কী?
খ) লোকাল ভেরিয়েবল ও গ্লোবাল ভেরিয়েবলের মধ্যে পার্থক্য কী?
গ) দৃশ্যপট-২ অনুযায়ী ফাংশন ব্যবহার করে দুটি সংখ্যার যোগ, বিয়োগ ও গুণ করার জন্য একটি সি প্রোগ্রাম লেখ।
ঘ) দৃশ্যপট-১ এর চেয়ে দৃশ্যপট-২ এ ব্যবহৃত পদ্ধতি (মডুলার প্রোগ্রামিং) বড় সফটওয়্যার তৈরিতে কেন বেশি উপযোগী? বিশ্লেষণ কর।

উত্তর

(ক) ফাংশন প্রোটোটাইপ হলো কম্পাইলারকে ফাংশনের নাম, রিটার্ন টাইপ এবং আর্গুমেন্ট সম্পর্কে পূর্বেই জানানোর একটি ঘোষণা, যাতে কম্পাইলার মূল কোডের আগেই ফাংশনটি সম্পর্কে ধারণা পায়।

(খ) লোকাল ভেরিয়েবল কোনো নির্দিষ্ট ফাংশন বা ব্লকের ভেতরে ঘোষণা করা হয় এবং শুধুমাত্র সেই ব্লকের ভেতরেই কাজ করে। অন্যদিকে, গ্লোবাল ভেরিয়েবল যেকোনো ফাংশনের বাইরে (সাধারণত ফাইলের শুরুতে) ঘোষণা করা হয় এবং প্রোগ্রামের যেকোনো ফাংশন থেকে এটি ব্যবহার করা যায়।

(গ) দৃশ্যপট-২ অনুযায়ী ইউজার ডিফাইনড ফাংশন ব্যবহার করে সি প্রোগ্রাম:

#include <stdio.h>

// ফাংশন ডেফিনিশন
int add(int a, int b) {
    return a + b;
}

int sub(int a, int b) {
    return a - b;
}

int mul(int a, int b) {
    return a * b;
}

int main() {
    int num1, num2;

    printf("Enter two numbers: ");
    scanf("%d %d", &num1, &num2);

    printf("Sum: %d\n", add(num1, num2));
    printf("Subtraction: %d\n", sub(num1, num2));
    printf("Multiplication: %d\n", mul(num1, num2));

    return 0;
}

(ঘ) দৃশ্যপট-১ এ সাধারণ প্রোগ্রামিং এবং দৃশ্যপট-২ এ ফাংশন বা মডুলার প্রোগ্রামিং পদ্ধতি ব্যবহার করা হয়েছে। বড় সফটওয়্যার তৈরিতে দৃশ্যপট-২ বা মডুলার পদ্ধতি অনেক বেশি উপযোগী। কারণ:

  1. কোড পুনঃব্যবহারযোগ্যতা (Reusability): একবার একটি ফাংশন লিখলে তা প্রোগ্রামের বিভিন্ন জায়গায় বারবার ব্যবহার করা যায়। একই কোড বারবার লেখার প্রয়োজন হয় না।

  2. ডিবাগিং সহজ: কোডকে ছোট ছোট ফাংশনে ভাগ করলে ভুল খুঁজে বের করা এবং সমাধান করা সহজ হয়। দৃশ্যপট-১ এর মতো সব কোড main ফাংশনে লিখলে বড় প্রোগ্রামে ভুল ধরা খুব কঠিন হয়ে পড়ে।

  3. মডুলারিটি ও ব্যবস্থাপনা: বড় প্রজেক্টে একাধিক প্রোগ্রামার কাজ করেন। ফাংশন ব্যবহার করলে কাজ ভাগ করে নেওয়া যায়। প্রত্যেকে আলাদা আলাদা মডিউল বা ফাংশন তৈরি করে পরে তা মূল প্রোগ্রামে যুক্ত করতে পারেন।

সুতরাং, কোডের স্বচ্ছতা, রক্ষণাবেক্ষণ এবং উন্নয়নের সুবিধার্থে বড় সফটওয়্যার তৈরিতে দৃশ্যপট-২ এর মডুলার বা ফাংশনভিত্তিক পদ্ধতিই অপরিহার্য।

এমসিকিউ

১। সি ভাষায় অ্যারে (Array) ইনডেক্স কত থেকে শুরু হয়?

ক) ১
খ) ০
গ) -১
ঘ) অনির্দিষ্ট

সঠিক উত্তর: খ) ০

ব্যাখ্যা: সি ভাষায় অ্যারের ইনডেক্স সর্বদা ০ (শূন্য) থেকে শুরু হয় এবং শেষ ইনডেক্স হয় (মোট উপাদান সংখ্যা - ১)।


২। int num[5]; অ্যারেটিতে সর্বশেষ উপাদানের ইনডেক্স কত?

ক) ৫
খ) ৪
গ) ৬
ঘ) ৩

সঠিক উত্তর: খ) ৪

ব্যাখ্যা: অ্যারের সাইজ ৫ হলে ইনডেক্স হবে ০, ১, ২, ৩, ৪। তাই সর্বশেষ ইনডেক্স ৪।


৩। char str[] = "HSC"; স্ট্রিংটির মেমোরি সাইজ কত বাইট?

ক) ৩ বাইট
খ) ৪ বাইট
গ) ৫ বাইট
ঘ) ২ বাইট

সঠিক উত্তর: খ) ৪ বাইট

ব্যাখ্যা: "HSC" তে ৩টি দৃশ্যমান ক্যারেক্টার আছে, কিন্তু স্ট্রিং শেষে একটি নাল ক্যারেক্টার (\0) স্বয়ংক্রিয়ভাবে যুক্ত হয়। তাই মোট সাইজ ৩ + ১ = ৪ বাইট।


৪। স্ট্রিং এর শেষে কোন ক্যারেক্টারটি থাকে?

ক) \n
খ) \t
গ) \0
ঘ) \r

সঠিক উত্তর: গ) \0

ব্যাখ্যা: সি ভাষায় স্ট্রিং এর সমাপ্তি বোঝানোর জন্য নাল ক্যারেক্টার (\0) ব্যবহার করা হয়।


৫। দুটি স্ট্রিং জোড়া লাগাতে কোন ফাংশনটি ব্যবহৃত হয়?

ক) strlen()
খ) strcpy()
গ) strcat()
ঘ) strcmp()

সঠিক উত্তর: গ) strcat()

ব্যাখ্যা: strcat (String Concatenation) ফাংশনটি দুটি স্ট্রিংকে যুক্ত বা কনক্যাটিনেট করতে ব্যবহৃত হয়।


৬। strlen("ICT") এর মান কত?

ক) ৩
খ) ৪
গ) ৫
ঘ) ১০

সঠিক উত্তর: ক) ৩

ব্যাখ্যা: strlen() ফাংশন নাল ক্যারেক্টার বাদ দিয়ে শুধুমাত্র দৃশ্যমান ক্যারেক্টারের সংখ্যা গণনা করে। তাই "ICT" এর দৈর্ঘ্য ৩।


৭। নিচের কোনটি সঠিক অ্যারে ডিক্লারেশন?

ক) int a(10);
খ) int a[10];
গ) array a[10];
ঘ) int a{10};

সঠিক উত্তর: খ) int a[10];

ব্যাখ্যা: সি ভাষায় অ্যারে ডিক্লেয়ার করার নিয়ম হলো data_type array_name[size];। এখানে তৃতীয় ব্র্যাকেট [] ব্যবহার করা হয়।


৮। ফাংশনের ভেতর ঘোষিত ভেরিয়েবলকে কী বলা হয়?

ক) গ্লোবাল ভেরিয়েবল
খ) লোকাল ভেরিয়েবল
গ) স্ট্যাটিক ভেরিয়েবল
ঘ) এক্সটার্ন ভেরিয়েবল

সঠিক উত্তর: খ) লোকাল ভেরিয়েবল

ব্যাখ্যা: কোনো ফাংশনের ব্লকের ভেতর যে ভেরিয়েবল ঘোষণা করা হয়, তা কেবল ঐ ফাংশনেই কাজ করে এবং একে লোকাল ভেরিয়েবল বলে।


৯। int data[3][4]; অ্যারেটিতে মোট কতটি উপাদান থাকবে?

ক) ৭টি
খ) ১২টি
গ) ৩টি
ঘ) ৪টি

সঠিক উত্তর: খ) ১২টি

ব্যাখ্যা: এটি একটি দ্বিমাত্রিক (2D) অ্যারে। মোট উপাদান সংখ্যা = সারি সংখ্যা × কলাম সংখ্যা = ৩ × ৪ = ১২।


১০। কোন ফাংশনটি সি প্রোগ্রামের প্রধান অংশ যা থেকে এক্সিকিউশন শুরু হয়?

ক) start()
খ) begin()
গ) main()
ঘ) header()

সঠিক উত্তর: গ) main()

ব্যাখ্যা: সি প্রোগ্রামের এক্সিকিউশন সর্বদা main() ফাংশন থেকে শুরু হয়। এটি একটি ইউজার ডিফাইনড ফাংশন যা সিস্টেম কল করে।


১১। নিচের কোনটি স্ট্রিং ইনপুট নেওয়ার জন্য সঠিক ফরম্যাট স্পেসিফায়ার?

ক) %d
খ) %c
গ) %f
ঘ) %s

সঠিক উত্তর: ঘ) %s

ব্যাখ্যা: স্ট্রিং ইনপুট ও আউটপুটের জন্য %s ফরম্যাট স্পেসিফায়ার ব্যবহৃত হয়।


১২। strcmp() ফাংশনটি দুটি স্ট্রিং সমান হলে কী রিটার্ন করে?

ক) ১
খ) ০
গ) -১
ঘ) নাল

সঠিক উত্তর: খ) ০

ব্যাখ্যা: strcmp() ফাংশন দুটি স্ট্রিং তুলনা করে। স্ট্রিং দুটি হুবহু এক হলে এটি ০ (শূন্য) রিটার্ন করে।


১৩। হেডার ফাইল string.h কেন ব্যবহার করা হয়?

ক) গাণিতিক কাজের জন্য
খ) ইনপুট আউটপুটের জন্য
গ) স্ট্রিং লাইব্রেরি ফাংশনের জন্য
ঘ) গ্রাফিক্সের জন্য

সঠিক উত্তর: গ) স্ট্রিং লাইব্রেরি ফাংশনের জন্য

ব্যাখ্যা: strlen, strcpy, strcat ইত্যাদি স্ট্রিং ম্যানিপুলেশন ফাংশন ব্যবহার করার জন্য string.h হেডার ফাইল অন্তর্ভুক্ত করতে হয়।


১৪। ফাংশন কত প্রকার?

ক) ২ প্রকার
খ) ৩ প্রকার
গ) ৪ প্রকার
ঘ) ৫ প্রকার

সঠিক উত্তর: ক) ২ প্রকার

ব্যাখ্যা: সি ভাষায় ফাংশন প্রধানত ২ প্রকার: ১. লাইব্রেরি ফাংশন (যেমন printf, scanf) এবং ২. ইউজার ডিফাইনড ফাংশন (ব্যবহারকারীর তৈরি)।


১৫। void রিটার্ন টাইপ যুক্ত ফাংশন কী রিটার্ন করে?

ক) ইন্টিজার ভ্যালু
খ) ফ্লোট ভ্যালু
গ) কোনো মান রিটার্ন করে না
ঘ) নাল ক্যারেক্টার

সঠিক উত্তর: গ) কোনো মান রিটার্ন করে না

ব্যাখ্যা: void কিওয়ার্ডটি নির্দেশ করে যে ফাংশনটি কোনো ডেটা বা মান রিটার্ন করবে না।


১৬। অ্যারে ব্যবহারের সুবিধা হলো—
i. একই নামের অধীনে অনেক ডেটা রাখা যায়
ii. ডেটা খুঁজে বের করা সহজ
iii. মেমোরি অপচয় রোধ করে

নিচের কোনটি সঠিক?
ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: ক) i ও ii

ব্যাখ্যা: অ্যারে একই ধরণের ডেটা গুচ্ছাকারে রাখে এবং ইনডেক্স দিয়ে সহজে এক্সেস করা যায়। তবে অ্যারের সাইজ ফিক্সড হওয়ায় প্রয়োজন না থাকলেও মেমোরি দখল করে রাখে, তাই এটি মেমোরি অপচয় রোধ করে না বরং কখনো কখনো অপচয় করে।


১৭। লাইব্রেরি ফাংশন ব্যবহারের সুবিধা—
i. প্রোগ্রাম লেখা সহজ হয়
ii. সময় বাঁচে
iii. ডিবাগিং করার প্রয়োজন নেই

নিচের কোনটি সঠিক?
ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: ক) i ও ii

ব্যাখ্যা: লাইব্রেরি ফাংশন আগে থেকেই তৈরি করা থাকে বলে প্রোগ্রামারকে নতুন করে কোড লিখতে হয় না, ফলে সময় বাঁচে ও কাজ সহজ হয়। তবে প্রোগ্রামে ভুল থাকলে ডিবাগিং এর প্রয়োজন হতেই পারে।


১৮। char str[] = "BOOK"; এর ক্ষেত্রে—
i. str[0] এর মান 'B'
ii. str[4] এর মান '\0'
iii. সাইজ ৫ বাইট

নিচের কোনটি সঠিক?
ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: ঘ) i, ii ও iii

ব্যাখ্যা: "BOOK" এ ৪টি অক্ষর আছে (ইনডেক্স ০-৩)। ৪র্থ ইনডেক্সে স্বয়ংক্রিয়ভাবে \0 বসে। মোট সাইজ ৪+১=৫ বাইট। সবকটি তথ্য সঠিক।


১৯। ইউজার ডিফাইনড ফাংশনের অংশগুলো হলো—
i. ফাংশন প্রোটোটাইপ
ii. ফাংশন কল
iii. ফাংশন ডেফিনিশন

নিচের কোনটি সঠিক?
ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: ঘ) i, ii ও iii

ব্যাখ্যা: একটি পূর্ণাঙ্গ ইউজার ডিফাইনড ফাংশন ব্যবহারে ঘোষণা (প্রোটোটাইপ), কল করা এবং মূল কাজ (ডেফিনিশন) এই তিনটি ধাপই থাকে।


২০। অ্যারের ইনডেক্স হতে পারে—
i. ধনাত্মক পূর্ণসংখ্যা
ii. ঋণাত্মক পূর্ণসংখ্যা
iii. শূন্য (০)

নিচের কোনটি সঠিক?
ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: খ) i ও iii

ব্যাখ্যা: সি ভাষায় অ্যারের ইনডেক্স অবশ্যই অঋণাত্মক পূর্ণসংখ্যা (Non-negative integer) হতে হবে। অর্থাৎ ০ বা তার চেয়ে বড় পূর্ণসংখ্যা। ঋণাত্মক ইনডেক্স বৈধ নয়।


নিচের উদ্দীপকটি পড়ো এবং ২১ ও ২২ নং প্রশ্নের উত্তর দাও:

int A[5] = {10, 20, 30, 40, 50};
printf("%d", A[2]);

২১। প্রোগ্রামটির আউটপুট কত হবে?

ক) ১০
খ) ২০
গ) ৩০
ঘ) ৪০

সঠিক উত্তর: গ) ৩০

ব্যাখ্যা: অ্যারের ইনডেক্স ০ থেকে শুরু হয়। A[0]=10, A[1]=20, A[2]=30। তাই আউটপুট ৩০।


২২। উদ্দীপকের অ্যারেটিতে A[4] এর মান কত?

ক) ৪০
খ) ৫০
গ) ১০
ঘ) গারবেজ ভ্যালু

সঠিক উত্তর: খ) ৫০

ব্যাখ্যা: অ্যারেটিতে ৫টি উপাদান আছে। শেষ উপাদানের ইনডেক্স ৪। তাই A[4] এর মান ৫০।


নিচের উদ্দীপকটি পড়ো এবং ২৩ ও ২৪ নং প্রশ্নের উত্তর দাও:

char s1[] = "Hello";
char s2[] = "World";
strcat(s1, s2);

২৩। কোডটি এক্সিকিউট করার পর s1 এর মান কী হবে?

ক) Hello
খ) World
গ) HelloWorld
ঘ) WorldHello

সঠিক উত্তর: গ) HelloWorld

ব্যাখ্যা: strcat(s1, s2) ফাংশনটি s2 কে s1 এর শেষে যুক্ত করে এবং ফলাফল s1 এ সংরক্ষণ করে।


২৪। কোডটি শেষে s1 স্ট্রিংটির দৈর্ঘ্য কত হবে (নাল ক্যারেক্টার বাদে)?

ক) ৫
খ) ১০
গ) ১১
ঘ) ১২

সঠিক উত্তর: খ) ১০

ব্যাখ্যা: "Hello" (5) এবং "World" (5) যুক্ত হয়ে "HelloWorld" তৈরি হয়, যার দৈর্ঘ্য ১০।


২৫। int function(int n) — এখানে n কে কী বলা হয়?

ক) রিটার্ন টাইপ
খ) ফাংশন নেম
গ) আর্গুমেন্ট বা প্যারামিটার
ঘ) লোকাল ভেরিয়েবল

সঠিক উত্তর: গ) আর্গুমেন্ট বা প্যারামিটার

ব্যাখ্যা: ফাংশন ডিক্লারেশন বা ডেফিনিশনের সময় ব্র্যাকেটের ভেতর যে ভেরিয়েবল থাকে তাকে প্যারামিটার বা আর্গুমেন্ট বলা হয়।