গত দুই পর্বে আমরা C-এর বেসিক থেকে অ্যাডভান্সড মেমোরি ম্যানেজমেন্ট পর্যন্ত সবকিছু কভার করেছি। আপনি এখন জানেন কীভাবে ডায়নামিক মেমোরি বরাদ্দ করতে হয়, রিকারশন লিখতে হয় এবং ফাইল পরিচালনা করতে হয়।
কিন্তু বড় বড় সফটওয়্যার (যেমন: ডেটাবেস, অপারেটিং সিস্টেম) কীভাবে এত ডেটা দ্রুত ম্যানেজ করে? উত্তর হলো ডেটা স্ট্রাকচার। আজকে আমরা C ব্যবহার করে নিজের হাতে তৈরি করব লিংকড লিস্ট—একটি গতিশীল ডেটা স্ট্রাকচার। পাশাপাশি শিখব বিট লেভেল অপারেশন, যা এমবেডেড সিস্টেম ও গেম ডেভেলপমেন্টে অপরিহার্য। চলুন, শুরু করা যাক! 🔥
🔄 পর্ব-২ এর সংক্ষিপ্ত রিক্যাপ
আমরা আগের পর্বে শিখেছি:
malloc,calloc,freeদিয়ে মেমোরি ম্যানেজ করা।- রিকারশনের মাধ্যমে জটিল সমস্যা সমাধান।
#defineম্যাক্রো ও কমান্ড লাইন আর্গুমেন্ট (argc,argv)।- একটি কন্ট্যাক্ট ম্যানেজমেন্ট প্রোজেক্ট তৈরি করা।
আজ আমরা সেই জ্ঞানকেই কাজে লাগিয়ে আরও শক্তিশালী এবং পেশাদার কিছু বানাবো।
🧮 অধ্যায় ১৩: বিটওয়াইজ অপারেটর (Bitwise Operators) – ডেটার সঙ্গে খেলা
কম্পিউটার সব ডেটা বাইনারি (০ ও ১) আকারে বোঝে। বিটওয়াইজ অপারেটর সরাসরি এই বিটগুলোর ওপর কাজ করে। এগুলি অত্যন্ত দ্রুতগতির এবং মেমোরি সাশ্রয়ী।
C-তে মোট ৬টি বিটওয়াইজ অপারেটর আছে:
| অপারেটর | নাম | কাজের উদাহরণ |
|---|---|---|
& | AND | উভয় বিট ১ হলে ফল ১ |
| | OR | যেকোনো একটি বিট ১ হলে ফল ১ |
^ | XOR | বিট ভিন্ন হলে ফল ১ (অন্যথায় ০) |
~ | NOT (Complement) | ০ কে ১ এবং ১ কে ০ করে (উল্টো করে) |
<< | লেফট শিফট | বিটগুলোকে বামে সরায় (২ দিয়ে গুণের মতো) |
>> | রাইট শিফট | বিটগুলোকে ডানে সরায় (২ দিয়ে ভাগের মতো) |
বাস্তব উদাহরণ (ফ্ল্যাগ চেক করা):
ধরুন, আপনার একটি প্রোগ্রামে ইউজারের পারমিশন সংরক্ষণ করতে হবে (রিড, রাইট, এক্সিকিউট)।
c
#include <stdio.h>
#define READ 1 // 0001
#define WRITE 2 // 0010
#define EXEC 4 // 0100
int main() {
int permissions = READ | WRITE; // 0001 | 0010 = 0011 (রিড + রাইট)
// রিড পারমিশন আছে কিনা চেক করা
if (permissions & READ) {
printf("✅ ইউজারের রিড পারমিশন আছে!\n");
}
// এক্সিকিউট পারমিশন আছে কিনা
if (permissions & EXEC) {
printf("✅ ইউজারের এক্সিকিউট পারমিশন আছে!\n");
} else {
printf("❌ ইউজারের এক্সিকিউট পারমিশন নেই!\n");
}
return 0;
}
কেন ব্যবহার করবেন? বিটওয়াইজ অপারেশন গাণিতিক অপারেশনের চেয়ে অনেক দ্রুত। গেমস, গ্রাফিক্স, এনক্রিপশন—সবখানে এদের ব্যবহার রয়েছে।
🎯 অধ্যায় ১৪: ফাংশন পয়েন্টার (Function Pointers) – ফাংশনের ঠিকানা
আমরা আগে পয়েন্টার দিয়ে ভেরিয়েবলের ঠিকানা ধরতে শিখেছি। ঠিক তেমনই, C-তে ফাংশনেরও একটি ঠিকানা থাকে। ফাংশন পয়েন্টার ব্যবহার করে আপনি একটি ফাংশনকে আরেকটি ফাংশনের আর্গুমেন্ট হিসেবে পাঠাতে পারেন (একে কলব্যাক ফাংশনও বলে)।
সিনট্যাক্স: return_type (*pointer_name)(parameter_types);
c
#include <stdio.h>
// সাধারণ দুটি ফাংশন
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
// এই ফাংশনটি একটি ফাংশন পয়েন্টার প্যারামিটার হিসেবে নিচ্ছে
void calculate(int x, int y, int (*operation)(int, int)) {
int result = operation(x, y);
printf("ফলাফল: %d\n", result);
}
int main() {
// যোগ করার ফাংশন পাঠানো হচ্ছে
calculate(10, 5, add); // আউটপুট: 15
// বিয়োগ করার ফাংশন পাঠানো হচ্ছে
calculate(10, 5, subtract); // আউটপুট: 5
return 0;
}
বাস্তব ব্যবহার: সর্টিং অ্যালগরিদমে (
qsort) আপনি চাইলে নিজের মতো করে তুলনার পদ্ধতি বদলে দিতে পারেন ফাংশন পয়েন্টারের মাধ্যমেই।
🔗 অধ্যায় ১৫: নিজের ডেটা স্ট্রাকচার তৈরি – সিঙ্গলি লিংকড লিস্ট (Singly Linked List)
অ্যারের সমস্যা হলো এর সাইজ ফিক্সড। আর ডেটা ডিলিট বা ইনসার্ট করতে গেলে পুরো অ্যারে শিফট করতে হয়। লিংকড লিস্ট এই সমস্যার সমাধান করে। এটি একটি চেইনের মতো, যেখানে প্রতিটি এলিমেন্ট (নোড) পরের এলিমেন্টের ঠিকানা ধারণ করে রাখে।
লিংকড লিস্টের গঠন:
c
struct Node {
int data; // ডেটা
struct Node* next; // পরের নোডের পয়েন্টার
};
নোড ইনসার্ট, ডিলিট ও ডিসপ্লে করার সম্পূর্ণ কোড:
c
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// নতুন নোড তৈরি
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// লিস্টের শেষে নোড যোগ করা
void insertAtEnd(struct Node** head, int data) {
struct Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
return;
}
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
// একটি নির্দিষ্ট মান মুছে ফেলা
void deleteNode(struct Node** head, int key) {
struct Node *temp = *head, *prev = NULL;
// হেড নোড যদি ডিলিট করতে হয়
if (temp != NULL && temp->data == key) {
*head = temp->next;
free(temp);
return;
}
// বাকি নোড খোঁজা
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return; // কী পাওয়া যায়নি
prev->next = temp->next;
free(temp);
}
// লিস্ট প্রিন্ট করা
void display(struct Node* head) {
struct Node* temp = head;
printf("লিংকড লিস্ট: ");
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtEnd(&head, 30);
display(head); // আউটপুট: 10 -> 20 -> 30 -> NULL
deleteNode(&head, 20);
display(head); // আউটপুট: 10 -> 30 -> NULL
return 0;
}
📁 অধ্যায় ১৬: মাল্টি-ফাইল প্রোগ্রামিং (Header File & Separate Compilation)
আপনি কি কখনও ভেবেছেন, পাইথন বা জাভার মতো বড় প্রোজেক্ট কীভাবে পরিচালনা করা হয়? একটি বিশাল .c ফাইলে সব কোড লেখা সম্ভব নয়। আমরা কোডকে ভাগ করি মডিউলে।
কীভাবে করবেন:
১. header.h – ডিক্লেয়ারেশন (ফাংশনের প্রোটোটাইপ, স্ট্রাকচার, ম্যাক্রো) রাখুন।
২. functions.c – ফাংশনের ডেফিনেশন (বডি) রাখুন।
৩. main.c – প্রধান ফাইল যেখানে main() ফাংশন থাকে।
উদাহরণ (math_utils.h):
c
#ifndef MATH_UTILS_H #define MATH_UTILS_H int add(int a, int b); int subtract(int a, int b); #endif
math_utils.c:
c
#include "math_utils.h"
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
main.c:
c
#include <stdio.h>
#include "math_utils.h"
int main() {
printf("%d\n", add(5, 3)); // 8
return 0;
}
কম্পাইল করার নিয়ম:
gcc main.c math_utils.c -o project.exe
🏛️ অধ্যায় ১৭: ফাইনাল প্রোজেক্ট – ‘লাইব্রেরি ম্যানেজমেন্ট সিস্টেম’
এখন পর্যন্ত শেখা সবকিছু (লিংকড লিস্ট, ফাইল I/O, ডায়নামিক মেমোরি) ব্যবহার করে আমরা একটি লাইব্রেরি ম্যানেজমেন্ট সিস্টেম বানাবো।
বৈশিষ্ট্য:
- বই যোগ করা (ID, নাম, লেখক)।
- সব বই দেখানো।
- আইডি দিয়ে বই খোঁজা ও ডিলিট করা।
- প্রোগ্রাম বন্ধ করলে ফাইলে অটো-সেভ এবং শুরু করলে অটো-লোড।
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Book {
int id;
char name[100];
char author[50];
struct Book* next;
};
// ফাংশন প্রোটোটাইপ (ডিক্লেয়ারেশন)
struct Book* createBook(int id, char name[], char author[]);
void addBook(struct Book** head, int id, char name[], char author[]);
void displayBooks(struct Book* head);
void deleteBook(struct Book** head, int id);
void saveToFile(struct Book* head);
void loadFromFile(struct Book** head);
int main() {
struct Book* head = NULL;
loadFromFile(&head); // শুরুতে ফাইল থেকে লোড
int choice, id;
char name[100], author[50];
while (1) {
printf("\n📚 **লাইব্রেরি ম্যানেজমেন্ট**\n");
printf("1. বই যোগ করুন\n");
printf("2. সব বই দেখুন\n");
printf("3. বই ডিলিট করুন\n");
printf("4. সেভ করে প্রস্থান\n");
printf("পছন্দ: ");
scanf("%d", &choice);
getchar();
if (choice == 1) {
printf("আইডি: "); scanf("%d", &id); getchar();
printf("বইয়ের নাম: "); gets(name);
printf("লেখক: "); gets(author);
addBook(&head, id, name, author);
}
else if (choice == 2) {
displayBooks(head);
}
else if (choice == 3) {
printf("ডিলিট করতে আইডি দিন: "); scanf("%d", &id);
deleteBook(&head, id);
}
else if (choice == 4) {
saveToFile(head);
printf("💾 ডেটা সেভ হয়েছে। প্রস্থান করছি...\n");
break;
}
}
return 0;
}
// ---- ফাংশনের ডেফিনেশন ----
struct Book* createBook(int id, char name[], char author[]) {
struct Book* newBook = (struct Book*) malloc(sizeof(struct Book));
newBook->id = id;
strcpy(newBook->name, name);
strcpy(newBook->author, author);
newBook->next = NULL;
return newBook;
}
void addBook(struct Book** head, int id, char name[], char author[]) {
struct Book* newBook = createBook(id, name, author);
if (*head == NULL) { *head = newBook; return; }
struct Book* temp = *head;
while (temp->next != NULL) temp = temp->next;
temp->next = newBook;
printf("✅ বইটি যুক্ত হয়েছে!\n");
}
void displayBooks(struct Book* head) {
if (head == NULL) { printf("📭 লাইব্রেরি ফাঁকা!\n"); return; }
struct Book* temp = head;
printf("\n📖 **বইয়ের তালিকা:**\n");
while (temp != NULL) {
printf("আইডি: %d | নাম: %s | লেখক: %s\n", temp->id, temp->name, temp->author);
temp = temp->next;
}
}
void deleteBook(struct Book** head, int id) {
struct Book *temp = *head, *prev = NULL;
if (temp != NULL && temp->id == id) { *head = temp->next; free(temp); printf("🗑️ ডিলিট হয়েছে!\n"); return; }
while (temp != NULL && temp->id != id) { prev = temp; temp = temp->next; }
if (temp == NULL) { printf("❌ এই আইডির বই নেই!\n"); return; }
prev->next = temp->next;
free(temp);
printf("🗑️ ডিলিট হয়েছে!\n");
}
void saveToFile(struct Book* head) {
FILE* file = fopen("library.txt", "w");
if (file == NULL) return;
struct Book* temp = head;
while (temp != NULL) {
fprintf(file, "%d|%s|%s\n", temp->id, temp->name, temp->author);
temp = temp->next;
}
fclose(file);
}
void loadFromFile(struct Book** head) {
FILE* file = fopen("library.txt", "r");
if (file == NULL) return;
int id; char name[100], author[50];
while (fscanf(file, "%d|%[^|]|%[^\n]\n", &id, name, author) != EOF) {
addBook(head, id, name, author);
}
fclose(file);
}
🏁 উপসংহার ও ক্যারিয়ার টিপস
অভিনন্দন! আপনি এখন C প্রোগ্রামিংয়ের একটি পূর্ণাঙ্গ কোর্স শেষ করলেন। আপনি জানেন কীভাবে মেমোরি কাজ করে, ডেটা স্ট্রাকচার তৈরি করতে হয় এবং সেগুলো ফাইলে সংরক্ষণ করতে হয়।
এখন যেহেতু আপনি C জানেন, আপনার জন্য দারুণ কিছু ক্যারিয়ার পথ খোলা:
- এমবেডেড সিস্টেম ইঞ্জিনিয়ার: মাইক্রোকন্ট্রোলার, রোবটিক্স, IoT ডিভাইসের প্রোগ্রামিং (C এখানে রাজা)।
- অপারেটিং সিস্টেম ডেভেলপার: লিনাক্স কার্নেল, ড্রাইভার ডেভেলপমেন্ট।
- গেম ডেভেলপমেন্ট: ইউনিটি বা আনরিয়ালের নিচের লেয়ারের কাজ।
- ডেটাবেস ইঞ্জিনিয়ার: MySQL, PostgreSQL-এর মতো ডেটাবেসের অভ্যন্তরীণ কাঠামো বুঝতে।
শেষ কথাঃ
শুধু পড়লে হবে না। প্রতিদিন একটি করে প্রোগ্রাম লিখুন। লিংকড লিস্টে বাগ খুঁজুন, নিজের মতো করে সাজান। সি শেখা মানে কম্পিউটারকে তার নিজের ভাষায় ভালোবাসা শেখা।
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 (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার
