এর আগের প্রোগ্রামে আমরা মাত্র এক লাইন এর একটা আউটপুট দেখিয়েছি। যা শুধু মাত্র প্রোগ্রামিং শুরু করার জন্যই যথেষ্ট ছিল। বাস্তবে আমাদের জটিল কিছু প্রোগ্রাম লিখতে হবে। যার জন্য দরকার আমাদের ভ্যারিয়েবল এর ধারনা।
ভ্যারিয়েবল হচ্ছে একটি নাম, যা দিয়ে কম্পিউটারের মেমরিতে কোন ডেটা রাখা হয়। এ ডেটা হতে পারে নিউম্যারিক (যে কোন সংখ্যা) অথবা একটি character মান। এ ভ্যারিয়েবল এর মধ্যে কি ধরনের ডেটা রাখব আমরা তাই হচ্ছে ডেটা টাইপ। ভ্যারিয়েবল সম্পর্কে আমরা পরে আবার জানব। এবার একটু এ ডেটা টাইফ সম্পর্কে জানি।
সি প্রোগ্রামিং এ অনেক প্রকারের ডাটা টাইপ আছে। তার মধ্য প্রধান চারটি হচ্ছেঃ
- int data type
- char data type
- float data type
- double data type
int data type
int data type বলতে integer quantity(অবিভাজ্য সংখা যেমনঃ ১, ২, ৩ ইত্যাদি) বুঝায়। এর সাইজ ২ বাইট বা ১৬ বিট(১বাইট=৮বিট)এবং রেঞ্জঃ -৩২৭৬৮ থেকে +৩২৭৬৭ পর্যন্ত। কিছু কিছু কম্পাইলারে int ডেটার জন্য ৪ বাইট মেমরি দেয়। অর্থাৎ একটা int ডেটা টাইপের জন্য সর্বোচ্চ ৪ বাইট ডেটা রাখা যাবে। যার রেঞ্জ হচ্ছে -2,147,483,648 থেকে 2,147,483,647 এ রেঞ্জ এর মানে হচ্ছে এর থেকে বড় মানের সংখ্যা যদি আমরা ব্যবহার করি তাহলে কম্পাইলার সঠিক মান দিবে না। এ সাইজ এবং রেঞ্জ কম্পাইলার ভেদে ভিন্ন হতে পারে।
int data type এর উদাহরন হিসেবে আমরা একটা প্রোগ্রাম দেখতে পারি। একটি আয়াতাকার জমির দৈর্ঘ্য এবং প্রস্থ জানলে আমরা তার ক্ষেত্রফল বের করতে পারি। তাই না? মনে করে নিচ্ছি দৈর্ঘ্য ৫ একক এবং প্রস্থ ৮ একক। আমরা এর ক্ষেত্রফল হবে ৫*৮ = ৪০ একক। প্রোগ্রামে আমরা কিভাবে তা বের করতে পারি? নিচের প্রোগ্রামটি দেখি।
int data type এর উদাহরন হিসেবে আমরা একটা প্রোগ্রাম দেখতে পারি। একটি আয়াতাকার জমির দৈর্ঘ্য এবং প্রস্থ জানলে আমরা তার ক্ষেত্রফল বের করতে পারি। তাই না? মনে করে নিচ্ছি দৈর্ঘ্য ৫ একক এবং প্রস্থ ৮ একক। আমরা এর ক্ষেত্রফল হবে ৫*৮ = ৪০ একক। প্রোগ্রামে আমরা কিভাবে তা বের করতে পারি? নিচের প্রোগ্রামটি দেখি।
1
2
3
4
5
6
7
8
9
10
11
| #include <stdio.h> int main() { int volume; int length = 5; int width = 8; volume = length * width; printf ( "%d" , volume); return 0; } |
প্রোগ্রামটি রান করলে আমরা আউটপুট দেখতে পাবো 40
এটা অবশ্যই আমাদের প্রথম প্রোগ্রাম থেকে দেখতে অনেক জটিল। এবং কিছুটা বড়। তবে অবশ্যই অনেক সহজ। কিছুক্ষন আগে আমরা ভ্যারিয়বল নামে একটা বস্তুর নাম শুনছি যা কোন কিছু স্টোর বা সেভ করে রাখে কম্পিউটার মেমরিতে।
আমাদের হিসেব করা জমির ক্ষেত্রফল বের করে ও তো কম্পিউটার মেমরিতে রাখতে হবে। কম্পিউটার মেমরিতে রাখার জন্য আমাদের দরকার একটা ভ্যারিয়েবল। ক্ষেত্রফল রাখার জন্য আমাদের ভ্যারিয়েবল এর নাম দিয়েছি volume, কিন্তু volume এ আমরা কি ধরনের ডেটা রাখব তা কম্পিউটারকে জানতে হবে না? আমরা যেহেতু একটা ক্ষেত্রফল রাখব এবং তা হচ্ছে একটা সংখ্যা।
আমাদের হিসেব করা জমির ক্ষেত্রফল বের করে ও তো কম্পিউটার মেমরিতে রাখতে হবে। কম্পিউটার মেমরিতে রাখার জন্য আমাদের দরকার একটা ভ্যারিয়েবল। ক্ষেত্রফল রাখার জন্য আমাদের ভ্যারিয়েবল এর নাম দিয়েছি volume, কিন্তু volume এ আমরা কি ধরনের ডেটা রাখব তা কম্পিউটারকে জানতে হবে না? আমরা যেহেতু একটা ক্ষেত্রফল রাখব এবং তা হচ্ছে একটা সংখ্যা।
কিছুক্ষন আগে int নামে আমরা একটা ডেটা টাইপ সম্পর্কে জেনেছি। যা দিয়ে কম্পিউটারে Integer/ পূর্ণসংখ্যা কম্পিউটারে সংরক্ষন করা যায়। তাই আমরা int ব্যবহার করেছি। আর এর সব টুকু লিখছি একটা লাইনের মধ্যে int volume;যাকে বলা হয় ভ্যারিয়েবল ডিক্লারেশন। অর্থাৎ একটা ভ্যারিয়েবল ব্যবহার করার আগে একে ডিক্লেয়ার করতে হয়। ডিক্লেয়ারেশন শেষ আমরা একটা সেমি কোলন দিয়েছি। একটি ভেরিয়েবল ডিক্লেয়ারেশন শেষে তা শেষ করার জন্য একটা সেমিকোলন ব্যবহার করতে হয়। অর্থাৎ একটি ভ্যারিয়েবল ডিক্লেয়ার করতে হয় নিচের মত করেঃ
1
| data_type variable_name; |
কম্পিউটারকে তো আমাদের জানাতে হবে যে আমাদের জমির দৈর্ঘ্য এবং প্রস্থ কত, তাই না? এর জন্য আমরা আরো দুটি ভ্যারিয়েবল নিয়েছি length এবং width নামে। এ দুটি আবার int volume; থেকে একটু ভিন্ন। আমরা এ দুটি ভ্যারিয়েবল ডিক্লেয়ার করার সাথে সাথে একটি মান সেট করে দিয়েছি। যাকে বলে ভ্যালু এসাইন করা। মান সহ ভ্যারিয়েবল ডিক্লেয়ার করার নিয়ম হচ্ছেঃ
1
| data_type variable_name = value; |
এর পর বর্তীতে আমরা লিখছি volume = length * width; এর মানে হচ্ছে length ভ্যারিয়েবল এর মান এবং width ভ্যারিয়েবল এর মান গুন করে volume এ রাখা।
এর পরবর্তী লাইন এর সাথে আমরা কিছুটা পরিচিত। printf(“%d”, volume); যা হচ্ছে printf() ফাংশন।
printf() ফাংশন এর কাজ হচ্ছে কোন কিছু প্রিন্ট করা। একটা লেখা প্রিন্ট করার জন্য printf() এর ভেতর ডাবল কোটেশন এর মধ্যে কিছু লিখলেই তা প্রিন্ট করে দেয়, তা আমরা এর আগেই জেনে এসেছি।
printf() ফাংশন এর কাজ হচ্ছে কোন কিছু প্রিন্ট করা। একটা লেখা প্রিন্ট করার জন্য printf() এর ভেতর ডাবল কোটেশন এর মধ্যে কিছু লিখলেই তা প্রিন্ট করে দেয়, তা আমরা এর আগেই জেনে এসেছি।
কিন্তু এবার আমরা একটা ইন্টিজার ভ্যালু প্রিন্ট করব এবং একট ভ্যারিয়েবল এর থেকে। এর জন্য কিছু নিয়ম আমাদের ফলো করতে হবে। একটি ইন্টিজার প্রিন্ট করার জন্য printf() এর ভেতর ডাবল কোটেশন দিয়ে লিখতে হয় %d, এটিকে বলে placeholder। প্রত্যেকটি ডেটা টাইপের জন্য আলাধা আলাধা placeholders রয়েছে। %d মানে হচ্ছে display integer। ডাবল কোটেশনের পর আমরা একটি কমা দিয়েছি। এর পর লিখছি আমাদের ইন্টিজার ভ্যারিয়েবলটি। যা আমাদের জমির ক্ষেত্রফল প্রিন্ট করে দিয়েছে।
এ কাজটা তো আমরা মুখেই করতে পারতাম তাই না? ভালো হতো যদি প্রোগ্রামটা রান হওয়ার পর দৈর্ঘ্য এবং প্রস্থ নেওয়া যেত। তাহলে আমরা যে কোন জমির ক্ষেত্রফল বের করতে পারতাম। আমরা এমন কিছুই শিখব। তার আগে আরো কিছু ব্যাসিক ধারনা নিয়ে নি।
এ কাজটা তো আমরা মুখেই করতে পারতাম তাই না? ভালো হতো যদি প্রোগ্রামটা রান হওয়ার পর দৈর্ঘ্য এবং প্রস্থ নেওয়া যেত। তাহলে আমরা যে কোন জমির ক্ষেত্রফল বের করতে পারতাম। আমরা এমন কিছুই শিখব। তার আগে আরো কিছু ব্যাসিক ধারনা নিয়ে নি।
প্লেসহোল্ডার / Placeholder
কিছুক্ষণ আগে আমরা placeholder নামে একটা শব্দ শুনেছি। প্রত্যেকটা ডেটা টাইপের জন্য আলাদা আলাদা প্লেসহোল্ডার রয়েছে। নিচে ভিন্ন ভিন্ন ডেটা টাইপ ও তাদের প্লেসহোল্ডার গুলো দেওয়া হলোঃ
ডেটা টাইপ | প্লেসহোল্ডার |
int | %d |
char | %c |
float | %f |
double | %lf |
character data type
এবার আমরা character data type সম্পর্কে একটু জানতে পারি।
char data type বলতে single character( একটি বর্ন যেমন a, b, z, A, N ইত্যাদি) বুঝায়। এর সাইজ ১ বাইট বা ৮ বিট।বিট (১বাইট=৮বিট) এবং রেঞ্জঃ -১২৮ থেকে +১২৭ পর্যন্ত। আমাদের কীবোর্ডের প্রত্যেকটি চিহ্নই এক একটা character। কারেকটার ভ্যারিয়েবল ডিক্লেয়ার করার নিয়ম হচ্ছেঃ
char variable_name;
character ভ্যারিয়েবলে মাত্র একটি কারেকটার / লেটার / বর্ণ সংরক্ষন করা যায়। নিচের প্রোগ্রাম দেখিঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { char ch = 'A' ; printf ( "%c" , ch); return 0; } |
এখানে ch নামে একটা কারেকটার ভ্যারিয়েবল নিয়েছি। এরপর তা প্রিন্ট করেছি। ভ্যারিয়েবলের মধ্যে কোন কারেকটার এসাইন করার জন্য তা সিঙ্গেল কোটেশনের মধ্যে রাখতে হয়। এভাবে ‘A’ ।
float data type:
integer ডেটা টাইফে শুধু মাত্র পূর্ণ সংখ্যা গুলো সংরক্ষন করা যায়। আপনি একটা integer ভ্যারিয়েবলে একটি দশমিক মান যেমনঃ ৮.৯ বা ইচ্ছে মত কিছু রাখুন। এর পর ঐ ভ্যারিয়েবলটি প্রিন্ট করুন। কি দেখলেন? দশমিকের পরের অংশ নেই তাই না? নিচের প্রোগ্রামটা আপনি রান করিয়ে দেখতে পারেনঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { int n = 8.9; printf ( "%f" , n); return 0; } |
এটা শুধু আমাদের 8 দেখাবে। যদিও আমরা ভ্যারিয়েবলটির মধ্যে রেখেছি 8.9 । এর কারন হচ্ছে int শুধু মাত্র পূর্ণ সংখ্যা গুলোকে কম্পিউটার মেমরিতে সংরক্ষিত করতে পারে। দশমিক মান কম্পিউটারে রাখার জন্য আমাদের দরকার আরেকটি ডেটা টাইফ, যার নাম float ।
float data type বলতে floating point number( দশমিক সংখা যেমনঃ ১০.৫, ১.৮, ৫.৬ ইত্যাদি) বুঝায়। floating point ডেটা টাইফ দশমিকের পর ৬ ঘর পর্যন্ত নির্ভুল মান দিতে পারে। উপরের প্রোগ্রামটার ভ্যারিয়েবল n এর Data Type পরিবর্তন করে float দিয়ে রান করিয়ে দেখুনঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { float n = 8.9; printf ( "%d" , n); return 0; } |
এটি এবার সঠিক মান দিবে।
বৃত্তের ক্ষেত্রফলের জন্য দরকার এর ব্যাসার্ধের মান। ধরে নিচ্ছি একটি বৃত্তের ব্যাসার্ধ 7.6 একক। আমরা এর ক্ষেত্রফল বের করার একটা প্রোগ্রাম লিখে ফেলিঃ
1
2
3
4
5
6
7
8
9
| #include <stdio.h> int main() { float radius = 7.6; float area = (radius*radius * 3.1416); printf ( "%f" , area); return 0; } |
আমরা radius নামে একটা floting point ভ্যারিয়েবল নিয়েছি। এর মধ্যে বৃত্তের ব্যাসার্ধ রেখেছি। area নামে আরেকটি ভ্যারিয়েবল নিয়েছি যার মধ্যে ক্ষেত্রফল বের করে রেখেছি।
আমরা যানি বৃত্তের ক্ষেত্রফল হচ্ছে ব্যাসার্ধ*ব্যাসার্ধ্য * পাই এর মান। তাই লিখছি এবং মানটি প্রিন্ট করেছি।
এর আগে integer এর উদাহরনে printf ফাংশনে placeholder হিসেবে ব্যবহার করেছি %d, floating point এর জন্য placeholder হচ্ছে %f । বাকিটা তো সহজ তাই না?
আমরা জেনেছি যে floating point দশমিকের পর ৬ ঘর পর্যন্ত নির্ভুল মান দিতে পারে। এর থেকে বেশি ঘর পর্যন্ত নির্ভুল মান পেতে হলে আমাদের আরেকটি ডেটা টাইফ ব্যবহার করতে হবে যার নাম হচ্ছে double ।
double data type
double data type বলতে Double precision floating point number বুঝায়।এটা float data type এর মতোই তবে সাইজ বিশাল। এর সাইজ ৮ বাইট বা ৬৪ বিট। এবং এটি দশমিকের পর ১৫ ঘর পর্যন্ত নির্ভুল মান দিতে পারে।
আমরা জানি বৃত্তের পরিধি ও ব্যাসের অনুপাতকে পাই/ Pi [Π] দিয়ে প্রকাশ করা হয়। এটি একটি অমূলদ সংখ্যা। এটিকে দশমিক আকারে সম্পূর্ণ প্রকাশ করা সম্ভব নয়। দশমিকের পর অসীম সংখ্যা রয়েছে, এ জন্য। আমরা যদি float দিয়ে এর মান বের করার চেষ্টা করি, আমরা পাব দশমিকের পর ৬ ঘর পর্যন্ত। কিন্তু double দিয়ে যদি এর মান বের করি, তাহলে পাব দশমিকের পর ১৫ ঘর পর্যন্ত নির্ভুল মান। double এর মান প্রিন্ট বা আউটপুট পাবার জন্য প্লেসহোল্ডার হিসেবে আমাদের lf ব্যবহার করতে হবে। নিচের প্রোগ্রামটি দেখিঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { double pi = 3.14159265358979323846; printf ( "%lf" , pi); return 0; } |
এখন যদিও কম্পাইল করে রান করার পর দশমিকের পর ৬ ঘরই দেখাবে। কিন্তু আমরা বলছি ১৫ ঘর পর্যন্ত নির্ভুল মান দিবে। ঠিকই বলেছি। এখন কম্পাইলারকে বলে দিতে হবে কত দশমিকের পর কত ঘর প্রিন্ট করবে। নিচের প্রোগ্রামটি দেখিঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { double pi = 3.14159265358979323846; printf ( "%.9lf" , pi); return 0; } |
এখানে আমরা প্লেসহোল্ডারে লিখেছি .9lf । প্লেসহোল্ডারে দশমিক দিয়ে কত ঘর পর্যন্ত প্রিন্ট করবে, তা বলে দিলে তত ঘর পর্যন্তই প্রিন্ট করবে। উপরের প্রোগ্রামটি এখন পাই এর মান দশমিকের পর ৯ ঘর পর্যন্ত প্রিন্ট করবে।
মাথায় দুষ্টু বুদ্ধি খেলা করে তাই না? .9lf এর জায়গায় .50lf দিলে দশমিকের পর ৫০ ঘর প্রিন্ট করবে, তাই তো? হ্যা, ঠিকই .50lf লিখলে ঠিকই দশমিকের পর ৫০ ঘর পর্যন্ত প্রিন্ট করবে। তবে তা আমরা যে রেজাল্ট চাচ্ছি তা পাবো না। ভুল কিছু পাবো। নিচের প্রোগ্রামটি দেখিঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { double pi = 3.14159265358979323846; printf ( "%.20f" , pi); return 0; } |
এখানে আমরা পাই এর মান দশমিকের পর ২০ঘর পর্যন্ত দিয়েছি। এরপর আমরা চাচ্ছি ২০ ঘর পর্যন্তই মান পেতে। তাই প্লেসহোল্ডারে .20f দিয়ে বলে দিয়েছি যেন দশমিকের পর ২০ ঘর পর্যন্ত প্রিন্ট করে। কিন্তু দশমিকের পর ১৫ ঘর পর্যন্ত ঠিক মানই প্রিন্ট করেছে। এরপর কত গুলো শূন্য দিয়ে পূরণ করে দিয়েছে। কারণ dobule ডেটা টাইপ দশমিকের পর ১৫ ঘর পর্যন্ত মান ঠিক মত মনে রাখতে পারে।
ডেটা টাইপ এবং তাদের রেঞ্জঃ
শুরুতেআমরা রেঞ্জ নিয়ে কিছু পড়েছি, হয়তো ঠিক মত বুঝতে পারি নি। কিন্তু এবার বুঝেই ছাড়ব। আমরা বলেছি int data type এর সাইজ হচ্ছে ২ বাইট। আমরা জানি এক বাইট সমান ৮ বিট। তাহলে দুই বাইট সমান ১৬ বিট। আর এই ১৬ বিটের মানে হচ্ছে কম্পিউটার (216 -1) = (65536 -1) = 65535 পর্যন্ত নির্ভুল ভাবে সেভ করতে পারবে। মানে আমরা সুন্দর ভাবেই0-65535 পর্যন্ত যে কোন মান একটি ইন্টিজারে সেভ করতে পারব। এখন যদি আমরা এর থেকে বড় কোন মান যেমন। 65538 ইন্টিজার ডেটা টাইপে সেভ করি, কম্পাইলার ঠিক মত মান আমাদের আউটপুট দিতে পারবে না।
আমরা বলেছি যে কিছু কিছু কম্পাইলার ইন্টিজারের জন্য ৪ বাইট মেমরি বরাদ্ধ করে। ৪ বাইট মানে হচ্ছে ৪*৮ বিট। = ৩২ বিট। আর ৩২ বিট মানে আমরা (232 -1) = (4294967296 -১) = 4294967295 পর্যন্ত নির্ভুল মান সেভ করতে পারব ইন্টিজার ডেটা টাইপ হিসেবে। এর থেকে বড় কোন মান যদি ইন্টিজার হিসেবে সেভ করতে চাই, তাহলে ঠিক মত আউটপুট পাবো না। যেটা পাবো সেটা দারুণ। দারুণ কেন বলছি। আগে 4294967295 এর থেকে বড় যে কোন একটা সংখ্যা ইন্টিজার ভ্যারিয়েবল হিসেবে প্রিন্ট করে দেখি। যেমন 6294967295
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { int n = 6294967295; printf ( "%d" , n); return 0; } |
কি আউটপুট পাচ্ছি? আমি পাচ্ছি 1999999999… যেটা পাওয়ার কথা সেটা পাই নি। কারণ ইন্টিজার ডেটাটাইপে যতটুকু ক্ষমতা তার থেকে বড় মান আমরা সেভ করার চেষ্টা করেছি, তাই।
4294967295 এর পরবর্তি সংখ্যা 4294967296 , এটা প্রিন্ট করে দেখিঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { int n = 4294967296; printf ( "%d" , n); return 0; } |
আউটপুট পাচ্ছি শূন্য। ০ ।
4294967297 প্রিন্ট করে দেখলে পাবো ১।
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { int n = 4294967297; printf ( "%d" , n); return 0; } |
এভাবে যদি 4294967298 প্রিন্ট করি, তাহলে পাবো ২। মানে কি দাড়ালো? মানে 4294967295 এর পরের সংখ্যা গুলো প্রিন্ট করার চেষ্টা করলে আবার ০ থেকে প্রিন্ট করা শুরু করে। সুন্দর একটা কারণ আছে। কারণটা কি? চিন্তা করে বের করতে পারেন।
এতক্ষণ আমরা Unsigned ইন্টিজার সম্পর্কে আলোচনা করেছি। Unsigned মানে হচ্ছে সংখ্যাটা কি ধণাত্ত্বক নাকি ঋণাত্ত্বক, তা বলে দি নি। কিন্তু মাঝে মাঝে আমাদের Singed Integer নিয়ে কাজ করতে হবে। মানে আমরা ভ্যারিয়েবল ডিক্লারেশনের সময় বলে দিব সংখ্যাটা কি ধনাত্ত্বক নাকি ঋণাত্ত্বক, তখন আবার রেঞ্জ ছোট হয়ে যাবে। তখন একটি ইন্টিজারের রেঞ্জ হয়ে যাবে -2,147,483,648 থেকে +2,147,483,647। মানে আমরা -2,147,483,648 পর্যন্ত এবং 2,147,483,647 পর্যন্ত ইন্টিজার মান একটা ইন্টিজার ভ্যারিয়েবলে সেভ করতে পারব।
ধণাত্ত্বক হলে কম্পাইলার আউটপুটে + চিহ্ন প্রিন্ট করবে না। কিন্তু ঋণাত্ত্বক হলে তা দেখাবেঃ
ধণাত্ত্বক হলে কম্পাইলার আউটপুটে + চিহ্ন প্রিন্ট করবে না। কিন্তু ঋণাত্ত্বক হলে তা দেখাবেঃ
1
2
3
4
5
6
7
8
| #include <stdio.h> int main() { int n = -899; printf ( "%d" , n); return 0; } |
উপরে একটি ধণাত্ত্বক সংখ্যা আমরা বলতে পারি Singed Integer ভ্যারিয়েবল তৈরি করা হয়েছে। এবং পরে তা প্রিন্ট করা হয়েছে।
নিচে ভিন্ন ভিন্ন ডেটা টাইপ এবং তাদের সাইজ দেওয়া হলোঃ
ডেটা টাইপ | সাইজ |
int | 2 bytes |
char | 1 byte |
float | 4 bytes |
double | 8 bytes |
পোস্টঃ মোঃ মোস্তফা কামাল