C Programming: Algorithms & Memory Management Report
C Programming: Algorithms & Memory Management Report
Report
Laboratory Work No.4
Checked:
Burlacu Natalia, PhD, associate professor
Department of Software and Automation Engineering,
FCIM Faculty, UTM
Chisinau – 2023
1
1. The purpose of the laboratory work
The objective of this lab work is to enhance my practical C programming skills
through the implementation and modification of complex algorithms, particularly
focusing on dynamic memory management, subarray sum calculations, and sorting
techniques. Throughout this lab, I have been tasked with identifying all subarrays
within a 2D matrix that sum up to a given value. This process required me to
adeptly manage memory dynamically, ensuring efficient allocation, usage, and
deallocation to prevent leaks and ensure program stability.In addition to subarray
identification, I have delved into sorting algorithms, specifically adapting the
Quick Sort and Radix Sort algorithms to sort matrix columns under certain
conditions. Also we had to learn working with structures, and to optimize it using
bitwise operators and unions.
Condition
Task:
2
Problems:
int main() {
int mainChoice;
printf("Use the program with:\n");
printf("1. Struct\n");
printf("2. Union\n");
printf("Enter your choice: ");
if (scanf("%d", &mainChoice) != 1) {
3
printf("Invalid input. Exiting.\n");
return 1; // Early return if the choice input fails
}
if (mainChoice == 1) {
int choice;
int num_equipment = 0; // Keeps track of the number of equipment
entries
struct Equipment* equipmentArray = NULL; // Pointer to the array
of Equipment structures
while (1) {
printf("\nMenu:\n");
printf("1. Input new equipment\n");
printf("2. Display all equipment\n");
printf("3. Sort by type (ascending) \n");
printf("4. Sort by registration number (ascending) \n");
printf("5. Change the informations in base of reg_num\n");
printf("6. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
num_equipment++;
equipmentArray = realloc(equipmentArray,
num_equipment * sizeof(struct Equipment));
inputEquipment(&equipmentArray[num_equipment - 1]);
break;
case 2: // Display all equipment
for (int i = 0; i < num_equipment; ++i) {
displayEquipment(&equipmentArray[i]);
}
break;
case 3: // Sort by type (ascending)
quickSort(equipmentArray, 0, num_equipment-1);
printf("\nSorted by type (ascending):\n");
for (int i = 0; i < num_equipment; i++) {
displayEquipment(&equipmentArray[i]);
}
break;
case 4:
radixSort(equipmentArray, num_equipment);
printf("\nSorted by registration number (ascending):\
n");
for (int i = 0; i < num_equipment; i++) {
displayEquipment(&equipmentArray[i]);
}
break;
case 5: // Modify existing equipment by registration
number
modifyEquipmentByRegNum(equipmentArray,
num_equipment);
break;
case 6: // Exit
// Free the allocated memory before exiting
for (int i = 0; i < num_equipment; ++i) {
// Assume we have a function to free the
internals of an Equipment
freeEquipment(&equipmentArray[i]);
}
free(equipmentArray);
printf("Exiting program.\n");
4
return 0;
default:
printf("Invalid choice. Please try again.\n");
}
}
} else if (mainChoice == 2) {
int choice;
int num_equipment = 0; // Keeps track of the number of equipment
entries
struct Equipment2* equipmentArray = NULL; // Pointer to the array
of Equipment structures
while (1) {
clearScreen();
printf("\nMenu:\n");
printf("1. Input new equipment\n");
printf("2. Display all equipment\n");
printf("3. Sort by type (ascending) \n");
printf("4. Sort by registration number (ascending) \n");
printf("5. Change the informations in base of reg_num\n");
printf("6. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1: // Input new equipment
equipmentArray = realloc(equipmentArray,
(num_equipment + 1) * sizeof(struct Equipment2));
if (equipmentArray == NULL) {
printf("Memory allocation failed\n");
exit(1); // Exit if we fail to allocate memory
}
inputEquipmentu(&equipmentArray[num_equipment]);
num_equipment++;
break;
case 2: // Display all equipment
for (int i = 0; i < num_equipment; ++i) {
displayEquipmentu(&equipmentArray[i]);
}
getch(); // Wait for user input to continue
break;
case 3: // Sort by type (ascending)
quickSortu(equipmentArray, 0, num_equipment-1);
printf("\nSorted by type (ascending):\n");
for (int i = 0; i < num_equipment; i++) {
displayEquipmentu(&equipmentArray[i]);
}
break;
case 4:
radixSortu(equipmentArray, num_equipment);
printf("\nSorted by registration number (ascending):\
n");
for (int i = 0; i < num_equipment; i++) {
displayEquipmentu(&equipmentArray[i]);
}
break;
case 5: // Modify equipment by registration number
modifyEquipmentByRegNumu(equipmentArray,
num_equipment);
getch(); // Wait for user input to continue
break;
5
case 6: // Exit
// Free the allocated memory before exiting
for (int i = 0; i < num_equipment; ++i) {
freeEquipmentu(&equipmentArray[i]);
}
free(equipmentArray);
equipmentArray = NULL;
printf("Exiting program.\n");
return 0; // Return from version2 to end the program
default:
printf("Invalid choice. Please try again.\n");
getch(); // Wait for user input to continue
}
}
}
return 0;
}
Version 1 that uses streucture
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#include "structure.h"
void clearScreen() {
// Clear the console screen
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
}
// Function to input details into provided Equipment structure
void inputEquipment(struct Equipment* equip) {
// Allocate memory for the strings within the structure
equip->type = malloc(50 * sizeof(char));
equip->brand = malloc(50 * sizeof(char));
equip->color = malloc(50 * sizeof(char));
equip->owner_info.name = malloc(50 * sizeof(char));
equip->owner_info.surname = malloc(50 * sizeof(char));
equip->owner_info.id_code = malloc(50 * sizeof(char));
6
printf("Enter owner's name: ");
scanf("%49s", equip->owner_info.name);
7
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void quickSort(struct Equipment* arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
// Copy the output array to arr[], so that arr[] now contains sorted
numbers according to current digit
for (i = 0; i < n; i++)
arr[i] = output[i];
// The main function to that sorts arr[] of size n using Radix Sort
void radixSort(struct Equipment arr[], int n) {
// Find the maximum number to know the number of digits
int m = getMax(arr, n);
// Do counting sort for every digit. Note that instead of passing digit
8
number, exp is passed. exp is 10^i where i is current digit number
for (int exp = 1; m / exp > 0; exp *= 10)
countSort(arr, n, exp);
}
void modifyEquipmentByRegNum(struct Equipment* equipmentArray, int
num_equipment) {
int reg_num;
char input[50]; // General purpose input buffer for user responses
printf("Enter registration number of the equipment to modify: ");
scanf("%d", ®_num);
getchar(); // To consume the newline character after number input
9
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#include "structure2.h"
void unpackDate(unsigned int packedDate, int* day, int* month, int* year) {
*day = packedDate & DAY_MASK;
*month = (packedDate >> DAY_BITS) & ((1 << MONTH_BITS) - 1);
*year = (packedDate >> (DAY_BITS + MONTH_BITS));
}
10
scanf("%d %d %d", &day, &month, &year);
equip->inspection_date.packedDate = packDate(day, month, year);
if (equip->owner_info.id.str_id != NULL) {
printf("Owner's ID: %s\n", equip->owner_info.id.str_id);
} else {
printf("Owner's ID Code: %u\n", equip->owner_info.id.int_id);
}printf("Owner's Name: %s\n", equip->owner_info.name);
printf("Owner's Surname: %s\n", equip->owner_info.surname);
}
}
void modifyEquipmentByRegNumu(struct Equipment2* equipmentArray, int
num_equipment) {
int reg_num;
printf("Enter registration number of the equipment to modify: ");
scanf("%d", ®_num);
11
scanf("%49s", input);
free(equipmentArray[i].brand);
equipmentArray[i].brand = strdup(input);
}
12
printf("No equipment found with registration number %d.\n", reg_num);
}
void swap2(struct Equipment2* a, struct Equipment2* b) {
struct Equipment2 t = *a;
*a = *b;
*b = t;
}
int partition2(struct Equipment2 arr[], int low, int high) {
struct Equipment2 pivot = arr[high];
int i = (low - 1);
// Copy the output array to arr[], so that arr[] now contains sorted
numbers according to current digit
13
for (i = 0; i < n; i++)
arr[i] = output[i];
// The main function to that sorts arr[] of size n using Radix Sort
void radixSortu(struct Equipment2 arr[], int n) {
// Find the maximum number to know the number of digits
int m = getMax2(arr, n);
// Do counting sort for every digit. Note that instead of passing digit
number, exp is passed. exp is 10^i where i is current digit number
for (int exp = 1; m / exp > 0; exp *= 10)
countSort2(arr, n, exp);
}
Structure1.h
#ifndef STRUCTURE_H
#define STRUCTURE_H
struct Date {
};
struct Owner {
char* name;
char* surname;
};
struct Equipment {
int reg_num;
char* type;
char* brand;
char* color;
struct Date inspection_date;
struct Owner owner_info;
};
void inputEquipment(struct Equipment* equip);
void displayEquipment(struct Equipment* equip);
void freeEquipment(struct Equipment *equip);
void quickSort(struct Equipment* arr[], int low, int high);
void modifyEquipmentByRegNum(struct Equipment* equipmentArray, int
num_equipment);
void radixSort(struct Equipment arr[], int n);
#endif // STRUCTURE_H
Structure2.h
#ifndef STRUCTURE2_H
#define STRUCTURE2_H
14
#define MONTH_BITS 4
#define MONTH_MASK (0xF << DAY_BITS)
#define YEAR_MASK (0xFFF << (DAY_BITS + MONTH_BITS))
struct Owner2 {
char* name;
char* surname;
union ID {
char* str_id;
unsigned int int_id;
} id;
};
struct Equipment2 {
int reg_num;
char* type;
char* brand;
char* color;
struct Date2 inspection_date;
struct Owner2 owner_info;
};
#endif // STRUCTURE2_H
4. Conclusions
The laboratory work focusing on structures, unions, and bitwise operations serves as a
fundamental exploration into the efficient manipulation and storage of data in C programming.
Through this hands-on approach, learners are introduced to advanced aspects of data
management and optimization techniques that are pivotal for developing performant and
15
resource-efficient applications.Structures provide a means to aggregate different data types into a
single unit, facilitating complex data handling. By using structures, programmers can create
more organized and readable code, which is essential for representing objects or entities within
software applications. This lab work emphasizes not just the creation of structures but also their
practical application in managing data more coherently.Unions, on the other hand, introduce an
effective way to manage memory by allowing different data types to share the same memory
location. Through lab exercises, the utility of unions in scenarios where variable types may
change or where memory footprint is a critical consideration becomes evident. Unions
underscore the flexibility of C in handling data, illustrating how to economize memory usage
without compromising functionality.Bitwise operations further the discussion on optimization by
delving into the manipulation of individual bits. These operations are instrumental in tasks
requiring compact data representation, encryption, quick arithmetic operations, or direct
hardware manipulation. The laboratory work showcases how bitwise operations can serve as a
powerful tool for optimization, allowing for operations that are both speed-efficient and
memory-efficient.
16