Basic Dynamic Memory Allocation Programming Questions
Here are 10 C programming exercises that involve dynamic memory allocation:
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.
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.
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.
Dynamic Linked List: Implement a linked list using dynamic memory allocation. Allow users to insert, delete, and display elements in the linked list.
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.
Dynamic Queue: Implement a queue using dynamic memory allocation. Allow users to enqueue and dequeue elements and display the contents of the queue.
Dynamic String Concatenation: Write a program that concatenates two strings using dynamic memory allocation. Allocate memory only for the resulting string.
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.
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.
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.
Dynamic Array
#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; }
Matrix Multiplication
#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); }
String Reversal
#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; }
Dynamic Linked List
#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); } }
Dynamic Stack
#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); } }
Dynamic Queue
#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); }
Dynamic String Concatenation
#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; }
Dynamic Structure
#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); }
File Reading and Dynamic Memory
#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); }
Dynamic 2D Array
#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); }
Subscribe to my newsletter
Read articles from Jyotiprakash Mishra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jyotiprakash Mishra
Jyotiprakash Mishra
I am Jyotiprakash, a deeply driven computer systems engineer, software developer, teacher, and philosopher. With a decade of professional experience, I have contributed to various cutting-edge software products in network security, mobile apps, and healthcare software at renowned companies like Oracle, Yahoo, and Epic. My academic journey has taken me to prestigious institutions such as the University of Wisconsin-Madison and BITS Pilani in India, where I consistently ranked among the top of my class. At my core, I am a computer enthusiast with a profound interest in understanding the intricacies of computer programming. My skills are not limited to application programming in Java; I have also delved deeply into computer hardware, learning about various architectures, low-level assembly programming, Linux kernel implementation, and writing device drivers. The contributions of Linus Torvalds, Ken Thompson, and Dennis Ritchie—who revolutionized the computer industry—inspire me. I believe that real contributions to computer science are made by mastering all levels of abstraction and understanding systems inside out. In addition to my professional pursuits, I am passionate about teaching and sharing knowledge. I have spent two years as a teaching assistant at UW Madison, where I taught complex concepts in operating systems, computer graphics, and data structures to both graduate and undergraduate students. Currently, I am an assistant professor at KIIT, Bhubaneswar, where I continue to teach computer science to undergraduate and graduate students. I am also working on writing a few free books on systems programming, as I believe in freely sharing knowledge to empower others.