একটুখানি গণিত

একটুখানি গণিত
এই অধ্যায়ে আমরা প্রোগ্রামিংয়ের নতুন কিছু শিখব না। এখন পর্যন্ত আমরা যতটুকু প্রোগ্রামিং শিখেছি, তা দিয়েই কিছু সহজ-সরল গাণিতিক সমস্যার সমাধান করব।
১) x + y = 15, x – y = 5 হলে x ও y-এর মান কত?
সমীকরণদুটি যোগ করলে পাই 2x = 20, বা x = 10। আবার বিয়োগ করলে পাই, 2y = 10, বা y = 5। এখন একটি প্রোগ্রাম লিখতে হবে যেখানে x + y ও x – y-এর মান দেওয়া থাকবে, x ও y-এর মান বের করতে হবে। আমি প্রোগ্রামটি একটু পরে লিখে দেব। এর মধ্যে তুমি নিজে লিখার চেষ্টা করো। সহজ প্রোগ্রাম।
২) 4x + 5y = 14, 5x + 6y = 17 হলে x ও y-এর মান কত?
সমীকরণদুটিকে আমরা এভাবে লিখতে পারি: a1x + b1y = c1, a2x + b2y = c2। তোমরা বিভিন্নভাবে এর সমাধান করতে পার। এর মধ্যে দুটি জনপ্রিয় উপায় হচ্ছে প্রতিস্থাপন (substitution) ও নির্ণায়কের (determinant) সাহায্যে সমাধান। পদ্ধতিগুলো জানা না থাকলে ক্লাস এইট বা নাইনের গণিত বই দেখো। সমাধান করলে দেখবে, x = (b2c1 – b1c2) / (a1b2 – a2b1) এবং y = (a1c2 – a2c1) / (a1b2 – a2b1)। এখন a1, a2, b1, b2, c1, c2-এর জায়গায় নির্দিষ্ট মান বসিয়ে দিলেই x ও y-এর মান পেয়ে যাবে।
এই ধরনের সমীকরণ সমাধানের জন্যও আমরা একটি প্রোগ্রাম লিখব, যার ইনপুট হবে a1, a2, b1, b2, c1, c2 এবং আউটপুট হবে x ও y-এর মান। এটিও সহজ প্রোগ্রাম। নিজে চেষ্টা করো।
আশা করি, তোমরা দুটি সমস্যারই সমাধান নিজে করে ফেলতে পারবে। এখন আমি প্রথম সমস্যার কোড দিচ্ছি:
#include <stdio.h> int main() { double x, y, x_plus_y, x_minus_y; printf("Enter the value of x + y: "); scanf("%lf", &x_plus_y); printf("Enter the value of x - y: "); scanf("%lf", &x_minus_y); x = (x_plus_y + x_minus_y) / 2; y = (x_plus_y - x_minus_y) / 2; printf("x = %0.2lf, y = %0.2lf\n", x, y); return 0; } প্রোগ্রাম: ৫.১
সমাধান খুবই সহজ। তবে লক্ষ করো যে আমি ভেরিয়েবলের ডাটা টাইপ int ব্যবহার না করে double ব্যবহার করেছি।
এবারে দ্বিতীয় সমস্যার কোড:
#include <stdio.h> int main() { double a1, a2, b1, b2, c1, c2, x, y; printf("a1 = "); scanf("%lf", &a1); printf("a2 = "); scanf("%lf", &a2); printf("b1 = "); scanf("%lf", &b1); printf("b2 = "); scanf("%lf", &b2); printf("c1 = "); scanf("%lf", &c1); printf("c2 = "); scanf("%lf", &c2); x = (b2 * c1 - b1 * c2) / (a1 * b2 - a2 * b1); y = (a1 * c2 - a2 * c1) / (a1 * b2 - a2 * b1); printf("x = %0.2lf, y = %0.2lf\n", x, y); return 0; } প্রোগ্রাম: ৫.২
এটিও সহজ প্রোগ্রাম! তবে তোমরা দেখো (a1 * b2 - a2 * b1)-এর মান আমি দুবার বের করেছি (x-এর মান বের করার সময়, আবার y-এর মান বের করার সময়)। কাজটি একবারেই করা যেত এবং একবারে করলেই ভালো, তাহলে আমাদের প্রোগ্রাম দুটি গুণ ও একটি বিয়োগের কাজ কম করবে। আবার (a1 * b2 - a2 * b1)-এর মান যদি শূন্য হয়, তাহলে একটি ঝামেলা হয়ে যাচ্ছে, কারণ কোনো কিছুকে তো শূন্য দিয়ে ভাগ করা যায় না। তাই ওই মানটি শূন্য হলে আসলে সমীকরণের কোনো সমাধান নেই। এবার প্রোগ্রামটি আরও ভালোভাবে লিখে ফেলি।
#include <stdio.h> int main() { double a1, a2, b1, b2, c1, c2, d, x, y; printf("a1 = "); scanf("%lf", &a1); printf("a2 = "); scanf("%lf", &a2); printf("b1 = "); scanf("%lf", &b1); printf("b2 = "); scanf("%lf", &b2); printf("c1 = "); scanf("%lf", &c1); printf("c2 = "); scanf("%lf", &c2); d = a1 * b2 - a2 * b1; if ((int) d == 0) { printf("Value of x and y can not be determined.\n"); } else { x = (b2 * c1 - b1 * c2) / d; y = (a1 * c2 - a2 * c1) / d; printf("x = %0.2lf, y = %0.2lf\n", x, y); } return 0; } প্রোগ্রাম: ৫.৩
এখানে একটি ব্যাপার খেয়াল করো। আমি if-এর ভেতর লিখেছি (int) d == 0। এখানে আমি প্রথমে d (যা একটি double টাইপের ভেরিয়েবল)-কে ইন্টিজারে টাইপ কাস্ট করে তারপর তার মানটি 0-এর সমান কি না তা পরীক্ষা করেছি। পরীক্ষাটা এভাবেও করা যেত: if (d == 0.0) তবে এতে মাঝে মাঝে ঝামেলা হয়, ফ্লোটিং পয়েন্ট-সংক্রান্ত হিসাব-নিকাশের জন্য। তোমরা কম্পিউটার আর্কিটেকচার নিয়ে লেখাপড়া করলে বিষয়টা বুঝতে পারবে।
তোমাদের মনে একটি প্রশ্ন আসতে পারে যে এই সহজ সমস্যাগুলো প্রোগ্রামিং করে সমাধান করে কী লাভ? আসলে একবার প্রোগ্রাম লিখে ফেলার পরে কিন্তু আর সমাধান করতে হয় না। তারপর শুধু ইনপুট দেবে, প্রোগ্রামটি নিজেই সমস্যার সমাধান করে তোমাকে আউটপুট দেবে।
৩) আমি যদি তোমাকে দশ হাজার টাকা ঋণ দিই 35% সুদে এবং টাকাটা পাঁচ বছর সময়ের মধ্যে তোমাকে সুদে-আসলে পরিশোধ করতে বলি, তাহলে পাঁচ বছরে মোট কত টাকা তোমার দিতে হবে এবং প্রতি মাসে কত টাকা দিতে হবে? ঋণটা যদি জটিল কিছু না হয়, তাহলে তোমার মোট পরিশোধ করতে হবে 10000 + 10000 * 35 / 100 টাকা। এই সহজ-সরল ঋণের জন্য একটি

প্রোগ্রাম লিখে ফেলা যাক:
#include <stdio.h> int main() { double loan_amount, interest_rate, number_of_years, total_amount, monthly_amount; printf("Enter the loan amount: "); scanf("%lf", &loan_amount); printf("Enter the interest rate: "); scanf("%lf", &interest_rate); printf("Number of years: "); scanf("%lf", &number_of_years); total_amount = loan_amount + loan_amount * interest_rate / 100.00; monthly_amount = total_amount / (number_of_years * 12); printf("Total amount: %0.2lf\n", total_amount); printf("Monthly amount: %0.2lf\n", monthly_amount); return 0; } প্রোগ্রাম: ৫.৪
আমাদের ফর্মুলাতে একটু সমস্যা আছে। আসলে 35% সুদ দিতে হলে সেটা বাৎসরিক সুদ হবে। অর্থাৎ প্রতি বছর মোট ঋণের উপর 35% সুদ দেওয়া লাগবে। তাহলে দেখা যাচ্ছে পাঁচ বছরে তোমার মোট পরিশোধ করতে হবে 10000 + 10000 * 35 * 5 / 100 টাকা। এখন এই ফর্মুলা অনুযায়ী প্রোগ্রাম লিখে ফেলো।
তবে বাস্তবে ঋণের হিসাব-নিকাশ কিন্তু এত সরল নয়। তুমি ব্যাংক থেকে ঋণ নিতে গেলেই সেটি টের পাবে।
৪) পদার্থবিজ্ঞানের একটি সমস্যার সমাধান করা যাক।
কোনো বস্তু u আদিবেগে (initial velocity) এবং a ত্বরণে (acceleration) যাত্রা শুরু করল (ত্বরণের মান সব সময় a থাকবে, বাড়বে বা কমবে না)। t সময় পরে এর বেগ যদি v হয় তাহলে 2t সময়ে বস্তুটি কত দূরত্ব অতিক্রম করবে? (সমস্যাটি দিয়েছেন শাহরিয়ার মঞ্জুর, এটি ভ্যালাডলিড অনলাইন জাজের 10071 নম্বর সমস্যা)।
2t সময়ে অতিক্রান্ত দূরত্ব হবে v x 2t। এটি প্রমাণ করে ফেলো। তারপর আবার পড়া শুরু করো। নবম-দশম শ্রেণীর পদার্থবিজ্ঞান বইতে তোমরা দুটি সূত্র পাবে: v = u + at s = ut + 0.5 at^2 (এখানে s হচ্ছে t সময়ে অতিক্রান্ত দূরত্ব)। তাহলে 2t সময় পরে অতিক্রান্ত দূরত্ব হবে u x 2t + 0.5 x a x (2t)^2 = u x 2t + 0.5 x a x 4t^2 = u x 2t + a x 2t^2 = 2t (u + at) = 2tv
এখন, তোমাদেরকে একটি প্রোগ্রাম লিখতে হবে, যেখানে v ও t-এর মান ইনপুট হিসেবে দেওয়া হবে, 2t সময়ে অতিক্রান্ত দূরত্ব নির্ণয় করতে হবে। প্রোগ্রামটি নিজে নিজে লিখে ফেলো।
৫) 1 + 2 + 3 + … + 998 + 999 + 1000 এই ধারার সমষ্টি কত?
তোমরা যারা ধারার যোগফলের সূত্র জানো, তারা চট করে বলে দিতে পারবে, এই ধারাটির যোগফল হচ্ছে 1000 x 1001 / 2। তাহলে এর জন্য একটি প্রোগ্রাম লিখে ফেলা যাক, যেখানে শেষ পদের মান হবে ইনপুট আর আউটপুট হবে যোগফল।
#include <stdio.h> int main() { int n, sum; scanf("%d", &n); sum = (n * (n + 1)) / 2; printf("Summation is %d\n", sum); return 0; } প্রোগ্রাম: ৫.৫
ধারার যোগফল নির্ণয়ের সূত্র জানা না থাকলে আমরা লুপ ব্যবহার করে প্রোগ্রামটি লিখতে পারি।
#include <stdio.h> int main() { int i, n, sum; scanf("%d", &n); for(i = 1, sum = 0; i <= n; i++) { sum = sum + i; } printf("Summation is %d\n", sum); return 0; } প্রোগ্রাম: ৫.৬
সুতরাং ধারার সমস্যা নিয়ে আর চিন্তা নেই। তুমি যদি একটি পদের মান তার আগের পদের চেয়ে কত করে বাড়ছে, সেটি বের করতে পারো, তাহলেই লুপ ব্যবহার করে যোগফল বের করে ফেলতে পারবে। তবে সূত্র বের করতে পারলে লুপ ব্যবহার না করাই ভালো। কারণ প্রথম প্রোগ্রামটি দেখো (যেখানে সূত্র ব্যবহার করেছি)। সেখানে একটি যোগ, একটি গুণ আর একটি ভাগ করতে হয়েছে, n-এর মান যত বড়ই হোক না কেন। আর দ্বিতীয় প্রোগ্রামে (যেখানে লুপ ব্যবহার করেছি) n-এর মান যত, ততবার যোগ করতে হয়েছে, আবার সেই যোগফলটি sum ভেরিয়েবলে রাখতে হয়েছে (ভেরিয়েবলে কোনো মান রাখতেও কিন্তু একটু সময় লাগে)।
এখন তোমাদের একটি সহজ প্রোগ্রাম লিখতে হবে। প্রথম n সংখ্যক ধনাত্মক বেজোড় সংখ্যার যোগফল নির্ণয়ের প্রোগ্রাম। n-এর মান হবে ইনপুট, আর যোগফল হবে আউটপুট

৬) আমাদের এবারকার প্রোগ্রামটি হবে তাপমাত্রাকে সেলসিয়াস (Celsius) থেকে ফারেনহাইটে (Farenheit) রূপান্তর করার প্রোগ্রাম।
সেলসিয়াসকে ফারেনহাইটে রূপান্তরের সূত্র হচ্ছে: °F = (°C × 1.8) + 32।
#include <stdio.h> int main() { double celsius, farenheit; printf("Enter the temperature in celsius: "); scanf("%lf", &celsius); farenheit = 1.8 * celsius + 32; printf("Temperature in farenheit is: %lf\n", farenheit); return 0; } প্রোগ্রাম: ৫.৭
এখন তোমাদের কাজ হচ্ছে ফারেনহাইট থেকে সেলসিয়াসে রূপান্তরের প্রোগ্রাম লেখা।
৭) এখন আমরা দুটি সংখ্যার গসাগু (GCD → Greatest Common Divisor বা HCF → Highest Common Factor) ও লসাগু (LCM → Least Common Multiple) নির্ণয় করার জন্য প্রোগ্রাম লিখব।
দুটি সংখ্যার গসাগু হচ্ছে যেসব সংখ্যা দিয়ে ওই দুটি সংখ্যা নিঃশেষে বিভাজ্য হয়, তাদের মধ্যে সবচেয়ে বড় সংখ্যা। তাহলে আমরা যেটি করব, দুটি সংখ্যা a ও b নেব। তারপর এদের মধ্যে যেটি ছোট, সেই মানটি আবার x ভেরিয়েবলে রাখব। গসাগু এর মান x-এর চেয়ে বড় হওয়া সম্ভব নয় (5 ও 10-এর গসাগু-এর মান নিশ্চয়ই 5-এর চেয়ে বড় হবে না)। এখন a ও b, x দিয়ে নিঃশেষে বিভাজ্য হয় কি না (a % x == 0 এবং b % x == 0) সেটি পরীক্ষা করব। যদি হয় তবে আমরা গসাগু পেয়ে গেছি। যদি a ও b উভয়েই নিঃশেষে বিভাজ্য না হয়, তখন x-এর মান এক কমিয়ে পরীক্ষা করব। যতক্ষণ না আমরা গসাগু পাচ্ছি x-এর মান কমাতেই থাকব। একসময় আমরা গসাগু পাবই, কারণ x-এর মান যখন 1 হবে, তখন তো x দিয়ে a ও b দুটি সংখ্যাই নিঃশেষে বিভাজ্য। তোমরা কি প্রোগ্রামটি নিজে লিখার চেষ্টা করবে? না পারলে আমার কোড দেখো:
#include <stdio.h> int main() { int a, b, x, gcd; scanf("%d %d", &a, &b); if (a < b) { x = a; } else { x = b; } for(; x >= 1; x--) { if (a % x == 0 && b % x == 0) { gcd = x; break; } } printf("GCD is %d\n", gcd); return 0; } প্রোগ্রাম: ৫.৮
প্রোগ্রামে দেখো gcd পাওয়ার সঙ্গে সঙ্গে লুপ থেকে বের হয়ে যেতে হবে (আমি break ব্যবহার করেছি এই জন্য)। break ব্যবহার না করলে কী হবে সেটি পরীক্ষা করে দেখো।
তবে গসাগু বের করার জন্য আমি যেই পদ্ধতি ব্যবহার করেছি সেটি খুব সহজ পদ্ধতি হলেও ইফিশিয়েন্ট (efficient) নয়। যেমন, সংখ্যা দুটি খুব বড় হলে এবং সহমৌলিক (co-prime) হলে লুপটি কিন্তু অনেকবার ঘুরবে। কারণ সহমৌলিক হলে গসাগু হবে 1। তোমরা নিশ্চয়ই জানো যে, দুটি সংখ্যার মধ্যে 1 ছাড়া আর কোনো সাধারণ উৎপাদক না থাকলে সংখ্যা দুটি সহমৌলিক।
গসাগু বের করার জন্য ইউক্লিডের একটি চমৎকার পদ্ধতি আছে। ইউক্লিড ভাগশেষ উপপাদ্যের (division algorithm) সাহায্যে গসাগু বের করার উপায় দেখিয়েছেন। এই পদ্ধতিতে খুব সহজে গসাগু বের করা যায় এবং প্রোগ্রামটিও বেশ ইফিশিয়েন্ট হয়। এর জন্য দুটি জিনিস জানা লাগবে: a ও 0-এর গসাগু-এর মান a। a ও b-এর গসাগু = b ও a % b-এর গসাগু।
তাহলে প্রোগ্রামে যেটি করতে হবে, একটি লুপের সাহায্যে a-এর মান b আর b-এর মান a%b বসিয়ে যেতে হবে, যতক্ষণ না b-এর মান শূন্য হয়। b-এর মান শূন্য হলেই বুঝে যাব যে গসাগু হচ্ছে a (এটা কিন্তু প্রোগ্রাম শুরুর সময় a-এর মান না, b-এর মান যখন শূন্য হবে সেই সময় a-এর মান)।
#include <stdio.h> int main() { int a, b, t, x, gcd; scanf("%d %d", &a, &b); if (a == 0) gcd = b; else if (b == 0) gcd = a; else { while (b != 0) { t = b; b = a % b; a = t; } gcd = a; } printf("GCD is %d\n", gcd); return 0; } প্রোগ্রাম: ৫.৯
এই প্রোগ্রামটি আরও ইফিশিয়েন্ট করার চেষ্টা করো।
এবার লসাগু বের করার প্রোগ্রাম। তোমরা নিশ্চয়ই স্কুলে শিখেছ, কীভাবে লসাগু বের করতে হয়। সেই পদ্ধতি অবলম্বন করে প্রোগ্রাম লিখে ফেলো। আর যারা সেই পদ্ধতি জানো না, তাদের জন্য একটি সূত্র বলে দিচ্ছি। আশা করি, লসাগু বের করার প্রোগ্রাম লিখতে আর সমস্যা হবে না।দুটি সংখ্যার লসাগু x দুটি সংখ্যার গসাগু = সংখ্যা দুটির গুণফল
Share:

প্রোগ্রামিং লুপ (Loop)

প্রোগ্রামিং  লুপ (Loop)
তোমরা এরই মধ্যে প্রোগ্রামের মধ্যে বিভিন্ন ধরনের শর্ত (condition) ব্যবহার করতে শিখে গেছ। এইসব শর্ত দিয়ে বিভিন্ন প্রোগ্রাম তৈরি করাও হয়তো শুরু করে দিয়েছ। খুব ভালো কথা। কিন্তু এখন আমরা আরেকটি সমস্যা ও তার সমাধানের পথ খুঁজব। একটি প্রোগ্রাম লিখতে হবে, যেটি 1 থেকে 10 পর্যন্ত সব পূর্ণসংখ্যা মনিটরে দেখাবে (প্রতি লাইনে একটি সংখ্যা থাকবে)। খুবই সহজ সমস্যা এবং সমাধানও অত্যন্ত সহজ। আমি জানি, তোমরা এক মিনিটের মধ্যেই নিচের প্রোগ্রামটি লিখে ফেলবে: #include <stdio.h> int main() { printf("1\n"); printf("2\n"); printf("3\n"); printf("4\n"); printf("5\n"); printf("6\n"); printf("7\n"); printf("8\n"); printf("9\n"); printf("10\n"); return 0; } প্রোগ্রাম: ৪.১ এখানে আমরা 1 থেকে 10 পর্যন্ত সবগুলো সংখ্যা প্রিন্ট করে দিয়েছি। অবশ্য একটি printf() ব্যবহার করেও কাজটি করা যেত: printf("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
আবার প্রোগ্রামটি এভাবেও লেখা যেত। n একটি ইন্টিজার ভেরিয়েবল, যার মান আমরা প্রথমে 1 বসাব। তারপর n-এর মান প্রিন্ট করব। তারপর n-এর মান এক বাড়াব (n = n + 1 অথবা সংক্ষেপে, n++ লিখে)।
int n = 1; printf("%d\n", n); n = n + 1; printf("%d\n", n); n = n + 1; printf("%d\n", n); n = n + 1; /* এভাবে মোট দশ বার */
আবার nএর মান 1 বাড়ানোর কাজটি কিন্তু এক লাইনেই সেরে ফেলা যায়। printf("%d\n", n); n = n + 1; এর পরিবর্তে আমরা লিখতে পারি: printf("%d\n", n++);
যা-ই হোক, এ তো গেল 1 থেকে 10 পর্যন্ত প্রিন্ট করা। কিন্তু আমাদের যদি 1 থেকে 100, বা 1000, বা 10000 পর্যন্ত প্রিন্ট করতে বলা হতো তাহলে আমরা কী করতাম? ওপরে যে পদ্ধতি অবলম্বন করা হয়েছে সেটি তো অবশ্যই করা যেত। কিন্তু আমি জানি, তোমরা কেউই এত কষ্ট করতে রাজি না।
এ সমস্যা সমাধানের জন্য সব প্রোগ্রামিং ল্যাঙ্গুয়েজেই লুপ (loop) বলে একটি পদ্ধতি রয়েছে। এটি দিয়ে একই কাজ বারবার করা যায়। লুপের মধ্যে একটি শর্ত বসিয়ে দিতে হয়, যেটি পূরণ না হওয়া পর্যন্ত প্রোগ্রামটি লুপের ভেতরের কাজ বারবার করতে থাকবে। সি ল্যাঙ্গুয়েজে দুটি জনপ্রিয় লুপ হচ্ছে while এবং for। আমরা এখন while ব্যবহার করে ওই প্রোগ্রামটি লিখব। #include <stdio.h> int main() { int n = 1; while(n <= 10) { printf("%d\n", n); n++; } return 0; } প্রোগ্রাম: ৪.২ কী চমৎকার! এখন আমরা চাইলে 10-এর বদলে যত খুশি বসাতে পারি, যত বসাব 1 থেকে তত পর্যন্ত প্রিন্ট হবে। while লুপে প্রথম বন্ধনীর ভেতর শর্ত লিখে দিতে হয়। প্রোগ্রাম সেই শর্ত পরীক্ষা করে। যতক্ষণ পর্যন্ত শর্তটি সত্য হয় ততক্ষণ পর্যন্ত লুপের ভেতরের কাজগুলো চলতে থাকে। লুপের ভেতরের কাজগুলো থাকবে দ্বিতীয় বন্ধনীর ভেতর। যেমন এখানে লুপের ভেতরে আমরা দুটি কাজ করেছি। n-এর মান প্রিন্ট করেছি আর তারপর n-এর মান 1 বাড়িয়েছি। n-এর মান 1 করে বাড়তে থাকলে একসময় এটি 11 হবে আর তখন n <= 10 এই শর্তটি মিথ্যা হয়ে যাবে (কারণ 11 > 10)। আর প্রোগ্রামটিও লুপ থেকে বের হয়ে আসবে। অর্থাৎ, শর্তটি যখনই মিথ্যা হবে তখনই লুপ থেকে বের হয়ে যাবে।
ইন্ডেন্টেশনের ব্যাপারটিও খেয়াল করো। লুপের ভেতরের অংশের কোড চার ঘর ডানদিক থেকে শুরু হয়েছে।
এবারে তোমাদের জন্য একটি প্রশ্ন। বলো তো নিচের প্রোগ্রামটির আউটপুট কী হবে? #include <stdio.h> int main() { int n = 1; while(n <= 10) { printf("%d\n", n); } n++; return 0; } প্রোগ্রাম: ৪.৩ এটাও কি 1 থেকে 10 পর্যন্ত সব সংখ্যা প্রিন্ট করবে? দেখা যাক। প্রোগ্রামটি রান করাও। আউটপুট কী?
মনিটরে প্রতি লাইনে 1 প্রিন্ট হচ্ছে এবং প্রোগ্রামটি বন্ধ হচ্ছে না। খুবই দুঃখের বিষয়। দেখা যাক দুঃখের পেছনে কারণটা কী।
int n = 1; প্রথমে প্রোগ্রামটি n-এর মান 1 বসাবে। তারপর while লুপে গিয়ে শর্ত পরীক্ষা করবে। আমরা শর্ত দিয়েছি n <= 10 মানে n-এর মান 10-এর ছোট বা সমান। এই শর্ত তো সত্য কারণ n-এর মান 1। তারপর প্রোগ্রামটি n-এর মান প্রিন্ট করবে printf("%d\n", n);। তারপর কি n-এর মান 1 বাড়বে? বাড়বে না, কারণ আমরা দ্বিতীয় বন্ধনী শেষ করে দিয়েছি '}' চিহ্ন দিয়ে (মানে লুপ শেষ)। তার মানে প্রোগ্রামটি আবার শর্ত পরীক্ষা করবে, আবার n-এর মান প্রিন্ট করবে...এভাবে চলতেই থাকবে কারণ n-এর মান যেহেতু বাড়ছে না, n <= 10 শর্তটি সব সময় সত্যই রয়ে যাচ্ছে – কখনো মিথ্যা হচ্ছে না। এখন তোমরা while লুপ নিয়ে বিভিন্ন ধরনের গবেষণা চালিয়ে যেতে পারো। সব সময় সত্য হয় এমন শর্ত ব্যবহার করে তোমার কম্পিউটারকে ব্যস্ত রাখতে পারো। while(1){...} এখানে শর্ত হিসেবে 1 ব্যবহার করা হয়েছে। কম্পিউটার 1 বলতে বোঝে সত্য। সুতরাং লুপের ভেতরের কাজগুলো সব সময় চলতে থাকবে, বন্ধ হবে না। while(1 == 1){...} ও একই আচরণ করবে। তবে এখন আমি তোমাদের একটি দরকারি জিনিস বলে রাখি, যেটি দিয়ে তোমরা জোর করে লুপ থেকে বের হয়ে যেতে পারবে। সেটি হচ্ছে break স্টেটমেন্ট। কথা না বাড়িয়ে একটি প্রোগ্রাম লিখলেই ব্যাপারটি পরিষ্কার হয়ে যাবে। #include <stdio.h> int main() { int n = 1; while(n <= 100) { printf("%d\n", n); n++; if(n > 10) { break; } } return 0; } প্রোগ্রাম: ৪.৪ এই প্রোগ্রামটি কী করবে? 1 থেকে 10 পর্যন্ত প্রিন্ট করবে। যদিও while-এর ভেতর আমরা বলেছি যে শর্ত হচ্ছে n <= 100, কিন্তু লুপের ভেতরে আবার বলে দিয়েছি যে যদি n > 10 হয়, তবে break; মানে বের হয়ে যাও, বা লুপটি ভেঙে দাও। break সব সময় যেই লুপের ভেতর থাকে সেটির বাইরে প্রোগ্রামটিকে নিয়ে আসে। সুতরাং n-এর মান 10 প্রিন্ট হওয়ার পরে এর মান এক বাড়বে (n++;) অর্থাৎ n-এর
মান হবে 11। আর তখন n > 10 সত্য হবে, ফলে প্রোগ্রামটি if কন্ডিশনের ভেতরে ঢুকে যাবে। সেখানে গিয়ে সে দেখবে তাকে break করতে বলা হয়েছে তাই সে লুপের বাইরে চলে যাবে। break-এর উল্টা কাজ করে, এমন একটি স্টেটমেন্ট হচ্ছে continue;। কোনো জায়গায় continue ব্যবহার করলে লুপের ভেতরে continue-এর পরের অংশের কাজ আর হয় না। নিচের প্রোগ্রামটি কোড করে কম্পাইল ও রান করো: #include <stdio.h> int main() { int n = 0; while (n < 10) { n = n + 1; if (n % 2 == 0) { continue; } printf("%d\n", n); } return 0; } প্রোগ্রাম: ৪.৫ এই প্রোগ্রামটি 1 থেকে 10-এর মধ্যে কেবল বেজোড় সংখ্যাগুলো প্রিন্ট করবে। জোড় সংখ্যার বেলায় continue ব্যবহার করার কারণে প্রোগ্রামটি printf("%d\n", n); স্টেটমেন্ট এক্সিকিউট না করে লুপের পরবর্তী ধাপের কাজ শুরু করবে।
এবারে আমরা আরেকটি প্রোগ্রাম লিখব। ছোটবেলায় যে নামতাগুলো তোমরা শিখেছ সেগুলো এখন আমরা প্রোগ্রাম লিখে কম্পিউটারের মনিটরে দেখব। চলো 5-এর নামতা দিয়ে শুরু করা যাক। আমাদের প্রোগ্রামের আউটপুট হবে এরকম:
5 X 1 = 5 5 X 2 = 10 5 X 3 = 15 5 X 4 = 20 5 X 5 = 25 5 X 6 = 30 5 X 7 = 35 5 X 8 = 40 5 X 9 = 45 5 X 10 = 50
তোমরা নিশ্চয়ই এখন অনেকগুলো printf ফাংশন লেখা শুরু করবে না। লুপের সাহায্যে প্রোগ্রামটি লিখে ফেলবে: #include <stdio.h> int main() { int n = 5; int i = 1; while (i <= 10) { printf("%d X %d = %d\n", n, i, n*i); i = i + 1; } return 0; } প্রোগ্রাম: ৪.৬ এতক্ষণ আমরা while লুপ ব্যবহার করলাম। এবার চলো for লুপ ব্যবহার করতে শিখি। 5-এর নামতার প্রোগ্রামটি যদি আমরা for লুপ ব্যবহার করে লিখি তাহলে সেটির চেহারা দাঁড়াবে: #include <stdio.h> int main() { int n = 5; int i; for(i = 1; i <= 10; i = i + 1) { printf("%d X %d = %d\n", n, i, n*i); } return 0; } প্রোগ্রাম: ৪.৭ for লুপের প্রথম বন্ধনীর ভেতর তিনটি অংশ লক্ষ করো। প্রতিটি অংশ সেমিকোলন (;) দিয়ে আলাদা করা হয়েছে। প্রোগ্রামটি যখন লুপের ভেতর ঢুকে তখন প্রথম সেমিকোলনের আগে আমরা যে কাজগুলো করতে বলব, সেগুলো একবার করবে। যেমন এখানে i-এর মান 1 বসাবে। তারপর দ্বিতীয় অংশের কাজ করবে। দ্বিতীয় অংশে সাধারণত শর্ত ব্যবহার করা হয় (while লুপে প্রথম বন্ধনীর ভেতর আমরা যে কাজটি করি আরকি)। ওপরের প্রোগ্রামে আমরা দ্বিতীয় অংশে i <= 10 শর্তটি ব্যবহার করেছি। এই শর্ত যদি মিথ্যা হয় তবে প্রোগ্রামটি লুপ থেকে বেরিয়ে আসবে। আর যদি সত্য হয় তবে লুপের ভেতরের কাজগুলো করবে এবং তার পর for লুপের সেই প্রথম বন্ধনীর ভেতর তৃতীয় অংশে যে কাজগুলো করতে বলা হয়েছে সেগুলো করবে। তারপর আবার দ্বিতীয় অংশে এসে শর্ত পরীক্ষা করবে। প্রথম অংশের কাজ কিন্তু আর হবে না। তো আমাদের প্রোগ্রামটি আবার লক্ষ করো। i <= 10 সত্য, কারণ i-এর মান 1। তারপর printf() ফাংশনের কাজ হবে। তারপর i = i + 1 স্টেটমেন্ট এক্সিকিউট হবে (i-এর মান এক বেড়ে যাবে)। তারপর আবার i <= 10 সত্য না মিথ্যা সেটি পরীক্ষা করা হবে (i-এর মান এখন 2)। তারপর আবার লুপের ভেতরের কাজ হবে (printf())। এভাবে যতক্ষণ না i <= 10 শর্তটি মিথ্যা হচ্ছে ততক্ষণ লুপের ভেতরের কাজ চলতে থাকবে। i-এর মান এক এক করে বেড়ে বেড়ে যখন 11 হবে তখন শর্তটি মিথ্যা হবে আর প্রোগ্রামটি লুপ থেকে বের হয়ে আসবে। for লুপের প্রথম বন্ধনীর ভেতরের তিনটি অংশই যে ব্যবহার করতে হবে এমন কোন কথা নেই। কোন অংশ ব্যবহার করতে না চাইলে আমরা সেটি ফাঁকা রেখে দিতে পারি, তবে সেমিকোলন কিন্তু অবশ্যই দিতে হবে। যেমন আমরা যদি i-এর মান আগেই নির্ধারণ করে দেই তবে সেটি লুপের ভেতর না করলেও চলে
। int i = 1;
for(; i<= 10; i = i + 1) { printf("%d X %d = %d\n", n, i, n*i); } যদি তিনটি অংশের কোনোটিই লিখতে না চাই, তবে পুরো প্রোগ্রামটি এভাবে লেখা যায়: #include <stdio.h> int main() { int n = 5; int i = 1; for( ; ; ) { printf("%d X %d = %d\n", n, i, n*i); i = i + 1; if (i > 10) { break; } } return 0; } প্রোগ্রাম: ৪.৮ এখন আমরা আরেকটি কাজ করব। for লুপ ব্যবহার করে 5-এর নামতায় যে গুণ করেছি (n*i) সেটি না করে কেবল যোগ করে প্রোগ্রামটি লিখব। তোমরা কি অবাক হচ্ছ যে নামতার প্রোগ্রাম আবার গুণ ছাড়া কীভাবে হবে? আমরা কিন্তু 5 x 3-কে লিখতে পারি 5 + 5 + 5। আমি কী করতে যাচ্ছি তা বুঝতে পারছ নিশ্চয়ই। প্রোগ্রামটি লিখে ফেলি: #include <stdio.h> int main() { int m, n = 5; int i; m = 0; for(i = 1; i <= 10; i = i + 1) { m = m + n; printf("%d X %d = %d\n", n, i, m); } return 0; } প্রোগ্রাম: ৪.৯ প্রোগ্রামটিতে আমরা গুণ না করে যোগ করলাম। কম্পাইল ও রান করে দেখো। কাজ করবে ঠিকঠাক। কোনো সংখ্যার গুণিতকগুলো যেমন গুণ করে বের করা যায়, তেমনই যোগ করেও করা যায়। আমরা যদি কোনো প্রোগ্রামে দেখি যে গুণ না করে যোগ করলেই কাজ হচ্ছে, তাহলে যোগ করাই ভালো কারণ কম্পিউটারের প্রসেসর একটি যোগ করতে যে সময় নেয়, একটি গুণ করতে তার চেয়ে অনেক বেশি সময় নেয়। যদিও তুমি হয়তো প্রোগ্রাম রান করার সময় তা বুঝতে পারো না। কম্পিউটারের প্রসেসর সম্পর্কে বিস্তারিত লেখাপড়া করলে বিষয়টা জানতে পারবে। আপাতত এটি জানলেই চলবে যে একটি গুণ করার চেয়ে একটি যোগ করা ভালো, কারণ যোগ করতে কম্পিউটার অপেক্ষাকৃত কম সময় নেয়।
তো আমরা for লুপ শিখে ফেললাম। এখন আমরা চেষ্টা করব শুধু নির্দিষ্ট একটি সংখ্যার নামতা না লিখে 1 থেকে 20 পর্যন্ত সবগুলো সংখ্যার নামতা একবারে লিখে ফেলতে। অর্থাৎ n-এর মান 5 নির্দিষ্ট না করে 1 থেকে 20 পর্যন্ত হবে। এটি করার একটি বোকা পদ্ধতি (নাকি চোরা পদ্ধতি?) হচ্ছে নামতা লিখার অংশটি বারবার কপি-পেস্ট করা। কিন্তু আমরা এটি করব লুপের ভেতর লুপ ব্যবহার করে। একটি লুপের সাহায্যে n-এর মান 1 থেকে 20 পর্যন্ত এক করে বাড়াব। আর তার ভেতর n-এর একটি নির্দিষ্ট মানের জন্য নামতাটা লিখব। #include <stdio.h> int main() { int n, i; for(n = 1; n <= 20; n = n + 1) { for(i = 1; i <= 10; i = i + 1) { printf("%d X %d = %d\n", n, i, n*i); } } return 0; } প্রোগ্রাম: ৪.১০ এখন তোমরা প্রোগ্রামটি চালাও। তারপর তোমাদের কাজ হবে গুণ না করে কেবল যোগ ব্যবহার করে প্রোগ্রামটি লেখা।
আমরা এখানে একটি for লুপের ভেতর আরেকটি for লুপ, যাকে নেস্টেড লুপও (nested loop) বলে, সেটি ব্যবহার করলাম। তো আমরা চাইলে for লুপের ভেতর for বা while অথবা while লুপের ভেতর for বা while লুপ একাধিকবার ব্যবহার করতে পারি। অবশ্য সেটি কখনোই চার বা পাঁচবারের বেশি দরকার হওয়ার কথা না। নেস্টেড লুপ দিয়ে আমরা এখন আরেকটি প্রোগ্রাম লিখব। 1, 2, 3 – এই তিনটি সংখ্যার সব বিন্যাস (permutation) বের করার প্রোগ্রাম। বিন্যাসগুলো ছোট থেকে বড় ক্রমে দেখাতে হবে অর্থাৎ প্রোগ্রামটির আউটপুট হবে এই রকম:
1, 2, 3 1, 3, 2 2, 1, 3 2, 3, 1 3, 1, 2 3, 2, 1
এই প্রোগ্রামটি অনেকভাবে লেখা যেতে পারে, কিন্তু আমরা এখন পর্যন্ত যতটুকু প্রোগ্রামিং শিখেছি, তাতে নেস্টেড লুপের ব্যবহারই সবচেয়ে ভালো সমাধান।
এখানে আমরা প্রথম সংখ্যাটির জন্য একটি লুপ, দ্বিতীয় সংখ্যাটির জন্য প্রথম লুপের ভেতরে একটি লুপ এবং তৃতীয় সংখ্যাটির জন্য দ্বিতীয় লুপের ভেতর আরেকটি লুপ ব্যবহার করব। #include <stdio.h> int main() { int a, b, c; for (a = 1; a <= 3; a++) { for (b = 1; b <= 3; b++) { for (c = 1; c <= 3; c++) { printf ("%d, %d, %d\n", a, b, c); } } } return 0; } প্রোগ্রাম: ৪.১১ এখন প্রোগ্রামটি রান করলে আমরা এই রকম আউটপুট পাব:
1, 1, 1 1, 1, 2 1, 1, 3 1, 2, 1 1, 2, 2 1, 2, 3 1, 3, 1 1, 3, 2 1, 3, 3 2, 1, 1 2, 1, 2 2, 1, 3 2, 2, 1 2, 2, 2 2, 2, 3 2, 3, 1 2, 3, 2 2, 3, 3 3, 1, 1 3, 1, 2 3, 1, 3 3, 2, 1 3, 2, 2 3, 2, 3 3, 3, 1 3, 3, 2 3, 3, 3
কিন্তু আমরা তো আসলে এই রকম জিনিস চাচ্ছি না। a-এর মান যখন 1 তখন b ও c-এর মান 1 হবে না, আবার b এবং c-এর মানও সমান হবে না। মানে a, b ও c আলাদা হবে। তাহলে আমরা লুপের ভেতর শর্তগুলো একটু পরিবর্তন করব। দ্বিতীয় লুপের শর্ত b <= 3-এর সঙ্গে আরেকটি শর্ত জুড়ে দেব, b != a। b <= 3 && b != a মানে b-এর মান 3-এর চেয়ে ছোট বা সমান হবে এবং b-এর মান a-এর মানের সমান হবে না। তৃতীয় লুপে আমরা এখন শর্ত দেব, c <= 3 && c != a && c != b, মানে c-এর মান 3-এর ছোট বা সমান হতে হবে এবং c-এর মান a-এর মানের সমান হওয়া চলবে না এবং c-এর মান b-এর মানের সমান হলেও চলবে না। তাহলে আমাদের প্রোগ্রামটির চেহারা দাঁড়াবে এই রকম: #include <stdio.h> int main() { int a, b, c; for (a = 1; a <= 3; a++) { for (b = 1; b <= 3 && b != a; b++) { for (c = 1; c <= 3 && c != a && c != b; c++) { printf ("%d, %d, %d\n", a, b, c); } } } return 0; } প্রোগ্রাম: ৪.১২ রান করলে আমরা আউটপুট কী দেখব? 3, 2, 1
মাত্র একটি লাইন! আমরা প্রোগ্রামটি ঠিক করতে গিয়ে ঝামেলা পাকিয়ে ফেলেছি মনে হচ্ছে। তোমরা কি একটু চিন্তা করে ঝামেলার কারণ বের করতে পারবে?
প্রথমে a-এর মান 1তাই a <= 3 সত্য। প্রোগ্রামটি প্রথম লুপের ভেতর ঢুকে গেল। তারপর দ্বিতীয় লুপের শুরুতে b-এর মান 1। b <= 3 সত্য। কিন্তু b != a মিথ্যা। কারণ aও b-এর মান তো সমান, দুটোর মানই 1। তাই প্রোগ্রামটি আর দ্বিতীয় লুপের ভেতর ঢুকবে না। এরপর a-এর মান 1 বাড়ল (a++)। a <= 3 সত্য (a-এর মান 2)। এখন দ্বিতীয় লুপ শুরু হবে। b-এর মান 1। এবারে b <= 3 এবং b != a দুটি শর্তই সত্য। প্রোগ্রামটি দ্বিতীয় লুপের ভেতর ঢুকে যাবে। তৃতীয় লুপের শুরুতে c-এর মান 1। c <=3 সত্য, c !=a সত্য কিন্তু c !=b মিথ্যা (দুটোর মানই 1)। তাই প্রোগ্রামটি তৃতীয় লুপ থেকে বের হয়ে যাবে– কেবল তিনটি শর্ত সত্য হলেই প্রোগ্রামটি তৃতীয় লুপের ভেতর ঢুকবে এবং a, b ও c-এর মান প্রিন্ট করবে। এভাবে কিছুক্ষণ গবেষণা করলে তোমরা দেখবে যে যখন a-এর মান 3, b-এর মান 2 এবং c-এর মান 1, তখনই কেবল সব শর্ত সত্য হয় আর আমরা আউটপুট পাই: 3, 2, 1। আসলে দ্বিতীয় লুপে আমরা b-এর মান a-এর মানের সমান হলে লুপ থেকে বের হয়ে যাচ্ছি। সেই কাজটি করা ঠিক হচ্ছে না। আমাদের উচিত দুটো মান সমান হলে পরবর্তী মানের জন্য চেষ্টা করা। আর মান দুটো সমান না হলেই কেবল পরবর্তী কাজ করা। তাহলে আমরা লিখতে পারি: for (b = 1; b <= 3; b++) { if (b != a) { /* b-এর মান a-এর মানের সমান না হলেই ভেতরের অংশে প্রোগ্রামটি ঢুকবে। */ for (c = 1; c <= 3; c++) { if (c != a && c != b) { /*c-এর মান a-এর মানের সমান না হলে এবং c-এর মান b-এর মানের সমান না হলেই কেবল ভেতরের অংশে প্রোগ্রামটি ঢুকবে। */ printf ("%d, %d, %d\n", a, b, c); } } } } তাহলে আমাদের পুরো প্রোগ্রামটি দাঁড়াচ্ছে এই রকম: #include <stdio.h> int main() { int a, b, c; for (a = 1; a <= 3; a++) { for (b = 1; b <= 3; b++) { if (b != a) { for (c = 1; c <= 3; c++) { if (c != b && c != a){ printf ("%d, %d, %d\n", a, b, c); } } } } } return 0; } প্রোগ্রাম: ৪.১৩ প্রোগ্রামটি চালালে আমরা নিচের আউটপুট দেখব, যেটি আমরা চাচ্ছিলাম। 1, 2, 3 1, 3, 2 2, 1, 3 2, 3, 1 3, 1, 2 3, 2, 1 যাক, অবশেষে আমাদের সমস্যার সমাধান হলো। তবে আমরা কিন্তু আরও সহজেই সমাধান করতে পারতাম এভাবে– #include <stdio.h> int main() { int a, b, c; for (a = 1; a <= 3; a++) { for (b = 1; b <= 3; b++) { for (c = 1; c <= 3; c++) { if(b != a && c != a && c != b) { printf ("%d, %d, %d\n", a, b, c); } } } } return 0; } প্রোগ্রাম: ৪.১৪ এখানে আমাদের বেশি চিন্তা করতে হলো না। কেবল প্রিন্ট করার সময় a, b, c তিনটির মান পরস্পরের সমান নয়, সেটি নিশ্চিত করে নিলেই হলো! বুদ্ধিটা ভালোই, তবে এটির চেয়ে আমাদের আগের প্রোগ্রামটি কম্পিউটারকে দিয়ে কম কাজ করায়, তাই চলতেও কম সময় লাগে, বা কম্পিউটারের ভাষায় বললে রান টাইম (run time) কম। আসলে একটি প্রোগ্রাম চলতে কেমন সময় লাগবে সেটি নির্ভর করে মূলত প্রোগ্রামটি মোট কয়টি অ্যাসাইনমেন্ট অপারেশন (assignment operation) আর কয়টি কম্পারিজন অপারেশন (comparison operation) করল তার ওপর।
Share:

প্রোগ্রামিং কন্ডিশনাল লজিক।

কন্ডিশনাল লজিক।
তোমরা অনেকেই হয়তো জানো যে 'চাচা চৌধুরীর বুদ্ধি কম্পিউটারের চেয়েও প্রখর'! এটি শুনে প্রথম প্রথম চাচা চৌধুরীর ওপর ভক্তি-শ্রদ্ধা অনেক বেড়ে গেলেও একটু চিন্তা করলেই তোমরা বুঝতে পারবে যে আসলে তোমাদের সবার বুদ্ধি কম্পিউটারের চেয়ে প্রখর। আসলে কম্পিউটারের তো কোনো বুদ্ধিই নেই। প্রোগ্রামাররা যেভাবে প্রোগ্রাম লিখে দেয় কম্পিউটার সেভাবে কাজ করে। এখন আমরা প্রোগ্রামিংয়ের সহজ অথচ খুব গুরুত্বপূর্ণ একটি বিষয় শিখব। সেটি হচ্ছে কন্ডিশনাল লজিক। কোন শর্তে কী করতে হবে সেটি প্রোগ্রাম লিখে কম্পিউটারকে বোঝাতে হবে। কথা না বাড়িয়ে আমরা প্রোগ্রাম লেখা শুরু করে দিই। তোমরা কিন্তু অবশ্যই প্রতিটি প্রোগ্রাম কম্পিউটারে চালিয়ে দেখবে। #include <stdio.h> int main() { int n; n = 10; if(n >= 0) { printf("The number is positive\n"); } else { printf("The number is negative\n"); } return 0; } প্রোগ্রাম: ৩.১ ওপরের প্রোগ্রামটির কাজ কী? n-এর বিভিন্ন মান (যেমন: 0, -10, -2, 5, 988 ইত্যাদি) বসিয়ে তোমরা প্রোগ্রামটি চালাও। দেখা যাচ্ছে যে এর কাজ হচ্ছে n ধনাত্মক (positive) না ঋণাত্মক (negative) সেটি নির্ণয় করা। কোন সংখ্যা ধনাত্মক হতে গেলে একটি শর্ত পূরণ করতে হয়। সেটি হচ্ছে তাকে শূন্যের সমান বা তার চেয়ে বড় হতে হয়। তাহলে আমাদের লজিকটি দাঁড়াচ্ছে এ রকম যে, 'n যদি শূন্যের সমান বা বড় হয়, তবে nধনাত্মক, না হলে n ঋণাত্মক'। এই ব্যাপারটি সি ল্যাঙ্গুয়েজে প্রকাশ করতে হয় if এবং তার সঙ্গে else ব্যবহার করে। if-এর ভেতর একটি শর্ত (কন্ডিশন) লিখে দিতে হয় যা সত্যি হলেই কেবল তার ভেতরের অংশের কাজ হয় (মানে if-এর পর যে দ্বিতীয় বন্ধনী { } ব্যবহার করা হয়েছে তার ভেতরের সব কাজ)। আর কন্ডিশনটা লিখতে হয় প্রথম বন্ধনীর ভেতরে। if-এর ভেতরে যেই কন্ডিশনটা আছে সেটি যদি মিথ্যা হয়, তবে else-এর ভেতরের (দ্বিতীয় বন্ধনীর ভেতরে) অংশের কাজ হয়। সব প্রোগ্রামিং ল্যাঙ্গুয়েজেই এটি আছে, তবে লিখার ধরন হয়তো আলাদা।
এখন আমাদের দেখতে হবে, কন্ডিশনগুলো কীভাবে লিখতে হবে? তোমরা এতক্ষণে জেনে গেছ যে 'বড় কিংবা সমান' এই তুলনা করার জন্য >= চিহ্ণ ব্যবহার করা হয়। 'ছোট কিংবা সমান'-এর জন্য ব্যবহার করে <= চিহ্ন। দুটি সংখ্যা একটি আরেকটির সমান কি না সেটি পরীক্ষার
জন্য < আর > চিহ্ন ব্যবহার করতে হয়। আরও ব্যাপার-স্যাপার আছে। একবারে সব না শিখে চলো আস্তে আস্তে প্রোগ্রাম লিখে শেখা যাক। এখানে ইন্ডেন্টেশনের ব্যাপারটিও কিন্তু খেয়াল কোরো। if কিংবা else-এর ভেতরের ব্লকের সব লাইন কিন্তু if বা else যেখানে শুরু, তার চার ঘর (চারটি স্পেস) ডান থেকে শুরু হয়েছে। আমরা ওপরের প্রোগ্রামটি এভাবেও লিখতে পারতাম: #include <stdio.h> int main() { int n; n = 10; if(n < 0) { printf("The number is negative\n"); } else { printf("The number is positive\n"); } return 0; } প্রোগ্রাম: ৩.২ এখানে আমরা প্রথমে পরীক্ষা করেছি যে n শূন্যের চেয়ে ছোট কি না। যদি ছোট হয়, তবে n নেগেটিভ; আর সেটি না হলে (সেটি না হওয়া মানে n অবশ্যই শূন্যের সমান বা বড়) n পজিটিভ।
তোমাদের মধ্যে যারা একটু খুঁতখুঁতে স্বভাবের, তারা নিশ্চয়ই ভাবছ যে শূন্য তো আসলে পজিটিভ বা নেগেটিভ কোনোটাই না। শূন্যের চেয়ে বড় সব সংখ্যা হচ্ছে পজিটিভ আর ছোট সব সংখ্যা হচ্ছে নেগেটিভ। কম্পিউটারকে সেটি বোঝাতে গেলে আমরা নিচের প্রোগ্রামটি লিখতে পারি: #include <stdio.h> int main() { int n = 10; if(n < 0) { printf("The number is negative\n"); } else if (n > 0) { printf("The number is positive\n"); } else if (n == 0) { printf("The number is zero!\n"); } return 0; } প্রোগ্রাম: ৩.৩ প্রোগ্রামটি একটু ব্যাখ্যা করা যাক: if(n < 0): এখানে আমরা প্রথমে পরীক্ষা করেছি n শূন্যের চেয়ে ছোট কি না । ছোট হলে তো কথাই নেই। আমরা বলে দিচ্ছি যে সংখ্যাটি নেগেটিভ। else if(n > 0): আর যদি ছোট না হয়, তবে n শূন্যের চেয়ে বড় কি না সেটি পরীক্ষা করেছি if(n > 0)। এই শর্ত সত্যি হলে সংখ্যাটি পজিটিভ। else if(n == 0): আর n > 0ও যদি সত্যি না হয় তবে কোন শর্তটি বাদ রইল? দুটি সমান কি না সেটি পরীক্ষা করা। তাহলে আমরা পরীক্ষা করছি যে n শূন্যের সমান কি না এবং সমান হলে বলে দিচ্ছি যে এটি শূন্য।
দুটি সংখ্যা তুলনা করার সময় প্রথমটা যদি দ্বিতীয়টির চেয়ে বড় না হয়, ছোটও না হয়, তবে তারা অবশ্যই সমান। তাই তৃতীয় কন্ডিশনটা আসলে আমাদের দরকার নেই। আমরা প্রথম দুটি কন্ডিশন মিথ্যা হলেই বলে দিতে পারি যে n-এর মান শূন্য। #include <stdio.h> int main() { int n = 10; if(n < 0) { printf("The number is negative\n"); } else if (n > 0) { printf("The number is positive\n"); } else { printf("The number is zero!\n"); } return 0; } প্রোগ্রাম: ৩.৪ আবার সব সময় যে if ব্যবহার করলেই সঙ্গে else কিংবা else if ব্যবহার করতে হবে, এমন কোনো কথা নেই। নিচের প্রোগ্রামটি দেখো: #include <stdio.h> int main() { int number = 12; if(number > 10) { printf("The number is greater than ten\n"); } return 0; } প্রোগ্রাম: ৩.৫ এখানে কেবল দেখা হচ্ছে যে সংখ্যাটির মান কি দশের চেয়ে বড় কি না।
নিচের প্রোগ্রামটি দেখে বলো তো আউটপুট কী হবে? #include <stdio.h> int main() { int n = 10; if (n < 30) { printf("n is less than 30.\n"); } else if(n < 50) { printf("n is less than 50.\n"); } return 0; } প্রোগ্রাম: ৩.৬ আউটপুট হবে: n is less than 30. যদিও else if(n < 50) এটিও সত্য কিন্তু যেহেতু if (n < 30) সত্য হয়ে গেছে, তাই এর সঙ্গে বাকি যত else if কিংবা else থাকবে, সেগুলো আর পরীক্ষা করা হবে না। এখন তোমরা নিশ্চয়ই নিচের প্রোগ্রামটির আউটপুট বলতে পারবে। #include <stdio.h>
int main()
{
int n = 10;
if (n < 30) {
printf("n is less than 30.\n");
}
if(n < 50) {
printf("n is less than 50.\n");
}
return 0;
}
প্রোগ্রাম: ৩.৭
এখন আমরা আরেকটি প্রোগ্রাম লিখব। কোনো সংখ্যা জোড় না বেজোড় সেটি নির্ণয় করার প্রোগ্রাম। কোনো সংখ্যা জোড় কি না সেটি বোঝার উপায় হচ্ছে সংখ্যাটিকে 2দিয়ে ভাগ করা। যদি ভাগশেষ শূন্য হয়, তবে সংখ্যাটি জোড়; আর ভাগশেষ শূন্য না হয়ে এক হলে সেটি বেজোড়। সি ল্যাঙ্গুয়েজে ভাগশেষ বের করার জন্য মডুলাস অপারেটর (modulus operator) আছে, যেটাকে '%' চিহ্ন দিয়ে প্রকাশ করা হয়। তাহলে আর চিন্তা নেই।
শুরুতে একটি সংখ্যা নেব: int number; এবারে number-এর জন্য একটি মান ঠিক করি: number = 5; এখন numberকে 2 দিয়ে ভাগ করলে যে ভাগশেষ পাব সেটি বের করি: remainder = number % 2; এখন if-এর সাহায্যে remainder-এর মান পরীক্ষা করে আমরা সিদ্ধান্তে পৌঁছে যেতে পারি। remainder-এর কেবল দুটি মানই সম্ভব– 0 আর 1। পুরো প্রোগ্রামটি লিখে ফেলি: #include <stdio.h> int main() { int number, remainder; number = 5; remainder = number % 2; if(remainder == 0) { printf("The number is even\n"); } else { printf("The number is odd\n"); } return 0; } প্রোগ্রাম: ৩.৮ প্রোগ্রামটি remainder ভেরিয়েবল ব্যবহার না করেও লেখা যায়: #include <stdio.h> int main() { int number = 9; if(number % 2 == 0) { printf("The number is even\n"); } else { printf("The number is odd\n"); } return 0; } প্রোগ্রাম: ৩.৯ আচ্ছা, আমাদের যদি কেবল জোড় সংখ্যা
নির্ণয় করতে হতো, তাহলে আমরা কী করতাম? else ব্লকটা বাদ দিয়ে দিতাম।
তোমাদের জন্য এখন একটি ছোট্ট পরীক্ষা। মডুলাস অপারেটর ব্যবহার না করে ভাগশেষ বের করতে পারবে? একবার করে গুণ, ভাগ ও বিয়োগ (*, /, -) ব্যবহার করে কিন্তু কাজটি করা যায়। তোমরা সেটি করার চেষ্টা করতে পারো।
এবার আরেকটি প্রোগ্রাম দেখা যাক। কোনো একটি অক্ষর ছোট হাতের (small letter বা lower case letter) নাকি বড় হাতের (capital letter বা upper case letter), সেটি বের করতে হবে। এর জন্য সবচেয়ে সহজ সমাধানটা হতে পারে এই রকম যে আমরা একটি character টাইপের ভেরিয়েবলের ভেতরে অক্ষরটা রাখতে পারি। তারপর একে একে সেটিকে 26টি lower case letter এবং 26টি upper case letter-এর সঙ্গে তুলনা করে দেখতে পারি। যখনই মিলে যাবে, তখনই বলে দেওয়া যায়, অক্ষরটা কোন ধরনের। char ch = 'p'; if (ch == 'a') { printf("%c is lower case\n", ch); } else if (ch == 'A') { printf("%c is upper case\n", ch); } else if (ch == 'b') { printf("%c is lower case\n", ch); } else if (ch == 'B') { printf("%c is upper case\n", ch); } else if (ch == 'c') { printf("%c is lower case\n", ch); } else if (ch == 'C') { printf("%c is upper case\n", ch); } … এভাবে চলবে।
কিন্তু এই সমস্যার সমাধান করার জন্য এত কোড লিখার কোনো দরকার নেই। এটি সহজে করার জন্য আমাদের জানতে হবে এন্ড অপারেটরের (AND operator) ব্যবহার। সি ল্যাঙ্গুয়েজে একে '&&' চিহ্ন দিয়ে প্রকাশ করা হয়। নিচের কোডটি দেখলেই তোমরা এর কাজ বুঝে যাবে। #include <stdio.h> int main() { char ch = 'W'; if(ch >= 'a' && ch <= 'z') { printf("%c is lower case\n", ch); } if(ch >= 'A' && ch <= 'Z') { printf("%c is upper case\n", ch); } return 0; } প্রোগ্রাম: ৩.১০ '&&'-এর বাঁ পাশে একটি কন্ডিশন এবং ডান পাশে একটি কন্ডিশন থাকবে, এবং দুটি কন্ডিশন সত্য হলেই সম্পূর্ণ কন্ডিশনটা সত্য হবে। ch >= 'a' && ch <= 'z' এটি পুরোটা একটি কন্ডিশন। এখন &&-এর বাঁ দিকে একটি কন্ডিশন আছে ch >= 'a' আর ডানদিকে আরেকটি কন্ডিশন ch <= 'z'। দুটি কন্ডিশনই যদি সত্য হয়, তবে পুরো কন্ডিশনটা সত্য হবে। এখন কম্পিউটার প্রতিটি অক্ষর বোঝার জন্য যেই কোড ব্যবহার করে তাতে a-এর চেয়ে b-এর মান এক বেশি, b-এর চেয়ে c-এর মান এক বেশি, c-এর চেয়ে d-এর মান এক বেশি … এরকম। তাই কোনো অক্ষর lower case হলে সেটি অবশ্যই 'a'-এর সমান কিংবা বড় হতে হবে। আবার সেটি 'z'-এর সমান কিংবা ছোট হতে হবে। একইভাবে A-এর চেয়ে B-এর মান এক বেশি, B-এর চেয়ে C-এর মান এক বেশি … এরকম। তাই কোনো ক্যারেক্টারের মান 'A' থেকে 'Z'-এর মধ্যে হলে আমরা বলতে পারি যে সেটি upper case। 'A'-এর সমান কিংবা বড় হতে হবে এবং 'Z'-এর সমান কিংবা ছোট হতে হবে। আরেকটি ব্যাপার। দ্বিতীয় if-এর আগে else ব্যবহার করা উচিত। তাহলে কম্পাইলার প্রথম if-এর ভেতরের শর্ত সত্য হলে আর পরের if-এর কন্ডিশন পরীক্ষা করবে না। তাতে সময় বাঁচবে। #include <stdio.h>
int main() { char ch = 'k'; if(ch >= 'a' && ch <= 'z') { printf("%c is lower case\n", ch); } else if(ch >= 'A' && ch <= 'Z') { printf("%c is upper case\n", ch); } return 0; } প্রোগ্রাম: ৩.১১
আশা করি, তোমরা '&&'-এর ব্যবহার বুঝে গেছ।
এখন আরেকটি অপারেটরের ব্যবহার দেখব। সেটি হচ্ছে অর (OR)। একে প্রকাশ করা হয় '||' চিহ্ন দিয়ে (পরপর দুটি |)। '&&'-এর ক্ষেত্রে যেমন দুই পাশের শর্ত সত্য হলেই সম্পূর্ণ শর্ত সত্য হয়, '||'-এর ক্ষেত্রে যেকোনো এক পাশের শর্ত সত্য হলেই সম্পূর্ণ শর্ত সত্য হয়।
নিচের প্রোগ্রামটির আউটপুট কী হবে? কোড দেখে বলতে না পারলে প্রোগ্রামটি চালাও। #include <stdio.h> int main() { int num = 5; if(num >= 1 || num <= 10) { printf("yes\n"); } else { printf("no\n"); } return 0; } প্রোগ্রাম: ৩.১২ এটির আউটপুট হবে yes। এখন num-এর মান 50 করে দাও। আউটপুট কী হবে?
এবারেও আউটপুট yesই হবে। কারণ num-এর মান 50 হলে, প্রথম শর্তটি সত্য হবে (num >= 1) আর দ্বিতীয় শর্তটি (n <= 10) মিথ্যা হবে। তবে আমরা যেহেতু দুটি শর্তের মাঝে '||' ব্যবহার করেছি, তাই যেকোনো একটি শর্ত সত্য হলেই সম্পূর্ণ শর্তটি সত্য হবে। এখন আরও একটি সমস্যা। কোনো অক্ষর vowel নাকি consonant, সেটি নির্ণয় করতে হবে। আমরা জানি, vowelগুলো হচ্ছে a, e, i, o, u। এখন কোনো ক্যারেক্টার এই পাঁচটির মধ্যে পড়ে কি না সেটি নির্ণয় করার জন্য যদি আমরা এমন শর্ত দিই: ch >= 'a' && ch <= 'u' তাহলে কিন্তু হবে না। কারণ তাহলে a থেকে u পর্যন্ত সব অক্ষরের জন্যই শর্তটি সত্যি হবে কিন্তু আমাদের দরকার নির্দিষ্ট কিছু অক্ষর। তাই শর্তটি আমরা এভাবে লিখতে পারি: if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') { printf("%c is vowel\n", ch); } else { printf("%c is consonant\n", ch); }
তাহলে এবার সম্পূর্ণ প্রোগ্রামটি তোমরা লিখে ফেলতে পারো
Share:

প্রোগ্রামিং ডাটা টাইপ, ইনপুট ও আউটপুট।

এ অধ্যায়ে আমরা কিছু ছোট ছোট প্রোগ্রাম লিখব। সবগুলো প্রোগ্রাম অবশ্যই কম্পিউটারে চালিয়ে দেখবে এবং একটু পরিবর্তন করে কম্পাইল ও রান করার চেষ্টা করবে।

আমাদের প্রথম প্রোগ্রামটি হবে দুটি সংখ্যা যোগ করার প্রোগ্রাম। এখন কথা হচ্ছে, সংখ্যাগুলো তো কম্পিউটারের মেমোরিতে রাখতে হবে, সেই জটিল কাজটি কীভাবে করব? চিন্তা নেই! সব প্রোগ্রামিং ল্যাঙ্গুয়েজে ভেরিয়েবল বলে একটি জিনিস আছে যেটি কোন নির্দিষ্ট মান ধারণ করার জন্য ব্যবহার করা হয়। ভেরিয়েবলের একটি নাম দিতে হয়, তারপর ভেরিয়েবল = কোনো মান  লিখে দিলে ভেরিয়েবলের ভেতর সেটি ঢুকে যায়। এটির সঙ্গে গাণিতিক সমীকরণের কিন্তু কোনো সম্পর্ক নেই। চলো, প্রোগ্রামটি লিখে রান করাই, তারপর ব্যাখ্যা করা যাবে।
                                                           #include <stdio.h>
                                                            int main()
                                                            {
                                                                 int a;
                                                                  int b;
                                                                  int sum;
                                                                  a = 50;
                                                                  b = 60;
                                                                 sum = a + b;
                                                                 printf("Sum is %d", sum);
                                                                  return 0;
                                                                }  

 প্রোগ্রাম: ২.১  
প্রোগ্রামটি রান করাও, তুমি স্ক্রিনে দেখবে: Sum is 110।

এখানে a, b, sum তিনটি ভেরিয়েবল (variable) আলাদা সংখ্যা ধারণ করে। প্রথমে আমাদের বলে দিতে হবে যে a, b, sum নামে তিনটি ভেরিয়েবল আছে। এবং এগুলোতে কী ধরনের ডাটা থাকবে সেটিও বলে দিতে হবে। int a; দিয়ে আমরা কম্পাইলারকে বলছি a নামে একটি ভেরিয়েবল এই প্রোগ্রামে আছে যেটি একটি পূর্ণসংখ্যা (integer)-এর মান ধারণ করার জন্য ব্যবহার করা হবে। এই কাজটিকে বলে ভেরিয়েবল ডিক্লারেশন। আর int হচ্ছে ডাটা টাইপ, যেটি দেখে সি-এর কম্পাইলার বুঝবে যে এতে ইন্টিজার টাইপ ডাটা থাকবে। আরও বেশ কিছু ডাটা টাইপ আছে, সেগুলো আমরা আস্তে আস্তে দেখব। আমরা চাইলে একই টাইপের ভেরিয়েবলগুলো ডিক্লেয়ার করার সময় আলাদা লাইনে না লিখে একসঙ্গে কমা দিয়েও লিখতে পারতাম, যেমন: int a, b, sum;। আর লক্ষ করো যে ভেরিয়েবল ডিক্লারেশনের শেষে সেমিকোলন ব্যবহার করতে হয়।

এরপর আমি দুটি স্টেটমেন্ট লিখেছি:
a = 50;
b = 60;
এখানে a-এর মান 50 আর b-এর মান 60 বলে দিলাম (assign করলাম), যতক্ষণ না এটি আমরা পরিবর্তন করছি, কম্পাইলার a-এর মান 50 আর b-এর মান 60 ধরবে।

পরের স্টেটমেন্ট হচ্ছে: sum = a + b;। এতে বোঝায়, sum-এর মান হবে a + b-এর সমান, অর্থাৎ a ও b-এর যোগফল যে সংখ্যাটি হবে সেটি আমরা sum নামের ভেরিয়েবলে রেখে দিলাম (বা assign করলাম)।

এবারে যোগফলটি মনিটরে দেখাতে হবে, তাই আমরা printf ফাংশন ব্যবহার করব।
                                                                 printf("Sum is %d", sum);

এখানে দেখো printf ফাংশনের ভেতরে দুটি অংশ। প্রথম অংশে "Sum is %d" দিয়ে বোঝানো হয়েছে স্ক্রিনে প্রিন্ট করতে হবে Sum is এবং তার পরে একটি ইন্টিজার ভেরিয়েবলের মান যেটি %d-এর জায়গায় বসবে। তারপর কমা দিয়ে আমরা sum লিখে বুঝিয়ে দিয়েছি যে %d-তে sum-এর মান প্রিন্ট করতে হবে। ইন্টিজারের জন্য যেমন %d ব্যবহার করলাম, অন্য ধরনের ভেরিয়েবলের জন্য অন্য কিছু লিখতে হবে, যেটি আমরা ব্যবহার করতে করতে শিখব। খুব ভালো হতো যদি আমি এখন একটি চার্ট লিখে দিতাম যে সি ল্যাঙ্গুয়েজে কী কী ডাটা টাইপ আছে, সেগুলো কী দিয়ে লেখে এবং প্রিন্ট করার জন্য কী করতে হবে আর তোমরা সেই চার্ট মুখস্থ করে ফেলতে। কিন্তু শুধু শুধু মুখস্থ করার কোনো দরকার নেই, মুখস্থ করার প্রবণতা চিন্তাশক্তি কমায় আর প্রোগ্রামারদের জন্য চিন্তা করার ক্ষমতা খুবই গুরুত্বপূর্ণ।

আমরা ওপরের প্রোগ্রামটি চাইলে এভাবেও লিখতে পারতাম:
                                                                  #include <stdio.h>
                                                                  int main()
                                                                 {
                                                                       int a, b, sum;
                                                                        a = 50;
                                                                        b = 60;
                                                                        sum = a + b;
                                                                       printf("Sum is %d", sum);
                                                                       return 0;
                                                                   }
                                      প্রোগ্রাম: ২.২
আবার ভেরিয়েবল ডিক্লেয়ার করার সময় একই সঙ্গে অ্যাসাইনও করা যায়:
                                                                      #include <stdio.h>
                                                                      int main()
                                                                      {
                                                                                int a = 50, b = 60, sum;
                                                                                sum = a + b;
                                                                                printf("Sum is %d", sum);
                                                                                return 0;
                                                                          }
                                        প্রোগ্রাম: ২.৩
এখন তোমাদের জন্য একটি প্রশ্ন। নিচের প্রোগ্রামটির আউটপুট কী হবে?
                                                                      #include <stdio.h>
                                                                       int main() 
                                                                       {
                                                                               int x, y;
                                                                               x = 1;
                                                                               y = x;
                                                                               x = 2;
                                                                               printf("%d", y);
                                                                                return 0;
                                                                        }
                                  প্রোগ্রাম: ২.৪
কী মনে হয়? আউটপুট 1 নাকি 2? আউটপুট হবে 1, কারণ প্রথমে কম্পাইলার দেখবে, x-এর মান 1 অ্যাসাইন করা হয়েছে (x = 1;)। তারপর x-এর মানটি আবার y-এ অ্যাসাইন করা হয়েছে (y = x;)। এখন y-এর মান 1। তারপর আবার x-এর মান 2 অ্যাসাইন করা হয়েছে। কিন্তু তাতে y-এর মানের কোনো পরিবর্তন হবে না। প্রোগ্রামিংয়ে y = x; আসলে কোনো সমীকরণ না যে এটি সবসময় সত্য হবে। '=' চিহ্ন দিয়ে একটি ভেরিয়েবলে নির্দিষ্ট কোনো মান রাখা হয়।

এবারে নিচের প্রোগ্রামটি দেখো:
                                                                 #include <stdio.h>
                                                                  int main()
                                                                  {
                                                                      int a = 50, b = 60, sum;
                                                                      sum = a + b;
                                                                      printf("%d + %d = %d", a, b, sum);
                                                                      return 0;
                                                                   }
                              প্রোগ্রাম: ২.৫
প্রোগ্রামটি মনিটরে কী প্রিন্ট করে? চালিয়ে দেখো। printf("%d + %d = %d", a, b, sum); না লিখে printf("%d + %d = %d", b, a, sum); লিখে প্রোগ্রামটি আবার চালাও। এখন জিনিসটি চিন্তা করে বুঝে নাও।

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

যা-হোক, প্রোগ্রামিংয়ের ব্যাপারে যখনই মনে কোনো প্রশ্ন আসবে, সঙ্গে সঙ্গে একটি প্রোগ্রাম লিখে ফেলবে। দেখো তোমার কম্পাইলার কী বলে। ধরা যাক, আমরা যদি int টাইপের ভেরিয়েবলে দশমিক যুক্ত সংখ্যা (বাস্তব সংখ্যা বা real number) ব্যবহার করতাম, তাহলে কী হতো?
                                                                 #include <stdio.h>
                                                                 int main()
                                                               {
                                                                        int a = 50.45, b = 60, sum;
                                                                        sum = a + b;
                                                                         printf("%d + %d = %d", a, b, sum);
                                                                         return 0;
                                                                   }
                                 প্রোগ্রাম: ২.৬
এখানে a-এর মান 50.45 ব্যবহার করলাম। এবারে প্রোগ্রাম চালাও, দেখো কী হয়। আবার মনে যদি প্রশ্ন আসে যে, main ফাংশনের শেষ লাইনে return 0; না লিখলে কী হয়? তাহলে return 0; ছাড়া প্রোগ্রাম চালিয়ে দেখো কী হয়।

আউটপুট হবে: 50 + 60 = 110।

সি কম্পাইলার a-এর মান 50 ধরেছে, যদিও আমরা 50.45 অ্যাসাইন করেছি। এই ব্যাপারটিকে বলে টাইপ কাস্ট (type cast)। বাস্তব সংখ্যা রাখার জন্য সি ভাষায় double নামের ডাটা টাইপ রয়েছে। টাইপ কাস্ট করে double সংখ্যাটিকে int-এ নেওয়া হয়েছে, এটি অটোমেটিক হয়। আবার কম্পাইলারকে বলেও দেওয়া যায়: int a = (int) 50.45।

int a = 50.99; এখানে a-এর মান হবে 50। int a = -50.9; লিখলে a-এর মান হয় -50। এক কথায় বললে double থেকে int-এ টাইপ কাস্ট করলে দশমিকের পরের অংশটি বাদ পড়ে যাবে।

আরেকটি কথা। যেই ভেরিয়েবলকে টাইপ কাস্ট করা হচ্ছে, তার মান কিন্তু পরিবর্তন হয় না। টাইপ কাস্ট করা মানটি একটি ভেরিয়েবলে রাখা যায়। নিচের প্রোগ্রামটি কম্পিউটারে চালালেই বুঝতে পারবে।
                                                                        #include <stdio.h>
                                                                        int main()
                                                                       {
                                                                               int n;
                                                                               double x;
                                                                                x = 10.5;
                                                                                 n = (int)x;
                                                                                printf("Value of n is %d\n", n);
                                                                                printf("Value of x is %lf\n", x);
                                                                                return 0;
                                                                              }                                 
                              প্রোগ্রাম: ২.৭
প্রোগ্রামের আউটপুট দেখো। x-এর মান কিন্তু পরিবর্তন হয়নি। আর বুঝতেই পারছ যে বাস্তব সংখ্যা রাখার জন্য সি-তে যে double টাইপের ভেরিয়েবল ব্যবহার করা হয়, তা প্রিন্ট করার সময় %lf (l এখানে ইংরেজি ছোট হাতের L) ব্যবহার করতে হয়।

int ডাটা টাইপে তো কেবল পূর্ণ সংখ্যা রাখা যায়। কিন্তু সেটি কী যেকোনো পূর্ণসংখ্যা? উত্তরের জন্য একটি প্রোগ্রাম লিখি:
                                                                            #include <stdio.h>
                                                                             int main()
                                                                             {
                                                                                    int a;
                                                                                    a = 1000;
                                                                                    printf("Value of a is %d", a);
                                                                                   a = -21000;
                                                                                   printf("Value of a is %d", a);
                                                                                    a = 10000000;
                                                                                     printf("Value of a is %d", a);
                                                                                     a = -10000000;
                                                                                     printf("Value of a is %d", a);
                                                                                    a = 100020004000503;
                                                                                   printf("Value of a is %d", a);
                                                                                    a = -4325987632;
                                                                                    printf("Value of a is %d", a);
                                                                                    return 0;
                                                                                }
                               প্রোগ্রাম: ২.৮
এখানে আমরা a-তে বিভিন্ন সংখ্যা অ্যাসাইন করলাম। সব মান কি ঠিকঠাক আসছে? আসেনি। কেন আসেনি সেটি ব্যাখ্যা করার আগে একটি কথা বলে নিই। পরপর এতগুলো printf-এর কারণে তোমার কম্পিউটারের স্ক্রিনে নিশ্চয়ই দেখতে একটু অস্বস্তিকর লাগছে। প্রতিটি printf তোমরা এভাবে লিখতে পারো: printf("Value of a is %d\n", a);। এখন printf ফাংশনে ""-এর ভেতর \n লিখলে কী হয় সেটি আমি বলব না। প্রোগ্রামটি চালালেই বুঝতে পারবে।

a-এর সবগুলো মান কিন্তু ঠিকভাবে দেখা যায়নি, যেসব মান -2147483648 থেকে 2147483647 পর্যন্ত কেবল সেগুলোই ঠিকঠাক প্রিন্ট হবে, কারণ এই রেঞ্জের বাইরের সংখ্যা int টাইপের ভেরিয়েবলে রাখা যায় না। এটি হলো int টাইপের সংখ্যার সীমা। সি-তে int টাইপের ডাটার জন্য মেমোরিতে চার বাইট (byte) জায়গা ব্যবহৃত হয়। চার বাইট মানে বত্রিশ বিট (1 byte = 8 bit)। প্রতি বিটে দুটি জিনিস রাখা যায়, 0 আর 1। দুই বিটে রাখা যায় চারটি সংখ্যা (00, 01, 10, 11)। তাহলে 32 বিটে রাখা যাবে: 2^32 টা সংখ্যা অর্থাৎ 4294967296টি সংখ্যা। এখন অর্ধেক ধনাত্মক আর অর্ধেক ঋণাত্মক যদি রাখি, তাহলে -2147483648 থেকে -1 পর্যন্ত মোট 2147483648 সংখ্যা আবার 0 থেকে 2147483647 পর্যন্ত মোট 2147483648টি সংখ্যা, সর্বমোট 4294967296টি সংখ্যা। আশা করি, হিসাবটা বুঝতে পেরেছ।

এখন আমরা যোগ করার প্রোগ্রামটি লিখব যেটি সব বাস্তব সংখ্যা (real number) যোগ করতে পারবে। তোমাদের মনে করিয়ে দিই, পূর্ণসংখ্যা হচ্ছে, ... -3, -2, -1, 0, 1, 2, 3 ... ইত্যাদি। আর বাস্তব সংখ্যা হচ্ছে -5, -3, -2.43, 0, 0.49, 2.92 ইত্যাদি (সংখ্যারেখার ওপর সব সংখ্যাই কিন্তু বাস্তব সংখ্যা)।
 #include <stdio.h>
 int main()
 {
     double a, b, sum;
     a = 9.5;
     b = 8.743;
     sum = a + b;
     printf("Sum is: %lf\n", sum);
     printf("Sum is: %0.2lf\n", sum);
     return 0;
 }
 প্রোগ্রাম: ২.৯
প্রোগ্রামটি কম্পাইল এবং রান করো। আউটপুট হবে নিচের দুই লাইন:

Sum is: 18.243000
Sum is: 18.24

%lf ব্যবহার করায় প্রথম লাইনে দশমিকের পরে ছয় ঘর পর্যন্ত প্রিন্ট হয়েছে। আবার দ্বিতীয় লাইনে দশমিকের পরে দুই ঘর পর্যন্ত প্রিন্ট হয়েছে, কারণ %0.2lf লিখেছি (তিন ঘর পর্যন্ত প্রিন্ট করতে চাইলে %0.3lf লিখতাম, আবার দশমিক অংশ প্রিন্ট করতে না চাইলে %0.0lf)। double টাইপের ডাটার জন্য 64 বিট ব্যবহৃত হয় এবং 1.7E-308 (1.7 x 10-308) থেকে 1.7E+308 (1.7 x 10308) পর্যন্ত ডাটা রাখা যায়। বিস্তারিত হিসাব বুঝতে হলে কম্পিউটার বিজ্ঞানসংক্রান্ত আরও কিছু জ্ঞানবুদ্ধির দরকার, তাই আমি আর এখন সেদিকে যাচ্ছি না।

এখন আমরা আমাদের প্রোগ্রামে এমন ব্যবস্থা রাখতে চাই, যাতে কোন দুটি সংখ্যা যোগ করতে হবে সেটি আমরা কোডের ভেতর লিখব না, ব্যবহারকারীর কাছ থেকে ইনপুট আকারে জেনে নেব। ব্যবহারকারীর (মানে যে প্রোগ্রামটি ব্যবহার করছে) কাছ থেকে ইনপুট নেওয়ার জন্য আমরা scanf ফাংশন ব্যবহার করব (সি-তে আরও ফাংশন আছে এই কাজের জন্য)। তাহলে দেরি না করে প্রোগ্রাম লিখে ফেলি:
 #include <stdio.h>
 int main()
 {
     int a, b, sum;
     scanf("%d", &a);
     scanf("%d", &b);
     sum = a + b;
     printf("Sum is: %d\n", sum);
     return 0;
 }
 প্রোগ্রাম: ২.১০
প্রোগ্রামটি রান করলে দেখবে ফাঁকা স্ক্রিন (blank screen) আসে। তখন তুমি একটি সংখ্যা লিখবে, তারপর স্পেস (space) বা এন্টার (enter) দিয়ে আরেকটি সংখ্যা লিখবে। তারপর আবার এন্টার চাপলে যোগফল দেখতে পাবে।

তোমরা নিশ্চয়ই scanf ফাংশনের ব্যবহার শিখে ফেলেছ। scanf("%d", &a); এখানে ডবল কোটেশনের ভেতরে %d দিয়ে scanf-কে বলে দেওয়া হচ্ছে যে একটি ইন্টিজার বা int টাইপের ভেরিয়েবলের মান পড়তে হবে (ব্যবহারকারী কিবোর্ড থেকে ইনপুট দেবে)। আর দেখো a-এর আগে এমপারসেন্ড (&) চিহ্ন ব্যবহার করা হয়েছে, &a দিয়ে বোঝানো হয়েছে যে সংখ্যাটি ইনপুট দেওয়া হবে সেটি a ভেরিয়েবলের মাঝে অ্যাসাইন হবে। তোমরা যখন সি আরেকটু ভালোভাবে শিখবে, তখন &a-এর প্রকৃত অর্থ বুঝতে পারবে, আপাতত আমরা ব্যবহারের দিকেই মনোযোগ দিই। a এবং b-এর মান একটি scanf ফাংশন দিয়েও নেওয়া যেত এভাবে: scanf("%d %d", &a, &b);। ভেরিয়েবলের আগে & চিহ্ন না দিলে কী সমস্যা? নিচের প্রোগ্রামটি রান করার চেষ্টা করো, কিছু একটি এরর পাবে। এই মুহূর্তে এররটা ব্যাখ্যা করছি না, কারণ ব্যাখ্যাটা একটু জটিল আর এখন বোঝাতে গেলে তোমরা ভুল বুঝতে পারো এবং পরে আমাকে গালমন্দ করবে।
 #include <stdio.h>
 int main()
 {
     int a, b, sum;
     scanf("%d", &a);
     scanf("%d", b);
     sum = a + b;
     printf("Sum is: %d\n", sum);
     return 0;
 }
 প্রোগ্রাম: ২.১১
এখন আমরা যদি ইনপুট হিসেবে ইন্টিজার না নিয়ে ডবল টাইপের ডাটা নিতে চাইতাম তাহলে কী করতে হতো? scanf-এ %d-এর বদলে %lf ব্যবহার করলেই চলত। তোমরা প্রোগ্রামটি লিখে ফেলো এবং দেখো ঠিকঠাক রান হয় কি না। তারপরে বাকি অংশ পড়া শুরু করো।

আসলে ঠিকঠাক রান হবে না, কারণ ডাটা টাইপও পরিবর্তন করতে হবে। মানে int না লিখে double লিখতে হবে। প্রোগ্রামটি ঠিক করে আবার চালাও।

বইতে যখনই আমি কোনো প্রোগ্রাম লেখতে বলব সেটি যত সহজ কিংবা কঠিনই মনে হোক না কেন, সেটি কম্পিউটারে লিখে কম্পাইল ও রান করতে হবে। এ কাজ না করে সামনে আগানো যাবে না। মনে রাখবে, গাড়ি চালানো শেখার জন্য যেমন গাড়ি চালানোর কোনো বিকল্প নেই, সাঁতার শেখার জন্য যেমন সাঁতার কাটার বিকল্প নেই, তেমনই প্রোগ্রামিং শেখার জন্য প্রোগ্রামিং করার কোনো বিকল্প নেই, শুধু বই পড়ে প্রোগ্রামার হওয়া যায় না।

এবারে আমরা আরেক ধরনের ডাটা টাইপ দেখব, সেটি হচ্ছে char (character) টাইপ। তো এই character টাইপের চরিত্র হচ্ছে একে মেমোরিতে রাখার জন্য মাত্র এক বাইট জায়গার দরকার হয়। সাধারণত যেকোনো অক্ষর বা চিহ্ন রাখার জন্য এই টাইপের ডাটা ব্যবহার করা হয়। তবে সেই অক্ষরটা ইংরেজি বর্ণমালার অক্ষর হতে হবে, অন্য ভাষার অক্ষর char টাইপের ভেরিয়েবলে রাখা যাবে না। নিচের প্রোগ্রামটি কম্পিউটারে লিখে রান করাও:
 #include <stdio.h>
 int main()
 {
     char ch;
     printf("Enter the first letter of your name: ");
     scanf("%c", &ch);
     printf("The first letter of your name is: %c\n", ch);
     return 0;
 }
 প্রোগ্রাম: ২.১২
কোড দেখে বুঝতেই পারছ, char টাইপের জন্য printf এবং scanf ফাংশনের ভেতরে %c ব্যবহার করতে হয়। আরেকটি ফাংশন আছে getchar, এটি দিয়েও char টাইপের ডাটা রিড করা যায়। নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     char ch;
     printf("Enter the first letter of your name: ");
     ch = getchar();
     printf("The first letter of your name is: %c\n", ch);
     return 0;
 }
 প্রোগ্রাম: ২.১৩
এটি রান করাও। আগের প্রোগ্রামটির মতো একই কাজ করবে। getchar ফাংশন একটি অক্ষর পড়ে সেটি ch ভেরিয়েবলের ভেতরে অ্যাসাইন করে দিল। আর সরাসরি কোনো কিছু char টাইপ ভেরিয়েবলে রাখতে চাইলে যেই অক্ষর বা চিহ্ন রাখবে তার দুই পাশে সিঙ্গেল কোটেশন চিহ্ন দেবে। যেমন: char c = 'A';

এখন নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     int num1, num2;
     printf("Please enter a number: ");
     scanf("%d", &num1);
     printf("Please enter another number: ");
     scanf("%d", &num2);
     printf("%d + %d = %d\n", num1, num2, num1+num2);
     printf("%d - %d = %d\n", num1, num2, num1-num2);
     printf("%d * %d = %d\n", num1, num2, num1*num2);
     printf("%d / %d = %d\n", num1, num2, num1/num2);
     return 0;
 }
 প্রোগ্রাম: ২.১৪
এটি কম্পাইল ও রান করাও। এটি দেখে নিশ্চয়ই বুঝতে পারছ বিয়োগ, গুণ ও ভাগের কাজ কীভাবে করতে হয়। এবারে তোমাদের কাজ হচ্ছে চারটি। এক, num1 ও num2-এর মধ্যেকার যোগ, বিয়োগ, গুণ, ভাগের কাজটি printf ফাংশনের ভেতরে না করে আগে করা এবং মানটি অন্য একটি ভেরিয়েবলে রেখে দেওয়া। এর জন্য একটি প্রোগ্রাম লিখে ফেলো। দ্বিতীয় কাজ হচ্ছে প্রোগ্রামটি ডবল টাইপের ভেরিয়েবল ব্যবহার করে করো। তৃতীয় কাজ হচ্ছে, num2-এর মান 0 দিয়ে দেখো কী হয়। চতুর্থ কাজটি হচ্ছে printf ফাংশনের ভেতরে ডবল কোটেশনের ভেতরে যেই +, -, *, / চিহ্ন আছে সেগুলো সরাসরি ব্যবহার না করে একটি char টাইপ ভেরিয়েবলে রেখে তারপর ব্যবহার করা। চারটি কাজ ঠিকমতো করার পরে নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     int num1, num2, value;
     char sign;
     printf("Please enter a number: ");
     scanf("%d", &num1);
     printf("Please enter another number: ");
     scanf("%d", &num2);
     value = num1 + num2;
     sign = '+';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     value = num1 - num2;
     sign = '-';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     value = num1 * num2;
     sign = '*';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     value = num1 / num2;
     sign = '/';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     return 0;
 }
 প্রোগ্রাম: ২.১৫
প্রোগ্রামটি দেখলেই বুঝতে পারবে কী কাজ করে। তবে শুধু দেখে বুঝলেই হবে না। কোড করে কম্পাইল ও রান করো।

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

এখন একটি মজার এবং দরকারি জিনিস বলে রাখি। প্রোগ্রামের কোডের ভেতরে তুমি নিজের ভাষাও ব্যবহার করতে পারো। এটিকে বলে কমেন্ট (comment) করা। কম্পাইলার কমেন্টগুলোকে প্রোগ্রামের অংশ ধরবে না। এক লাইনের কমেন্ট হলে // চিহ্ন দিয়ে কমেন্ট শুরু করতে পারো। আর একাধিক লাইন থাকলে /* দিয়ে শুরু এবং */ দিয়ে শেষ করতে হবে। নিচের প্রোগ্রামটি কিন্তু ঠিকঠাক কম্পাইল ও রান হবে।
 #include <stdio.h>
 int main()
 {
     // test program - comment 1
     printf("Hello ");
     /* We have printed Hello,
     now we shall print World.
     Note that this is a multi-line comment */
     printf("World"); // printed world
     return 0;
 }
 প্রোগ্রাম: ২.১৬
এবারে একটি প্রশ্ন, (যেটি সি-এর টেক্সট বইয়ে এই চ্যাপ্টারের শুরুতেই বলে দিত), ভেরিয়েবলগুলোর নামকরণের নিয়মকানুন কী? ভেরিয়েবলের নাম এক বা একাধিক অক্ষরের হতে পারে, অক্ষরগুলো হতে পারে a থেকে z, A থেকে Z, 0 থেকে 9 এবং _ (আন্ডারস্কোর বা আন্ডারবার)। তবে একাধিক অক্ষরের ক্ষেত্রে প্রথম অক্ষরটা অঙ্ক (ডিজিট) হতে পারবে না। তুমি একটি প্রোগ্রামে int 7d; লিখে দেখো কম্পাইলার কী বলে। আর ভেরিয়েবলের নামগুলো অর্থপূর্ণ হলে ভালো হয়। যেমন, যোগফল রাখার জন্য ভেরিয়েবলের নাম sum হলেই ভালো, যদিও y নাম দিলেও প্রোগ্রাম চলে। অর্থপূর্ণ নাম দিলে বুঝতে সুবিধা হয়, ভেরিয়েবলটা কী উদ্দেশ্যে ব্যবহার করা হয়েছে।

[প্রোগ্রামিং বইঃ অধ্যায় দুই] ডাটা টাইপ, ইনপুট ও আউটপুট।

এ অধ্যায়ে আমরা কিছু ছোট ছোট প্রোগ্রাম লিখব। সবগুলো প্রোগ্রাম অবশ্যই কম্পিউটারে চালিয়ে দেখবে এবং একটু পরিবর্তন করে কম্পাইল ও রান করার চেষ্টা করবে।

আমাদের প্রথম প্রোগ্রামটি হবে দুটি সংখ্যা যোগ করার প্রোগ্রাম। এখন কথা হচ্ছে, সংখ্যাগুলো তো কম্পিউটারের মেমোরিতে রাখতে হবে, সেই জটিল কাজটি কীভাবে করব? চিন্তা নেই! সব প্রোগ্রামিং ল্যাঙ্গুয়েজে ভেরিয়েবল বলে একটি জিনিস আছে যেটি কোন নির্দিষ্ট মান ধারণ করার জন্য ব্যবহার করা হয়। ভেরিয়েবলের একটি নাম দিতে হয়, তারপর ভেরিয়েবল = কোনো মান  লিখে দিলে ভেরিয়েবলের ভেতর সেটি ঢুকে যায়। এটির সঙ্গে গাণিতিক সমীকরণের কিন্তু কোনো সম্পর্ক নেই। চলো, প্রোগ্রামটি লিখে রান করাই, তারপর ব্যাখ্যা করা যাবে।
 #include <stdio.h>
 int main()
 {
     int a;
     int b;
     int sum;
     a = 50;
     b = 60;
     sum = a + b;
     printf("Sum is %d", sum);
     return 0;
 }
 প্রোগ্রাম: ২.১
প্রোগ্রামটি রান করাও, তুমি স্ক্রিনে দেখবে: Sum is 110।

এখানে a, b, sum তিনটি ভেরিয়েবল (variable) আলাদা সংখ্যা ধারণ করে। প্রথমে আমাদের বলে দিতে হবে যে a, b, sum নামে তিনটি ভেরিয়েবল আছে। এবং এগুলোতে কী ধরনের ডাটা থাকবে সেটিও বলে দিতে হবে। int a; দিয়ে আমরা কম্পাইলারকে বলছি a নামে একটি ভেরিয়েবল এই প্রোগ্রামে আছে যেটি একটি পূর্ণসংখ্যা (integer)-এর মান ধারণ করার জন্য ব্যবহার করা হবে। এই কাজটিকে বলে ভেরিয়েবল ডিক্লারেশন। আর int হচ্ছে ডাটা টাইপ, যেটি দেখে সি-এর কম্পাইলার বুঝবে যে এতে ইন্টিজার টাইপ ডাটা থাকবে। আরও বেশ কিছু ডাটা টাইপ আছে, সেগুলো আমরা আস্তে আস্তে দেখব। আমরা চাইলে একই টাইপের ভেরিয়েবলগুলো ডিক্লেয়ার করার সময় আলাদা লাইনে না লিখে একসঙ্গে কমা দিয়েও লিখতে পারতাম, যেমন: int a, b, sum;। আর লক্ষ করো যে ভেরিয়েবল ডিক্লারেশনের শেষে সেমিকোলন ব্যবহার করতে হয়।

এরপর আমি দুটি স্টেটমেন্ট লিখেছি:
a = 50;
b = 60;
এখানে a-এর মান 50 আর b-এর মান 60 বলে দিলাম (assign করলাম), যতক্ষণ না এটি আমরা পরিবর্তন করছি, কম্পাইলার a-এর মান 50 আর b-এর মান 60 ধরবে।

পরের স্টেটমেন্ট হচ্ছে: sum = a + b;। এতে বোঝায়, sum-এর মান হবে a + b-এর সমান, অর্থাৎ a ও b-এর যোগফল যে সংখ্যাটি হবে সেটি আমরা sum নামের ভেরিয়েবলে রেখে দিলাম (বা assign করলাম)।

এবারে যোগফলটি মনিটরে দেখাতে হবে, তাই আমরা printf ফাংশন ব্যবহার করব।
printf("Sum is %d", sum);

এখানে দেখো printf ফাংশনের ভেতরে দুটি অংশ। প্রথম অংশে "Sum is %d" দিয়ে বোঝানো হয়েছে স্ক্রিনে প্রিন্ট করতে হবে Sum is এবং তার পরে একটি ইন্টিজার ভেরিয়েবলের মান যেটি %d-এর জায়গায় বসবে। তারপর কমা দিয়ে আমরা sum লিখে বুঝিয়ে দিয়েছি যে %d-তে sum-এর মান প্রিন্ট করতে হবে। ইন্টিজারের জন্য যেমন %d ব্যবহার করলাম, অন্য ধরনের ভেরিয়েবলের জন্য অন্য কিছু লিখতে হবে, যেটি আমরা ব্যবহার করতে করতে শিখব। খুব ভালো হতো যদি আমি এখন একটি চার্ট লিখে দিতাম যে সি ল্যাঙ্গুয়েজে কী কী ডাটা টাইপ আছে, সেগুলো কী দিয়ে লেখে এবং প্রিন্ট করার জন্য কী করতে হবে আর তোমরা সেই চার্ট মুখস্থ করে ফেলতে। কিন্তু শুধু শুধু মুখস্থ করার কোনো দরকার নেই, মুখস্থ করার প্রবণতা চিন্তাশক্তি কমায় আর প্রোগ্রামারদের জন্য চিন্তা করার ক্ষমতা খুবই গুরুত্বপূর্ণ।

আমরা ওপরের প্রোগ্রামটি চাইলে এভাবেও লিখতে পারতাম:
 #include <stdio.h>
 int main()
 {
     int a, b, sum;
     a = 50;
     b = 60;
     sum = a + b;
     printf("Sum is %d", sum);
     return 0;
 }
 প্রোগ্রাম: ২.২
আবার ভেরিয়েবল ডিক্লেয়ার করার সময় একই সঙ্গে অ্যাসাইনও করা যায়:
 #include <stdio.h>
 int main()
 {
     int a = 50, b = 60, sum;
     sum = a + b;
     printf("Sum is %d", sum);
     return 0;
 }
 প্রোগ্রাম: ২.৩
এখন তোমাদের জন্য একটি প্রশ্ন। নিচের প্রোগ্রামটির আউটপুট কী হবে?
 #include <stdio.h>
 int main() 
 {
     int x, y;
     x = 1;
     y = x;
     x = 2;
     printf("%d", y);
     return 0;
 }
 প্রোগ্রাম: ২.৪
কী মনে হয়? আউটপুট 1 নাকি 2? আউটপুট হবে 1, কারণ প্রথমে কম্পাইলার দেখবে, x-এর মান 1 অ্যাসাইন করা হয়েছে (x = 1;)। তারপর x-এর মানটি আবার y-এ অ্যাসাইন করা হয়েছে (y = x;)। এখন y-এর মান 1। তারপর আবার x-এর মান 2 অ্যাসাইন করা হয়েছে। কিন্তু তাতে y-এর মানের কোনো পরিবর্তন হবে না। প্রোগ্রামিংয়ে y = x; আসলে কোনো সমীকরণ না যে এটি সবসময় সত্য হবে। '=' চিহ্ন দিয়ে একটি ভেরিয়েবলে নির্দিষ্ট কোনো মান রাখা হয়।

এবারে নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     int a = 50, b = 60, sum;
     sum = a + b;
     printf("%d + %d = %d", a, b, sum);
     return 0;
 }
 প্রোগ্রাম: ২.৫
প্রোগ্রামটি মনিটরে কী প্রিন্ট করে? চালিয়ে দেখো। printf("%d + %d = %d", a, b, sum); না লিখে printf("%d + %d = %d", b, a, sum); লিখে প্রোগ্রামটি আবার চালাও। এখন জিনিসটি চিন্তা করে বুঝে নাও।

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

যা-হোক, প্রোগ্রামিংয়ের ব্যাপারে যখনই মনে কোনো প্রশ্ন আসবে, সঙ্গে সঙ্গে একটি প্রোগ্রাম লিখে ফেলবে। দেখো তোমার কম্পাইলার কী বলে। ধরা যাক, আমরা যদি int টাইপের ভেরিয়েবলে দশমিক যুক্ত সংখ্যা (বাস্তব সংখ্যা বা real number) ব্যবহার করতাম, তাহলে কী হতো?
 #include <stdio.h>
 int main()
 {
     int a = 50.45, b = 60, sum;
     sum = a + b;
     printf("%d + %d = %d", a, b, sum);
     return 0;
 }
 প্রোগ্রাম: ২.৬
এখানে a-এর মান 50.45 ব্যবহার করলাম। এবারে প্রোগ্রাম চালাও, দেখো কী হয়। আবার মনে যদি প্রশ্ন আসে যে, main ফাংশনের শেষ লাইনে return 0; না লিখলে কী হয়? তাহলে return 0; ছাড়া প্রোগ্রাম চালিয়ে দেখো কী হয়।

আউটপুট হবে: 50 + 60 = 110।

সি কম্পাইলার a-এর মান 50 ধরেছে, যদিও আমরা 50.45 অ্যাসাইন করেছি। এই ব্যাপারটিকে বলে টাইপ কাস্ট (type cast)। বাস্তব সংখ্যা রাখার জন্য সি ভাষায় double নামের ডাটা টাইপ রয়েছে। টাইপ কাস্ট করে double সংখ্যাটিকে int-এ নেওয়া হয়েছে, এটি অটোমেটিক হয়। আবার কম্পাইলারকে বলেও দেওয়া যায়: int a = (int) 50.45।

int a = 50.99; এখানে a-এর মান হবে 50। int a = -50.9; লিখলে a-এর মান হয় -50। এক কথায় বললে double থেকে int-এ টাইপ কাস্ট করলে দশমিকের পরের অংশটি বাদ পড়ে যাবে।

আরেকটি কথা। যেই ভেরিয়েবলকে টাইপ কাস্ট করা হচ্ছে, তার মান কিন্তু পরিবর্তন হয় না। টাইপ কাস্ট করা মানটি একটি ভেরিয়েবলে রাখা যায়। নিচের প্রোগ্রামটি কম্পিউটারে চালালেই বুঝতে পারবে।
 #include <stdio.h>
 int main()
 {
     int n;
     double x;
     x = 10.5;
     n = (int)x;
     printf("Value of n is %d\n", n);
     printf("Value of x is %lf\n", x);
     return 0;
 }
 প্রোগ্রাম: ২.৭
প্রোগ্রামের আউটপুট দেখো। x-এর মান কিন্তু পরিবর্তন হয়নি। আর বুঝতেই পারছ যে বাস্তব সংখ্যা রাখার জন্য সি-তে যে double টাইপের ভেরিয়েবল ব্যবহার করা হয়, তা প্রিন্ট করার সময় %lf (l এখানে ইংরেজি ছোট হাতের L) ব্যবহার করতে হয়।

int ডাটা টাইপে তো কেবল পূর্ণ সংখ্যা রাখা যায়। কিন্তু সেটি কী যেকোনো পূর্ণসংখ্যা? উত্তরের জন্য একটি প্রোগ্রাম লিখি:
 #include <stdio.h>
 int main()
 {
     int a;
     a = 1000;
     printf("Value of a is %d", a);
     a = -21000;
     printf("Value of a is %d", a);
     a = 10000000;
     printf("Value of a is %d", a);
     a = -10000000;
     printf("Value of a is %d", a);
     a = 100020004000503;
     printf("Value of a is %d", a);
     a = -4325987632;
     printf("Value of a is %d", a);
     return 0;
 }
 প্রোগ্রাম: ২.৮
এখানে আমরা a-তে বিভিন্ন সংখ্যা অ্যাসাইন করলাম। সব মান কি ঠিকঠাক আসছে? আসেনি। কেন আসেনি সেটি ব্যাখ্যা করার আগে একটি কথা বলে নিই। পরপর এতগুলো printf-এর কারণে তোমার কম্পিউটারের স্ক্রিনে নিশ্চয়ই দেখতে একটু অস্বস্তিকর লাগছে। প্রতিটি printf তোমরা এভাবে লিখতে পারো: printf("Value of a is %d\n", a);। এখন printf ফাংশনে ""-এর ভেতর \n লিখলে কী হয় সেটি আমি বলব না। প্রোগ্রামটি চালালেই বুঝতে পারবে।

a-এর সবগুলো মান কিন্তু ঠিকভাবে দেখা যায়নি, যেসব মান -2147483648 থেকে 2147483647 পর্যন্ত কেবল সেগুলোই ঠিকঠাক প্রিন্ট হবে, কারণ এই রেঞ্জের বাইরের সংখ্যা int টাইপের ভেরিয়েবলে রাখা যায় না। এটি হলো int টাইপের সংখ্যার সীমা। সি-তে int টাইপের ডাটার জন্য মেমোরিতে চার বাইট (byte) জায়গা ব্যবহৃত হয়। চার বাইট মানে বত্রিশ বিট (1 byte = 8 bit)। প্রতি বিটে দুটি জিনিস রাখা যায়, 0 আর 1। দুই বিটে রাখা যায় চারটি সংখ্যা (00, 01, 10, 11)। তাহলে 32 বিটে রাখা যাবে: 2^32 টা সংখ্যা অর্থাৎ 4294967296টি সংখ্যা। এখন অর্ধেক ধনাত্মক আর অর্ধেক ঋণাত্মক যদি রাখি, তাহলে -2147483648 থেকে -1 পর্যন্ত মোট 2147483648 সংখ্যা আবার 0 থেকে 2147483647 পর্যন্ত মোট 2147483648টি সংখ্যা, সর্বমোট 4294967296টি সংখ্যা। আশা করি, হিসাবটা বুঝতে পেরেছ।

এখন আমরা যোগ করার প্রোগ্রামটি লিখব যেটি সব বাস্তব সংখ্যা (real number) যোগ করতে পারবে। তোমাদের মনে করিয়ে দিই, পূর্ণসংখ্যা হচ্ছে, ... -3, -2, -1, 0, 1, 2, 3 ... ইত্যাদি। আর বাস্তব সংখ্যা হচ্ছে -5, -3, -2.43, 0, 0.49, 2.92 ইত্যাদি (সংখ্যারেখার ওপর সব সংখ্যাই কিন্তু বাস্তব সংখ্যা)।
 #include <stdio.h>
 int main()
 {
     double a, b, sum;
     a = 9.5;
     b = 8.743;
     sum = a + b;
     printf("Sum is: %lf\n", sum);
     printf("Sum is: %0.2lf\n", sum);
     return 0;
 }
 প্রোগ্রাম: ২.৯
প্রোগ্রামটি কম্পাইল এবং রান করো। আউটপুট হবে নিচের দুই লাইন:

Sum is: 18.243000
Sum is: 18.24

%lf ব্যবহার করায় প্রথম লাইনে দশমিকের পরে ছয় ঘর পর্যন্ত প্রিন্ট হয়েছে। আবার দ্বিতীয় লাইনে দশমিকের পরে দুই ঘর পর্যন্ত প্রিন্ট হয়েছে, কারণ %0.2lf লিখেছি (তিন ঘর পর্যন্ত প্রিন্ট করতে চাইলে %0.3lf লিখতাম, আবার দশমিক অংশ প্রিন্ট করতে না চাইলে %0.0lf)। double টাইপের ডাটার জন্য 64 বিট ব্যবহৃত হয় এবং 1.7E-308 (1.7 x 10-308) থেকে 1.7E+308 (1.7 x 10308) পর্যন্ত ডাটা রাখা যায়। বিস্তারিত হিসাব বুঝতে হলে কম্পিউটার বিজ্ঞানসংক্রান্ত আরও কিছু জ্ঞানবুদ্ধির দরকার, তাই আমি আর এখন সেদিকে যাচ্ছি না।

এখন আমরা আমাদের প্রোগ্রামে এমন ব্যবস্থা রাখতে চাই, যাতে কোন দুটি সংখ্যা যোগ করতে হবে সেটি আমরা কোডের ভেতর লিখব না, ব্যবহারকারীর কাছ থেকে ইনপুট আকারে জেনে নেব। ব্যবহারকারীর (মানে যে প্রোগ্রামটি ব্যবহার করছে) কাছ থেকে ইনপুট নেওয়ার জন্য আমরা scanf ফাংশন ব্যবহার করব (সি-তে আরও ফাংশন আছে এই কাজের জন্য)। তাহলে দেরি না করে প্রোগ্রাম লিখে ফেলি:
 #include <stdio.h>
 int main()
 {
     int a, b, sum;
     scanf("%d", &a);
     scanf("%d", &b);
     sum = a + b;
     printf("Sum is: %d\n", sum);
     return 0;
 }
 প্রোগ্রাম: ২.১০
প্রোগ্রামটি রান করলে দেখবে ফাঁকা স্ক্রিন (blank screen) আসে। তখন তুমি একটি সংখ্যা লিখবে, তারপর স্পেস (space) বা এন্টার (enter) দিয়ে আরেকটি সংখ্যা লিখবে। তারপর আবার এন্টার চাপলে যোগফল দেখতে পাবে।

তোমরা নিশ্চয়ই scanf ফাংশনের ব্যবহার শিখে ফেলেছ। scanf("%d", &a); এখানে ডবল কোটেশনের ভেতরে %d দিয়ে scanf-কে বলে দেওয়া হচ্ছে যে একটি ইন্টিজার বা int টাইপের ভেরিয়েবলের মান পড়তে হবে (ব্যবহারকারী কিবোর্ড থেকে ইনপুট দেবে)। আর দেখো a-এর আগে এমপারসেন্ড (&) চিহ্ন ব্যবহার করা হয়েছে, &a দিয়ে বোঝানো হয়েছে যে সংখ্যাটি ইনপুট দেওয়া হবে সেটি a ভেরিয়েবলের মাঝে অ্যাসাইন হবে। তোমরা যখন সি আরেকটু ভালোভাবে শিখবে, তখন &a-এর প্রকৃত অর্থ বুঝতে পারবে, আপাতত আমরা ব্যবহারের দিকেই মনোযোগ দিই। a এবং b-এর মান একটি scanf ফাংশন দিয়েও নেওয়া যেত এভাবে: scanf("%d %d", &a, &b);। ভেরিয়েবলের আগে & চিহ্ন না দিলে কী সমস্যা? নিচের প্রোগ্রামটি রান করার চেষ্টা করো, কিছু একটি এরর পাবে। এই মুহূর্তে এররটা ব্যাখ্যা করছি না, কারণ ব্যাখ্যাটা একটু জটিল আর এখন বোঝাতে গেলে তোমরা ভুল বুঝতে পারো এবং পরে আমাকে গালমন্দ করবে।
 #include <stdio.h>
 int main()
 {
     int a, b, sum;
     scanf("%d", &a);
     scanf("%d", b);
     sum = a + b;
     printf("Sum is: %d\n", sum);
     return 0;
 }
 প্রোগ্রাম: ২.১১
এখন আমরা যদি ইনপুট হিসেবে ইন্টিজার না নিয়ে ডবল টাইপের ডাটা নিতে চাইতাম তাহলে কী করতে হতো? scanf-এ %d-এর বদলে %lf ব্যবহার করলেই চলত। তোমরা প্রোগ্রামটি লিখে ফেলো এবং দেখো ঠিকঠাক রান হয় কি না। তারপরে বাকি অংশ পড়া শুরু করো।

আসলে ঠিকঠাক রান হবে না, কারণ ডাটা টাইপও পরিবর্তন করতে হবে। মানে int না লিখে double লিখতে হবে। প্রোগ্রামটি ঠিক করে আবার চালাও।

বইতে যখনই আমি কোনো প্রোগ্রাম লেখতে বলব সেটি যত সহজ কিংবা কঠিনই মনে হোক না কেন, সেটি কম্পিউটারে লিখে কম্পাইল ও রান করতে হবে। এ কাজ না করে সামনে আগানো যাবে না। মনে রাখবে, গাড়ি চালানো শেখার জন্য যেমন গাড়ি চালানোর কোনো বিকল্প নেই, সাঁতার শেখার জন্য যেমন সাঁতার কাটার বিকল্প নেই, তেমনই প্রোগ্রামিং শেখার জন্য প্রোগ্রামিং করার কোনো বিকল্প নেই, শুধু বই পড়ে প্রোগ্রামার হওয়া যায় না।

এবারে আমরা আরেক ধরনের ডাটা টাইপ দেখব, সেটি হচ্ছে char (character) টাইপ। তো এই character টাইপের চরিত্র হচ্ছে একে মেমোরিতে রাখার জন্য মাত্র এক বাইট জায়গার দরকার হয়। সাধারণত যেকোনো অক্ষর বা চিহ্ন রাখার জন্য এই টাইপের ডাটা ব্যবহার করা হয়। তবে সেই অক্ষরটা ইংরেজি বর্ণমালার অক্ষর হতে হবে, অন্য ভাষার অক্ষর char টাইপের ভেরিয়েবলে রাখা যাবে না। নিচের প্রোগ্রামটি কম্পিউটারে লিখে রান করাও:
 #include <stdio.h>
 int main()
 {
     char ch;
     printf("Enter the first letter of your name: ");
     scanf("%c", &ch);
     printf("The first letter of your name is: %c\n", ch);
     return 0;
 }
 প্রোগ্রাম: ২.১২
কোড দেখে বুঝতেই পারছ, char টাইপের জন্য printf এবং scanf ফাংশনের ভেতরে %c ব্যবহার করতে হয়। আরেকটি ফাংশন আছে getchar, এটি দিয়েও char টাইপের ডাটা রিড করা যায়। নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     char ch;
     printf("Enter the first letter of your name: ");
     ch = getchar();
     printf("The first letter of your name is: %c\n", ch);
     return 0;
 }
 প্রোগ্রাম: ২.১৩
এটি রান করাও। আগের প্রোগ্রামটির মতো একই কাজ করবে। getchar ফাংশন একটি অক্ষর পড়ে সেটি ch ভেরিয়েবলের ভেতরে অ্যাসাইন করে দিল। আর সরাসরি কোনো কিছু char টাইপ ভেরিয়েবলে রাখতে চাইলে যেই অক্ষর বা চিহ্ন রাখবে তার দুই পাশে সিঙ্গেল কোটেশন চিহ্ন দেবে। যেমন: char c = 'A';

এখন নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     int num1, num2;
     printf("Please enter a number: ");
     scanf("%d", &num1);
     printf("Please enter another number: ");
     scanf("%d", &num2);
     printf("%d + %d = %d\n", num1, num2, num1+num2);
     printf("%d - %d = %d\n", num1, num2, num1-num2);
     printf("%d * %d = %d\n", num1, num2, num1*num2);
     printf("%d / %d = %d\n", num1, num2, num1/num2);
     return 0;
 }
 প্রোগ্রাম: ২.১৪
এটি কম্পাইল ও রান করাও। এটি দেখে নিশ্চয়ই বুঝতে পারছ বিয়োগ, গুণ ও ভাগের কাজ কীভাবে করতে হয়। এবারে তোমাদের কাজ হচ্ছে চারটি। এক, num1 ও num2-এর মধ্যেকার যোগ, বিয়োগ, গুণ, ভাগের কাজটি printf ফাংশনের ভেতরে না করে আগে করা এবং মানটি অন্য একটি ভেরিয়েবলে রেখে দেওয়া। এর জন্য একটি প্রোগ্রাম লিখে ফেলো। দ্বিতীয় কাজ হচ্ছে প্রোগ্রামটি ডবল টাইপের ভেরিয়েবল ব্যবহার করে করো। তৃতীয় কাজ হচ্ছে, num2-এর মান 0 দিয়ে দেখো কী হয়। চতুর্থ কাজটি হচ্ছে printf ফাংশনের ভেতরে ডবল কোটেশনের ভেতরে যেই +, -, *, / চিহ্ন আছে সেগুলো সরাসরি ব্যবহার না করে একটি char টাইপ ভেরিয়েবলে রেখে তারপর ব্যবহার করা। চারটি কাজ ঠিকমতো করার পরে নিচের প্রোগ্রামটি দেখো:
 #include <stdio.h>
 int main()
 {
     int num1, num2, value;
     char sign;
     printf("Please enter a number: ");
     scanf("%d", &num1);
     printf("Please enter another number: ");
     scanf("%d", &num2);
     value = num1 + num2;
     sign = '+';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     value = num1 - num2;
     sign = '-';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     value = num1 * num2;
     sign = '*';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     value = num1 / num2;
     sign = '/';
     printf("%d %c %d = %d\n", num1, sign, num2, value);
     return 0;
 }
 প্রোগ্রাম: ২.১৫
প্রোগ্রামটি দেখলেই বুঝতে পারবে কী কাজ করে। তবে শুধু দেখে বুঝলেই হবে না। কোড করে কম্পাইল ও রান করো।

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

এখন একটি মজার এবং দরকারি জিনিস বলে রাখি। প্রোগ্রামের কোডের ভেতরে তুমি নিজের ভাষাও ব্যবহার করতে পারো। এটিকে বলে কমেন্ট (comment) করা। কম্পাইলার কমেন্টগুলোকে প্রোগ্রামের অংশ ধরবে না। এক লাইনের কমেন্ট হলে // চিহ্ন দিয়ে কমেন্ট শুরু করতে পারো। আর একাধিক লাইন থাকলে /* দিয়ে শুরু এবং */ দিয়ে শেষ করতে হবে। নিচের প্রোগ্রামটি কিন্তু ঠিকঠাক কম্পাইল ও রান হবে।
 #include <stdio.h>
 int main()
 {
     // test program - comment 1
     printf("Hello ");
     /* We have printed Hello,
     now we shall print World.
     Note that this is a multi-line comment */
     printf("World"); // printed world
     return 0;
 }
 প্রোগ্রাম: ২.১৬
এবারে একটি প্রশ্ন, (যেটি সি-এর টেক্সট বইয়ে এই চ্যাপ্টারের শুরুতেই বলে দিত), ভেরিয়েবলগুলোর নামকরণের নিয়মকানুন কী? ভেরিয়েবলের নাম এক বা একাধিক অক্ষরের হতে পারে, অক্ষরগুলো হতে পারে a থেকে z, A থেকে Z, 0 থেকে 9 এবং _ (আন্ডারস্কোর বা আন্ডারবার)। তবে একাধিক অক্ষরের ক্ষেত্রে প্রথম অক্ষরটা অঙ্ক (ডিজিট) হতে পারবে না। তুমি একটি প্রোগ্রামে int 7d; লিখে দেখো কম্পাইলার কী বলে। আর ভেরিয়েবলের নামগুলো অর্থপূর্ণ হলে ভালো হয়। যেমন, যোগফল রাখার জন্য ভেরিয়েবলের নাম sum হলেই ভালো, যদিও y নাম দিলেও প্রোগ্রাম চলে। অর্থপূর্ণ নাম দিলে বুঝতে সুবিধা হয়, ভেরিয়েবলটা কী উদ্দেশ্যে ব্যবহার করা হয়েছে।
Share:

Pages

Theme Support