# Basic Dynamic Memory Allocation Programming Questions

Here are 10 C programming exercises that involve dynamic memory allocation:

1. **Dynamic Array:** Create a program that dynamically allocates memory for an array of integers. Allow the user to input the size of the array and elements, and then print the array.
    
2. **Matrix Operations:** Implement a program to perform matrix addition and multiplication using dynamic memory allocation. Allow the user to input the dimensions and elements of the matrices.
    
3. **String Reversal:** Write a program that takes a string as input, dynamically allocates memory to store the reversed string, and then prints the reversed string.
    
4. **Dynamic Linked List:** Implement a linked list using dynamic memory allocation. Allow users to insert, delete, and display elements in the linked list.
    
5. **Dynamic Stack:** Create a program that simulates a stack using dynamic memory allocation. Implement push and pop operations and display the contents of the stack.
    
6. **Dynamic Queue:** Implement a queue using dynamic memory allocation. Allow users to enqueue and dequeue elements and display the contents of the queue.
    
7. **Dynamic String Concatenation:** Write a program that concatenates two strings using dynamic memory allocation. Allocate memory only for the resulting string.
    
8. **Dynamic Structure:** Define a structure representing a student with name, roll number, and marks. Dynamically allocate memory for an array of such structures and allow the user to input and display the data.
    
9. **File Reading and Dynamic Memory:** Create a program that reads data from a file, dynamically allocates memory to store the data, and then prints the contents.
    
10. **Dynamic 2D Array:** Implement a program that dynamically allocates memory for a 2D array of integers. Allow the user to input the dimensions and elements, and then print the array.
    

These exercises cover a range of dynamic memory allocation-related concepts and will help you practice and strengthen your skills in C programming. I have solved all of the above with explanatory comments. You should first make a sincere attempt at solving these problems before looking at the solutions.

1. Dynamic Array
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    int main() {
        int *arr; // Declare a pointer to int to store the base address of the dynamically allocated array
        int size;
    
        // Get array size from the user
        printf("Enter the size of the array: ");
        scanf("%d", &size);
    
        // Dynamically allocate memory for the array
        arr = (int *)malloc(size * sizeof(int));
    
        // Check if memory allocation was successful
        if (arr == NULL) {
            printf("Memory allocation failed. Exiting...");
            return 1; // Exit with an error code
        }
    
        // Input array elements from the user
        printf("Enter %d elements:\n", size);
        for (int i = 0; i < size; i++) {
            scanf("%d", &arr[i]);
        }
    
        // Display array elements
        printf("Array elements: ");
        for (int i = 0; i < size; i++) {
            printf("%d ", arr[i]);
        }
    
        // Free dynamically allocated memory
        free(arr);
    
        return 0;
    }
    ```
    

1. Matrix Multiplication
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Function prototypes
    int** allocateMatrix(int rows, int cols);
    void inputMatrix(int** matrix, int rows, int cols);
    void displayMatrix(int** matrix, int rows, int cols);
    void addMatrices(int** matrix1, int** matrix2, int** result, int rows, int cols);
    void multiplyMatrices(int** matrix1, int** matrix2, int** result, int rows1, int cols1, int rows2, int cols2);
    void freeMatrix(int** matrix, int rows);
    
    int main() {
        int **matrix1, **matrix2, **result;
        int rows1, cols1, rows2, cols2;
    
        // Input dimensions of the first matrix
        printf("Enter dimensions of Matrix 1:\n");
        printf("Rows: ");
        scanf("%d", &rows1);
        printf("Columns: ");
        scanf("%d", &cols1);
    
        // Input dimensions of the second matrix
        printf("Enter dimensions of Matrix 2:\n");
        printf("Rows: ");
        scanf("%d", &rows2);
        printf("Columns: ");
        scanf("%d", &cols2);
    
        // Check if matrix multiplication is possible
        if (cols1 != rows2) {
            printf("Matrix multiplication not possible. Exiting...");
            return 1; // Exit with an error code
        }
    
        // Dynamically allocate memory for matrices
        matrix1 = allocateMatrix(rows1, cols1);
        matrix2 = allocateMatrix(rows2, cols2);
        result = allocateMatrix(rows1, cols2);
    
        // Input elements of matrices
        printf("Enter elements of Matrix 1:\n");
        inputMatrix(matrix1, rows1, cols1);
    
        printf("Enter elements of Matrix 2:\n");
        inputMatrix(matrix2, rows2, cols2);
    
        // Perform matrix addition
        addMatrices(matrix1, matrix2, result, rows1, cols1);
        printf("\nMatrix Addition Result:\n");
        displayMatrix(result, rows1, cols1);
    
        // Perform matrix multiplication
        multiplyMatrices(matrix1, matrix2, result, rows1, cols1, rows2, cols2);
        printf("\nMatrix Multiplication Result:\n");
        displayMatrix(result, rows1, cols2);
    
        // Free dynamically allocated memory
        freeMatrix(matrix1, rows1);
        freeMatrix(matrix2, rows2);
        freeMatrix(result, rows1);
    
        return 0;
    }
    
    // Function to allocate memory for a matrix
    int** allocateMatrix(int rows, int cols) {
        int **matrix = (int **)malloc(rows * sizeof(int *));
        for (int i = 0; i < rows; i++) {
            matrix[i] = (int *)malloc(cols * sizeof(int));
        }
        return matrix;
    }
    
    // Function to input elements of a matrix
    void inputMatrix(int** matrix, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                printf("Enter element at position (%d, %d): ", i + 1, j + 1);
                scanf("%d", &matrix[i][j]);
            }
        }
    }
    
    // Function to display a matrix
    void displayMatrix(int** matrix, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                printf("%d\t", matrix[i][j]);
            }
            printf("\n");
        }
    }
    
    // Function to add two matrices
    void addMatrices(int** matrix1, int** matrix2, int** result, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[i][j] = matrix1[i][j] + matrix2[i][j];
            }
        }
    }
    
    // Function to multiply two matrices
    void multiplyMatrices(int** matrix1, int** matrix2, int** result, int rows1, int cols1, int rows2, int cols2) {
        for (int i = 0; i < rows1; i++) {
            for (int j = 0; j < cols2; j++) {
                result[i][j] = 0;
                for (int k = 0; k < cols1; k++) {
                    result[i][j] += matrix1[i][k] * matrix2[k][j];
                }
            }
        }
    }
    
    // Function to free memory allocated for a matrix
    void freeMatrix(int** matrix, int rows) {
        for (int i = 0; i < rows; i++) {
            free(matrix[i]);
        }
        free(matrix);
    }
    ```
    
2. String Reversal
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // Function prototypes
    char* reverseString(const char* input);
    
    int main() {
        char inputString[100];  // Assuming a maximum string length of 100
        char *reversedString;
    
        // Input a string
        printf("Enter a string: ");
        scanf("%s", inputString);
    
        // Call the function to reverse the string and allocate memory
        reversedString = reverseString(inputString);
    
        // Display the reversed string
        printf("Reversed string: %s\n", reversedString);
    
        // Free dynamically allocated memory
        free(reversedString);
    
        return 0;
    }
    
    // Function to reverse a string and allocate memory
    char* reverseString(const char* input) {
        int length = strlen(input);
        char *reversed = (char *)malloc((length + 1) * sizeof(char));  // +1 for the null terminator
    
        // Check if memory allocation was successful
        if (reversed == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);  // Exit with an error code
        }
    
        // Reverse the string
        for (int i = 0; i < length; i++) {
            reversed[i] = input[length - 1 - i];
        }
    
        // Add null terminator at the end of the reversed string
        reversed[length] = '\0';
    
        return reversed;
    }
    ```
    
3. Dynamic Linked List
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Node structure to represent elements in the linked list
    struct Node {
        int data;
        struct Node* next;
    };
    
    // Function prototypes
    struct Node* createNode(int data);
    void insertNode(struct Node** head, int data);
    void deleteNode(struct Node** head, int data);
    void displayList(struct Node* head);
    void freeList(struct Node* head);
    
    int main() {
        struct Node* head = NULL; // Initialize an empty linked list
    
        // Insert elements into the linked list
        insertNode(&head, 10);
        insertNode(&head, 20);
        insertNode(&head, 30);
    
        // Display the linked list
        printf("Linked List: ");
        displayList(head);
    
        // Delete an element from the linked list
        deleteNode(&head, 20);
    
        // Display the linked list after deletion
        printf("Linked List after deletion: ");
        displayList(head);
    
        // Free the memory allocated for the linked list
        freeList(head);
    
        return 0;
    }
    
    // Function to create a new node with given data
    struct Node* createNode(int data) {
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        if (newNode == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
        newNode->data = data;
        newNode->next = NULL;
        return newNode;
    }
    
    // Function to insert a new node with given data at the end of the linked list
    void insertNode(struct Node** head, int data) {
        struct Node* newNode = createNode(data);
        if (*head == NULL) {
            *head = newNode; // If the list is empty, the new node becomes the head
        } else {
            struct Node* temp = *head;
            while (temp->next != NULL) {
                temp = temp->next;
            }
            temp->next = newNode;
        }
    }
    
    // Function to delete a node with given data from the linked list
    void deleteNode(struct Node** head, int data) {
        if (*head == NULL) {
            printf("Linked list is empty. Cannot delete.\n");
            return;
        }
    
        struct Node* temp = *head;
        struct Node* prev = NULL;
    
        // Search for the node with the given data
        while (temp != NULL && temp->data != data) {
            prev = temp;
            temp = temp->next;
        }
    
        // If the node with the data is found
        if (temp != NULL) {
            if (prev == NULL) {
                *head = temp->next; // If the node to be deleted is the head
            } else {
                prev->next = temp->next;
            }
            free(temp); // Free the memory of the deleted node
            printf("Node with data %d deleted.\n", data);
        } else {
            printf("Node with data %d not found.\n", data);
        }
    }
    
    // Function to display the elements of the linked list
    void displayList(struct Node* head) {
        struct Node* temp = head;
        while (temp != NULL) {
            printf("%d ", temp->data);
            temp = temp->next;
        }
        printf("\n");
    }
    
    // Function to free the memory allocated for the linked list
    void freeList(struct Node* head) {
        struct Node* temp;
        while (head != NULL) {
            temp = head;
            head = head->next;
            free(temp);
        }
    }
    ```
    
4. Dynamic Stack
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Structure to represent a stack node
    struct Node {
        int data;
        struct Node* next;
    };
    
    // Function prototypes
    struct Node* createNode(int data);
    void push(struct Node** top, int data);
    void pop(struct Node** top);
    void displayStack(struct Node* top);
    void freeStack(struct Node* top);
    
    int main() {
        struct Node* stackTop = NULL; // Initialize an empty stack
    
        // Push elements onto the stack
        push(&stackTop, 10);
        push(&stackTop, 20);
        push(&stackTop, 30);
    
        // Display the contents of the stack
        printf("Stack contents: ");
        displayStack(stackTop);
    
        // Pop an element from the stack
        pop(&stackTop);
    
        // Display the contents of the stack after popping
        printf("Stack contents after popping: ");
        displayStack(stackTop);
    
        // Free the memory allocated for the stack
        freeStack(stackTop);
    
        return 0;
    }
    
    // Function to create a new node with given data
    struct Node* createNode(int data) {
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        if (newNode == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
        newNode->data = data;
        newNode->next = NULL;
        return newNode;
    }
    
    // Function to perform push operation on the stack
    void push(struct Node** top, int data) {
        struct Node* newNode = createNode(data);
        newNode->next = *top;
        *top = newNode;
    }
    
    // Function to perform pop operation on the stack
    void pop(struct Node** top) {
        if (*top == NULL) {
            printf("Stack is empty. Cannot pop.\n");
            return;
        }
    
        struct Node* temp = *top;
        *top = (*top)->next;
        free(temp);
        printf("Popped an element from the stack.\n");
    }
    
    // Function to display the contents of the stack
    void displayStack(struct Node* top) {
        struct Node* temp = top;
        while (temp != NULL) {
            printf("%d ", temp->data);
            temp = temp->next;
        }
        printf("\n");
    }
    
    // Function to free the memory allocated for the stack
    void freeStack(struct Node* top) {
        struct Node* temp;
        while (top != NULL) {
            temp = top;
            top = top->next;
            free(temp);
        }
    }
    ```
    
5. Dynamic Queue
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Structure to represent a queue node
    struct Node {
        int data;
        struct Node* next;
    };
    
    // Structure to represent a queue
    struct Queue {
        struct Node* front;
        struct Node* rear;
    };
    
    // Function prototypes
    struct Node* createNode(int data);
    struct Queue* createQueue();
    void enqueue(struct Queue* queue, int data);
    void dequeue(struct Queue* queue);
    void displayQueue(struct Queue* queue);
    void freeQueue(struct Queue* queue);
    
    int main() {
        struct Queue* myQueue = createQueue(); // Initialize an empty queue
    
        // Enqueue elements into the queue
        enqueue(myQueue, 10);
        enqueue(myQueue, 20);
        enqueue(myQueue, 30);
    
        // Display the contents of the queue
        printf("Queue contents: ");
        displayQueue(myQueue);
    
        // Dequeue an element from the queue
        dequeue(myQueue);
    
        // Display the contents of the queue after dequeuing
        printf("Queue contents after dequeue: ");
        displayQueue(myQueue);
    
        // Free the memory allocated for the queue
        freeQueue(myQueue);
    
        return 0;
    }
    
    // Function to create a new node with given data
    struct Node* createNode(int data) {
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        if (newNode == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
        newNode->data = data;
        newNode->next = NULL;
        return newNode;
    }
    
    // Function to create an empty queue
    struct Queue* createQueue() {
        struct Queue* newQueue = (struct Queue*)malloc(sizeof(struct Queue));
        if (newQueue == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
        newQueue->front = newQueue->rear = NULL;
        return newQueue;
    }
    
    // Function to perform enqueue operation on the queue
    void enqueue(struct Queue* queue, int data) {
        struct Node* newNode = createNode(data);
        if (queue->rear == NULL) {
            // If the queue is empty
            queue->front = queue->rear = newNode;
        } else {
            // If the queue is not empty
            queue->rear->next = newNode;
            queue->rear = newNode;
        }
    }
    
    // Function to perform dequeue operation on the queue
    void dequeue(struct Queue* queue) {
        if (queue->front == NULL) {
            printf("Queue is empty. Cannot dequeue.\n");
            return;
        }
    
        struct Node* temp = queue->front;
        queue->front = temp->next;
        free(temp);
        printf("Dequeued an element from the queue.\n");
    
        // If the last element is dequeued, update rear to NULL
        if (queue->front == NULL) {
            queue->rear = NULL;
        }
    }
    
    // Function to display the contents of the queue
    void displayQueue(struct Queue* queue) {
        struct Node* temp = queue->front;
        while (temp != NULL) {
            printf("%d ", temp->data);
            temp = temp->next;
        }
        printf("\n");
    }
    
    // Function to free the memory allocated for the queue
    void freeQueue(struct Queue* queue) {
        while (queue->front != NULL) {
            dequeue(queue);
        }
        free(queue);
    }
    ```
    

1. Dynamic String Concatenation
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // Function prototype
    char* concatenateStrings(const char* str1, const char* str2);
    
    int main() {
        // Input two strings
        char str1[50], str2[50];
    
        printf("Enter the first string: ");
        scanf("%s", str1);
    
        printf("Enter the second string: ");
        scanf("%s", str2);
    
        // Call the function to concatenate strings
        char* result = concatenateStrings(str1, str2);
    
        // Display the concatenated string
        printf("Concatenated string: %s\n", result);
    
        // Free the dynamically allocated memory
        free(result);
    
        return 0;
    }
    
    // Function to concatenate two strings and allocate memory for the result
    char* concatenateStrings(const char* str1, const char* str2) {
        // Calculate the length of the resulting string
        int len1 = strlen(str1);
        int len2 = strlen(str2);
        int resultLen = len1 + len2 + 1; // +1 for the null terminator
    
        // Dynamically allocate memory for the resulting string
        char* result = (char*)malloc(resultLen * sizeof(char));
        if (result == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
    
        // Copy the contents of the first string into the resulting string
        strcpy(result, str1);
    
        // Concatenate the second string to the resulting string
        strcat(result, str2);
    
        return result;
    }
    ```
    

1. Dynamic Structure
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Structure to represent a student
    struct Student {
        char name[50];
        int rollNumber;
        float marks;
    };
    
    // Function prototypes
    struct Student* createStudentArray(int size);
    void inputStudentData(struct Student* students, int size);
    void displayStudentData(struct Student* students, int size);
    void freeStudentArray(struct Student* students);
    
    int main() {
        int size;
    
        // Get the number of students from the user
        printf("Enter the number of students: ");
        scanf("%d", &size);
    
        // Create an array of structures dynamically
        struct Student* studentArray = createStudentArray(size);
    
        // Input data for each student
        inputStudentData(studentArray, size);
    
        // Display data for each student
        displayStudentData(studentArray, size);
    
        // Free the dynamically allocated memory
        freeStudentArray(studentArray);
    
        return 0;
    }
    
    // Function to dynamically create an array of structures
    struct Student* createStudentArray(int size) {
        struct Student* students = (struct Student*)malloc(size * sizeof(struct Student));
        if (students == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
        return students;
    }
    
    // Function to input data for each student
    void inputStudentData(struct Student* students, int size) {
        for (int i = 0; i < size; i++) {
            printf("\nEnter data for student %d:\n", i + 1);
            printf("Name: ");
            scanf("%s", students[i].name);
            printf("Roll Number: ");
            scanf("%d", &students[i].rollNumber);
            printf("Marks: ");
            scanf("%f", &students[i].marks);
        }
    }
    
    // Function to display data for each student
    void displayStudentData(struct Student* students, int size) {
        printf("\nStudent Data:\n");
        for (int i = 0; i < size; i++) {
            printf("Student %d:\n", i + 1);
            printf("Name: %s\n", students[i].name);
            printf("Roll Number: %d\n", students[i].rollNumber);
            printf("Marks: %.2f\n", students[i].marks);
        }
    }
    
    // Function to free the dynamically allocated memory
    void freeStudentArray(struct Student* students) {
        free(students);
    }
    ```
    
2. File Reading and Dynamic Memory
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Function prototypes
    char* readFromFile(const char* filename);
    void printFileContent(const char* content);
    
    int main() {
        const char* filename = "input.txt"; // Replace with the actual file name
    
        // Read data from the file
        char* fileContent = readFromFile(filename);
    
        // Print the contents read from the file
        printf("File Contents:\n");
        printFileContent(fileContent);
    
        // Free the dynamically allocated memory
        free(fileContent);
    
        return 0;
    }
    
    // Function to read data from a file and dynamically allocate memory
    char* readFromFile(const char* filename) {
        FILE* file = fopen(filename, "r");
        if (file == NULL) {
            printf("Error opening file. Exiting...");
            exit(1);
        }
    
        // Determine the size of the file
        fseek(file, 0, SEEK_END);
        long fileSize = ftell(file);
        fseek(file, 0, SEEK_SET);
    
        // Allocate memory to store the file content
        char* content = (char*)malloc((fileSize + 1) * sizeof(char));
        if (content == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
    
        // Read the file content into the allocated memory
        fread(content, sizeof(char), fileSize, file);
        content[fileSize] = '\0'; // Null-terminate the string
    
        // Close the file
        fclose(file);
    
        return content;
    }
    
    // Function to print the contents read from the file
    void printFileContent(const char* content) {
        printf("%s", content);
    }
    ```
    
3. Dynamic 2D Array
    
    ```c
    #include <stdio.h>
    #include <stdlib.h>
    
    // Function prototypes
    int** createDynamicArray(int rows, int cols);
    void inputArrayElements(int** array, int rows, int cols);
    void displayArray(int** array, int rows, int cols);
    void freeDynamicArray(int** array, int rows);
    
    int main() {
        int **dynamicArray;
        int rows, cols;
    
        // Input dimensions of the array
        printf("Enter dimensions of the 2D array:\n");
        printf("Rows: ");
        scanf("%d", &rows);
        printf("Columns: ");
        scanf("%d", &cols);
    
        // Dynamically allocate memory for the 2D array
        dynamicArray = createDynamicArray(rows, cols);
    
        // Input elements of the array
        printf("Enter elements of the 2D array:\n");
        inputArrayElements(dynamicArray, rows, cols);
    
        // Display the 2D array
        printf("\n2D Array:\n");
        displayArray(dynamicArray, rows, cols);
    
        // Free dynamically allocated memory
        freeDynamicArray(dynamicArray, rows);
    
        return 0;
    }
    
    // Function to dynamically create a 2D array
    int** createDynamicArray(int rows, int cols) {
        int **array = (int **)malloc(rows * sizeof(int *));
        if (array == NULL) {
            printf("Memory allocation failed. Exiting...");
            exit(1);
        }
    
        for (int i = 0; i < rows; i++) {
            array[i] = (int *)malloc(cols * sizeof(int));
            if (array[i] == NULL) {
                printf("Memory allocation failed. Exiting...");
                exit(1);
            }
        }
    
        return array;
    }
    
    // Function to input elements of the 2D array
    void inputArrayElements(int** array, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                printf("Enter element at position (%d, %d): ", i + 1, j + 1);
                scanf("%d", &array[i][j]);
            }
        }
    }
    
    // Function to display the 2D array
    void displayArray(int** array, int rows, int cols) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                printf("%d\t", array[i][j]);
            }
            printf("\n");
        }
    }
    
    // Function to free dynamically allocated memory for the 2D array
    void freeDynamicArray(int** array, int rows) {
        for (int i = 0; i < rows; i++) {
            free(array[i]);
        }
        free(array);
    }
    ```
