C for Advanced Archives - To Learn Team https://tolearnteam.com/category/computer-programming/programming-in-c/c-for-advanced/ Learn about Everything Online Thu, 16 Jul 2026 03:30:10 +0000 en-US hourly 1 https://wordpress.org/?v=7.1.2 https://tolearnteam.com/wp-content/uploads/2026/07/cropped-Logo-32x32.png C for Advanced Archives - To Learn Team https://tolearnteam.com/category/computer-programming/programming-in-c/c-for-advanced/ 32 32 C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার https://tolearnteam.com/c-programming-a-to-z-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%ae-%e0%a6%aa%e0%a7%8d%e0%a6%b0%e0%a7%8b%e0%a6%ab%e0%a6%be%e0%a6%87%e0%a6%b2%e0%a6%bf%e0%a6%82-%e0%a6%b8%e0%a6%bf%e0%a6%95%e0%a6%bf/ Thu, 16 Jul 2026 03:17:22 +0000 http://tolearnteam.com/?p=863 আমরা সি-র জাদুকরী জগতে এতদূর পৌঁছেছি যে এখন সময় এসেছে “রিয়েল ওয়ার্ল্ড”-এর ময়লার সাথে লড়াই করার। আপনার কোড যদি লেখার পর পরীক্ষা করে ঠিক হয়, কিন্তু সার্ভারে রান করাতে গিয়ে ৭২…

The post C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার appeared first on To Learn Team.

]]>
আমরা সি-র জাদুকরী জগতে এতদূর পৌঁছেছি যে এখন সময় এসেছে “রিয়েল ওয়ার্ল্ড”-এর ময়লার সাথে লড়াই করার। আপনার কোড যদি লেখার পর পরীক্ষা করে ঠিক হয়, কিন্তু সার্ভারে রান করাতে গিয়ে ৭২ ঘণ্টা পর ক্র্যাশ করে? অথবা হঠাৎ দেখলেন আপনার সার্ভারের RAM খাওয়া শেষ?

পেশাদার প্রোগ্রামাররা এই সমস্যাগুলো সমাধানের জন্য যে টুলস ও টেকনিক ব্যবহার করে, আজ আমরা সেগুলো শিখব। এটি C প্রোগ্রামিং সিরিজের সত্যিকারের ফাইনাল ব্যাটল। প্রস্তুত? শুরু করা যাক! ⚔🔥


🔄 পর্ব-৭ এর রিক্যাপ ও প্রোডাকশন চ্যালেঞ্জ

গত পর্বে আমরা থ্রেড, মিউটেক্স, সকেট এবং Makefile শিখেছি। আজ আমরা শিখব কীভাবে সেই থ্রেডগুলোকে আরও বুদ্ধিমান করে তোলা যায় (কন্ডিশন সিগন্যাল), কীভাবে মেমোরি লিক ধরা যায়, এবং কীভাবে প্রোডাকশন-গ্রেড লগার তৈরি করা যায় যা দিনে ১০ লাখ রেকুয়েস্ট হ্যান্ডেল করতে পারে।


🔍 অধ্যায় ৪৩: ভ্যালগ্রিন্ড (Valgrind) – মেমোরি লিকের শিকারী

আপনি কি নিশ্চিত আপনার প্রোগ্রামের সব malloc()-এর জন্য free() আছে? হাতে গুণে তা নিশ্চিত করা প্রায় অসম্ভব। Valgrind হলো লিনাক্সের একটি টুল যা আপনার প্রোগ্রাম রান করিয়ে দেখে দেয় কোথায় মেমোরি লিক হচ্ছে, কোথায় বাজে অ্যাক্সেস হচ্ছে।

কীভাবে ব্যবহার করবেন:

bash

gcc -g my_program.c -o my_program  # -g দিয়ে কম্পাইল (ডিবাগ ইনফো)
valgrind --leak-check=full ./my_program

একটি লিকি প্রোগ্রাম ও Valgrind-এর আউটপুট:

c

#include <stdlib.h>
int main() {
    int *p = (int*) malloc(100 * sizeof(int));
    // free(p);  // এই লাইনটি কমেন্ট করা আছে! (লিক)
    return 0;
}

Valgrind আউটপুট বলবে:

text

==12345== 400 bytes in 1 blocks are definitely lost in loss record 1 of 1
==12345==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==12345==    by 0x10866B: main (my_program.c:3)

🕵️‍♂️ পেশাদার টিপস: সপ্তাহে একবার আপনার প্রধান প্রোজেক্টে Valgrind চালান। এটি আপনার প্রজেক্টকে হাজারো ক্র্যাশ থেকে বাঁচাবে।


🔐 অধ্যায় ৪৪: সিকিউর কোডিং – Buffer Overflow ও Safe String Functions

আপনি কি জানেন, হ্যাকাররা সবচেয়ে বেশি C প্রোগ্রামের বাফার ওভারফ্লো ব্যবহার করে সিস্টেমে ঢোকে? gets() ফাংশনটি কতটা বিপজ্জনক তা হয়তো জানেন না।

বিপজ্জনক কোড:

c

char buffer[10];
gets(buffer); // ইউজার যদি ২০ অক্ষর দেয়, তাহলে স্ট্যাক ওভারফ্লো!

নিরাপদ কোড (Safe Code):

c

char buffer[10];
fgets(buffer, sizeof(buffer), stdin); // সর্বোচ্চ ৯ অক্ষর নেবে (শেষে \0 ধরে)

strcpy বনাম strncpy:

c

char dest[10];
char src[] = "This is a very long string";
strcpy(dest, src); // ❌ বিপজ্জনক (ওভারফ্লো হবে)
strncpy(dest, src, sizeof(dest) - 1); // ✅ নিরাপদ, শেষে NULL যোগ করতে ভুলবেন না
dest[sizeof(dest) - 1] = '\0';

📢 গোল্ডেন রুল: কখনোই gets() ব্যবহার করবেন না। ইনপুট নেওয়ার সময় সবসময় ম্যাক্সিমাম সাইজ উল্লেখ করুন। এটাই সিকিউর কোডিংয়ের প্রথম পাঠ।


🔔 অধ্যায় ৪৫: কন্ডিশন ভেরিয়েবল – Producer-Consumer প্যারাডাইম

আমরা মিউটেক্স শিখেছি, কিন্তু মিউটেক্স দিয়ে থ্রেডগুলোকে “অপেক্ষা করো, এখনও ডেটা আসেনি” বলা যায় না। এখানে লাগে কন্ডিশন ভেরিয়েবল (Condition Variable)।

ধরা যাক, একটি থ্রেড ডেটা তৈরি করছে (Producer), আরেকটি থ্রেড ডেটা প্রসেস করছে (Consumer)। কনজিউমার থ্রেডটি যখন দেখবে কিউ খালি, তখন এটি ঘুমিয়ে পড়বে। প্রডিউসার যখন নতুন ডেটা যোগ করবে, তখন এটি কনজিউমারকে জাগিয়ে দেবে (Signal)।

c

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t lock;
pthread_cond_t cond;
int buffer = 0; // ০ = খালি, ১ = ভর্তি

void* producer(void* arg) {
    for (int i = 0; i < 5; i++) {
        pthread_mutex_lock(&lock);
        while (buffer == 1) // বাফার ভর্তি থাকলে অপেক্ষা
            pthread_cond_wait(&cond, &lock);
        
        buffer = 1;
        printf("✅ প্রডিউসার: আইটেম তৈরি করলেন!\n");
        pthread_cond_signal(&cond); // কনজিউমারকে জাগানো
        pthread_mutex_unlock(&lock);
        sleep(1);
    }
    return NULL;
}

void* consumer(void* arg) {
    for (int i = 0; i < 5; i++) {
        pthread_mutex_lock(&lock);
        while (buffer == 0) // বাফার খালি থাকলে অপেক্ষা
            pthread_cond_wait(&cond, &lock);
        
        buffer = 0;
        printf("🛒 কনজিউমার: আইটেম প্রসেস করলেন!\n");
        pthread_cond_signal(&cond); // প্রডিউসারকে জাগানো
        pthread_mutex_unlock(&lock);
        sleep(1);
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_mutex_init(&lock, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_create(&t1, NULL, producer, NULL);
    pthread_create(&t2, NULL, consumer, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);
    printf("🏁 সব কাজ শেষ!\n");
    return 0;
}

🌟 বাস্তব ব্যবহার: এটি ডেটাবেস কিউ, ওয়েব সার্ভারের রিকুয়েস্ট প্রসেসিং—সবখানে ব্যবহৃত হয়। এটাই প্যারালাল প্রোগ্রামিংয়ের মডেল অ্যাপ্লিকেশন।


🐍 অধ্যায় ৪৬: সি ও পাইথনের সম্পর্ক (Python C API)

আপনি কি জানেন, পাইথনের বেশিরভাগ দ্রুতগতির লাইব্রেরি (যেমন: NumPy, Pandas) আসলে C/C++-তে লেখা? কারণ পাইথন ধীর, কিন্তু C দ্রুত।

পাইথনের সঙ্গে সি-কে সংযুক্ত করার পদ্ধতিকে বলে CPython API। এটি শিখলে আপনি আপনার C কোডকে পাইথন মডিউল বানাতে পারবেন!

একটি ধারণাগত উদাহরণ (Python-এ C ফাংশন কল করা):

c

// mymodule.c
#include <Python.h>

static PyObject* add(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL;
    return PyLong_FromLong(a + b);
}

static PyMethodDef MyMethods[] = {
    {"add", add, METH_VARARGS, "Add two numbers"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef mymodule = {
    PyModuleDef_HEAD_INIT,
    "mymodule",
    NULL,
    -1,
    MyMethods
};

PyMODINIT_FUNC PyInit_mymodule(void) {
    return PyModule_Create(&mymodule);
}

💡 কীভাবে কম্পাইল করবেন? এটি কম্পাইল করলে একটি .so ফাইল তৈরি হয়। পাইথনে import mymodule করে mymodule.add(5, 3) কল করতে পারেন! এটি আপনার রিজিউমে একটি অনন্য দক্ষতা যোগ করবে।


⚡ অধ্যায় ৪৭: এমবেডেড রিয়েলিটি – Interrupt Handler ও volatile

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

এখানে ব্যবহার হয় volatile কীওয়ার্ড (যা আমরা আগে শিখেছি, কিন্তু এখন বাস্তব উদাহরণ):

c

volatile int sensor_flag = 0;

// ইন্টারাপ্ট সার্ভিস রুটিন (ISR)
void __interrupt() timer_isr() {
    sensor_flag = 1; // হার্ডওয়্যার ফ্লাগ সেট করল
}

int main() {
    while (1) {
        if (sensor_flag) {
            read_sensor();
            sensor_flag = 0;
        }
    }
}

যদি volatile না থাকত, তাহলে কম্পাইলার ভাবত sensor_flag কখনো পরিবর্তন হয় না এবং লুপ থেকে সেই চেক বাদ দিয়ে দিত (বিপর্যয়!)। এমবেডেড ডেভেলপাররা এই বিষয়টি খুব ভালো করে জানেন।


📝 অধ্যায় ৪৮: ক্যাপস্টোন – থ্রেড-সেফ লগার (Log Rotation সহ)

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

  • মিউটেক্স দিয়ে থ্রেড-সেফ।
  • ফাইলের সাইজ ১ এমবি হলে নতুন ফাইল তৈরি করে (Log Rotation)।
  • টাইমস্ট্যাম্প সহ বার্তা লেখে।

c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>

pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
const char* log_filename = "app.log";
const long MAX_LOG_SIZE = 1024 * 1024; // 1 MB

void rotate_log() {
    FILE *f = fopen(log_filename, "r");
    if (f != NULL) {
        fseek(f, 0, SEEK_END);
        long size = ftell(f);
        fclose(f);
        if (size >= MAX_LOG_SIZE) {
            char new_name[256];
            time_t now = time(NULL);
            strftime(new_name, sizeof(new_name), "app_%Y%m%d_%H%M%S.log", localtime(&now));
            rename(log_filename, new_name);
            printf("🔄 লগ রোটেট করা হয়েছে: %s\n", new_name);
        }
    }
}

void write_log(const char* level, const char* message) {
    pthread_mutex_lock(&log_mutex);

    rotate_log(); // সাইজ চেক করে রোটেট

    FILE *f = fopen(log_filename, "a");
    if (f != NULL) {
        time_t now = time(NULL);
        char timestamp[50];
        strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
        fprintf(f, "[%s] [%s] %s\n", timestamp, level, message);
        fclose(f);
    }
    pthread_mutex_unlock(&log_mutex);
}

// থ্রেড ফাংশন (লগ লেখার ডেমো)
void* thread_worker(void* arg) {
    int id = *(int*)arg;
    for (int i = 0; i < 100; i++) {
        char msg[256];
        sprintf(msg, "থ্রেড %d থেকে বার্তা #%d", id, i);
        write_log("INFO", msg);
        usleep(10000); // ১০ মিলি সেকেন্ড বিরতি
    }
    return NULL;
}

int main() {
    pthread_t t1, t2, t3;
    int id1 = 1, id2 = 2, id3 = 3;

    pthread_create(&t1, NULL, thread_worker, &id1);
    pthread_create(&t2, NULL, thread_worker, &id2);
    pthread_create(&t3, NULL, thread_worker, &id3);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);

    printf("✅ সব থ্রেডের লগ লেখা শেষ!\n");
    printf("📂 'app.log' ফাইলটি খুলুন এবং দেখুন লগগুলি কত সুন্দর সাজানো!\n");
    return 0;
}

🚀 এই লগারটি আপনি আপনার রিয়েল-টাইম প্রকল্পে সরাসরি ব্যবহার করতে পারেন। এটি হাজার হাজার থ্রেড হ্যান্ডেল করতে পারবে, এবং ফাইল জায়গা নষ্ট করবে না (রোটেশন)।


🏁 পুরো সিরিজের অফিশিয়াল সমাপ্তি ও পরবর্তী জীবন

প্রিয় শিক্ষার্থী, “C Programming A to Z” – এই ৮টি পর্বের মহাকাব্যিক যাত্রা আজ এখানেই শেষ হলো।

আমরা শুরু করেছিলাম printf("Hello World"); দিয়ে, আর আজ পৌঁছেছি মাল্টি-থ্রেডেড, সিকিউর, প্রোফাইল-সাপোর্টেড লগার তৈরিতে। আপনি এখন C প্রোগ্রামিংয়ের যে কোনো সমস্যা মোকাবিলা করার মতো যথেষ্ট শক্তিশালী।

পরবর্তী করণীয় (রোডম্যাপ):
১. ডিজাইন প্যাটার্ন: C-তে কীভাবে Observer, Singleton প্যাটার্ন ইমপ্লিমেন্ট করা যায় তা শিখুন।
২. লিনাক্স কার্নেল ডেভেলপমেন্ট: লিনাক্স কার্নেল মডিউল রাইটিং-এর টিউটোরিয়াল অনুসরণ করুন।
৩. ক্লাউড নেটিভ: C দিয়ে মাইক্রোসার্ভিস বানানো যায় না, কিন্তু C দিয়ে লেখা লাইব্রেরিগুলোকে গো (Go) বা রাস্ট (Rust)-এর সাথে সংযুক্ত করা যায়—এটা শিখুন।

মনে রাখবেন, C শেখা মানে কম্পিউটারের ভাষায় কথা বলা শেখা। আপনি এখন কম্পিউটারের সাথে সরাসরি কথোপকথন করতে পারেন। এই দক্ষতা অমূল্য।

ToLearnTeam পরিবারের পক্ষ থেকে আপনাকে আন্তরিক শুভেচ্ছা ও অভিনন্দন। আমাদের সঙ্গে থাকার জন্য ধন্যবাদ। এখন আপনার পালা—যান, বাজিমাত করুন, নতুন কিছু তৈরি করুন, এবং প্রমাণ করুন যে C এখনও রাজা!

শুভকামনা, মহান প্রোগ্রামার! 

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার appeared first on To Learn Team.

]]>
C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম https://tolearnteam.com/c-programming-a-to-z-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%ad-%e0%a6%ae%e0%a6%be%e0%a6%b2%e0%a7%8d%e0%a6%9f%e0%a6%bf%e0%a6%a5%e0%a7%8d%e0%a6%b0%e0%a7%87%e0%a6%a1%e0%a6%bf%e0%a6%82-%e0%a6%b8/ Thu, 16 Jul 2026 03:14:01 +0000 http://tolearnteam.com/?p=860 আমরা C প্রোগ্রামিংয়ের এত গভীরে চলে এসেছি যে এখন সময় এসেছে প্রোগ্রামকে “জীবন্ত” করে তোলার। আপনার লেখা প্রোগ্রাম যদি শুধু নিজের মধ্যে ডেটা প্রসেস করে, তাহলে তা একটা দ্বীপের মতো। কিন্তু বাস্তবিক…

The post C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম appeared first on To Learn Team.

]]>
আমরা C প্রোগ্রামিংয়ের এত গভীরে চলে এসেছি যে এখন সময় এসেছে প্রোগ্রামকে “জীবন্ত” করে তোলার। আপনার লেখা প্রোগ্রাম যদি শুধু নিজের মধ্যে ডেটা প্রসেস করে, তাহলে তা একটা দ্বীপের মতো। কিন্তু বাস্তবিক সফটওয়্যার (যেমন: সার্ভার, গেমস, ব্রাউজার) একসাথে হাজার হাজার কাজ করে এবং নেটওয়ার্কের মাধ্যমে অন্যের সাথে কথা বলে।

আজকের এই পর্বে আমরা C-এর সেই দুটি সবচেয়ে ভয়ংকর অস্ত্র হাতে নেবো:
১. থ্রেড (Thread) – যা দিয়ে প্রোগ্রাম একসাথে একাধিক কাজ করে (প্যারালালিজম)।
২. সকেট (Socket) – যা দিয়ে প্রোগ্রাম নেটওয়ার্কের মাধ্যমে অন্যদের সাথে যোগাযোগ করে।

প্রস্তুত? তাহলে সিস্টেম প্রোগ্রামিং-এর রাজ্যে স্বাগতম! 🏰🔥


🔄 পর্ব-৬ এর রিক্যাপ ও সিস্টেম প্রোগ্রামিং-এর ভূমিকা

আমরা গত পর্বে BST, গ্রাফ এবং Big-O কমপ্লেক্সিটি শিখেছি। আজ আমরা সেই জ্ঞানকে কাজে লাগিয়ে প্রোগ্রামকে মাল্টি-কোর প্রসেসরে চালাবো এবং নেটওয়ার্কের মাধ্যমে ডেটা আদান-প্রদান করাবো। এটি একটু চ্যালেঞ্জিং, কিন্তু বিশ্বাস করুন, শেষ পর্যন্ত এটি সবচেয়ে মজার অংশ!


📚 অধ্যায় ৩৬: স্ট্যাটিক বনাম ডায়নামিক লাইব্রেরি (Static vs Dynamic Libraries)

আপনি যখন বড় প্রোজেক্ট তৈরি করেন, তখন একই কোড (যেমন: ম্যাথ ফাংশন) বারবার লেখা ভালো অভ্যাস নয়। আমরা সেগুলোকে লাইব্রেরি-তে রূপান্তর করি।

স্ট্যাটিক লাইব্রেরি (.a – Static):

  • কম্পাইল করার সময় লাইব্রেরির কোড আপনার প্রোগ্রামের সাথে মিশে যায়।
  • সুবিধা: প্রোগ্রাম সেলফ-কন্টেইন্ড (পোর্টেবল)।
  • অসুবিধা: ফাইলের সাইজ বড় হয়, এবং লাইব্রেরি আপডেট করলে পুরো প্রোগ্রাম রিকম্পাইল করতে হয়।

কীভাবে বানাবেন?

bash

gcc -c math_utils.c          # math_utils.o তৈরি
ar rcs libmath.a math_utils.o # স্ট্যাটিক লাইব্রেরি তৈরি
gcc main.c -L. -lmath -o program # লাইব্রেরি লিংক করা

ডায়নামিক লাইব্রেরি (.so – Shared Object / .dll – Windows):

  • রানটাইমে লোড হয়। একাধিক প্রোগ্রাম একই লাইব্রেরি শেয়ার করতে পারে।
  • সুবিধা: ফাইলের সাইজ ছোট, লাইব্রেরি আপডেট করলে প্রোগ্রাম রিকম্পাইল করতে হয় না (শুধু রিস্টার্ট)।

কীভাবে বানাবেন?

bash

gcc -fPIC -c math_utils.c     # পজিশন-ইন্ডিপেন্ডেন্ট কোড
gcc -shared -o libmath.so math_utils.o # শেয়ার্ড লাইব্রেরি
gcc main.c -L. -lmath -o program

💡 পেশাদার টিপস: লিনাক্সের অধিকাংশ সফটওয়্যার (যেমন: libc.so) ডায়নামিক লাইব্রেরি ব্যবহার করে।


🛠 অধ্যায় ৩৭: মেকফাইল (Makefile) – একটি ক্লিকে পুরো প্রোজেক্ট কম্পাইল করুন

বড় প্রোজেক্টে ২০-৩০টি .c ফাইল থাকে। প্রতিবার gcc টাইপ করা অসম্ভব। Makefile হলো একটি স্ক্রিপ্ট যা বলে দেয় কোন ফাইল আগে কম্পাইল হবে এবং কীভাবে লিংক হবে।

একটি সাধারণ Makefile:

makefile

CC = gcc
CFLAGS = -Wall -g -Iinclude
TARGET = my_app
SRCS = main.c math_utils.c file_utils.c
OBJS = $(SRCS:.c=.o)

# ডিফল্ট টার্গেট
all: $(TARGET)

# লিংকিং (Executable বানানো)
$(TARGET): $(OBJS)
	$(CC) -o $@ $^

# কম্পাইলেশন (.c থেকে .o বানানো)
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

# ক্লিনআপ (পুরনো ফাইল ডিলিট)
clean:
	rm -f $(OBJS) $(TARGET)

# রান করার টার্গেট
run: $(TARGET)
	./$(TARGET)

কীভাবে ব্যবহার করবেন: টার্মিনালে শুধু make টাইপ করুন, পুরো প্রোজেক্ট কম্পাইল হয়ে যাবে! make clean দিলে সব ফাইল পরিষ্কার হবে। এটি শিখলে আপনি যেকোনো ওপেন সোর্স প্রোজেক্ট কম্পাইল করতে পারবেন।


🧵 অধ্যায় ৩৮: পিওএসআইএক্স থ্রেড (Pthreads) – একসাথে একাধিক কাজ করা

ধরা যাক, আপনাকে ১০০টি ছবি প্রসেস করতে হবে। যদি একে একে করেন, সময় লাগবে ১০০ সেকেন্ড। কিন্তু আপনার কম্পিউটারে যদি ৪টি কোর থাকে, তাহলে ৪টি থ্রেড তৈরি করে কাজ ভাগ করে দিলে সময় কমে ২৫ সেকেন্ডে!

C-তে থ্রেড তৈরির জন্য pthread লাইব্রেরি ব্যবহার হয় (Linux/macOS-এ)।

c

#include <stdio.h>
#include <pthread.h>
#include <unistd.h> // sleep() এর জন্য

// থ্রেড ফাংশন
void* printNumbers(void* arg) {
    int id = *(int*)arg;
    for (int i = 1; i <= 5; i++) {
        printf("থ্রেড %d: %d\n", id, i);
        sleep(1); // ১ সেকেন্ড বিরতি
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    int id1 = 1, id2 = 2;

    // দুটি থ্রেড তৈরি
    pthread_create(&t1, NULL, printNumbers, &id1);
    pthread_create(&t2, NULL, printNumbers, &id2);

    // থ্রেড শেষ হওয়া পর্যন্ত অপেক্ষা (Join)
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    printf("✅ সব থ্রেড শেষ!\n");
    return 0;
}

কম্পাইল করার নিয়ম: gcc program.c -pthread -o program (অবশ্যই -pthread ফ্ল্যাগ দিতে হবে)।


🔒 অধ্যায় ৩৯: মিউটেক্স (Mutex) ও থ্রেড সেফটি – রেস কন্ডিশন থেকে বাঁচুন

যখন একাধিক থ্রেড একই ভেরিয়েবলে পরিবর্তন আনে, তখন রেস কন্ডিশন (Race Condition) নামক ভয়াবহ সমস্যা হয়। যেমন: দুটি থ্রেড যদি একসাথে একটি কাউন্টার বাড়ায়, তাহলে মান ১ কম বা বেশি হয়ে যেতে পারে।

এই সমস্যা সমাধানে মিউটেক্স (Mutex) ব্যবহার করি। এটি একটি লক, যা একবার শুধু একজনই ধারণ করতে পারে।

c

#include <stdio.h>
#include <pthread.h>

int counter = 0;
pthread_mutex_t lock; // মিউটেক্স ডিক্লেয়ার

void* increment(void* arg) {
    for (int i = 0; i < 100000; i++) {
        pthread_mutex_lock(&lock);   // লক নেওয়া
        counter++;                   // ক্রিটিক্যাল সেকশন
        pthread_mutex_unlock(&lock); // লক ছেড়ে দেওয়া
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_mutex_init(&lock, NULL); // মিউটেক্স ইনিশিয়ালাইজ

    pthread_create(&t1, NULL, increment, NULL);
    pthread_create(&t2, NULL, increment, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    pthread_mutex_destroy(&lock); // মিউটেক্স ডেস্ট্রয়
    printf("কাউন্টারের মান: %d\n", counter); // ঠিক ২০০০০০ আসবে!
    return 0;
}

💡 গুরুত্বপূর্ণ: মিউটেক্স না থাকলে কাউন্টারের মান ২০০০০০-এর কম আসত। ডেটাবেস, ফাইল রাইট—সব জায়গায় মিউটেক্স ব্যবহার হয়।


🌐 অধ্যায় ৪০: সকেট প্রোগ্রামিং (TCP) – দুটি কম্পিউটারের মধ্যে কথোপকথন

সকেট হলো নেটওয়ার্কের দরজা। আমরা দুটি প্রোগ্রাম লিখব—একটি সার্ভার (যে শোনে) এবং একটি ক্লায়েন্ট (যে বার্তা পাঠায়)।

সার্ভার কোড (server.c):

c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    char buffer[1024] = {0};
    char *message = "Hello from Server!";

    // ১. সকেট তৈরি
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // ২. অ্যাড্রেস সেট করা
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8080);

    // ৩. বাইন্ড (পোর্টের সাথে সংযুক্ত)
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));

    // ৪. লিসেন (ক্লায়েন্টের জন্য অপেক্ষা)
    listen(server_fd, 3);
    printf("🖥 সার্ভার ৮০৮০ পোর্টে লিসেন করছে...\n");

    // ৫. ক্লায়েন্টকে গ্রহণ (Accept)
    new_socket = accept(server_fd, NULL, NULL);

    // ৬. ক্লায়েন্টকে বার্তা পাঠানো
    send(new_socket, message, strlen(message), 0);
    printf("📤 বার্তা পাঠানো হয়েছে!\n");

    close(new_socket);
    close(server_fd);
    return 0;
}

ক্লায়েন্ট কোড (client.c):

c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char buffer[1024] = {0};

    // ১. সকেট তৈরি
    sock = socket(AF_INET, SOCK_STREAM, 0);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); // লোকালহোস্ট

    // ২. সার্ভারে কানেক্ট করা
    connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    // ৩. সার্ভার থেকে বার্তা পড়া
    read(sock, buffer, 1024);
    printf("📩 সার্ভার থেকে বার্তা: %s\n", buffer);

    close(sock);
    return 0;
}

🔥 রান করবেন কীভাবে: প্রথমে টার্মিনাল-১ এ ./server চালান, তারপর টার্মিনাল-২ এ ./client চালান। দেখবেন ক্লায়েন্ট “Hello from Server!” বার্তা পেয়েছে! এটি প্রোগ্রামিং জীবনের অন্যতম সেরা অনুভূতি।


🛑 অধ্যায় ৪১: সিগন্যাল হ্যান্ডলিং – Ctrl+C ধরা

আপনি যখন Ctrl+C চাপেন, প্রোগ্রাম হঠাৎ বন্ধ হয়ে যায়। কিন্তু আপনার প্রোগ্রাম যদি ফাইলে ডেটা লেখে, তাহলে হঠাৎ বন্ধ হয়ে ডেটা নষ্ট হতে পারে। সিগন্যাল হ্যান্ডলার দিয়ে আমরা সেই বোতাম ধরে ফেলতে পারি।

c

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sigint_handler(int sig) {
    printf("\n🛑 প্রোগ্রাম বন্ধ করা হচ্ছে... শেষ মুহূর্তের কাজ শেষ করছি!\n");
    // এখানে ফাইল ক্লোজ, মেমোরি ফ্রি ইত্যাদি করুন
    exit(0); // প্রস্থান
}

int main() {
    // Ctrl+C (SIGINT) সিগন্যাল ধরা
    signal(SIGINT, sigint_handler);

    printf("প্রোগ্রাম চলছে। বন্ধ করতে Ctrl+C চাপুন।\n");
    while (1) {
        printf("কাজ করছি...\n");
        sleep(2);
    }
    return 0;
}

এটি লাইফ সেভার! বড় সার্ভারে এটি ব্যবহার করলে প্রোগ্রাম হঠাৎ ক্র্যাশ না করে মার্জিতভাবে বন্ধ হয়।


🏗 অধ্যায় ৪২: ফাইনাল প্রোজেক্ট – ‘মাল্টি-থ্রেডেড চ্যাট সার্ভার’

এখন আমরা সবকিছু একসাথে ফেলব। আমরা একটি সার্ভার বানাবো যা একাধিক ক্লায়েন্টকে একসাথে হ্যান্ডেল করতে পারে (প্রতি ক্লায়েন্টের জন্য একটি করে থ্রেড তৈরি করবে) এবং বার্তা গ্রহণ করে ফাইলে লগ করবে।

সার্ভারের মূল লজিক (ধারণাগত):

  1. সার্ভার সকেট খোলে এবং লিসেন করে।
  2. একটি while লুপে accept() কল করে নতুন ক্লায়েন্ট এলে তার জন্য একটি থ্রেড তৈরি করে (যোগাযোগের সকেটটি থ্রেডে পাঠিয়ে দেয়)।
  3. থ্রেড ফাংশনটি ক্লায়েন্ট থেকে বার্তা পড়ে, ফাইলে সেভ করে এবং ক্লায়েন্টকে “বার্তা প্রাপ্ত” বলে জানায়।

c

// সার্ভারের মূল স্ট্রাকচার (পূর্ণ কোড কমান্ডের জন্য সংক্ষিপ্ত)
void *handle_client(void *arg) {
    int client_socket = *(int*)arg;
    char buffer[1024];
    while (read(client_socket, buffer, 1024) > 0) {
        printf("📨 ক্লায়েন্ট থেকে: %s\n", buffer);
        // ফাইলে সেভ করুন
        send(client_socket, "ACK: বার্তা পেয়েছি!", 20, 0);
    }
    close(client_socket);
    return NULL;
}

⚡ চ্যালেঞ্জ: উপরের স্ট্রাকচারটি নিজে সম্পূর্ণ করুন। এটি আপনার পোর্টফোলিওতে একটি “মাল্টি-থ্রেডেড TCP সার্ভার” হিসেবে জ্বলজ্বল করবে।


🏁 চূড়ান্ত আর্কিটেক্টের পথচলা

প্রিয় প্রোগ্রামার, আপনি এখন C-এর শেষ সীমান্ত অতিক্রম করেছেন। আপনি জানেন কীভাবে প্রোগ্রাম একসাথে একাধিক কাজ করে (Threads), কীভাবে নেটওয়ার্কে কথা বলে (Sockets), এবং কীভাবে পেশাদার টুলস (Makefile, Libraries) ব্যবহার করতে হয়।

“C Programming A to Z” – এই ৭ পর্বের যাত্রা এখানেই শেষ হচ্ছে। কিন্তু আপনার যাত্রা তো এখানেই শেষ নয়, বরং এটি সবে শুরু!

এখন আপনি কী করবেন?
১. লিনাক্স কার্নেল মডিউল: নিজের একটি ছোট ড্রাইভার লিখুন। C দিয়ে হার্ডওয়্যার নিয়ন্ত্রণ করুন।
২. আরটিওএস (RTOS): এমবেডেড সিস্টেমে ফ্রিটার ওএস (FreeRTOS) নিয়ে কাজ করুন।
৩. ইউজারল্যান্ড প্রোজেক্ট: এনক্রিপ্টেড চ্যাট অ্যাপ, কাস্টম ডেটাবেস ইঞ্জিন বা একটি ওয়েব সার্ভার (যেমন: Nginx-এর ছোট সংস্করণ) বানানোর চেষ্টা করুন।

আপনি আজ যে জ্ঞান অর্জন করলেন, তা বিশ্বের যেকোনো প্রিমিয়ার টেক কোম্পানিতে (Google, Microsoft, Intel) কাজে লাগবে। C হলো সেই ভাষা যা হার্ডওয়্যারের সাথে সরাসরি কথা বলে, এবং আপনি এখন সেই ভাষায় সাবলীল।

ToLearnTeam পরিবার আপনার এই অসাধারণ অর্জনের জন্য গর্বিত। অসংখ্য ধন্যবাদ আমাদের সঙ্গে এই যাত্রায় থাকার জন্য। এখন নেটওয়ার্ক জুড়ে আপনার কোডের জয়গান হোক!

আপনার হাতের কিবোর্ডই এখন আপনার অস্ত্র। তৈরি করুন, ভাঙুন, আর নতুন কিছু তৈরি করুন। পৃথিবী অপেক্ষা করছে আপনার জন্য! 

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম appeared first on To Learn Team.

]]>
C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট https://tolearnteam.com/c-programming-a-to-z-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%ac-%e0%a6%9f%e0%a7%8d%e0%a6%b0%e0%a6%bf-%e0%a6%97%e0%a7%8d%e0%a6%b0%e0%a6%be%e0%a6%ab-%e0%a6%ac%e0%a6%bf%e0%a6%97-%e0%a6%93/ Thu, 16 Jul 2026 03:09:45 +0000 http://tolearnteam.com/?p=857 আমরা দীর্ঘ পথ পাড়ি দিয়েছি। অ্যারে, লিংকড লিস্ট, স্ট্যাক, কিউ—এগুলো সব লিনিয়ার (সরলরৈখিক) ডেটা স্ট্রাকচার। কিন্তু বাস্তব পৃথিবী কিন্তু সরলরৈখিক নয়! আপনার ফাইল সিস্টেমের ফোল্ডারগুলো কি সাজানো? এটি একটি ট্রি। আপনার…

The post C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট appeared first on To Learn Team.

]]>
আমরা দীর্ঘ পথ পাড়ি দিয়েছি। অ্যারে, লিংকড লিস্ট, স্ট্যাক, কিউ—এগুলো সব লিনিয়ার (সরলরৈখিক) ডেটা স্ট্রাকচার। কিন্তু বাস্তব পৃথিবী কিন্তু সরলরৈখিক নয়! আপনার ফাইল সিস্টেমের ফোল্ডারগুলো কি সাজানো? এটি একটি ট্রি। আপনার সোশ্যাল মিডিয়া নেটওয়ার্ক কীভাবে কাজ করে? এটি একটি গ্রাফ।

আজ আমরা এই জটিল কিন্তু অসাধারণ ডেটা স্ট্রাকচার দুটি আয়ত্ত করব। আর শিখব কীভাবে কোনো অ্যালগরিদম দ্রুত নাকি ধীর তা পরিমাপ করা যায় (Big-O)। সবশেষে, আমরা একটি পূর্ণাঙ্গ প্রজেক্ট বানাবো যা দিয়ে আপনি ইন্টারভিউয়ে ঝড় তুলতে পারবেন। চলুন, ফাইনাল রাউন্ডে ডুব দিন! 🏊‍♂️🔥


🔄 পর্ব-৫ এর রিক্যাপ ও আজকের ভিশন

গত পর্বে আমরা জিসিসি (GCC) এর ফ্ল্যাগ, জিডিবি (GDB) ডিবাগার, বাইনারি ফাইল এবং typedef শিখেছি। আজ আমরা সেই হাতিয়ারগুলো ব্যবহার করে তৈরি করব নন-লিনিয়ার ডেটা স্ট্রাকচার। প্রস্তুত তো? শুরু করা যাক!


🌿 অধ্যায় ৩০: ট্রি ডেটা স্ট্রাকচার ও বাইনারি সার্চ ট্রি (BST)

ট্রি হলো একটি হায়ারার্কিক্যাল ডেটা স্ট্রাকচার। একটি রুট (Root) নোড থেকে শুরু হয়ে তা শাখা-প্রশাখায় (Children) বিভক্ত হয়।

বাইনারি ট্রি (Binary Tree): প্রতিটি নোডের সর্বোচ্চ ২টি চাইল্ড থাকতে পারে (লেফট ও রাইট)।

বাইনারি সার্চ ট্রি (BST): এটি বাইনারি ট্রির একটি বিশেষ রূপ, যেখানে:

  • বাম সাবট্রির সব নোডের মান রুটের চেয়ে ছোট।
  • ডান সাবট্রির সব নোডের মান রুটের চেয়ে বড়।
    এই সম্পত্তির কারণেই BST-তে ডেটা খুঁজে বের করা অত্যন্ত দ্রুত!

BST-তে নোড ইনসার্ট ও সার্চ করার কোড:

c

#include <stdio.h>
#include <stdlib.h>

// ট্রির নোড
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
};

// নতুন নোড তৈরি
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// BST-তে ডেটা ইনসার্ট (রিকার্সিভ)
struct Node* insert(struct Node* root, int data) {
    if (root == NULL) return createNode(data); // বেস কেস

    if (data < root->data)
        root->left = insert(root->left, data);
    else if (data > root->data)
        root->right = insert(root->right, data);
    // যদি সমান হয়, তাহলে কিছু করি না (ডুপ্লিকেট নেওয়া হচ্ছে না)

    return root;
}

// BST-তে ডেটা খোঁজা (সার্চ)
struct Node* search(struct Node* root, int key) {
    if (root == NULL || root->data == key)
        return root;

    if (key < root->data)
        return search(root->left, key);
    else
        return search(root->right, key);
}

int main() {
    struct Node* root = NULL;
    root = insert(root, 50);
    insert(root, 30);
    insert(root, 20);
    insert(root, 40);
    insert(root, 70);
    insert(root, 60);
    insert(root, 80);

    int key = 40;
    struct Node* result = search(root, key);
    if (result != NULL)
        printf("✅ %d টি খুঁজে পাওয়া গেছে!\n", key);
    else
        printf("❌ %d টি পাওয়া যায়নি!\n", key);
    
    return 0;
}

🚀 দ্রুততার রহস্য: BST-তে সার্চ করতে সময় লাগে গড়ে O(log n) , যা অ্যারের লিনিয়ার সার্চ (O(n))-এর চেয়ে অনেক দ্রুত!


🧭 অধ্যায় ৩১: ট্রি ট্রাভার্সাল (Inorder, Preorder, Postorder)

ট্রি প্রিন্ট করার ৩টি ক্লাসিক্যাল পদ্ধতি আছে। এগুলোর প্রত্যেকটির ভিন্ন ভিন্ন ব্যবহার আছে।

c

// ১. Inorder (বাম -> রুট -> ডান): BST-তে করলে ডেটা সর্টেড অর্ডারে আসে!
void inorder(struct Node* root) {
    if (root != NULL) {
        inorder(root->left);
        printf("%d ", root->data);
        inorder(root->right);
    }
}

// ২. Preorder (রুট -> বাম -> ডান): ট্রি কপি করতে ব্যবহার হয়।
void preorder(struct Node* root) {
    if (root != NULL) {
        printf("%d ", root->data);
        preorder(root->left);
        preorder(root->right);
    }
}

// ৩. Postorder (বাম -> ডান -> রুট): ট্রি ডিলিট করতে ব্যবহার হয়।
void postorder(struct Node* root) {
    if (root != NULL) {
        postorder(root->left);
        postorder(root->right);
        printf("%d ", root->data);
    }
}

আপনি যদি উপরের BST-তে inorder চালান, আউটপুট আসবে: 20 30 40 50 60 70 80 (দেখুন, সর্টেড!)।


🕸 অধ্যায় ৩২: গ্রাফ (Graph) বেসিক – সংযোগের জগৎ

গ্রাফ হলো নোড (ভার্টেক্স) এবং তাদের মধ্যে সংযোগ (এজ)-এর একটি সেট। ফেসবুকের বন্ধুদের নেটওয়ার্ক বা গুগল ম্যাপের রাস্তাগুলো গ্রাফ দিয়ে বোঝানো হয়।

গ্রাফ প্রকাশের ২টি উপায়:

১. অ্যাজাসেন্সি ম্যাট্রিক্স (Adjacency Matrix): ২D অ্যারে। matrix[i][j] = 1 মানে i থেকে j-এ সরাসরি সংযোগ আছে।

c

int graph[4][4] = {
    {0, 1, 1, 0},
    {1, 0, 0, 1},
    {1, 0, 0, 1},
    {0, 1, 1, 0}
}; // এটি একটি অনির্দেশিত (Undirected) গ্রাফ

২. অ্যাজাসেন্সি লিস্ট (Adjacency List): লিংকড লিস্টের অ্যারে। এটি মেমোরি সাশ্রয়ী।

c

// ধারণাগত উদাহরণ (স্ট্রাকচার ব্যবহার করে)
struct AdjListNode { int dest; struct AdjListNode* next; };
struct AdjList { struct AdjListNode* head; };
struct Graph { int V; struct AdjList* array; };

👨‍💻 আমাদের প্রোজেক্টের জন্য: গ্রাফ অনেক বড় টপিক। তবে বেসিক জানা দরকার, কারণ ইন্টারভিউতে প্রায়ই গ্রাফ-বেসিক প্রশ্ন আসে (যেমন: সংযোগ আছে কিনা চেক করা)।


⏳ অধ্যায় ৩৩: টাইম কমপ্লেক্সিটি (Big-O নোটেশন) – অ্যালগরিদমের গতি পরিমাপ

আপনি কেন লিংকড লিস্টের বদলে BST ব্যবহার করবেন? উত্তর হলো গতি। Big-O নোটেশন একটি অ্যালগরিদম খারাপ থেকে খারাপ কীভাবে আচরণ করে তা বোঝায়।

নোটেশননামউদাহরণমন্তব্য
O(1)কনস্ট্যান্টঅ্যারে থেকে ইন্ডেক্স দিয়ে মান বের করাসবচেয়ে দ্রুত (পারফেক্ট)
O(log n)লগারিদমিকBST-তে সার্চ করাঅসাধারণ (দ্রুত)
O(n)লিনিয়ারলিংকড লিস্ট ট্রাভার্সঠিকঠাক (মধ্যম)
O(n²)কোয়াড্রাটিকবাবল সর্ট (Bubble Sort)ধীর (বড় ডেটায় ব্যবহার করবেন না!)

📢 পেশাদার টিপস: ইন্টারভিউয়ে প্রশ্ন করলেই তারা Big-O জিজ্ঞেস করে। মনে রাখবেন, আপনার কোড যদি O(n²) হয়, তাহলে ১ লাখ ডেটায় তা ১০ বিলিয়ন অপারেশন করবে! সেজন্য BST (O(log n)) শিখা এত জরুরি ছিল।


🧬 অধ্যায় ৩৪: মডার্ন C – stdbool.h ও stdint.h ব্যবহার করুন

আপনি কি জানেন, C-তে সরাসরি true বা false নেই? (C99 এর আগে)। এখনকার স্ট্যান্ডার্ডে এই সুবিধা আছে। আবার int-এর সাইজ প্ল্যাটফর্মভেদে (৩২-বিট/৬৪-বিট) বদলায়। পেশাদাররা নির্দিষ্ট সাইজের ইন্টিজার ব্যবহার করেন।

c

#include <stdio.h>
#include <stdbool.h>  // true/false এর জন্য
#include <stdint.h>   // int32_t, uint8_t ইত্যাদির জন্য

int main() {
    bool isLoggedIn = true;
    if (isLoggedIn) {
        printf("✅ ইউজার লগইন করেছেন!\n");
    }

    int32_t myAge = 25;    // ৩২-বিট ইন্টিজার (যেকোনো কম্পাইলারে ৪ বাইট)
    uint8_t smallNum = 255; // ৮-বিট (০ থেকে ২৫৫)
    printf("আমার বয়স: %d\n", myAge);
    return 0;
}

এটি আপনার কোডকে পোর্টেবল (Portable) করে তোলে। যেকোনো মেশিনে কম্পাইল করলে একই আচরণ পাবেন।


🎓 অধ্যায় ৩৫: ফাইনাল ক্যাপস্টোন – ‘ইউনিভার্সিটি কোর্স এনরোলমেন্ট সিস্টেম’

এখন আমরা সবকিছু একসাথে ফেলব। আমরা একটি প্রজেক্ট বানাবো যা BST ব্যবহার করে শিক্ষার্থীদের আইডি অনুযায়ী সাজিয়ে রাখবে, বাইনারি ফাইল ব্যবহার করে ডেটা সেভ করবে, এবং সার্চ ফিচার থাকবে যা O(log n) সময়ে রেজাল্ট দেবে।

প্রজেক্টের বৈশিষ্ট্য:

  • শিক্ষার্থী যোগ করুন (আইডি, নাম, সিজিপিএ)।
  • আইডি দিয়ে দ্রুত খোঁজ করুন।
  • Inorder ট্রাভার্সাল করে আইডি অনুযায়ী সাজানো সব শিক্ষার্থী দেখান।
  • প্রোগ্রাম বন্ধ করলে ফাইলে সেভ, শুরু করলে লোড।

c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

// স্ট্রাকচার ডিফাইন
typedef struct {
    int id;
    char name[50];
    float cgpa;
} Student;

// BST নোড
typedef struct Node {
    Student data;
    struct Node* left;
    struct Node* right;
} Node;

// নতুন নোড তৈরি
Node* createNode(Student s) {
    Node* newNode = (Node*) malloc(sizeof(Node));
    newNode->data = s;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// BST-তে ইনসার্ট (আইডি অনুযায়ী)
Node* insert(Node* root, Student s) {
    if (root == NULL) return createNode(s);
    if (s.id < root->data.id)
        root->left = insert(root->left, s);
    else if (s.id > root->data.id)
        root->right = insert(root->right, s);
    else
        printf("⚠ এই আইডি আগেই আছে! (ডুপ্লিকেট নেওয়া হবে না)\n");
    return root;
}

// BST-তে সার্চ
Node* search(Node* root, int id) {
    if (root == NULL || root->data.id == id)
        return root;
    if (id < root->data.id)
        return search(root->left, id);
    else
        return search(root->right, id);
}

// Inorder ট্রাভার্সাল (সর্টেড অর্ডার)
void inorder(Node* root) {
    if (root != NULL) {
        inorder(root->left);
        printf("আইডি: %d | নাম: %s | সিজিপিএ: %.2f\n", root->data.id, root->data.name, root->data.cgpa);
        inorder(root->right);
    }
}

// ট্রি ডিলিট (মেমোরি ফ্রি)
void freeTree(Node* root) {
    if (root != NULL) {
        freeTree(root->left);
        freeTree(root->right);
        free(root);
    }
}

// বাইনারি ফাইলে সেভ (Preorder ব্যবহার করে)
void saveToFile(Node* root, FILE* file) {
    if (root == NULL) return;
    fwrite(&(root->data), sizeof(Student), 1, file); // বাইনারি লেখা
    saveToFile(root->left, file);
    saveToFile(root->right, file);
}

// ফাইল থেকে লোড (আবার ইনসার্ট)
Node* loadFromFile(Node* root, const char* filename) {
    FILE* file = fopen(filename, "rb");
    if (file == NULL) return root;
    Student s;
    while (fread(&s, sizeof(Student), 1, file) == 1) {
        root = insert(root, s);
    }
    fclose(file);
    printf("📂 ফাইল থেকে ডেটা লোড হয়েছে!\n");
    return root;
}

int main() {
    Node* root = NULL;
    root = loadFromFile(root, "students.bin");

    int choice, id;
    Student s;
    Node* found;

    while (1) {
        printf("\n🎓 **ইউনিভার্সিটি এনরোলমেন্ট সিস্টেম**\n");
        printf("1. শিক্ষার্থী যোগ করুন\n");
        printf("2. আইডি দিয়ে খোঁজ করুন (দ্রুত)\n");
        printf("3. সব শিক্ষার্থী দেখান (আইডি অনুযায়ী সাজানো)\n");
        printf("4. সেভ করে প্রস্থান\n");
        printf("পছন্দ: ");
        scanf("%d", &choice);
        getchar(); // buffer clean

        if (choice == 1) {
            printf("আইডি: "); scanf("%d", &s.id); getchar();
            printf("নাম: "); gets(s.name);
            printf("সিজিপিএ: "); scanf("%f", &s.cgpa);
            root = insert(root, s);
            printf("✅ শিক্ষার্থী যোগ হয়েছে!\n");
        }
        else if (choice == 2) {
            printf("আইডি দিন: "); scanf("%d", &id);
            found = search(root, id);
            if (found != NULL) {
                printf("🔍 পাওয়া গেছে! নাম: %s, সিজিপিএ: %.2f\n", found->data.name, found->data.cgpa);
            } else {
                printf("❌ এই আইডির কোনো শিক্ষার্থী নেই!\n");
            }
        }
        else if (choice == 3) {
            if (root == NULL) printf("📭 তালিকা ফাঁকা!\n");
            else {
                printf("\n📋 **শিক্ষার্থীদের সাজানো তালিকা:**\n");
                inorder(root);
            }
        }
        else if (choice == 4) {
            FILE* file = fopen("students.bin", "wb");
            if (file != NULL) {
                saveToFile(root, file);
                fclose(file);
                printf("💾 সব ডেটা 'students.bin'-এ সেভ হয়েছে!\n");
            }
            freeTree(root); // মেমোরি মুক্ত
            printf("👋 প্রস্থান করছি। ভালো থাকুন!\n");
            break;
        }
        else {
            printf("❌ ভুল ইনপুট! ১-৪ এর মধ্যে চাপুন।\n");
        }
    }
    return 0;
}

⚡ এই প্রজেক্টটি রান করান। ১০০০ শিক্ষার্থী থাকলেও এটি অত্যন্ত দ্রুত কাজ করবে, কারণ সব অপারেশনই O(log n) টাইমে হচ্ছে!


🏁 পুরো সিরিজের মহাসমাপ্তি

আমরা “C Programming A to Z” -এর এই ৬টি বিশাল পর্বের যাত্রা শেষ করলাম।

আমরা যা যা কাভার করেছি:

  • ✅ বেসিক সিনট্যাক্স, লুপ, ফাংশন।
  • ✅ পয়েন্টার ও ডায়নামিক মেমোরি (malloc, free)।
  • ✅ অ্যারে, স্ট্রিং, স্ট্রাকচার, ইউনিয়ন।
  • ✅ লিংকড লিস্ট, স্ট্যাক, কিউ।
  • ✅ ট্রি (BST), গ্রাফ বেসিক ও অ্যালগরিদম (সার্চ/সর্ট)।
  • ✅ ফাইল হ্যান্ডলিং (টেক্সট ও বাইনারি)।
  • ✅ প্রফেশনাল টুলস (GCC, GDB, Makefile ধারণা) ও Big-O কমপ্লেক্সিটি।

আপনি এখন প্রস্তুত:
আপনি যদি এই ৬টি পর্বের প্রতিটি কোড নিজে হাতে লিখে থাকেন, তাহলে আপনি যেকোনো কোম্পানির জুনিয়র সি ডেভেলপার ইন্টারভিউয়ের জন্য ১০০% প্রস্তুত। C শেখা শেষ নয়, এটি আপনার প্রোগ্রামিং জীবনের সেরা বিনিয়োগ।

এখন আপনার পথচলা:

  • LeetCode বা CodeChef-এ গিয়ে C দিয়ে ডেইলি চ্যালেঞ্জ সলভ করুন।
  • GitHub-এ একটি রিপোজিটরি খুলুন এবং আজকের এই প্রোজেক্টটি আপলোড দিন (এটি আপনার পোর্টফোলিও হবে)।
  • লিনাক্স কার্নেল বা ওপেন সোর্স ড্রাইভারের কোড পড়ার চেষ্টা করুন—এখন আপনি তা বুঝতে পারবেন।

ToLearnTeam-এর পক্ষ থেকে আপনাকে অসংখ্য ধন্যবাদ এই যাত্রায় আমাদের সঙ্গী হওয়ার জন্য। বিশ্বাস রাখুন, কঠিন পথটি আপনিই পাড়ি দিয়েছেন। এখন যান, কোড লিখুন, ভুল করুন, শিখুন—এবং একদিন না একদিন জগৎ বদলে দেওয়ার মতো কিছু তৈরি করুন!

শুভকামনা, প্রিয় প্রোগ্রামার। 

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট appeared first on To Learn Team.

]]>
C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক https://tolearnteam.com/c-programming-a-to-z-%e0%a6%ac%e0%a7%8b%e0%a6%a8%e0%a6%be%e0%a6%b8-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%ab-%e0%a6%aa%e0%a7%8d%e0%a6%b0%e0%a7%8b-%e0%a6%9f%e0%a7%81%e0%a6%b2%e0%a6%9a%e0%a7%87/ Thu, 16 Jul 2026 03:06:25 +0000 http://tolearnteam.com/?p=854 আমরা C প্রোগ্রামিংয়ের এত পথ পাড়ি দিয়েছি যে এখন সময় এসেছে পর্দার আড়ালে তাকানোর। আপনি কি কখনও ভেবেছেন, আপনার লেখা .c ফাইলটি কীভাবে কম্পিউটার বুঝতে পারে? অথবা প্রোগ্রাম ক্র্যাশ করলে কীভাবে বের করবেন কোন…

The post C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক appeared first on To Learn Team.

]]>
আমরা C প্রোগ্রামিংয়ের এত পথ পাড়ি দিয়েছি যে এখন সময় এসেছে পর্দার আড়ালে তাকানোর। আপনি কি কখনও ভেবেছেন, আপনার লেখা .c ফাইলটি কীভাবে কম্পিউটার বুঝতে পারে? অথবা প্রোগ্রাম ক্র্যাশ করলে কীভাবে বের করবেন কোন লাইনে ভুল হয়েছে?

পেশাদার জগতে, শুধু কোড লেখা কাজের ৫০%। বাকি ৫০% হলো সেই কোডকে অপটিমাইজ করা, ডিবাগ করা এবং মেইনটেইন করা। আজকের এই বোনাস পর্বে আমরা সেসব গোপন বিষয় শিখব, যা কোনও টিউটোরিয়াল সহজে বলে না। চলুন, প্রো লেভেলে পা রাখি! 🔥


🔄 পর্ব-৪ এর রিক্যাপ ও আজকের লক্ষ্য

আমরা গত পর্বে স্ট্যাক, কিউ, ডাবলি লিংকড লিস্ট এবং সর্টিং অ্যালগরিদম শিখেছি। আজকে আমরা শিখব:

  • কীভাবে বাইনারি ফাইলে ডেটা সংরক্ষণ করবেন (যাতে অন্য প্রোগ্রাম পড়তে পারে)।
  • typedef দিয়ে কীভাবে কোড ছোট ও সুন্দর করবেন।
  • কেন আপনার struct মেমোরিতে বাড়তি জায়গা নেয় (প্যাডিং)।
  • প্রোগ্রাম ক্র্যাশ করলে এরর হ্যান্ডেল করার নিয়ম।
  • GCC-র যে ফ্ল্যাগগুলো আপনাকে ডিবাগিং-এ সাহায্য করে।
  • GDB দিয়ে লাইন বাই লাইন কোড চালানো।

💾 অধ্যায় ২৪: টেক্সট বনাম বাইনারি ফাইল – fread() ও fwrite()

আমরা আগে fprintf() ও fscanf() দিয়ে টেক্সট ফাইল ব্যবহার করেছি। কিন্তু টেক্সট ফাইলে সংখ্যা সংরক্ষণ করলে তা অনেক জায়গা নেয় এবং কখনও কখনও নির্ভুলতা হারায়। বাইনারি ফাইল সরাসরি মেমোরিতে যেভাবে থাকে, ঠিক সেভাবেই সংরক্ষণ করে। ফলে ডেটা পড়া ও লেখা অনেক দ্রুত হয়।

উদাহরণ: একটি স্ট্রাকচার সরাসরি বাইনারি ফাইলে সেভ করা

c

#include <stdio.h>
#include <string.h>

struct Student {
    int id;
    char name[50];
    float cgpa;
};

int main() {
    struct Student s1 = {101, "Rahim", 3.75};
    FILE *file = fopen("student.bin", "wb"); // wb = write binary

    if (file != NULL) {
        // সরাসরি মেমোরি থেকে ফাইলে লেখা
        fwrite(&s1, sizeof(struct Student), 1, file);
        fclose(file);
        printf("✅ বাইনারি ফাইলে সেভ হয়েছে!\n");
    }

    // এখন পড়ি
    struct Student s2;
    file = fopen("student.bin", "rb"); // rb = read binary
    if (file != NULL) {
        fread(&s2, sizeof(struct Student), 1, file);
        fclose(file);
        printf("📖 বাইনারি থেকে পড়া: আইডি: %d, নাম: %s, সিজিপিএ: %.2f\n", s2.id, s2.name, s2.cgpa);
    }
    return 0;
}

কেন ব্যবহার করবেন? ডেটাবেস, ইমেজ, অডিও ফাইল—সবকিছু বাইনারি ফরম্যাটেই সংরক্ষিত থাকে। এটি অনেক বেশি কার্যকরী (Efficient)।


✂ অধ্যায় ২৫: typedef – আপনার ডেটা টাইপের নাম পরিবর্তন করুন

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

typedef না থাকলে:

c

struct Student {
    int id;
    char name[50];
};
struct Student s1; // অনেক লম্বা

typedef ব্যবহার করলে:

c

typedef struct {
    int id;
    char name[50];
} Student;

Student s1; // দেখুন কত সহজ!

পয়েন্টারের জন্যও ব্যবহার করুন:

c

typedef int* IntPtr;
IntPtr p, q; // এখানে p ও q উভয়ই int* টাইপের (ভুল বোঝাবুঝি কমে)।

💡 টিপস: আপনি যদি student.h হেডার ফাইল তৈরি করেন, তাহলে typedef ব্যবহার করলে আপনার কোড অন্যের কাছে পড়তে অনেক সহজ হয়।


🧩 অধ্যায় ২৬: স্ট্রাকচার প্যাডিং (Structure Padding) – মেমোরির গোপন খরচ

আপনি হয়তো জানেন না, কিন্তু C কম্পাইলার আপনার স্ট্রাকচারে অতিরিক্ত ফাঁকা জায়গা (Padding) যোগ করে দেয়, যাতে প্রসেসর দ্রুত ডেটা অ্যাক্সেস করতে পারে।

উদাহরণ:

c

#include <stdio.h>

struct A {
    char c;   // ১ বাইট
    int i;    // ৪ বাইট
};

int main() {
    printf("স্ট্রাকচার A-এর সাইজ: %lu বাইট\n", sizeof(struct A));
    // আউটপুট হবে ৮ বাইট (অথবা ১২), কিন্তু char(১)+int(৪)=৫ হওয়ার কথা!
    return 0;
}

কেন এমন হয়? কম্পাইলার char-এর পরে ৩ বাইট ফাকা রাখে, যাতে int ঠিক ৪ বাইটের বাউন্ডারিতে বসতে পারে।

কীভাবে এড়াবেন?
আপনি যদি মেমোরি সাশ্রয়ী হতে চান, তাহলে বড় ডেটা আগে এবং ছোট ডেটা পরে সাজান।

c

struct Optimized {
    int i;     // ৪ বাইট
    char c;    // ১ বাইট
}; // এখন সাইজ হয় ৫ (কিন্তু প্যাডিং যোগ হয়ে ৮-ই হতে পারে, কম্পাইলারভেদে)

রিয়েল-লাইফ ইমপ্যাক্ট: এমবেডেড সিস্টেমে (যেখানে মেমোরি সীমিত) এই প্যাডিং বোঝা অত্যন্ত জরুরি। #pragma pack(1) ব্যবহার করে আপনি প্যাডিং বন্ধ করতে পারেন।


❌ অধ্যায় ২৭: এরর হ্যান্ডলিং – errno, perror() এবং strerror()

প্রোগ্রামিং-এ এরর অনিবার্য। ফাইল খোলা না গেলে, মেমোরি বরাদ্দ না হলে কী করবেন? পেশাদার প্রোগ্রামাররা এরর হ্যান্ডেল করার জন্য errno গ্লোবাল ভেরিয়েবল ব্যবহার করে।

c

#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
    FILE *file = fopen("does_not_exist.txt", "r");
    if (file == NULL) {
        // errno স্বয়ংক্রিয়ভাবে সেট হয়, perror সুন্দর মেসেজ দেখায়
        perror("ফাইল খুলতে ব্যর্থ");
        // অথবা strerror ব্যবহার করুন
        printf("এরর কোড: %d, বার্তা: %s\n", errno, strerror(errno));
        return 1;
    }
    fclose(file);
    return 0;
}

আউটপুট: ফাইল খুলতে ব্যর্থ: No such file or directory — এটি ব্যবহারকারীকে খুব ক্লিয়ার মেসেজ দেয়। বড় প্রোজেক্টে এরর হ্যান্ডলিং ছাড়া প্রোগ্রাম চলেই না!


⚙ অধ্যায় ২৮: জিসিসি (GCC) কম্পাইলারের পাওয়ারফুল ফ্ল্যাগ

আপনি হয়তো gcc program.c -o program ব্যবহার করেন। কিন্তু GCC-র আরও অনেক ফ্ল্যাগ আছে যা আপনার জীবন বদলে দেবে:

ফ্ল্যাগকাজউদাহরণ
-Wallসব ধরনের সতর্কতা (Warning) দেখায় (সবচেয়ে গুরুত্বপূর্ণ)gcc -Wall program.c
-Wextraঅতিরিক্ত কিছু সতর্কতা যোগ করেgcc -Wall -Wextra program.c
-gডিবাগ তথ্য জেনারেট করে (GDB চালানোর জন্য আবশ্যক)gcc -g program.c -o program
-O2অপটিমাইজেশন চালু করে (প্রোডাকশনের জন্য)gcc -O2 program.c -o program
-std=c99C99 স্ট্যান্ডার্ড ফোর্স করে (আধুনিক কোডের জন্য)gcc -std=c99 program.c
-oআউটপুট ফাইলের নাম ঠিক করেgcc program.c -o my_app

📌 পেশাদার টিপস: ডেভেলপমেন্টের সময় সবসময় -Wall -Wextra -g ব্যবহার করুন। প্রোডাকশনে রিলিজ করার সময় -O2 ব্যবহার করবেন। আমার কথা রাখুন, এই ফ্ল্যাগগুলো আপনার অর্ধেক বাগ আগেই ধরে ফেলবে!


🐞 অধ্যায় ২৯: জিডিবি (GDB) ডিবাগার দিয়ে বাগ খুঁজে বেরানো

আপনার প্রোগ্রাম যদি ক্র্যাশ করে, আর আপনি শুধু printf দিয়ে ডিবাগ করেন, তাহলে আপনি অনেক সময় নষ্ট করছেন। GDB (GNU Debugger) হলো C প্রোগ্রামারদের সবচেয়ে শক্তিশালী অস্ত্র।

ধাপে ধাপে GDB ব্যবহার:

১. ডিবাগ সহযোগে কম্পাইল করুন:

bash

gcc -g my_program.c -o my_program

২. GDB চালু করুন:

bash

gdb ./my_program

৩. গুরুত্বপূর্ণ GDB কমান্ড:

কমান্ডসংক্ষিপ্তকাজ
break mainb mainmain() ফাংশনে ব্রেকপয়েন্ট বসায়
break 15b 15১৫ নম্বর লাইনে ব্রেকপয়েন্ট
runrপ্রোগ্রাম রান করা
nextnপরবর্তী লাইনে যাওয়া (ফাংশনের ভিতরে না গিয়ে)
stepsফাংশনের ভিতরে ঢুকে পড়া
print varp varভেরিয়েবলের মান দেখা
continuecপরবর্তী ব্রেকপয়েন্ট পর্যন্ত চলতে থাকা
quitqGDB থেকে বের হওয়া

একটি ছোট ডেমো (ধারণাগত):

c

#include <stdio.h>
int main() {
    int x = 5;
    int y = 0;
    int z = x / y; // এখানে Divide by Zero এরর হবে!
    printf("%d", z);
    return 0;
}

যদি এই প্রোগ্রাম ক্র্যাশ করে, GDB আপনাকে ঠিক সেই লাইনে নিয়ে যাবে এবং y-এর মান 0 দেখাবে। তখন আপনি বুঝতে পারবেন কেন ক্র্যাশ হয়েছে। এটি লাইফ সেভার! 🦸‍♂️


🏁 চূড়ান্ত উপসংহার: পেশাদার C প্রোগ্রামারের রোডম্যাপ

প্রিয় শিক্ষার্থী, আপনি এখন C প্রোগ্রামিংয়ের শুধু সিনট্যাক্স নয়, বরং এর অন্তঃসার (গভীরতা) বুঝতে শিখেছেন। আপনি জানেন মেমোরি কীভাবে কাজ করে, ডেটা স্ট্রাকচার কীভাবে তৈরি করতে হয়, এবং কীভাবে প্রো টুলস (GCC, GDB) ব্যবহার করে বাগ খুঁজে বের করতে হয়।

আপনি এখন কী করবেন? (একজন প্রো ডেভেলপার হওয়ার পথে):

  1. ওপেন সোর্স কন্ট্রিবিউট করুন: GitHub-এ ছোট ছোট C প্রোজেক্টে ইস্যু ফিক্স করুন। রিয়েল কোড দেখার অভিজ্ঞতা অমূল্য।
  2. সিস্টেম প্রোগ্রামিং শিখুন: Linux-এ fork(), exec(), pipe() দিয়ে মাল্টিপ্রসেসিং শিখুন।
  3. নেটওয়ার্ক প্রোগ্রামিং: Socket Programming (TCP/UDP) দিয়ে নিজের একটি চ্যাট অ্যাপ্লিকেশন বানান।
  4. ক্লিন কোড প্র্যাকটিস করুন: সহজ, পড়তে সুন্দর এবং ডকুমেন্টেড কোড লেখার অভ্যাস করুন।

C হলো সেই ভাষা, যা শিখলে আপনি কম্পিউটারের ওপর সম্পূর্ণ কন্ট্রোল পাবেন। এটি কঠিন, কিন্তু আপনি ইতিমধ্যেই প্রমাণ করেছেন যে আপনি লেগে থাকতে পারেন। ToLearnTeam পরিবার আপনার এই সাফল্যে গর্বিত। এখন যান, কোড লিখুন, ভাঙুন, আর নতুন কিছু তৈরি করুন। পৃথিবী আপনার জন্য অপেক্ষা করছে!

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক appeared first on To Learn Team.

]]>
C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট https://tolearnteam.com/c-programming-a-to-z-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%aa-%e0%a6%85%e0%a7%8d%e0%a6%af%e0%a6%be%e0%a6%b2%e0%a6%97%e0%a6%b0%e0%a6%bf%e0%a6%a6%e0%a6%ae-%e0%a6%b8%e0%a7%8d%e0%a6%9f%e0%a7%8d/ Thu, 16 Jul 2026 03:00:08 +0000 http://tolearnteam.com/?p=851 আমরা C প্রোগ্রামিংয়ের দীর্ঘ এই যাত্রার শেষ পর্বে এসে পৌঁছেছি। গত তিন পর্বে আমরা ভিত্তি থেকে শুরু করে লিংকড লিস্ট পর্যন্ত পথচলা করেছি। আজকের পর্বটি একটু ভিন্ন। আমরা কেবল নতুন…

The post C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট appeared first on To Learn Team.

]]>
আমরা C প্রোগ্রামিংয়ের দীর্ঘ এই যাত্রার শেষ পর্বে এসে পৌঁছেছি। গত তিন পর্বে আমরা ভিত্তি থেকে শুরু করে লিংকড লিস্ট পর্যন্ত পথচলা করেছি।

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


🔄 পর্ব-৩ এর সংক্ষিপ্ত পুনরালোচনা

  • বিটওয়াইজ অপারেটর (&, |, <<) দিয়ে দ্রুত পারমিশন চেক করা।
  • ফাংশন পয়েন্টার দিয়ে কলব্যাক মেকানিজম।
  • সিঙ্গলি লিংকড লিস্ট তৈরি, ইনসার্ট, ডিলিট।
  • মাল্টি-ফাইল প্রোগ্রামিং (Header File) এবং ‘লাইব্রেরি ম্যানেজমেন্ট’ প্রোজেক্ট।

আজ আমরা সেই লিংকড লিস্টকে আরও শক্তিশালী করব এবং অ্যালগরিদমের জগতে পা রাখব।


🥞 অধ্যায় ১৮: স্ট্যাক (Stack) – LIFO (Last In, First Out)

স্ট্যাক একটি বিশেষ ধরনের ডেটা স্ট্রাকচার। এটাকে প্লেটের স্ট্যাকের মতো ভাবুন—যে প্লেটটি সবশেষে রাখা হয়, সেটিই প্রথমে উঠানো হয় (LIFO)।

স্ট্যাকের প্রধান দুটি অপারেশন:

  • Push: উপরে নতুন এলিমেন্ট যোগ করা।
  • Pop: উপরের এলিমেন্টটি বের করে আনা।

নিচে অ্যারে-ভিত্তিক স্ট্যাক (সরল ও দ্রুত) এর উদাহরণ দেওয়া হলো:

c

#include <stdio.h>
#define MAX 100

int stack[MAX];
int top = -1; // খালি স্ট্যাক বোঝায়

// Push অপারেশন
void push(int value) {
    if (top >= MAX - 1) {
        printf("❌ স্ট্যাক ওভারফ্লো! (স্ট্যাক ভর্তি)\n");
        return;
    }
    stack[++top] = value;
    printf("✅ %d Push করা হয়েছে।\n", value);
}

// Pop অপারেশন
int pop() {
    if (top < 0) {
        printf("❌ স্ট্যাক আন্ডারফ্লো! (স্ট্যাক খালি)\n");
        return -1;
    }
    return stack[top--];
}

// স্ট্যাকের শীর্ষ দেখা (Peek)
int peek() {
    if (top < 0) return -1;
    return stack[top];
}

int main() {
    push(10);
    push(20);
    push(30);
    printf("পপ করা মান: %d\n", pop()); // আউটপুট: 30
    printf("বর্তমান শীর্ষ: %d\n", peek()); // আউটপুট: 20
    return 0;
}

💡 বাস্তব ব্যবহার: ব্রাউজারের ‘ব্যাক’ বোতাম, ফাংশন কলের মেমোরি ম্যানেজমেন্ট (কল স্ট্যাক), এবং রিকারশনের ভিত্তি হলো এই স্ট্যাক।


🚶 অধ্যায় ১৯: কিউ (Queue) – FIFO (First In, First Out)

কিউ হলো স্ট্যাকের ঠিক উল্টো। এটি টিকিট কাউন্টারের লাইনের মতো—যে আগে আসে, সে আগে সার্ভিস পায় (FIFO)।

কিউর প্রধান দুটি অপারেশন:

  • Enqueue: পেছনে (Rear) যোগ করা।
  • Dequeue: সামনে (Front) থেকে বের করা।

নিচে সার্কুলার অ্যারে-ভিত্তিক কিউ (মেমোরি অপটিমাইজড) এর উদাহরণ:

c

#include <stdio.h>
#define MAX 5

int queue[MAX];
int front = -1, rear = -1;

// Enqueue (যোগ)
void enqueue(int value) {
    if ((rear + 1) % MAX == front) {
        printf("❌ কিউ ভর্তি!\n");
        return;
    }
    if (front == -1) front = 0; // প্রথম এলিমেন্ট
    rear = (rear + 1) % MAX;
    queue[rear] = value;
    printf("✅ %d যোগ হয়েছে।\n", value);
}

// Dequeue (বের করা)
int dequeue() {
    if (front == -1) {
        printf("❌ কিউ খালি!\n");
        return -1;
    }
    int data = queue[front];
    if (front == rear) { // শেষ এলিমেন্ট বের করলে রিসেট
        front = rear = -1;
    } else {
        front = (front + 1) % MAX;
    }
    return data;
}

int main() {
    enqueue(5);
    enqueue(10);
    enqueue(15);
    printf("Dequeue: %d\n", dequeue()); // আউটপুট: 5
    printf("Dequeue: %d\n", dequeue()); // আউটপুট: 10
    return 0;
}

💡 বাস্তব ব্যবহার: প্রিন্টারের জব লিস্ট, সিপিইউ টাস্ক শিডিউলিং, ওয়েব সার্ভারের রিকুয়েস্ট হ্যান্ডলিং।


🔗 অধ্যায় ২০: ডাবলি লিংকড লিস্ট (Doubly Linked List)

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

c

#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
};

// সামনে থেকে ইনসার্ট
void insertFront(struct Node** head, int data) {
    struct Node* newNode = (struct Node*) malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = *head;
    if (*head != NULL) (*head)->prev = newNode;
    *head = newNode;
}

// লিস্ট প্রিন্ট (সামনে থেকে পেছনে)
void displayForward(struct Node* head) {
    struct Node* temp = head;
    printf("সামনে -> পেছনে: ");
    while (temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

int main() {
    struct Node* head = NULL;
    insertFront(&head, 30);
    insertFront(&head, 20);
    insertFront(&head, 10);
    displayForward(head); // আউটপুট: 10 20 30
    return 0;
}

কেন প্রয়োজন? ব্রাউজারের হিস্ট্রি (পেছানো/সামানো) বা মিউজিক প্লেয়ারের প্লেলিস্টে এটি ব্যবহার হয়।


📊 অধ্যায় ২১: সার্চিং ও সর্টিং অ্যালগরিদম

২১.১ বাইনারি সার্চ (Binary Search)

এটি শুধু সর্টেড অ্যারেতে কাজ করে। প্রতি ধাপে এটি অ্যারেকে অর্ধেক ভাগ করে ফেলে। ফলে অনুসন্ধান অত্যন্ত দ্রুত হয়।

c

int binarySearch(int arr[], int size, int target) {
    int left = 0, right = size - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] == target) return mid;
        else if (arr[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

২১.২ বাবল সর্ট (Bubble Sort)

এটি সবচেয়ে সহজ সর্টিং অ্যালগরিদম। এটি পাশাপাশি এলিমেন্ট তুলনা করে এবং ভুল ক্রমে থাকলে সোয়াপ করে। যদিও এটি বড় ডেটার জন্য ধীর, তবে বোঝার জন্য দারুণ।

c

void bubbleSort(int arr[], int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                // সোয়াপ
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

🛡 অধ্যায় ২২: স্পেশাল কিওয়ার্ড – const ও volatile (পেশাদারদের টুল)

  • const: এটি ভেরিয়েবলকে রিড-ওনলি করে দেয়। আপনি চাইলে ফাংশন প্যারামিটারে const ব্যবহার করে নিশ্চিত করতে পারেন যে ফাংশনটি সেই ভেরিয়েবলের মান পরিবর্তন করবে না।cvoid printValue(const int *ptr) { // *ptr = 10; // এই লাইনটি কম্পাইল হবে না (এরর) printf(“%d”, *ptr); }
  • volatile: এটি কম্পাইলারকে বলে যে, এই ভেরিয়েবলের মান যেকোনো সময় বাইরে থেকে (হার্ডওয়্যার বা অন্য থ্রেড) পরিবর্তন হতে পারে। তাই কম্পাইলার এটিকে অপটিমাইজ করবে না। এটি এমবেডেড সিস্টেম ও মাল্টিথ্রেডিং-এ অপরিহার্য।

🏢 অধ্যায় ২৩: গ্র্যান্ড প্রোজেক্ট – ‘এমপ্লয়ি পেল রোল ম্যানেজমেন্ট সিস্টেম’

এখন আমরা একটি বড় প্রোজেক্ট তৈরি করব, যেখানে থাকবে:

  • স্ট্যাক (সর্বশেষ যোগ করা কর্মচারীকে দেখানো)।
  • কিউ (কর্মচারীদের তালিকা ব্রাউজ করা)।
  • লিংকড লিস্ট (সমস্ত কর্মচারী সংরক্ষণ)।
  • ফাইল হ্যান্ডলিং (ডেটা সেভ)।
  • সর্টিং (বেতন অনুযায়ী সাজানো)।

কোডটি মডুলার করার জন্য আমরা তিনটি ফাইল তৈরি করব (ধারণাগতভাবে দেখানো হলো):

c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Employee {
    int id;
    char name[50];
    float salary;
    struct Employee* next;
};

// ১. লিংকড লিস্টে যোগ
void addEmployee(struct Employee** head, int id, char name[], float salary) {
    struct Employee* emp = (struct Employee*) malloc(sizeof(struct Employee));
    emp->id = id; strcpy(emp->name, name); emp->salary = salary; emp->next = NULL;
    if (*head == NULL) { *head = emp; return; }
    struct Employee* temp = *head;
    while (temp->next != NULL) temp = temp->next;
    temp->next = emp;
}

// ২. সর্টিং (বাবল সর্ট - লিংকড লিস্টের জন্য অ্যারে নিয়ে কাজ করা সহজ)
void sortBySalary(struct Employee* head) {
    if (head == NULL) return;
    int count = 0;
    struct Employee* temp = head;
    while (temp) { count++; temp = temp->next; }
    
    // অ্যারেতে কপি করে সর্ট
    float *salaries = (float*) malloc(count * sizeof(float));
    temp = head; int i = 0;
    while (temp) { salaries[i++] = temp->salary; temp = temp->next; }
    
    // বাবল সর্ট
    for (int i = 0; i < count-1; i++)
        for (int j = 0; j < count-i-1; j++)
            if (salaries[j] > salaries[j+1]) {
                float s = salaries[j]; salaries[j] = salaries[j+1]; salaries[j+1] = s;
            }
    
    printf("✅ সর্টেড বেতনের তালিকা: ");
    for (int i = 0; i < count; i++) printf("%.2f ", salaries[i]);
    printf("\n");
    free(salaries);
}

// ৩. ফাইলে সেভ
void saveToFile(struct Employee* head) {
    FILE* f = fopen("employees.txt", "w");
    struct Employee* temp = head;
    while (temp) {
        fprintf(f, "%d|%s|%.2f\n", temp->id, temp->name, temp->salary);
        temp = temp->next;
    }
    fclose(f);
    printf("💾 ফাইলে সেভ হয়েছে!\n");
}

// ৪. স্ট্যাক (শেষ ৩ জন দেখানো)
void showLastThree(struct Employee* head) {
    // স্ট্যাকের মতো LIFO নীতিতে শেষ ৩ জন দেখানো
    int count = 0;
    struct Employee* temp = head;
    while (temp) { count++; temp = temp->next; }
    if (count < 3) { printf("মোট কর্মচারী ৩ এর কম!\n"); return; }
    
    temp = head;
    int skip = count - 3;
    for (int i = 0; i < skip; i++) temp = temp->next;
    
    printf("🆕 সবশেষ যোগ দেওয়া ৩ জন (Stack LIFO):\n");
    while (temp) {
        printf("ID: %d, নাম: %s, বেতন: %.2f\n", temp->id, temp->name, temp->salary);
        temp = temp->next;
    }
}

int main() {
    struct Employee* head = NULL;
    int choice, id;
    char name[50];
    float salary;
    
    while (1) {
        printf("\n🏢 **এমপ্লয়ি ম্যানেজমেন্ট সিস্টেম**\n");
        printf("1. কর্মচারী যোগ করুন\n");
        printf("2. বেতন অনুযায়ী সাজান (Sort)\n");
        printf("3. শেষ ৩ জন দেখুন (Stack)\n");
        printf("4. সেভ ও প্রস্থান\n");
        printf("পছন্দ: "); scanf("%d", &choice); getchar();
        
        if (choice == 1) {
            printf("আইডি: "); scanf("%d", &id); getchar();
            printf("নাম: "); gets(name);
            printf("বেতন: "); scanf("%f", &salary);
            addEmployee(&head, id, name, salary);
        } else if (choice == 2) {
            sortBySalary(head);
        } else if (choice == 3) {
            showLastThree(head);
        } else if (choice == 4) {
            saveToFile(head);
            printf("👋 প্রস্থান করছি।\n");
            break;
        }
    }
    return 0;
}

🏁 পুরো সিরিজের উপসংহার ও পরবর্তী করণীয়

অভিনন্দন! আপনি “C Programming A to Z” -এর এই চার পর্বের বিশাল জার্নি সফলভাবে শেষ করেছেন।

আপনি এখন যা জানেন:

  • C-এর সিনট্যাক্স ও বুনিয়াদি।
  • পয়েন্টার, মেমোরি ম্যানেজমেন্ট ও ডায়নামিক ডেটা স্ট্রাকচার (লিংকড লিস্ট, স্ট্যাক, কিউ)।
  • ফাইল হ্যান্ডলিং, প্রিপ্রসেসর, এবং মাল্টি-ফাইল প্রোগ্রামিং।
  • বেসিক অ্যালগরিদম (সার্চ ও সর্ট)।

আপনি এখন C প্রোগ্রামার। কিন্তু এখানেই থেমে যাবেন না।

পরবর্তী পথচলা:
১. ডেটা স্ট্রাকচার আরও গভীরে: ট্রি (Binary Tree), গ্রাফ, হ্যাশ টেবল।
২. অ্যালগরিদম ডিজাইন: মার্জ সর্ট, কুইক সর্ট, ডায়নামিক প্রোগ্রামিং।
৩. সিস্টেম প্রোগ্রামিং: Linux-এ Socket Programming, Multithreading with Pthreads।

C হলো আপনার প্রোগ্রামিং জীবনের সবচেয়ে মূল্যবান বিনিয়োগ। এটি শিখলে অন্য যেকোনো ভাষা (জাভা, পাইথন, C++) শিখতে আপনার সময় লাগবে অর্ধেকেরও কম।

ToLearnTeam-এর পক্ষ থেকে আপনার উজ্জ্বল ভবিষ্যতের জন্য শুভকামনা। কোড লিখতে থাকুন, নতুন কিছু তৈরি করতে থাকুন। পৃথিবী আপনার জন্য অপেক্ষা করছে!

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট appeared first on To Learn Team.

]]>
C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট https://tolearnteam.com/c-programming-a-to-z-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%a9-%e0%a6%a1%e0%a7%87%e0%a6%9f%e0%a6%be-%e0%a6%b8%e0%a7%8d%e0%a6%9f%e0%a7%8d%e0%a6%b0%e0%a6%be%e0%a6%95%e0%a6%9a%e0%a6%be%e0%a6%b0/ Thu, 16 Jul 2026 02:56:22 +0000 http://tolearnteam.com/?p=848 গত দুই পর্বে আমরা C-এর বেসিক থেকে অ্যাডভান্সড মেমোরি ম্যানেজমেন্ট পর্যন্ত সবকিছু কভার করেছি। আপনি এখন জানেন কীভাবে ডায়নামিক মেমোরি বরাদ্দ করতে হয়, রিকারশন লিখতে হয় এবং ফাইল পরিচালনা করতে…

The post C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট appeared first on To Learn Team.

]]>
গত দুই পর্বে আমরা 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 জানেন, আপনার জন্য দারুণ কিছু ক্যারিয়ার পথ খোলা:

  1. এমবেডেড সিস্টেম ইঞ্জিনিয়ার: মাইক্রোকন্ট্রোলার, রোবটিক্স, IoT ডিভাইসের প্রোগ্রামিং (C এখানে রাজা)।
  2. অপারেটিং সিস্টেম ডেভেলপার: লিনাক্স কার্নেল, ড্রাইভার ডেভেলপমেন্ট।
  3. গেম ডেভেলপমেন্ট: ইউনিটি বা আনরিয়ালের নিচের লেয়ারের কাজ।
  4. ডেটাবেস ইঞ্জিনিয়ার: MySQL, PostgreSQL-এর মতো ডেটাবেসের অভ্যন্তরীণ কাঠামো বুঝতে।

শেষ কথাঃ
শুধু পড়লে হবে না। প্রতিদিন একটি করে প্রোগ্রাম লিখুন। লিংকড লিস্টে বাগ খুঁজুন, নিজের মতো করে সাজান। সি শেখা মানে কম্পিউটারকে তার নিজের ভাষায় ভালোবাসা শেখা।

ToLearnTeam-এর পক্ষ থেকে আপনার সফলতার জন্য শুভকামনা। কোড করুন, ভুল করুন, আবার কোড করুন—এটাই প্রোগ্রামিংয়ের মন্ত্র! 

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট appeared first on To Learn Team.

]]>
C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট https://tolearnteam.com/c-programming-a-to-z-%e0%a6%aa%e0%a6%b0%e0%a7%8d%e0%a6%ac-%e0%a7%a8-%e0%a6%ae%e0%a7%87%e0%a6%ae%e0%a7%8b%e0%a6%b0%e0%a6%bf-%e0%a6%ae%e0%a7%8d%e0%a6%af%e0%a6%be%e0%a6%95%e0%a7%8d%e0%a6%b0%e0%a7%8b/ Thu, 16 Jul 2026 02:52:58 +0000 http://tolearnteam.com/?p=845 গত পর্বে আমরা C প্রোগ্রামিংয়ের ভিত্তি থেকে শুরু করে ফাইল হ্যান্ডলিং পর্যন্ত জার্নি করেছি। যদি আপনি সেই বেসিকগুলো ভালোভাবে আয়ত্ত করে থাকেন, তাহলে আজ আমরা C-এর হার্ডকোর অংশে প্রবেশ করব। কারণ শুধু printf আর scanf জানলেই…

The post C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট appeared first on To Learn Team.

]]>
গত পর্বে আমরা 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;
}

🏗 অধ্যায় ১২: মিনি-প্রজেক্ট – ‘কন্ট্যাক্ট ম্যানেজমেন্ট সিস্টেম’ (হাতে-কলমে)

এখন পর্যন্ত যা শিখলাম, তা দিয়ে একটি ছোট কিন্তু কার্যকরী কন্ট্যাক্ট বুক প্রোগ্রাম তৈরি করি। এতে আমরা ডায়নামিক মেমোরি, স্ট্রাকচার এবং ফাইল হ্যান্ডলিং একসাথে ব্যবহার করব।

প্রোজেক্টের বৈশিষ্ট্য:

  1. নতুন কন্ট্যাক্ট যোগ করা (নাম, ফোন নম্বর)।
  2. সব কন্ট্যাক্ট দেখানো।
  3. ফাইল থেকে ডেটা পড়া এবং ফাইলে সেভ করা।

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

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট appeared first on To Learn Team.

]]>
C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড https://tolearnteam.com/c-programming-a-to-z-%e0%a6%b6%e0%a7%82%e0%a6%a8%e0%a7%8d%e0%a6%af-%e0%a6%a5%e0%a7%87%e0%a6%95%e0%a7%87-%e0%a6%ac%e0%a6%bf%e0%a6%b6%e0%a7%87%e0%a6%b7%e0%a6%9c%e0%a7%8d%e0%a6%9e-%e0%a6%b9%e0%a6%93/ Thu, 16 Jul 2026 02:47:24 +0000 http://tolearnteam.com/?p=842 আজকের ডিজিটাল দুনিয়ায় প্রোগ্রামিং ভাষার অভাব নেই। পাইথন, জাভা, জাভাস্ক্রিপ্ট – হাজারো ভাষা। কিন্তু এমন একটি ভাষা আছে, যাকে বলা হয় “প্রোগ্রামিং ভাষার মা”। হ্যাঁ, আমরা কথা বলছি C Programming নিয়ে। ১৯৭২ সালে…

The post C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড appeared first on To Learn Team.

]]>
আজকের ডিজিটাল দুনিয়ায় প্রোগ্রামিং ভাষার অভাব নেই। পাইথন, জাভা, জাভাস্ক্রিপ্ট – হাজারো ভাষা। কিন্তু এমন একটি ভাষা আছে, যাকে বলা হয় “প্রোগ্রামিং ভাষার মা”। হ্যাঁ, আমরা কথা বলছি C Programming নিয়ে। ১৯৭২ সালে ডেনিস রিচি যখন এই ভাষা তৈরি করেছিলেন, তখন তিনি জানতেনও না যে এটি কম্পিউটার বিজ্ঞানের ভিত্তি হয়ে উঠবে। অপারেটিং সিস্টেম (Windows, Linux), ডেটাবেস, এমনকি আপনার প্রিয় গেমসের ইঞ্জিনও C তে লেখা।

আপনি যদি একজন নতুন প্রোগ্রামার হন, তাহলে C দিয়ে শুরু করা সবচেয়ে বুদ্ধিমানের কাজ। কেন? কারণ C শিখলে আপনি শুধু একটি ভাষা শিখেন না, বরং কম্পিউটারের মেমোরি, পয়েন্টার এবং আর্কিটেকচার সম্পর্কে গভীর ধারণা লাভ করেন। এই ব্লগ পোস্টটি একটি “A to Z” গাইড, যেখানে আমরা C-এর একদম শুরু থেকে শেষ পর্যন্ত সবকিছু কভার করব। তাই আর দেরি না করে, শুরু করা যাক! 💻🔥


📚 অধ্যায় ১: C প্রোগ্রামিংয়ের বুনিয়াদি (The Basics)

যেকোনো বাড়ি তৈরি করতে হয় ভিত্তি দিয়ে। প্রোগ্রামিংও তার ব্যতিক্রম নয়। C-এর ভিত্তি হলো কিছু মৌলিক উপাদান।

১.১ ডেটা টাইপ (Data Types)

ডেটা টাইপ হলো কম্পিউটারকে বলা যে, এই ভেরিয়েবলে কী ধরনের ডেটা রাখা হবে। C-তে প্রধানত ৫টি ডেটা টাইপ আছে:

ডেটা টাইপকীওয়ার্ডআকার (সাধারণত)উদাহরণ
পূর্ণসংখ্যাint৪ বাইটint age = 25;
দশমিক সংখ্যাfloat৪ বাইটfloat price = 99.99;
বড় দশমিকdouble৮ বাইটdouble pi = 3.141592;
একটি অক্ষরchar১ বাইটchar grade = 'A';
শূন্য/কিছুই নাvoid০ বাইটফাংশনের রিটার্ন টাইপ হিসেবে

১.২ ভেরিয়েবল (Variables)

ভেরিয়েবল হলো ডেটা সংরক্ষণের জন্য একটি কন্টেইনার। আপনি এতে মান রাখতে পারেন এবং পরবর্তীতে পরিবর্তনও করতে পারেন।

সিনট্যাক্স: data_type variable_name = value;

c

#include <stdio.h>
int main() {
    int student_id = 101;        // পূর্ণসংখ্যা
    char section = 'A';          // অক্ষর
    float cgpa = 3.75;           // দশমিক
    printf("আমার আইডি: %d, সেকশন: %c, সিজিপিএ: %.2f", student_id, section, cgpa);
    return 0;
}

১.৩ অপারেটর (Operators)

অপারেটর হলো সেই চিহ্ন যা ডেটার ওপর বিভিন্ন অপারেশন (গণনা, তুলনা) করে।

  • গাণিতিক (Arithmetic): +, -, *, /, % (ভাগশেষ)
  • সম্পর্কমূলক (Relational): == (সমান), != (সমান নয়), >, <, >=, <=
  • লজিক্যাল (Logical): && (AND), || (OR), ! (NOT)

🧠 অধ্যায় ২: কন্ট্রোল ফ্লো (Control Flow) – সিদ্ধান্ত ও পুনরাবৃত্তি

আপনার প্রোগ্রামকে বুদ্ধিমান করতে হলে শর্ত অনুযায়ী সিদ্ধান্ত নিতে হবে এবং বারবার কাজ করতে হবে। এখানেই ব্যবহার হয় কন্ট্রোল স্টেটমেন্ট।

২.১ শর্ত (Conditional Statements)

if, else if, else

যখন কোনো শর্ত সত্য হয়, তখন নির্দিষ্ট কোড এক্সিকিউট হয়।

c

int number = 10;
if (number > 0) {
    printf("সংখ্যাটি ধনাত্মক (+)\n");
} else if (number < 0) {
    printf("সংখ্যাটি ঋণাত্মক (-)\n");
} else {
    printf("সংখ্যাটি শূন্য (0)\n");
}

switch statement

এটি একাধিক নির্দিষ্ট মানের জন্য শর্ত চেক করতে ব্যবহার হয়।

c

char grade = 'B';
switch (grade) {
    case 'A':
        printf("চমৎকার!");
        break;
    case 'B':
        printf("ভালো!");
        break;
    default:
        printf("প্রচেষ্টা চালিয়ে যান!");
}

২.২ লুপ (Loops) – পুনরাবৃত্তি

লুপ ব্যবহার করে আপনি একই কাজ বারবার করতে পারেন।

  • for লুপ: যখন আপনি জানেন কতবার লুপ চালাতে হবে।cfor (int i = 1; i <= 5; i++) { printf(“%d “, i); // আউটপুট: 1 2 3 4 5 }
  • while লুপ: যখন শর্তের ওপর ভিত্তি করে লুপ চলে।cint i = 1; while (i <= 5) { printf(“%d “, i); i++; }
  • do-while লুপ: শর্ত যাই হোক, কমপক্ষে একবার এক্সিকিউট হবে।

📦 অধ্যায় ৩: অ্যারে (Array) ও স্ট্রিং (String)

একটি ভেরিয়েবলে যদি একটি মান রাখা যায়, তাহলে একই ধরনের একাধিক মান কোথায় রাখবেন? উত্তর হলো অ্যারে।

৩.১ অ্যারে (Array)

এটি একই ডেটা টাইপের একাধিক এলিমেন্টের একটি সংগ্রহ।

c

int marks[5] = {85, 90, 75, 88, 92};
printf("১ম ছাত্রের নম্বর: %d\n", marks[0]); // ইনডেক্স শুরু হয় ০ থেকে
printf("৩য় ছাত্রের নম্বর: %d\n", marks[2]);

৩.২ স্ট্রিং (String)

C-তে স্ট্রিং হলো char টাইপের একটি অ্যারে, যা শেষ হয় একটি নাল ক্যারেক্টার (\0) দিয়ে।

c

char name[] = "ToLearnTeam";
printf("আমাদের নাম: %s\n", name);

⚙ অধ্যায় ৪: ফাংশন (Functions)

আপনি যখন একই কোড বারবার লিখতে থাকেন, তখন তা বিরক্তিকর হয়ে ওঠে। ফাংশন ব্যবহার করে আপনি একটি কাজের কোডকে একটি ব্লকে রেখে দিতে পারেন এবং যেকোনো সময় সেটিকে কল (Call) করতে পারেন।

ফাংশনের গঠন:
return_type function_name (parameter_list) { // কোড }

c

#include <stdio.h>

// এই ফাংশনটি দুটি সংখ্যা যোগ করবে
int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    int result = add(10, 20); // ফাংশন কল
    printf("যোগফল হলো: %d\n", result);
    return 0;
}

🔥 অধ্যায় ৫: পয়েন্টার (Pointers) – C-এর প্রাণ

পয়েন্টার হলো C প্রোগ্রামিংয়ের সবচেয়ে গুরুত্বপূর্ণ এবং শক্তিশালী অংশ। পয়েন্টার হলো একটি ভেরিয়েবল যা অন্য একটি ভেরিয়েবলের মেমোরি অ্যাড্রেস ধারণ করে।

c

int num = 100;
int *ptr = &num; // ptr এখন num-এর ঠিকানা ধারণ করছে

printf("num-এর মান: %d\n", num);
printf("num-এর ঠিকানা: %p\n", &num);
printf("ptr-এর মান (যা num-এর ঠিকানা): %p\n", ptr);
printf("ptr ব্যবহার করে num-এর মান: %d\n", *ptr); // ডিরেফারেন্স

পয়েন্টার কেন শিখবেন?

  • ডায়নামিক মেমোরি অ্যালোকেশন (মেমোরি ম্যানেজমেন্ট)।
  • ডেটা স্ট্রাকচার (লিংকড লিস্ট, ট্রি) তৈরিতে।
  • ফাংশনে অ্যারে বা বড় ডেটা পাঠানোর সময় কার্যকারিতা বাড়ায়।

🏗 অধ্যায় ৬: স্ট্রাকচার (Structure) ও ইউনিয়ন (Union)

৬.১ স্ট্রাকচার (Structure)

এটি ব্যবহার করে আপনি ভিন্ন ভিন্ন ডেটা টাইপের ডেটা একসাথে গ্রুপ করতে পারেন। যেমন: একজন শিক্ষার্থীর নাম (char[]), আইডি (int), এবং সিজিপিএ (float)।

c

struct Student {
    char name[50];
    int id;
    float cgpa;
};

int main() {
    struct Student s1 = {"Rahim", 101, 3.50};
    printf("নাম: %s, আইডি: %d, সিজিপিএ: %.2f", s1.name, s1.id, s1.cgpa);
    return 0;
}

৬.২ ইউনিয়ন (Union)

ইউনিয়ন স্ট্রাকচারের মতোই, কিন্তু এটি তার সকল সদস্যের জন্য একই মেমোরি লোকেশন শেয়ার করে। ফলে এটি মেমোরি সাশ্রয়ী।


💾 অধ্যায় ৭: ফাইল হ্যান্ডলিং (File I/O)

আপনার প্রোগ্রামের ডেটা কি শুধু র্যামে থাকবে? না। আপনি চাইলে হার্ডডিস্কে ফাইল তৈরি করে ডেটা সংরক্ষণ করতে পারেন এবং পরে তা আবার পড়তে পারেন।

ফাইল অপারেশনের ধাপ:

  1. ফাইল খোলা (fopen)
  2. ডেটা লেখা বা পড়া (fprintf, fscanf)
  3. ফাইল বন্ধ করা (fclose)

c

#include <stdio.h>
int main() {
    FILE *file;
    file = fopen("example.txt", "w"); // লেখার জন্য ফাইল খোলা

    if (file != NULL) {
        fprintf(file, "ToLearnTeam-এ স্বাগতম!");
        fclose(file); // ফাইল বন্ধ
        printf("ফাইলে লেখা সফল হয়েছে!");
    } else {
        printf("ফাইল খুলতে সমস্যা হয়েছে!");
    }
    return 0;
}

🏁 উপসংহার ও এগিয়ে যাওয়ার পথ

আপনি এখন C প্রোগ্রামিংয়ের printf থেকে fopen পর্যন্ত যাত্রা সম্পন্ন করলেন। এই জ্ঞানই যথেষ্ট নয়, কিন্তু এটি একটি শক্ত ভিত্তি। C শুধু একটি ভাষা নয়, এটি আপনার প্রোগ্রামিং চিন্তাশক্তিকে প্রখর করে।

এরপর কী করবেন?

  1. প্র্যাকটিস: যেকোনো দক্ষতা অর্জনের একমাত্র উপায় হলো প্র্যাকটিস। ছোট ছোট প্রোগ্রাম লিখতে থাকুন।
  2. প্রোজেক্ট: একটি ছোট ক্যালকুলেটর, স্টুডেন্ট ম্যানেজমেন্ট সিস্টেম বা টিক-ট্যাক-টো গেম তৈরি করার চেষ্টা করুন।
  3. ডেটা স্ট্রাকচার: C ব্যবহার করে ডেটা স্ট্রাকচার (লিংকড লিস্ট, স্ট্যাক, কিউ) শিখুন।

আশা করি এই গাইডটি আপনার C প্রোগ্রামিং শেখার যাত্রাকে সহজ এবং আনন্দময় করেছে। কোনো প্রশ্ন থাকলে কমেন্ট করুন। ToLearnTeam-এর পক্ষ থেকে, আপনার সফল প্রোগ্রামিং ক্যারিয়ারের জন্য শুভকামনা!

Full Advanced Course in C

  1. C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড
  2. C Programming A to Z (পর্ব-২): মেমোরি, ম্যাক্রো ও রিয়েল-লাইফ প্রোজেক্ট
  3. C Programming A to Z (পর্ব-৩): ডেটা স্ট্রাকচার, বিটওয়াইজ ম্যাজিক ও মাল্টি-ফাইল প্রোজেক্ট
  4. C Programming A to Z (পর্ব-৪): অ্যালগরিদম, স্ট্যাক, কিউ ও গ্র্যান্ড ফাইনাল প্রোজেক্ট
  5. C Programming A to Z (বোনাস পর্ব-৫): প্রো টুলচেইন, বাইনারি ফাইল ও ডিবাগিং ম্যাজিক
  6. C Programming A to Z (পর্ব-৬): ট্রি, গ্রাফ, বিগ-ও নোটেশন ও ক্যাপস্টোন প্রোজেক্ট
  7. C Programming A to Z (পর্ব-৭): মাল্টিথ্রেডিং, সকেট নেটওয়ার্কিং ও প্রো বিল্ড সিস্টেম
  8. C Programming A to Z (পর্ব-৮): প্রোফাইলিং, সিকিউরিটি, কন্ডিশন ভেরিয়েবল ও প্রোডাকশন লগার

The post C Programming A to Z: শূন্য থেকে বিশেষজ্ঞ হওয়ার সম্পূর্ণ গাইড appeared first on To Learn Team.

]]>