গত পর্বে আমরা C প্রোগ্রামিংয়ের ভিত্তি থেকে শুরু করে ফাইল হ্যান্ডলিং পর্যন্ত জার্নি করেছি। যদি আপনি সেই বেসিকগুলো ভালোভাবে আয়ত্ত করে থাকেন, তাহলে আজ আমরা C-এর হার্ডকোর অংশে প্রবেশ করব।
কারণ শুধু printf আর scanf জানলেই C প্রোগ্রামার হওয়া যায় না। আসল মজা শুরু হয় যখন আপনি কম্পিউটারের মেমোরি নিজে হাতে ম্যানেজ করতে শুরু করেন, এবং নিজের তৈরি ডায়নামিক ডেটা স্ট্রাকচার দিয়ে একটি পূর্ণাঙ্গ প্রজেক্ট বানান। চলুন, আজকের যাত্রা শুরু করি! 🚀
🔄 পর্ব-১ এর সংক্ষিপ্ত পুনরালোচনা
আমরা আগে শিখেছি:
- ভেরিয়েবল, ডেটা টাইপ (int, char, float)।
- কন্ট্রোল স্টেটমেন্ট (if-else, switch) এবং লুপ (for, while)।
- অ্যারে ও স্ট্রিং হ্যান্ডলিং।
- ফাংশন ডিক্লেয়ার ও কল।
- পয়েন্টার দিয়ে ভেরিয়েবলের ঠিকানা ধরা।
- স্ট্রাকচার দিয়ে ইউজার-ডিফাইন্ড ডেটা তৈরি এবং ফাইল দিয়ে ডেটা সেভ করা।
আজ আমরা এই জ্ঞানকেই ব্যবহার করে আরও শক্তিশালী কিছু তৈরি করব।
🧠 অধ্যায় ৮: ডায়নামিক মেমোরি অ্যালোকেশন (Dynamic Memory Allocation)
আমরা আগে যতগুলো অ্যারে তৈরি করেছি (যেমন int arr[100];), তার সাইজ ছিল ফিক্সড। কিন্তু আপনি যদি নিশ্চিত না জানেন যে ব্যবহারকারী কতগুলো ডেটা ইনপুট দেবে? সেক্ষেত্রে আমরা রানটাইমে মেমোরি বরাদ্দ করি। এটাই ডায়নামিক মেমোরি।
C-তে এর জন্য চারটি ম্যাজিক ফাংশন আছে (সংরক্ষিত আছে <stdlib.h> হেডার ফাইলে):
| ফাংশন | কাজ |
|---|---|
malloc() | মেমোরির একটি ব্লক বরাদ্দ করে (মান অনির্ধারিত থাকে)। |
calloc() | মেমোরির ব্লক বরাদ্দ করে এবং সব জায়গায় 0 সেট করে দেয়। |
realloc() | আগে বরাদ্দ করা মেমোরির সাইজ পরিবর্তন করে। |
free() | বরাদ্দ করা মেমোরি ডি-অ্যালোকেট (মুক্ত) করে। |
⚠️ সতর্কতা: C-তে মেমোরি লিক হয় বলেই পরিচিত।
free()ব্যবহার না করলে আপনার প্রোগ্রামের মেমোরি ব্যবহার বাড়তে থাকবে এবং শেষ পর্যন্ত ক্র্যাশ করবে!
উদাহরণ (malloc ও free):
c
#include <stdio.h>
#include <stdlib.h> // malloc, free-এর জন্য
int main() {
int n, i;
printf("কতগুলো সংখ্যা রাখবেন? ");
scanf("%d", &n);
// n সংখ্যক int-এর জন্য মেমোরি বরাদ্দ
int *arr = (int*) malloc(n * sizeof(int));
// মেমোরি বরাদ্দ সফল হয়েছে কিনা চেক
if (arr == NULL) {
printf("মেমোরি বরাদ্দ করা সম্ভব হয়নি!\n");
return 1;
}
// ইনপুট নেওয়া
for (i = 0; i < n; i++) {
printf("arr[%d] = ", i);
scanf("%d", &arr[i]);
}
// আউটপুট দেখানো
printf("আপনার সংখ্যাগুলো: ");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
// মেমোরি মুক্ত করা (অত্যন্ত জরুরি!)
free(arr);
return 0;
}
🔁 অধ্যায় ৯: রিকারশন (Recursion) – ফাংশনের আত্মকল
রিকারশন হলো একটি প্রক্রিয়া যেখানে একটি ফাংশন নিজেই নিজেকে কল (Call) করে। এটি অনেকটা ডমিনো ইফেক্টের মতো—একটি পতন পরবর্তীটিকে পতিত করে।
রিকারশনের শর্তাবলী:
১. বেস কেস (Base Case): যেখানে ফাংশন নিজেকে আর কল করে না (স্টপিং কন্ডিশন)।
২. রিকার্সিভ কেস: যেখানে ফাংশন নিজেকে কল করে এবং ধাপে ধাপে বেস কেসের দিকে এগোয়।
উদাহরণ: ফ্যাক্টোরিয়াল (n!)
c
#include <stdio.h>
int factorial(int n) {
// বেস কেস: 0! বা 1! = 1
if (n == 0 || n == 1) {
return 1;
}
// রিকার্সিভ কেস
else {
return n * factorial(n - 1);
}
}
int main() {
int num = 5;
printf("%d-এর ফ্যাক্টোরিয়াল = %d\n", num, factorial(num));
return 0;
}
💡 বাস্তব ব্যবহার: রিকারশন প্রধানত ট্রি, গ্রাফ ডেটা স্ট্রাকচার অনুসন্ধানে (DFS) এবং কিছু গাণিতিক সমস্যা সমাধানে ব্যবহৃত হয়।
🛠️ অধ্যায় ১০: প্রিপ্রসেসর ও ম্যাক্রো (Preprocessor & Macros)
আপনি কি কখনও ভেবেছেন, #include <stdio.h> লাইনটি আসলে কী? এটি C-এর প্রিপ্রসেসর-এর একটি ডিরেক্টিভ। প্রোগ্রাম কম্পাইল হওয়ার আগেই প্রিপ্রসেসর এই লাইনগুলো প্রসেস করে ফেলে।
ম্যাক্রো (Macro) ব্যবহার:#define দিয়ে আপনি একটি কনস্ট্যান্ট বা মিনি-ফাংশন তৈরি করতে পারেন।
c
#include <stdio.h>
#define PI 3.1416
#define SQUARE(x) (x * x)
int main() {
float radius = 5.0;
float area = PI * SQUARE(radius); // PI * (5 * 5)
printf("বৃত্তের ক্ষেত্রফল: %.2f\n", area);
return 0;
}
কন্ডিশনাল প্রিপ্রসেসর: (
#ifdef,#ifndef,#endif) ব্যবহার করে আপনি ডিবাগ মোড বা রিলিজ মোড আলাদা করতে পারেন। এটি বড় প্রোজেক্টে অপরিহার্য।
⌨️ অধ্যায় ১১: কমান্ড লাইন আর্গুমেন্ট (Command Line Arguments)
আপনি যখন টার্মিনালে ./program.exe Rahim 25 টাইপ করেন, তখন এই Rahim ও 25 তথ্যগুলো প্রোগ্রামে প্রবেশ করে। এদের ক্যাপচার করে main() ফাংশনের বিশেষ প্যারামিটারগুলো।
সিনট্যাক্স: int main(int argc, char *argv[])
argc: আর্গুমেন্টের মোট সংখ্যা (কাউন্ট)।argv[]: আর্গুমেন্টগুলোর স্ট্রিং অ্যারে।
উদাহরণ:
c
#include <stdio.h>
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("দয়া করে দুটি নাম দিন! যেমন: ./program.exe Rahim Karim\n");
return 1;
}
printf("প্রথম নাম: %s\n", argv[1]);
printf("দ্বিতীয় নাম: %s\n", argv[2]);
return 0;
}
🏗️ অধ্যায় ১২: মিনি-প্রজেক্ট – ‘কন্ট্যাক্ট ম্যানেজমেন্ট সিস্টেম’ (হাতে-কলমে)
এখন পর্যন্ত যা শিখলাম, তা দিয়ে একটি ছোট কিন্তু কার্যকরী কন্ট্যাক্ট বুক প্রোগ্রাম তৈরি করি। এতে আমরা ডায়নামিক মেমোরি, স্ট্রাকচার এবং ফাইল হ্যান্ডলিং একসাথে ব্যবহার করব।
প্রোজেক্টের বৈশিষ্ট্য:
- নতুন কন্ট্যাক্ট যোগ করা (নাম, ফোন নম্বর)।
- সব কন্ট্যাক্ট দেখানো।
- ফাইল থেকে ডেটা পড়া এবং ফাইলে সেভ করা।
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// স্ট্রাকচার ডিফাইন
struct Contact {
char name[50];
char phone[15];
};
int main() {
FILE *file;
int choice, count = 0;
struct Contact contacts[100]; // সর্বোচ্চ ১০০টি কন্ট্যাক্ট
// ফাইল থেকে আগের ডেটা লোড করা
file = fopen("contacts.txt", "r");
if (file != NULL) {
while (fscanf(file, "%s %s", contacts[count].name, contacts[count].phone) != EOF) {
count++;
}
fclose(file);
printf("✅ মোট %dটি কন্ট্যাক্ট লোড হয়েছে!\n", count);
}
while (1) {
printf("\n📒 **কন্ট্যাক্ট ম্যানেজার**\n");
printf("1. নতুন কন্ট্যাক্ট যোগ করুন\n");
printf("2. সব কন্ট্যাক্ট দেখুন\n");
printf("3. প্রস্থান ও সেভ করুন\n");
printf("আপনার পছন্দ: ");
scanf("%d", &choice);
getchar(); // নিউলাইন ক্লিয়ার করতে
if (choice == 1) {
printf("নাম: ");
gets(contacts[count].name);
printf("ফোন নম্বর: ");
gets(contacts[count].phone);
count++;
printf("✅ কন্ট্যাক্ট সফলভাবে যুক্ত!\n");
}
else if (choice == 2) {
printf("\n📋 **কন্ট্যাক্ট লিস্ট:**\n");
for (int i = 0; i < count; i++) {
printf("%d. নাম: %s | ফোন: %s\n", i+1, contacts[i].name, contacts[i].phone);
}
}
else if (choice == 3) {
// ফাইলে সেভ করা
file = fopen("contacts.txt", "w");
if (file != NULL) {
for (int i = 0; i < count; i++) {
fprintf(file, "%s %s\n", contacts[i].name, contacts[i].phone);
}
fclose(file);
printf("💾 সব কন্ট্যাক্ট contacts.txt ফাইলে সেভ হয়েছে!\n");
}
printf("👋 প্রোগ্রাম থেকে প্রস্থান করছি। ভালো থাকুন!\n");
break;
}
else {
printf("❌ ভুল ইনপুট! ১, ২ অথবা ৩ চাপুন।\n");
}
}
return 0;
}
এই প্রোজেক্টটি রান করান। প্রতিবার প্রোগ্রাম বন্ধ করলেও আপনার ডেটা সেভ থাকবে!
🏁 উপসংহার ও এগিয়ে যাওয়ার পথ
আজ আমরা C প্রোগ্রামিংয়ের সবচেয়ে গুরুত্বপূর্ণ অ্যাডভান্সড টপিকগুলো কভার করলাম এবং সেগুলো ব্যবহার করে একটি রিয়েল-লাইফ প্রোজেক্টও বানিয়ে ফেললাম।
C প্রোগ্রামিং শেষ নয়, এটি আপনার প্রোগ্রামিং জীবনের সূচনা মাত্র। এখন আপনি যদি সত্যিই দক্ষ হতে চান, তাহলে:
১. লিংকড লিস্ট, স্ট্যাক, কিউ – এই ডেটা স্ট্রাকচারগুলো নিজে হাতে ইমপ্লিমেন্ট করুন।
২. লীটকোড (LeetCode) বা হ্যাকারর্যাঙ্ক (HackerRank) – এ গিয়ে C দিয়ে ডেইলি চ্যালেঞ্জ সলভ করুন।
৩. সিস্টেম প্রোগ্রামিং – Unix/Linux এনভায়নমেন্টে C ব্যবহার করে মাল্টিথ্রেডিং শিখুন।
মনে রাখবেন, C শেখা মানে কম্পিউটারের ভাষায় কথা বলা শেখা। এটি যত কঠিন, ততটাই মজার। ToLearnTeam-এর পক্ষ থেকে আপনার উজ্জ্বল প্রোগ্রামিং ক্যারিয়ারের জন্য রইল অসংখ্য শুভকামনা। বারবার প্র্যাকটিস করুন, কোড করুন এবং ভুল থেকে শিখুন!
Full Advanced Course in C
- C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
- C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
- C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
- C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
- C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
- C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
- C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
- C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার
