সি ভাষায় সমস্যা সমাধান ও ব্যবহারিক প্রোগ্রাম

এইচএসসি আইসিটি সি প্রোগ্রামিং: পরীক্ষার জন্য গুরুত্বপূর্ণ ১৪টি ব্যবহারিক প্রোগ্রাম। ক্ষেত্রফল, তাপমাত্রা, ধারা, ফ্যাক্টরিয়াল, জিসিডি, প্রাইম নম্বর, ফিবোনাচ্চি

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

সি ভাষায় সমস্যা সমাধান ও ব্যবহারিক প্রোগ্রাম

  1. সি ভাষায় সমস্যা সমাধান ও ব্যবহারিক প্রোগ্রাম
  2. আমাদের 'টুলবক্স' প্রস্তুত তো?
  3. ব্যবহারিক ১: ত্রিভুজ ও বৃত্তের ক্ষেত্রফল নির্ণয়
  4. ব্যবহারিক ২: তাপমাত্রা রূপান্তর (C to F)
  5. ব্যবহারিক ৩: জোড়-বিজোড় নির্ণয় (Even/Odd)
  6. ব্যবহারিক ৪: লিপ ইয়ার (Leap Year) নির্ণয়
  7. ব্যবহারিক ৫: তিনটি সংখ্যার মধ্যে বড় সংখ্যা নির্ণয়
  8. এবার লুপের খেলা: ধারার যোগফল
  9. ব্যবহারিক ৬: বর্গের ধারার যোগফল
  10. ব্যবহারিক ৭: ফ্যাক্টরিয়াল (Factorial) নির্ণয়
  11. ব্যবহারিক ৮: মৌলিক সংখ্যা (Prime Number) যাচাই
  12. ব্যবহারিক ৯: গ.সা.গু (GCD) ও ল.সা.গু (LCM)
  13. ব্যবহারিক ১০: ফিবোনাচ্চি ধারা (Fibonacci)
  14. প্রোগ্রামিংয়ে ভালো করার টিপস
  15. আজকের সারসংক্ষেপ

সি ভাষায় সমস্যা সমাধান ও ব্যবহারিক প্রোগ্রাম

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

১। সি প্রোগ্রামিং ব্যবহার করে গাণিতিক সমস্যা (যেমন: ক্ষেত্রফল, তাপমাত্রা) সমাধান করতে পারব।
২। কন্ডিশনাল লজিক ব্যবহার করে লিপ ইয়ার এবং ছোট-বড় সংখ্যা নির্ণয় করতে পারব।
৩। লুপ ব্যবহার করে বিভিন্ন ধারা, ফ্যাক্টরিয়াল এবং মৌলিক সংখ্যা নির্ণয় করতে পারব।
৪। গ.সা.গু (GCD), ল.সা.গু (LCM) এবং ফিবোনাচ্চি ধারার অ্যালগরিদম ব্যাখ্যা করতে পারব।

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

আমাদের 'টুলবক্স' প্রস্তুত তো?

প্রোগ্রামিং শেখা অনেকটা বাড়ি বানানোর মতো।

আমরা শিখেছি:
- ভেরিয়েবল (ইট-বালু)
- কন্ডিশন (নকশা)
- লুপ (পুনরাবৃত্তি কাজ)

আজকের কাজ:
এগুলো জোড়া দিয়ে পূর্ণাঙ্গ 'বিল্ডিং' বা প্রোগ্রাম তৈরি করা। মনে রাখবে, শুধু সিনট্যাক্স জানা আর সমস্যা সমাধান করা এক বিষয় নয়। লজিক সাজানোই আসল দক্ষতা।

তোমরা কি কখনো ভেবেছ, প্রোগ্রামিং শেখা আর একটা বিল্ডিং বানানো কতটা একই রকম? ধরো, তোমার কাছে ইট, বালু, সিমেন্ট সব আছে—এগুলো হলো আমাদের ভেরিয়েবল, ডেটা টাইপ। তোমার কাছে হাতুড়ি-বাটাল আছে—এগুলো হলো আমাদের লুপ আর কন্ডিশন। কিন্তু শুধু এগুলো থাকলেই কি বিল্ডিং হয়ে যাবে? না! তোমাকে জানতে হবে কোন ইটের পর কোন ইট বসবে। ঠিক তেমনি, সিনট্যাক্স জানাই সব না, আসল চ্যালেঞ্জ হলো লজিক সাজানো। আজ আমরা সেই 'আর্কিটেক্ট' এর কাজটাই করব। আমাদের এই টুলবক্স ব্যবহার করে রিয়েল প্রবলেম সলভ করব।

ব্যবহারিক ১: ত্রিভুজ ও বৃত্তের ক্ষেত্রফল নির্ণয়

গাণিতিক সূত্রগুলোকে কোডে রূপান্তর:

ত্রিভুজের ক্ষেত্রফল:
- সূত্র: $Area = 0.5 \times base \times height$
- কোড: area = 0.5 * b * h;

বৃত্তের ক্ষেত্রফল:
- সূত্র: $Area = \pi r^2$
- কোড: area = 3.1416 * r * r;

সতর্কতা: ক্ষেত্রফল দশমিকে আসতে পারে, তাই float ডেটা টাইপ ব্যবহার করা উচিত।

প্রথমেই একদম সহজ কিছু দিয়ে শুরু করি। জ্যামিতির সূত্র। ধরো তোমাকে বলা হলো একটি ত্রিভুজের ক্ষেত্রফল বের করার প্রোগ্রাম লিখতে। সূত্র আমরা জানি: হাফ ইনটু ভূমি ইনটু উচ্চতা। এখানে খেয়াল রাখার বিষয় হলো, হাফ মানে ০.৫। আর যেহেতু ক্ষেত্রফল দশমিকে আসতে পারে, তাই আমরা ভেরিয়েবল হিসেবে `float` ব্যবহার করব। কোডটা দেখো, আমরা প্রথমে `base` আর `height` ইনপুট নিচ্ছি, তারপর সূত্র বসাচ্ছি। ঠিক একইভাবে বৃত্তের ক্ষেত্রফলের জন্য আমরা ৩.১৪১৬ গুণ ব্যাসার্ধের স্কয়ার ব্যবহার করব। স্লাইডের ছবিটা দেখো, সূত্রগুলো কীভাবে কোডে লেখা হয়েছে।

ব্যবহারিক ২: তাপমাত্রা রূপান্তর (C to F)

সূত্র: $\frac{C}{5} = \frac{F-32}{9}$

সেলসিয়াস থেকে ফারেনহাইট বের করার কোড:

float C, F;
printf("Enter Celsius: ");
scanf("%f", &C);

// সূত্র রূপান্তর
F = (C * 9 / 5) + 32;

printf("Fahrenheit: %.2f", F);

গুরুত্বপূর্ণ: সি ভাষায় 5/9 লিখলে উত্তর 0 আসবে (Integer Division)। তাই সব সময় 5.0 বা 9.0 অথবা (float) ব্যবহার করতে হবে।

তাপমাত্রা রূপান্তরের প্রোগ্রামটি খুবই জনপ্রিয়। আমরা ছোটবেলায় শিখেছি C বাই 5 সমান F মাইনাস 32 বাই 9। এখন যদি তোমাকে সেলসিয়াস থেকে ফারেনহাইট বের করতে বলে, তাহলে সমীকরণটা একটু ঘুরিয়ে নিতে হবে: F সমান C গুণ 9 ভাগ 5, যোগ 32। এখানে একটা খুব গুরুত্বপূর্ণ বিষয় আছে যা অনেকেই ভুল করে। সি প্রোগ্রামে তুমি যদি পূর্ণসংখ্যা ৫ কে ৯ দিয়ে ভাগ করো, উত্তর আসবে ০! কারণ এটা ইন্টিজার ডিভিশন। তাই কোড লেখার সময় অবশ্যই ভগ্নাংশ বোঝাতে ৫.০ বা ৯.০ লিখতে হবে। এই ছোট ট্রিকটা মনে রাখলে অনেক লজিক্যাল এরর থেকে বাঁচবে।

ব্যবহারিক ৩: জোড়-বিজোড় নির্ণয় (Even/Odd)

একটি সংখ্যা জোড় না বিজোড় তা বোঝার উপায় কী?

লজিক:
- কোনো সংখ্যাকে ২ দিয়ে ভাগ করলে যদি ভাগশেষ ০ হয়, তবে তা জোড় (Even)
- অন্যথায় তা বিজোড় (Odd)

কোড:

int num;
scanf("%d", &num);

if (num % 2 == 0) {
    printf("Even Number");
} else {
    printf("Odd Number");
}

এখানে % (Modulus) অপারেটর ভাগশেষ বের করে।

এবার আসি কন্ডিশনাল লজিকের ব্যবহারে। তোমাকে বলা হলো একটা সংখ্যা জোড় না বিজোড় বের করো। কম্পিউটার তো আর দেখে বুঝতে পারে না, তাকে লজিক দিতে হয়। লজিকটা হলো—কোনো সংখ্যাকে ২ দিয়ে ভাগ করলে যদি ভাগশেষ ০ থাকে, তবেই সেটা জোড়। সি ভাষায় ভাগশেষ বের করার জন্য আমরা পার্সেন্ট সাইন বা মডুলাস অপারেটর ব্যবহার করি। ভিডিওটা পজ করে একটু ভাবো তো, `num % 2 == 1` হলে কী প্রিন্ট করতাম? ঠিক ধরেছ, সেটা হতো বিজোড় সংখ্যা।

ব্যবহারিক ৪: লিপ ইয়ার (Leap Year) নির্ণয়

সব ৪ দিয়ে ভাগ করা বছরই কি লিপ ইয়ার? না!

লজিক:
১. বছরটি ৪০০ দিয়ে ভাগ গেলে লিপ ইয়ার।
২. অথবা, ৪ দিয়ে ভাগ গেলে এবং ১০০ দিয়ে ভাগ না গেলে লিপ ইয়ার।

কোড কন্ডিশন:

if ((year % 400 == 0) || 
   ((year % 4 == 0) && (year % 100 != 0))) {
    printf("Leap Year");
} else {
    printf("Not Leap Year");
}

লিপ ইয়ার বা অধিবর্ষের লজিকটা একটু ট্রিকি। আমরা সাধারণত জানি ৪ বছরে একবার লিপ ইয়ার হয়। কিন্তু সব ৪ দিয়ে ভাগ যাওয়া বছরই লিপ ইয়ার না। যেমন ১৯০০ সাল লিপ ইয়ার ছিল না, কিন্তু ২০০০ সাল ছিল। লজিকটা হলো: বছরটি যদি ৪০০ দিয়ে নিঃশেষে ভাগ যায় তবে লিপ ইয়ার। অথবা, যদি ৪ দিয়ে ভাগ যায় কিন্তু ১০০ দিয়ে ভাগ না যায়, তাহলেও লিপ ইয়ার। এই 'অথবা' এবং 'কিন্তু' কে আমরা কোডে অর এবং এন্ড অপারেটর দিয়ে লিখি। ফ্লোচার্টটা খেয়াল করো, লজিকটা ধাপে ধাপে কীভাবে চেক করা হচ্ছে।

ব্যবহারিক ৫: তিনটি সংখ্যার মধ্যে বড় সংখ্যা নির্ণয়

সমস্যা: তিনটি সংখ্যা (a, b, c) ইনপুট নিয়ে সবচেয়ে বড়টি বের করা।

পদ্ধতি ১ (Nested If):

if (a > b) {
    if (a > c) printf("%d", a);
    else printf("%d", c);
} else {
    if (b > c) printf("%d", b);
    else printf("%d", c);
}

তিনজন বন্ধুর মধ্যে কার বয়স সবচেয়ে বেশি—এটা বের করতে হলে তুমি কী করবে? প্রথমে প্রথম দুজনকে তুলনা করবে, তারপর বিজয়ীর সাথে তৃতীয়জনকে। প্রোগ্রামেও তাই। আমরা `if-else ladder` ব্যবহার করতে পারি। যদি `a > b` এবং `a > c` হয়, তবে নিঃসন্দেহে `a` বড়। তা না হলে, চেক করব `b` কি `a` এবং `c` এর চেয়ে বড়? যদি তাও না হয়, তাহলে বাকি রইল কে? `c`! তখন `c` ই সবচেয়ে বড়। স্ক্রিনে দেখো, দুটি পদ্ধতি দেওয়া আছে। ডানদিকের পদ্ধতিটা অর্থাৎ লজিক্যাল এন্ড অপারেটর ব্যবহার করা পদ্ধতিটা বেশি সহজ এবং ক্লিন।

এবার লুপের খেলা: ধারার যোগফল

সমস্যা: $1 + 2 + 3 + ... + N$ পর্যন্ত যোগফল নির্ণয়।

উপকরণ:
১. লুপ (Loop): ১ থেকে N পর্যন্ত ঘোরার জন্য।
২. একুমুলেটর (Accumulator): যোগফল জমা রাখার ঝুড়ি (sum)।

কোড:

int sum = 0; // ঝুড়ি খালি
for (i = 1; i <= N; i++) {
   sum = sum + i; // ঝুড়িতে i রাখলাম
}

এতক্ষণ আমরা কন্ডিশন নিয়ে ছিলাম। এবার আসব লুপে। ধরো তোমাকে ১ থেকে ১০০ পর্যন্ত যোগ করতে বলা হলো। ক্যালকুলেটরে টিপতে অনেক সময় লাগবে, তাই না? লুপ দিয়ে এটা নিমিষেই করা যায়। আমাদের একটা খালি ঝুড়ি লাগবে, ধরলাম তার নাম `sum`, শুরুতে সেখানে কিছু নেই তাই `0`। এবার লুপ চালিয়ে ১ থেকে N পর্যন্ত সংখ্যাগুলো একটা একটা করে ঝুড়িতে ফেলব, অর্থাৎ যোগ করব। `sum = sum + i`—এই লাইনটাই হলো লুপের হার্টবিট। প্রতিবার `i` এর মান বাড়ছে আর `sum` এর সাথে যোগ হচ্ছে।

ব্যবহারিক ৬: বর্গের ধারার যোগফল

ধারা: $1^2 + 2^2 + 3^2 + ... + N^2$

আগের কোডের সাথে পার্থক্য শুধু যোগ করার লাইনে:
- লিনিয়ার ধারা ছিল: sum = sum + i;
- বর্গের ধারা হবে: sum = sum + (i * i);

যদি বিজোড় সংখ্যার ধারা হয়? ($1 + 3 + 5 + ...$)
তখন লুপের ইনক্রিমেন্ট হবে ২ করে:
for (i = 1; i <= N; i = i + 2)

যদি ধারাটি বদলে ১ স্কয়ার, ২ স্কয়ার, ৩ স্কয়ার... এমন হয়? ভয়ের কিছু নেই! আমাদের লুপের স্ট্রাকচার একই থাকবে। শুধু যোগ করার সময় `i` এর বদলে `i*i` যোগ করব। অর্থাৎ `sum = sum + (i*i)`। আচ্ছা, এখন তোমরাই বলো তো, যদি ধারাটি ১, ৩, ৫... এমন বিজোড় সংখ্যার হতো, তাহলে লুপের `i++` এর জায়গায় কী পরিবর্তন করতে হতো? ভিডিওটা পজ করে ভাবো। ঠিক! তখন প্রতি ধাপে ২ করে বাড়াতে হতো, অর্থাৎ `i = i + 2` দিতে হতো।

ব্যবহারিক ৭: ফ্যাক্টরিয়াল (Factorial) নির্ণয়

ফ্যাক্টরিয়াল কী?
$5! = 1 \times 2 \times 3 \times 4 \times 5 = 120$

কোড লজিক:
- এটিও ধারার মতো, কিন্তু যোগের বদলে গুণ হবে।
- fact ভেরিয়েবল শুরুতে 1 ধরতে হবে (কারণ 0 দিয়ে গুণ করলে সব 0 হয়ে যাবে)।

long long fact = 1;
for (i = 1; i <= num; i++) {
   fact = fact * i;
}

ফ্যাক্টরিয়াল মানে হলো ১ থেকে ওই সংখ্যা পর্যন্ত সবগুলোর গুণফল। যেমন ৫ এর ফ্যাক্টরিয়াল হলো ১ গুন ২ গুন ৩ গুন ৪ গুন ৫। এখানে একটা মারাত্মক ভুল অনেকেই করে। যোগফলের সময় আমরা `sum = 0` ধরি, কিন্তু গুণের সময় যদি `fact = 0` ধরো, তাহলে কী হবে? শূন্য দিয়ে যাই গুণ করো, সব শূন্য হয়ে যাবে! তাই গুণের ধারায় বা ফ্যাক্টরিয়ালে সব সময় প্রাথমিক মান বা ইনিশিয়াল ভ্যালু `1` ধরতে হবে। কোডটা দেখো, লজিকটা ঠিক ধারার যোগফলের মতোই, শুধু চিহ্ণটা গুণের।

ব্যবহারিক ৮: মৌলিক সংখ্যা (Prime Number) যাচাই

সংজ্ঞা: যে সংখ্যা ১ এবং ওই সংখ্যা ছাড়া অন্য কিছু দিয়ে ভাগ যায় না।

অ্যালগরিদম:
১. ২ থেকে (N-1) পর্যন্ত লুপ চালাও।
২. যদি N কোনো সংখ্যা দিয়ে ভাগ যায় (N % i == 0), তবে মৌলিক নয়।
৩. flag ব্যবহার করে অবস্থা মনে রাখা।

int isPrime = 1; // 1 means True
for(i=2; i<n; i++) {
    if(n % i == 0) {
        isPrime = 0; // False
        break;
    }
}

প্রাইম নম্বর বা মৌলিক সংখ্যা চেক করা প্রোগ্রামিংয়ের একটা ক্লাসিক প্রবলেম। ৭ কি প্রাইম? হ্যাঁ। কারণ ৭ কে ২, ৩, ৪, ৫, ৬—কিছু দিয়েই ভাগ করা যায় না। তাহলে লজিকটা কী? আমরা ২ থেকে শুরু করে ওই সংখ্যার আগ পর্যন্ত লুপ চালাব। যদি কোনো একটা সংখ্যা দিয়েও ভাগফল মিলে যায়, মানে ভাগশেষ ০ হয়, তাহলেই বুঝব এটা প্রাইম না। তখন আমরা লুপ থামিয়ে দেব `break` দিয়ে। আর যদি লুপ শেষ হয়ে যায় কিন্তু একবারও ভাগ না যায়, তখনই আমরা নিশ্চিত হব সংখ্যাটি প্রাইম। এটাকে নিয়ন্ত্রণ করতে আমরা একটা `flag` বা সংকেত ব্যবহার করি।

ব্যবহারিক ৯: গ.সা.গু (GCD) ও ল.সা.গু (LCM)

গ.সা.গু নির্ণয় (ইউক্লিডীয় পদ্ধতি):
দুটি সংখ্যার ভাগশেষ বের করে ভাজককে ভাজ্য এবং ভাগশেষকে ভাজক বানিয়ে লুপ চালানো।

কোড:

while(n2 != 0) {
  rem = n1 % n2;
  n1 = n2;
  n2 = rem;
}
printf("GCD = %d", n1);

ল.সা.গু (LCM):
সূত্র: $LCM = \frac{(OriginalNum1 \times OriginalNum2)}{GCD}$

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

ব্যবহারিক ১০: ফিবোনাচ্চি ধারা (Fibonacci)

ধারা: 0, 1, 1, 2, 3, 5, 8, 13...
বৈশিষ্ট্য: পরের পদ = আগের দুই পদের যোগফল।

লজিক (Swapping):

first = 0, second = 1;
printf("%d %d ", first, second);

for(i=3; i<=N; i++) {
  fibo = first + second;
  printf("%d ", fibo);
  first = second;
  second = fibo;
}

আজকের শেষ প্রোগ্রাম—ফিবোনাচ্চি সিরিজ। প্রকৃতিতে ফুলের পাপড়িতে বা শামুকের খোলসে এই ধারা দেখা যায়: ০, ১, ১, ২, ৩, ৫, ৮... খেয়াল করে দেখো, ১ যোগ ১ সমান ২, ১ যোগ ২ সমান ৩, ২ যোগ ৩ সমান ৫। অর্থাৎ পরের সংখ্যাটি হলো আগের দুটির যোগফল। কোডে এটা করতে হলে আমাদের 'সোয়াপিং' করতে হবে। নতুন সংখ্যা বের করার পর, 'দ্বিতীয়' সংখ্যাটি হয়ে যাবে 'প্রথম', আর 'নতুন' সংখ্যাটি হয়ে যাবে 'দ্বিতীয়'। এভাবে আমরা সামনের দিকে আগাব। এই লজিকটা একটু হাতে-কলমে ট্রেস করলে বা খাতায় লিখলে একদম ক্লিয়ার হয়ে যাবে।

প্রোগ্রামিংয়ে ভালো করার টিপস

কোড মুখস্থ না করে লজিক বুঝতে হবে।

  1. সমস্যা বিশ্লেষণ: কোড লেখার আগে সমস্যাটি ছোট ছোট ভাগে ভাগ করো।
  2. ফ্লোচার্ট: খাতায় লজিক বা ফ্লোচার্ট এঁকে নাও।
  3. ড্রাই রান (Dry Run): কোড কম্পিউটারে লেখার আগে খাতায় ইনপুট দিয়ে লজিক টেস্ট করো।
  4. ভেরিয়েবল নাম: a, b এর বদলে radius, area এমন অর্থপূর্ণ নাম ব্যবহার করো।
  5. সিনট্যাক্স: সেমিকোলন ; বা ব্র্যাকেট {} এর দিকে সতর্ক থাকো।

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

আজকের সারসংক্ষেপ

আজ আমরা শিখেছি:
১. গাণিতিক সমস্যার সমাধান (ক্ষেত্রফল, তাপমাত্রা)।
২. কন্ডিশনাল লজিক (লিপ ইয়ার, ম্যাক্স নম্বর)।
৩. লুপের ব্যবহার (ধারা, ফ্যাক্টরিয়াল, প্রাইম, ফিবোনাচ্চি)।

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

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

সি ভাষায় সমস্যা সমাধান: ব্যবহারিক প্রোগ্রাম ও লজিক বিশ্লেষণ

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

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

গাণিতিক সমস্যা সমাধান: ডেটা টাইপ ও সূত্রের সতর্কতা

সরল গাণিতিক সমস্যা (যেমন: ক্ষেত্রফল, গড়, তাপমাত্রা) সমাধানের ক্ষেত্রে ইনপুট এবং আউটপুট ভেরিয়েবলের সঠিক ডেটা টাইপ নির্বাচন করা সবচেয়ে গুরুত্বপূর্ণ। পূর্ণসংখ্যা (int) এবং ভগ্নাংশ (float/double) এর মিশ্র ব্যবহারে প্রায়ই লজিক্যাল এরর বা ভুল ফলাফল আসে। লেকচারে ত্রিভুজ ও বৃত্তের ক্ষেত্রফল দেখানো হয়েছে, এখানে আমরা হেরনের সূত্র (Heron's Formula) ব্যবহার করে বিষমবাহু ত্রিভুজের ক্ষেত্রফল এবং ইন্টিজার ডিভিশন সমস্যা নিয়ে আলোচনা করব।

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

সতর্কতা (Warning):
সি ভাষায় 5/9 লিখলে ফলাফল 0 আসে, কারণ ৫ এবং ৯ উভয়ই পূর্ণসংখ্যা। সঠিক ফলাফল পেতে 5.0/9.0 অথবা (float)5/9 লিখতে হবে। সেলসিয়াস থেকে ফারেনহাইট বা উল্টো রূপান্তরের সূত্র লেখার সময় এটি সবচেয়ে বেশি ভুল হয়।

বিষমবাহু ত্রিভুজের ক্ষেত্রফল নির্ণয়ের জন্য আমরা হেরনের সূত্র ব্যবহার করি। এই সূত্রটি ব্যবহার করার জন্য আমাদের <math.h> হেডার ফাইলটি প্রোগ্রামের শুরুতে যুক্ত করতে হয়, কারণ এতে sqrt() ফাংশনটি থাকে।

$$Area = \sqrt{s \times (s-a) \times (s-b) \times (s-c)}$$
যেখানে, $s = \frac{a+b+c}{2}$ (অর্ধ-পরিসীমা) এবং $a, b, c$ হলো ত্রিভুজের তিন বাহুর দৈর্ঘ্য।
দ্রষ্টব্য: এই সূত্র ব্যবহারের জন্য #include <math.h> অবশ্যই ব্যবহার করতে হবে।

কন্ডিশনাল লজিক: সিদ্ধান্ত গ্রহণের কৌশল

প্রোগ্রামিংয়ে সিদ্ধান্ত নেওয়ার জন্য if-else এবং লজিক্যাল অপারেটর (&&, ||) ব্যবহৃত হয়। পরীক্ষার জন্য লিপ ইয়ার (Leap Year) এবং তিনটি সংখ্যার মধ্যে বড় সংখ্যা নির্ণয়ের লজিকটি খুবই গুরুত্বপূর্ণ। আমরা প্রায়ই লিপ ইয়ারের শর্তগুলো গুলিয়ে ফেলি। নিচের ফ্লোচার্টটি লক্ষ্য করলে লজিকটি পরিষ্কার হবে।

লিপ ইয়ার নির্ণয়ের ফ্লোচার্ট

লিপ ইয়ার নির্ণয়ের জন্য দুটি পৃথক শর্তের যেকোনো একটি সত্য হলেই বছরটি লিপ ইয়ার হবে।

লিপ ইয়ার নির্ণয়ের শর্ত (Leap Year Logic):
১. সালটি ৪০০ দ্বারা বিভাজ্য হতে হবে। (যেমন: ২০০০, ২৪০০)

অথবা,

২. সালটি ৪ দ্বারা বিভাজ্য হবে কিন্তু ১০০ দ্বারা বিভাজ্য হবে না। (যেমন: ২০২০, ২০২৪)

তিনটি সংখ্যার মধ্যে বড় সংখ্যা নির্ণয়ের জন্য নেস্টেড if-else ব্যবহার করা যায়, তবে লজিক্যাল অপারেটর ব্যবহার করলে কোড অনেক ছোট ও সহজ হয়।

উদাহরণ (Example): লজিক্যাল অপারেটর দিয়ে বড় সংখ্যা নির্ণয়
ধরি, তিনটি সংখ্যা a, b এবং c।
- যদি (a > b && a > c) সত্য হয়, তবে a বড়।
- না হলে, যদি (b > a && b > c) সত্য হয়, তবে b বড়।
- অন্যথায়, c বড়।
এই পদ্ধতিটি নেস্টেড if-এর চেয়ে সহজ এবং পরীক্ষায় লিখতে কম সময় লাগে।

লুপ কন্ট্রোল: পুনরাবৃত্তিমূলক কাজ ও ধারার যোগফল

লুপ ব্যবহার করে ধারা (Series) এবং ফ্যাক্টরিয়াল নির্ণয়ের ক্ষেত্রে 'ইনিশিয়ালাইজেশন' এবং 'আপডেট' অংশটি খুব গুরুত্বপূর্ণ। ১ থেকে N পর্যন্ত যোগফল এবং ১ থেকে N পর্যন্ত গুণফল (ফ্যাক্টরিয়াল) বের করার লজিকে মূল পার্থক্য হলো ইনিশিয়াল ভ্যালুতে। যোগের সময় sum=0 ধরা হয়, কিন্তু গুণের সময় fact=1 ধরতে হয় (কারণ ০ দিয়ে গুণ করলে সব ০ হয়ে যাবে)।

একটি লুপ কীভাবে কাজ করে তা বোঝার জন্য 'ড্রাই রান' (Dry Run) বা ট্রেস টেবিল তৈরি করা সবচেয়ে ভালো উপায়। নিচে ৪-এর ফ্যাক্টরিয়াল নির্ণয়ের একটি ড্রাই রান দেখানো হলো:

ফ্যাক্টরিয়াল লুপের ড্রাই রান টেবিল

গুরুত্বপূর্ণ (Important): লুপের ৩টি প্রধান অংশ
১. Initialization (শুরুর মান): লুপ কোথা থেকে শুরু হবে (যেমন: i=1)।
২. Condition (চলমান থাকার শর্ত): লুপ কতক্ষণ চলবে (যেমন: i<=N)।
৩. Increment/Decrement (মান পরিবর্তন): প্রতি ধাপে মান কীভাবে বাড়বে বা কমবে (যেমন: i++ বা i=i+2)।
এর যেকোনো একটি ভুল হলে 'ইনফিনিট লুপ' (Infinite Loop) তৈরি হতে পারে।

পরীক্ষায় প্রায়ই বিভিন্ন ধারার যোগফল নির্ণয় করতে বলা হয়। ধারাটির প্যাটার্ন বুঝে লুপের update অংশটি লিখতে হয়।

পরীক্ষার টিপস (Exam Tip):
- যদি ধারাটি বর্গের হয় (যেমন: $1^2 + 2^2 + ...$), তবে যোগ করার লাইনটি হবে: sum = sum + (i*i);
- যদি ধারাটি ভগ্নাংশের হয় (যেমন: $1 + \frac{1}{2} + \frac{1}{3} ...$), তবে ভেরিয়েবল অবশ্যই float বা double নিতে হবে এবং যোগ করার সময় টাইপ কাস্টিং করতে হবে: sum = sum + 1.0/i;

জটিল লজিক: প্রাইম নম্বর, গসাগু ও ফিবোনাচ্চি

এই অংশটি উচ্চতর দক্ষতার (Higher Ability) প্রশ্নের জন্য। মৌলিক সংখ্যা বা প্রাইম নম্বর নির্ণয়ে break স্টেটমেন্টের ব্যবহার, গসাগু নির্ণয়ে ইউক্লিডীয় অ্যালগরিদম, এবং ফিবোনাচ্চি ধারায় ভেরিয়েবল সোয়াপিং (Swapping) লজিক বিস্তারিত বোঝা প্রয়োজন।

ফিবোনাচ্চি ধারা (Fibonacci Series):
ফিবোনাচ্চি হলো এমন একটি ধারা যেখানে প্রথম দুটি পদ যথাক্রমে ০ এবং ১, এবং পরবর্তী প্রতিটি পদ তার পূর্ববর্তী দুটি পদের যোগফলের সমান। অর্থাৎ, ০, ১, ১, ২, ৩, ৫, ৮, ১৩...

ফিবোনাচ্চি সূত্র (Formula):
$$F_{n} = F_{n-1} + F_{n-2}$$
প্রোগ্রামে আমরা সাধারণত তিনটি ভেরিয়েবল ব্যবহার করি: first=0, second=1, এবং fibo। লুপের ভেতরে প্রতিবার fibo = first + second করার পর মানগুলো বদল (swap) করতে হয়:
first = second; এবং second = fibo;

মৌলিক সংখ্যা (Prime Number):
যে সংখ্যা ১ এবং ওই সংখ্যা ছাড়া অন্য কোনো সংখ্যা দিয়ে বিভাজ্য নয়, তাকে মৌলিক সংখ্যা বলে। লুপের মধ্যে break স্টেটমেন্ট ব্যবহার করে এটি সহজেই নির্ণয় করা যায়।

উদাহরণ (Example): প্রাইম নম্বর লজিক
১. একটি ফ্ল্যাগ ভেরিয়েবল নিই, ধরলাম isPrime = 1 (সত্য)।
২. ২ থেকে (N-1) পর্যন্ত লুপ চালাই।
৩. যদি N কোনো সংখ্যা দিয়ে নিঃশেষে বিভাজ্য হয় (N % i == 0), তবে বুঝবো এটি মৌলিক নয়। তখন isPrime = 0 করে লুপ থেকে break দিয়ে বের হয়ে আসবো।
৪. লুপ শেষে যদি isPrime == 1 থাকে, তবে সংখ্যাটি মৌলিক।

সারাংশ ও রিভিশন চেকলিস্ট

পরীক্ষার হলে কোড লেখার সময় ছোটখাটো ভুলের কারণে পুরো প্রোগ্রাম কাজ নাও করতে পারে। নিচের চেকলিস্টটি মনে রাখলে ভুল হওয়ার সম্ভাবনা কমে যাবে।

সংক্ষিপ্ত সারাংশ (Quick Revision Checklist):
- প্রতিটি স্টেটমেন্টের শেষে সেমিকোলন (;) দিয়েছেন তো? (Condition বা Loop-এর লাইনে সেমিকোলন হয় না)।
- scanf ফাংশনে ভেরিয়েবলের আগে & চিহ্ন দিয়েছেন?
- main() ফাংশন কি সেকেন্ড ব্র্যাকেট { } দিয়ে ঠিকমতো শুরু ও শেষ হয়েছে?
- ভাগ করার সময় (যেমন গড় বা তাপমাত্রা নির্ণয়ে) float কাস্টিং বা দশমিক ব্যবহার করেছেন? (যেমন: 5.0/9.0)
- লুপের কন্ডিশন ঠিক আছে কি না (যেমন < বনাম <=) চেক করুন। ১ কম বা বেশি প্রিন্ট হচ্ছে কি না খেয়াল করুন।

পরিভাষা (Glossary)

পরিভাষা (Term) সংজ্ঞা (Definition)
Syntax Error প্রোগ্রামিং ভাষার ব্যাকরণগত ভুল, যেমন সেমিকোলন না দেওয়া বা বানান ভুল করা। এটি থাকলে প্রোগ্রাম রান করে না।
Logical Error ভুল লজিক বা সূত্রের ব্যবহার, যার ফলে প্রোগ্রাম রান করে কিন্তু ভুল উত্তর দেয়। যেমন: যোগের বদলে গুণ চিহ্ন দেওয়া।
Accumulator লুপের মধ্যে যোগফল বা গুণফল জমা রাখার জন্য ব্যবহৃত ভেরিয়েবল (যেমন: sum বা fact)।
Infinite Loop যে লুপের শর্ত কখনোই মিথ্যা হয় না এবং লুপটি আজীবন চলতে থাকে। এটি একটি লজিক্যাল এরর।
Type Casting এক ডেটা টাইপকে জোরপূর্বক অন্য ডেটা টাইপে রূপান্তর করা। যেমন: (float)a

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

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

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

একটি আবহাওয়া স্টেশনে তাপমাত্রার ডেটা প্রসেসিংয়ের জন্য একটি সফটওয়্যার তৈরির কাজ চলছে। সেখানে সেলসিয়াস তাপমাত্রাকে ফারেনহাইটে এবং ফারেনহাইটকে সেলসিয়াসে রূপান্তর করার প্রয়োজন হয়। কর্তৃপক্ষ এমন একটি সি প্রোগ্রাম চায় যেখানে ব্যবহারকারী একটি মেনু থেকে বাটন বা অপশন নির্বাচন করলে (যেমন ১ চাপলে C to F, ২ চাপলে F to C) নির্দিষ্ট রূপান্তরটি সম্পন্ন হবে।

ক) অ্যালগরিদম কী?
খ) সি ভাষায় break স্টেটমেন্ট কেন ব্যবহার করা হয়?
গ) উদ্দীপকের সমস্যাটি সমাধানের জন্য একটি ফ্লোচার্ট অঙ্কন কর।
ঘ) সি ভাষায় switch-case ব্যবহার করে উদ্দীপকের বর্ণনা অনুযায়ী একটি মেনু ভিত্তিক প্রোগ্রাম তৈরি কর।

উত্তর

(ক) কোনো নির্দিষ্ট সমস্যা সমাধানের জন্য ধাপে ধাপে যে যুক্তিনির্ভর নির্দেশনা বা পরিকল্পনা তৈরি করা হয়, তাকে অ্যালগরিদম বলে।

(খ) সি প্রোগ্রামে break স্টেটমেন্ট সাধারণত লুপ বা switch-case স্ট্রাকচার থেকে তাৎক্ষণিকভাবে বের হয়ে আসার জন্য ব্যবহার করা হয়। switch-case এ কোনো নির্দিষ্ট case সত্য হলে সেই কোড ব্লকটি রান করার পর পরবর্তী case গুলোতে যেন প্রোগ্রাম না যায়, তা নিশ্চিত করতে break ব্যবহার করা জরুরি।

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

  1. Start
  2. Input choice (1 or 2)
  3. If choice == 1:
    • Input Celsius (C)
    • Calculate F = (C * 9/5) + 32
    • Print F
  4. Else If choice == 2:
    • Input Fahrenheit (F)
    • Calculate C = (F - 32) * 5/9
    • Print C
  5. Else:
    • Print "Invalid Choice"
  6. End

(দ্রষ্টব্য: পরীক্ষার খাতায় এটি প্রচলিত ফ্লোচার্ট প্রতীকের সাহায্যে আঁকতে হবে। যেমন: Start/End এর জন্য ওভাল, Input/Output এর জন্য সামান্তরিক, Processing এর জন্য আয়তক্ষেত্র এবং Condition এর জন্য রম্বস আকৃতি।)

(ঘ) উদ্দীপকের বর্ণনা অনুযায়ী switch-case ব্যবহার করে সি প্রোগ্রামটি নিচে দেওয়া হলো:

#include <stdio.h>

int main() {
    int choice;
    float temp, convertedTemp;

    printf("Temperature Conversion Menu:\n");
    printf("1. Celsius to Fahrenheit\n");
    printf("2. Fahrenheit to Celsius\n");
    printf("Enter your choice (1 or 2): ");
    scanf("%d", &choice);

    switch(choice) {
        case 1:
            printf("Enter temperature in Celsius: ");
            scanf("%f", &temp);
            convertedTemp = (temp * 9 / 5) + 32;
            printf("Temperature in Fahrenheit: %.2f\n", convertedTemp);
            break;
        case 2:
            printf("Enter temperature in Fahrenheit: ");
            scanf("%f", &temp);
            convertedTemp = (temp - 32) * 5 / 9;
            printf("Temperature in Celsius: %.2f\n", convertedTemp);
            break;
        default:
            printf("Invalid choice! Please run the program again.\n");
    }

    return 0;
}

এই প্রোগ্রামে switch স্টেটমেন্ট ব্যবহারকারীর ইনপুট (1 বা 2) যাচাই করে নির্দিষ্ট case ব্লকটি চালায় এবং ফলাফল প্রদর্শন করে।


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

আইসিটি ক্লাসে শিক্ষক শিক্ষার্থীদের দুটি প্রোগ্রামিং সমস্যা সমাধান করতে দিলেন।
১ম সমস্যা: ১ + ৪ + ৭ + ... + N ধারাটির যোগফল নির্ণয় করা।
২য় সমস্যা: দুটি পূর্ণসংখ্যার গসাগু (GCD) নির্ণয় করা।
শিক্ষক বললেন, "দ্বিতীয় সমস্যাটি সমাধানের জন্য ইউক্লিডীয় পদ্ধতি এবং while লুপ ব্যবহার করা সুবিধাজনক।"

ক) লুপ কন্ট্রোল ভেরিয়েবল কী?
খ) do-while লুপকে কেন 'এক্সিট কন্ট্রোল লুপ' বলা হয়?
গ) শিক্ষকের দেওয়া ১ম সমস্যাটির (ধারার যোগফল) জন্য একটি সি প্রোগ্রাম লিখ।
ঘ) উদ্দীপকের ২য় সমস্যাটির (গসাগু) জন্য প্রোগ্রাম লিখ এবং গসাগু নির্ণয়ে while লুপের কার্যকারিতা বিশ্লেষণ কর।

উত্তর

(ক) লুপ কন্ট্রোল ভেরিয়েবল হলো এমন একটি চলক বা variable যা লুপের শুরুতে ইনিশশিয়ালাইজ করা হয়, লুপের শর্ত বা condition যাচাইয়ে ব্যবহৃত হয় এবং প্রতিবার লুপের শেষে যার মান পরিবর্তন (increment/decrement) হয়।

(খ) do-while লুপে শর্ত বা condition লুপের বডি বা ভেতরের স্টেটমেন্টগুলো একবার এক্সিকিউট হওয়ার পরে যাচাই করা হয়। অর্থাৎ শর্ত মিথ্যা হলেও লুপটি অন্তত একবার চলে। যেহেতু লুপ থেকে বের হওয়ার সময় (exit point-এ) কন্ডিশন চেক হয়, তাই একে 'এক্সিট কন্ট্রোল লুপ' বলা হয়।

(গ) ১ + ৪ + ৭ + ... + N ধারাটির যোগফল নির্ণয়ের সি প্রোগ্রাম:

#include <stdio.h>

int main() {
    int N, sum = 0, i;

    printf("Enter the value of N: ");
    scanf("%d", &N);

    // ধারাটি ১ থেকে শুরু এবং ব্যবধান ৩ (৪-১=৩, ৭-৪=৩)
    for(i = 1; i <= N; i = i + 3) {
        sum = sum + i;
    }

    printf("Sum of the series is: %d\n", sum);

    return 0;
}

(ঘ) দুটি সংখ্যার গসাগু (GCD) নির্ণয়ের জন্য সি প্রোগ্রাম (ইউক্লিডীয় পদ্ধতি ও while লুপ ব্যবহার করে):

#include <stdio.h>

int main() {
    int num1, num2, rem;

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

    while (num2 != 0) {
        rem = num1 % num2;
        num1 = num2;
        num2 = rem;
    }

    printf("GCD is: %d\n", num1);
    return 0;
}

বিশ্লেষণ:
গসাগু নির্ণয়ের ক্ষেত্রে আমাদের বারবার ভাগশেষ বের করতে হয় এবং ভাজক ও ভাজ্যকে পরিবর্তন করতে হয় যতক্ষণ না ভাগশেষ ০ (শূন্য) হয়। এখানে while লুপ অত্যন্ত কার্যকরী কারণ:
১. আমরা আগে থেকে জানি না কতবার লুপটি চলবে (ইটারেশন সংখ্যা অনির্দিষ্ট)।
২. while(num2 != 0) শর্তটি সরাসরি ইউক্লিডীয় অ্যালগরিদমের "ভাগশেষ শূন্য না হওয়া পর্যন্ত চালিয়ে যাও" লজিকটিকে বাস্তবায়ন করে।
৩. for লুপের চেয়ে এখানে while লুপের সিনট্যাক্স ও লজিক বেশি পরিষ্কার ও সহজবোধ্য।


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

রফিক তার কলেজের বার্ষিক ক্রীড়া প্রতিযোগিতার জন্য একটি প্রোগ্রাম তৈরি করতে চায়। সে এমন একটি প্রোগ্রাম লিখল যা একটি পূর্ণসংখ্যা ইনপুট নেয় এবং সংখ্যাটি 'মৌলিক' (Prime) কি না তা যাচাই করে। তার বন্ধু তাকে বলল, "তোর প্রোগ্রামটি সঠিক, কিন্তু বড় সংখ্যার জন্য এটি ধীরগতির হতে পারে। লুপটি N পর্যন্ত না চালিয়ে N/2 বা sqrt(N) পর্যন্ত চালালেই হয়।"

ক) নেস্টেড লুপ (Nested Loop) কী?
খ) continue এবং break এর মধ্যে পার্থক্য ব্যাখ্যা কর।
গ) রফিকের সমস্যাটির (মৌলিক সংখ্যা যাচাই) জন্য একটি সাধারণ সি প্রোগ্রাম লিখ (যেখানে লুপ N পর্যন্ত চলবে)।
ঘ) রফিকের বন্ধুর পরামর্শ অনুযায়ী প্রোগ্রামটির লজিক কীভাবে পরিবর্তন হবে? পরিবর্তিত লজিকটি কি অধিকতর দক্ষ? বিশ্লেষণ কর।

উত্তর

(ক) একটি লুপের ভেতরে যখন অন্য একটি লুপ ব্যবহার করা হয়, তখন তাকে নেস্টেড লুপ (Nested Loop) বলে। যেমন একটি for লুপের ভেতরে আরেকটি for লুপ।

(খ) break স্টেটমেন্ট লুপ বা কন্ডিশনাল ব্লক থেকে পুরোপুরি বেরিয়ে আসে এবং লুপের কার্যক্রম বন্ধ করে দেয়। অন্যদিকে, continue স্টেটমেন্ট লুপের বর্তমান ইটারেশনের বাকি অংশ স্কিপ করে এবং লুপের পরবর্তী ইটারেশন বা ধাপে চলে যায়।

(গ) মৌলিক সংখ্যা যাচাইয়ের সাধারণ সি প্রোগ্রাম (লুপ ২ থেকে N-1 পর্যন্ত):

#include <stdio.h>

int main() {
    int n, i, count = 0;
    printf("Enter a number: ");
    scanf("%d", &n);

    if (n <= 1) {
        printf("%d is not a prime number.\n", n);
        return 0;
    }

    for (i = 2; i < n; i++) {
        if (n % i == 0) {
            count++;
            break;
        }
    }

    if (count == 0)
        printf("%d is a prime number.\n", n);
    else
        printf("%d is not a prime number.\n", n);

    return 0;
}

(ঘ) রফিকের বন্ধুর পরামর্শ অনুযায়ী, কোনো সংখ্যা n যদি মৌলিক না হয়, তবে অবশ্যই ২ থেকে n/2 (বা গাণিতিকভাবে আরও নিখুঁত হলো sqrt(n)) এর মধ্যে তার অন্তত একটি উৎপাদক বা গুণনীয়ক থাকবে। তাই লুপটি n-1 পর্যন্ত চালানোর প্রয়োজন নেই।

পরিবর্তিত লজিক:

// লুপের শর্ত পরিবর্তন
for (i = 2; i <= n / 2; i++) { 
    if (n % i == 0) {
        count++;
        break; 
    }
}

বিশ্লেষণ:
হ্যাঁ, পরিবর্তিত লজিকটি অধিকতর দক্ষ।
১. সময় সাশ্রয়: যদি n একটি বড় সংখ্যা হয় (যেমন ১০০), সাধারণ লজিক ৯৮ বার লুপ চালাতে পারে। কিন্তু n/2 লজিক মাত্র ৪৯ বার এবং sqrt(n) লজিক মাত্র ৯ বার লুপ চালাবে।
২. Efficiency: অ্যালগরিদমের কমপ্লেক্সিটি O(n) থেকে কমে O(n/2) বা O(sqrt(n)) এ নেমে আসে, যা বড় ডেটার ক্ষেত্রে প্রোগ্রামের গতি বাড়ায়।
সুতরাং, বড় সংখ্যার মৌলিকত্ব যাচাইয়ের ক্ষেত্রে রফিকের বন্ধুর পরামর্শ বা অপটিমাইজড লজিকটি অনেক বেশি কার্যকর।

এমসিকিউ

১. সি ভাষায় int ডেটা টাইপ মেমোরিতে কত বাইট জায়গা দখল করে? (সাধারণত)

ক) ১ বাইট
খ) ২ বাইট
গ) ৪ বাইট
ঘ) ৮ বাইট

সঠিক উত্তর: খ) ২ বাইট
ব্যাখ্যা: ১৬-বিট কম্পাইলারে int সাধারণত ২ বাইট জায়গা নেয়। তবে আধুনিক ৩২-বিট বা ৬৪-বিট কম্পাইলারে এটি ৪ বাইটও হতে পারে। এইচএসসি সিলেবাস বা পুরোনো বই অনুযায়ী অনেক ক্ষেত্রে ২ বাইট ধরা হয়, তবে ৪ বাইটও সঠিক উত্তর হতে পারে প্রেক্ষাপট ভেদে। (স্ট্যান্ডার্ড হিসেবে ২ বাইট অনেক বইতে উল্লেখ থাকে)।


২. সি প্রোগ্রামে stdio.h হেডার ফাইলটি কেন ব্যবহার করা হয়?

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

সঠিক উত্তর: খ) ইনপুট ও আউটপুট ফাংশনের জন্য
ব্যাখ্যা: printf() এবং scanf() এর মতো স্ট্যান্ডার্ড ইনপুট-আউটপুট ফাংশনগুলো stdio.h (Standard Input Output) হেডার ফাইলের অন্তর্ভুক্ত।


৩. % অপারেটরটি নিচের কোন কাজে ব্যবহৃত হয়?

ক) ভাগফল নির্ণয়ে
খ) গুণফল নির্ণয়ে
গ) ভাগশেষ নির্ণয়ে
ঘ) শতকরা হার নির্ণয়ে

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


৪. নিচের কোনটি সি ভাষার সঠিক ভেরিয়েবল নাম?

ক) 1st_number
খ) total sum
গ) _value
ঘ) int

সঠিক উত্তর: গ) _value
ব্যাখ্যা: ভেরিয়েবল নাম ডিজিট দিয়ে শুরু হতে পারে না (ক বাদ), মাঝে স্পেস থাকতে পারে না (খ বাদ), এবং কোনো কিওয়ার্ড (যেমন int) হতে পারে না (ঘ বাদ)। তবে আন্ডারস্কোর (_) দিয়ে শুরু হওয়া বৈধ।


৫. for(i=0; i<5; i++) লুপটি কতবার চলবে?

ক) ৪ বার
খ) ৫ বার
গ) ৬ বার
ঘ) অসংখ্যবার

সঠিক উত্তর: খ) ৫ বার
ব্যাখ্যা: লুপটি ০ থেকে শুরু হয়ে ৪ পর্যন্ত চলবে (০, ১, ২, ৩, ৪)। মোট ৫টি ইটারেশন হবে। ৫ এর সমান হলে শর্ত মিথ্যা হবে।


৬. ফ্লোচার্টে সিদ্ধান্ত বা কন্ডিশন (Decision) বোঝাতে কোন প্রতীক ব্যবহৃত হয়?

ক) ওভাল (Oval)
খ) আয়তক্ষেত্র (Rectangle)
গ) রম্বস (Diamond)
ঘ) সামান্তরিক (Parallelogram)

সঠিক উত্তর: গ) রম্বস (Diamond)
ব্যাখ্যা: ফ্লোচার্টে সিদ্ধান্ত গ্রহণ বা শর্ত যাচাইয়ের (Yes/No path) জন্য রম্বস বা ডায়মন্ড আকৃতি ব্যবহার করা হয়।


৭. break স্টেটমেন্টটি নিচের কোনটির ক্ষেত্রে কাজ করে না?

ক) for লুপ
খ) while লুপ
গ) switch স্টেটমেন্ট
ঘ) if-else ব্লক (লুপের বাইরে)

সঠিক উত্তর: ঘ) if-else ব্লক (লুপের বাইরে)
ব্যাখ্যা: break শুধুমাত্র লুপ (for, while, do-while) এবং switch স্টেটমেন্ট থেকে বের হওয়ার জন্য ব্যবহৃত হয়। সাধারণ if-else ব্লকের ভেতরে break কাজ করে না যদি না সেটি কোনো লুপের ভেতরে থাকে।


৮. নিচের উদ্দীপকটি পড় এবং প্রশ্নের উত্তর দাও:
int a = 10;
printf("%d", a++);

আউটপুট কত হবে?

ক) 10
খ) 11
গ) 12
ঘ) Error

সঠিক উত্তর: ক) 10
ব্যাখ্যা: a++ হলো পোস্ট-ইনক্রিমেন্ট। এটি প্রথমে a এর বর্তমান মান (১০) প্রিন্ট করবে এবং পরে মেমোরিতে মান বাড়িয়ে ১১ করবে। তাই আউটপুট ১০ হবে।


৯. while লুপ এবং do-while লুপের মূল পার্থক্য কী?

ক) while লুপ দ্রুত কাজ করে
খ) do-while লুপে কন্ডিশন শেষে চেক করা হয়
গ) while লুপে break লাগে না
ঘ) কোনো পার্থক্য নেই

সঠিক উত্তর: খ) do-while লুপে কন্ডিশন শেষে চেক করা হয়
ব্যাখ্যা: while লুপে শুরুতে কন্ডিশন চেক হয় (Entry Control), আর do-while লুপে বডি এক্সিকিউট হওয়ার পর শেষে কন্ডিশন চেক হয় (Exit Control)। ফলে do-while অন্তত একবার চলবেই।


১০. একটি অ্যারে int marks[5]; ঘোষণা করলে মেমোরিতে এটি কয়টি ভেরিয়েবল তৈরি করে?

ক) ১টি
খ) ৪টি
গ) ৫টি
ঘ) ৬টি

সঠিক উত্তর: গ) ৫টি
ব্যাখ্যা: marks[5] মানে হলো এটি ৫টি পূর্ণসংখ্যা ধারণ করতে সক্ষম। এর ইনডেক্স ০ থেকে ৪ পর্যন্ত।


১১. সি ভাষায় রিলেশনাল অপারেটর হলো—
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 ও iii
ব্যাখ্যা: ফাংশন কোড রি-ইউজেবিলিটি বাড়ায়, ফলে কোড ছোট হয়, বারবার লিখতে হয় না এবং মডিউলার হওয়ায় ভুল খুঁজে বের করা (ডিবাগিং) সহজ হয়।


১৩. switch স্টেটমেন্টে ব্যবহার করা যায়—
i. int টাইপ
ii. char টাইপ
iii. float টাইপ

নিচের কোনটি সঠিক?

ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: ক) i ও ii
ব্যাখ্যা: switch স্টেটমেন্টে শুধুমাত্র পূর্ণসংখ্যা (int) এবং ক্যারেক্টার (char) কনস্ট্যান্ট ব্যবহার করা যায়। ভগ্নাংশ বা float/double ব্যবহার করা যায় না।


১৪. নিচের লুপটি লক্ষ্য কর:

for ( ; ; ) {
   printf("Hello");
}

এটি কেমন লুপ?

ক) এটি চলবেই না
খ) ১ বার চলবে
গ) অসীম (Infinite) লুপ
ঘ) সিনট্যাক্স এরর

সঠিক উত্তর: গ) অসীম (Infinite) লুপ
ব্যাখ্যা: for লুপের কন্ডিশন অংশটি ফাঁকা থাকলে সি কম্পাইলার সেটিকে সবসময় 'সত্য' (True) বলে ধরে নেয়। ফলে লুপটি অসীম সময় ধরে চলতে থাকে।


১৫. অনুবাদক প্রোগ্রাম (Translator Program) হলো—
i. কম্পাইলার
ii. ইন্টারপ্রেটার
iii. অ্যাসেম্বলার

নিচের কোনটি সঠিক?

ক) i ও ii
খ) i ও iii
গ) ii ও iii
ঘ) i, ii ও iii

সঠিক উত্তর: ঘ) i, ii ও iii
ব্যাখ্যা: উৎস প্রোগ্রামকে যান্ত্রিক ভাষায় রূপান্তর করার জন্য কম্পাইলার, ইন্টারপ্রেটার এবং অ্যাসেম্বলার—তিনটিই অনুবাদক প্রোগ্রাম হিসেবে ব্যবহৃত হয়।


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

int x = 5;
if (x > 5)
    printf("A");
else
    printf("B");

১৬. উদ্দীপকের কোডটির আউটপুট কী হবে?

ক) A
খ) B
গ) AB
ঘ) কিছুই প্রিন্ট হবে না

সঠিক উত্তর: খ) B
ব্যাখ্যা: এখানে x এর মান ৫। শর্ত দেওয়া হয়েছে x > 5 (৫ কি ৫ এর চেয়ে বড়?), যা মিথ্যা। তাই else ব্লকটি কাজ করবে এবং "B" প্রিন্ট হবে।

১৭. শর্তটি if (x >= 5) হলে আউটপুট কী হতো?

ক) A
খ) B
গ) AB
ঘ) Error

সঠিক উত্তর: ক) A
ব্যাখ্যা: যদি শর্ত x >= 5 হতো, তবে ৫ >= ৫ সত্য হতো। তখন if ব্লকটি কাজ করত এবং "A" প্রিন্ট হতো।


নিচের উদ্দীপকটি পড় এবং ১৮ ও ১৯ নং প্রশ্নের উত্তর দাও:
শিক্ষক ক্লাসে বললেন, "এমন একটি সংখ্যা নির্ণয় করতে হবে যা ১ এবং ওই সংখ্যা ছাড়া অন্য কিছু দিয়ে বিভাজ্য নয়।"

১৮. শিক্ষকের ইঙ্গিত করা সংখ্যাটি কী ধরনের সংখ্যা?

ক) জোড় সংখ্যা
খ) বিজোড় সংখ্যা
গ) মৌলিক সংখ্যা (Prime)
ঘ) ফিবোনাচ্চি সংখ্যা

সঠিক উত্তর: গ) মৌলিক সংখ্যা (Prime)
ব্যাখ্যা: ১ এবং ওই সংখ্যাটি ছাড়া অন্য কোনো গুণনীয়ক না থাকলে তাকে মৌলিক সংখ্যা বা Prime Number বলে।

১৯. এই ধরনের সংখ্যা নির্ণয়ের লজিক কোনটি?

ক) সংখ্যাটিকে ২ দিয়ে ভাগ করা
খ) ২ থেকে (সংখ্যা-১) পর্যন্ত লুপ চালিয়ে ভাগশেষ ০ কিনা দেখা
গ) সংখ্যাটিকে নিজের সাথে গুণ করা
ঘ) সংখ্যার ফ্যাক্টরিয়াল বের করা

সঠিক উত্তর: খ) ২ থেকে (সংখ্যা-১) পর্যন্ত লুপ চালিয়ে ভাগশেষ ০ কিনা দেখা
ব্যাখ্যা: মৌলিক সংখ্যা যাচাইয়ের জন্য ২ থেকে শুরু করে ওই সংখ্যার আগ পর্যন্ত সংখ্যাগুলো দিয়ে ভাগ করে দেখতে হয়। যদি কোনোটা দিয়ে ভাগশেষ ০ হয়, তবে তা মৌলিক নয়।


২০. ৫! (ফ্যাক্টরিয়াল) এর মান কত?

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

সঠিক উত্তর: গ) ১২০
ব্যাখ্যা: ৫! = ৫ × ৪ × ৩ × ২ × ১ = ১২০।


২১. ফিবোনাচ্চি সিরিজের (০, ১, ১, ২, ৩, ৫...) পরবর্তী পদটি কত?

ক) ৬
খ) ৭
গ) ৮
ঘ) ১০

সঠিক উত্তর: গ) ৮
ব্যাখ্যা: ফিবোনাচ্চি সিরিজে পরবর্তী পদটি আগের দুটি পদের যোগফল। এখানে শেষ দুটি পদ ৩ এবং ৫। সুতরাং পরবর্তী পদ = ৩ + ৫ = ৮।


২২. x = 5 + 2 * 3 এক্সপ্রেশনটিতে x এর মান কত হবে?

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

সঠিক উত্তর: খ) ১১
ব্যাখ্যা: অপারেটর প্রিসিডেন্স বা অগ্রাধিকার নিয়ম অনুযায়ী গুণের (*) কাজ যোগের (+) আগে হয়। তাই ২ * ৩ = ৬, তারপর ৫ + ৬ = ১১।


২৩. স্ট্রাকচার্ড প্রোগ্রামিং ল্যাঙ্গুয়েজ কোনটি?

ক) C
খ) Java
গ) C++
ঘ) Assembly

সঠিক উত্তর: ক) C
ব্যাখ্যা: সি ভাষাকে স্ট্রাকচার্ড বা প্রসিডিউরাল প্রোগ্রামিং ল্যাঙ্গুয়েজ বলা হয় কারণ এটি প্রোগ্রামকে ছোট ছোট ফাংশন বা ব্লকে ভাগ করে সমাধান করে।


২৪. && অপারেটরটি কখন সত্য (True) রিটার্ন করে?

ক) যখন উভয় শর্ত মিথ্যা
খ) যখন যেকোনো একটি শর্ত সত্য
গ) যখন উভয় শর্ত সত্য
ঘ) যখন প্রথমটি সত্য, দ্বিতীয়টি মিথ্যা

সঠিক উত্তর: গ) যখন উভয় শর্ত সত্য
ব্যাখ্যা: && (লজিক্যাল AND) অপারেটর তখনই ১ বা True রিটার্ন করে যখন এর বাম ও ডান—উভয় পাশের শর্তই সত্য হয়।


২৫. প্রোগ্রামে ভুল বা ত্রুটি (Bug) খুঁজে বের করে সংশোধন করার প্রক্রিয়াকে কী বলে?

ক) কোডিং
খ) এনকোডিং
গ) ডিবাগিং
ঘ) ডিকোডিং

সঠিক উত্তর: গ) ডিবাগিং
ব্যাখ্যা: প্রোগ্রামের ভুল (Bug) শনাক্ত করা এবং তা সমাধান করার প্রক্রিয়াকে ডিবাগিং (Debugging) বলা হয়।