> For the complete documentation index, see [llms.txt](https://cs.d19.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cs.d19.in/advanced-topics.md).

# Advanced topics

## **1. Preprocessor Directives**

Preprocessor directives are instructions that are processed before the actual compilation of the code begins. They start with the `#` symbol and are used for tasks like including files or defining constants.

**`#define`**

The `#define` directive defines a constant or macro. It helps make the code more readable and easier to maintain.

**Syntax:**

```c
#define NAME value
```

**Example:**

```c
#include <stdio.h>

#define PI 3.14159  // Define a constant for PI

int main() {
    printf("Value of PI: %.5f\n", PI);  // Use the defined constant
    return 0;
}
```

* **`#define PI 3.14159`**: Defines `PI` as `3.14159`.
* This allows us to use `PI` in our code instead of writing the number directly each time.

**`#include`**

The `#include` directive is used to include the contents of one file within another file. It’s commonly used to include standard library headers or other user-defined files.

**Syntax:**

```c
#include <header.h>    // For standard library headers
#include "myheader.h"  // For user-defined headers
```

**Example:**

```c
#include <stdio.h>  // Include standard I/O functions
#include "myheader.h"  // Include a user-defined header file

int main() {
    printf("Hello, World!\n");
    return 0;
}
```

* **`#include <stdio.h>`**: Includes the standard input/output library.
* **`#include "myheader.h"`**: Includes a custom header file named `myheader.h`.

***

## **2. Command Line Arguments**

Command line arguments are used to pass additional information to a program when it is executed. They provide a way to control the behavior of the program from the command line.

**Syntax:**

```c
int main(int argc, char *argv[]) {
    // argc: Number of command line arguments
    // argv: Array of strings representing the arguments
}
```

**Example:**

```c
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("Number of arguments: %d\n", argc);
    
    for (int i = 0; i < argc; i++) {
        printf("Argument %d: %s\n", i, argv[i]);
    }
    
    return 0;
}
```

* **`argc`**: Counts how many arguments were passed to the program.
* **`argv`**: An array of strings, where each string is one of the command line arguments.

**Running the Program:**

```
$ ./program arg1 arg2
Number of arguments: 3
Argument 0: ./program
Argument 1: arg1
Argument 2: arg2
```

***

## **3. Linked Lists**

A linked list is a data structure where each element (node) points to the next one, forming a chain. This allows for flexible memory usage and easy insertion and deletion of elements.

**Basic Linked List Node**

**Definition:**

```c
typedef struct Node {
    int data;          // Data part
    struct Node *next; // Pointer to the next node
} Node;
```

**Example:**

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

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

int main() {
    // Create nodes
    Node *head = (Node *)malloc(sizeof(Node));
    Node *second = (Node *)malloc(sizeof(Node));
    Node *third = (Node *)malloc(sizeof(Node));
    
    // Assign data and link nodes
    head->data = 1;
    head->next = second;
    
    second->data = 2;
    second->next = third;
    
    third->data = 3;
    third->next = NULL;
    
    // Traverse and print list
    Node *temp = head;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
    
    // Free memory
    free(head);
    free(second);
    free(third);
    
    return 0;
}
```

* **Node Structure**: Contains `data` and a pointer to the next node.
* **Traversal**: Moving from the `head` node through each `next` node until reaching `NULL`.

***

## **4. Stacks**

A stack is a data structure that follows the Last In, First Out (LIFO) principle. It has two main operations: push (add an item) and pop (remove an item).

**Stack Implementation Using Linked List**

**Example:**

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

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

typedef struct Stack {
    Node *top;
} Stack;

// Function to create a new stack
Stack *createStack() {
    Stack *stack = (Stack *)malloc(sizeof(Stack));
    stack->top = NULL;
    return stack;
}

// Push an item onto the stack
void push(Stack *stack, int data) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = stack->top;
    stack->top = newNode;
}

// Pop an item from the stack
int pop(Stack *stack) {
    if (stack->top == NULL) {
        printf("Stack is empty\n");
        return -1;
    }
    Node *temp = stack->top;
    int data = temp->data;
    stack->top = stack->top->next;
    free(temp);
    return data;
}

// Print the stack
void printStack(Stack *stack) {
    Node *temp = stack->top;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

int main() {
    Stack *stack = createStack();
    
    push(stack, 10);
    push(stack, 20);
    push(stack, 30);
    
    printStack(stack);
    
    printf("Popped: %d\n", pop(stack));
    printStack(stack);
    
    return 0;
}
```

* **Push**: Adds a new item to the top of the stack.
* **Pop**: Removes and returns the item from the top of the stack.

***

## **5. Queues**

A queue is a data structure that follows the First In, First Out (FIFO) principle. It has two main operations: enqueue (add an item) and dequeue (remove an item).

**Queue Implementation Using Linked List**

**Example:**

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

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

typedef struct Queue {
    Node *front;
    Node *rear;
} Queue;

// Function to create a new queue
Queue *createQueue() {
    Queue *queue = (Queue *)malloc(sizeof(Queue));
    queue->front = NULL;
    queue->rear = NULL;
    return queue;
}

// Enqueue an item
void enqueue(Queue *queue, int data) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    if (queue->rear == NULL) {
        queue->front = newNode;
        queue->rear = newNode;
    } else {
        queue->rear->next = newNode;
        queue->rear = newNode;
    }
}

// Dequeue an item
int dequeue(Queue *queue) {
    if (queue->front == NULL) {
        printf("Queue is empty\n");
        return -1;
    }
    Node *temp = queue->front;
    int data = temp->data;
    queue->front = queue->front->next;
    if (queue->front == NULL) {
        queue->rear = NULL;
    }
    free(temp);
    return data;
}

// Print the queue
void printQueue(Queue *queue) {
    Node *temp = queue->front;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

int main() {
    Queue *queue = createQueue();
    
    enqueue(queue, 10);
    enqueue(queue, 20);
    enqueue(queue, 30);
    
    printQueue(queue);
    
    printf("Dequeued: %d\n", dequeue(queue));
    printQueue(queue);
    
    return 0;
}
```

* **Enqueue**: Adds a new item to the rear of the queue.
* **Dequeue**: Removes and returns the item from the front of the queue.

***

#### **Summary**

* **Preprocessor Directives**: `#define` for constants, `#include` for file inclusion.
* **Command Line Arguments**: Access program arguments from the command line.
* **Linked Lists**: Dynamic data structures with nodes linked together.
* **Stacks**: LIFO structure with push and pop operations.
* **Queues**: FIFO structure with enqueue and dequeue operations.
