01. 🚀 C Programming Fundamentals
C is a powerful general-purpose programming language that has influenced many modern languages. It's known for its efficiency, portability, and low-level access to memory.
Why Learn C?
C is the foundation of modern computing. Operating systems (Linux, Windows), databases, embedded systems, and game engines are built with C. Learning C helps you understand how computers really work at a fundamental level.
Basic Structure of a C Program
- Preprocessor Directives: #include, #define
- Main Function: Program entry point
- Variable Declarations: Memory allocation
- Statements & Expressions: Program logic
- Comments: // for single-line, /* */ for multi-line
Example: Your First C Program
/* This is a multi-line comment
First C Program - Hello World */
// Single line comment
#include <stdio.h> // Standard Input Output header
int main() {
// Print Hello World to console
printf("Hello, World!\n");
// Return 0 indicates successful execution
return 0;
}
#include <stdio.h>
int main() {
printf("Welcome to C Programming!\n");
printf("Let's learn together.\n");
return 0;
}
02. 📊 Data Types & Variables
Data types define the type of data that can be stored in variables. C provides basic built-in data types that can be combined to form complex data structures.
Basic Data Types
- int: Integer numbers (2 or 4 bytes)
- float: Single precision floating point (4 bytes)
- double: Double precision floating point (8 bytes)
- char: Single character (1 byte)
- void: No value/type
Memory Representation
Example: Variables and Data Types
#include <stdio.h>
int main() {
// Integer types
int age = 25;
short smallNumber = 100;
long bigNumber = 1000000L;
unsigned int positiveOnly = 40000;
// Floating point types
float price = 19.99f;
double pi = 3.14159265359;
// Character type
char grade = 'A';
char symbol = '$';
// Display values
printf("Age: %d\n", age);
printf("Price: %.2f\n", price);
printf("PI: %.11f\n", pi);
printf("Grade: %c\n", grade);
// Size of data types
printf("\nSize of int: %zu bytes\n", sizeof(int));
printf("Size of float: %zu bytes\n", sizeof(float));
printf("Size of double: %zu bytes\n", sizeof(double));
printf("Size of char: %zu byte\n", sizeof(char));
return 0;
}
#include <stdio.h>
int main() {
// Declare variables
int score = 95;
float average = 85.5;
char initial = 'J';
// Modify and print
score = score + 5;
average = average * 1.1;
printf("Score: %d\n", score);
printf("Average: %.1f\n", average);
printf("Initial: %c\n", initial);
return 0;
}
03. ➕ Operators & Expressions
Operators are special symbols that perform operations on variables and values. C provides a rich set of operators for different purposes.
Types of Operators
- Arithmetic: +, -, *, /, %
- Relational: ==, !=, >, <, >=, <=
- Logical: &&, ||, !
- Bitwise: &, |, ^, ~, <<, >>
- Assignment: =, +=, -=, *=, /=
- Increment/Decrement: ++, --
- Ternary: ? :
Example: Operators in Action
#include <stdio.h>
int main() {
int a = 10, b = 3;
// Arithmetic operators
printf("a + b = %d\n", a + b); // Addition
printf("a - b = %d\n", a - b); // Subtraction
printf("a * b = %d\n", a * b); // Multiplication
printf("a / b = %d\n", a / b); // Integer division
printf("a %% b = %d\n", a % b); // Modulus
// Relational operators
printf("\na == b: %d\n", a == b); // 0 (false)
printf("a != b: %d\n", a != b); // 1 (true)
printf("a > b: %d\n", a > b); // 1 (true)
// Logical operators
int x = 1, y = 0;
printf("\nx && y: %d\n", x && y); // 0 (false)
printf("x || y: %d\n", x || y); // 1 (true)
printf("!x: %d\n", !x); // 0 (false)
// Bitwise operators
unsigned int num1 = 5; // 0101 in binary
unsigned int num2 = 3; // 0011 in binary
printf("\n5 & 3 = %u\n", num1 & num2); // 0001 = 1
printf("5 | 3 = %u\n", num1 | num2); // 0111 = 7
printf("5 ^ 3 = %u\n", num1 ^ num2); // 0110 = 6
// Assignment operators
int c = 10;
c += 5; // c = c + 5
printf("\nc = %d\n", c);
// Increment/Decrement
int d = 5;
printf("\nOriginal d: %d\n", d);
printf("Post-increment d++: %d\n", d++); // Prints 5, then becomes 6
printf("After increment: %d\n", d);
printf("Pre-increment ++d: %d\n", ++d); // Becomes 7, then prints 7
// Ternary operator
int max = (a > b) ? a : b;
printf("\nMax of %d and %d is: %d\n", a, b, max);
return 0;
}
04. 🎮 Control Structures
Control structures determine the flow of program execution. They allow you to make decisions, repeat code, and change the execution path.
Types of Control Structures
- Conditional: if, if-else, switch-case
- Loops: for, while, do-while
- Jump: break, continue, goto, return
Loop Comparison
for loop: Used when number of iterations is known
while loop: Used when condition needs checking before each iteration
do-while loop: Used when loop must execute at least once
Example: Control Flow
#include <stdio.h>
int main() {
// If-else statement
int number = 15;
if (number > 0) {
printf("%d is positive\n", number);
} else if (number < 0) {
printf("%d is negative\n", number);
} else {
printf("Number is zero\n");
}
// Switch statement
char grade = 'B';
printf("\nGrade: ");
switch (grade) {
case 'A':
printf("Excellent!\n");
break;
case 'B':
printf("Good job!\n");
break;
case 'C':
printf("Well done\n");
break;
case 'D':
printf("You passed\n");
break;
case 'F':
printf("Better try again\n");
break;
default:
printf("Invalid grade\n");
}
// For loop
printf("\nFor loop (1 to 5): ");
for (int i = 1; i <= 5; i++) {
printf("%d ", i);
}
printf("\n");
// While loop
printf("While loop (countdown): ");
int count = 5;
while (count > 0) {
printf("%d ", count);
count--;
}
printf("\n");
// Do-while loop
printf("Do-while loop: ");
int input;
do {
printf("Enter positive number: ");
scanf("%d", &input);
} while (input <= 0);
printf("Thank you! You entered: %d\n", input);
// Break and continue
printf("\nBreak example: ");
for (int i = 1; i <= 10; i++) {
if (i == 6) {
break; // Exit loop when i is 6
}
printf("%d ", i);
}
printf("\nContinue example: ");
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // Skip even numbers
}
printf("%d ", i);
}
printf("\n");
return 0;
}
#include <stdio.h>
int main() {
// FizzBuzz Challenge
for (int i = 1; i <= 20; i++) {
if (i % 3 == 0 && i % 5 == 0) {
printf("FizzBuzz ");
} else if (i % 3 == 0) {
printf("Fizz ");
} else if (i % 5 == 0) {
printf("Buzz ");
} else {
printf("%d ", i);
}
}
printf("\n");
return 0;
}
05. 🛠️ Functions in C
Functions are reusable blocks of code that perform specific tasks. They help in modular programming, code reuse, and better organization.
Function Components
- Function Declaration: Tells compiler about function
- Function Definition: Actual implementation
- Function Call: Using the function
- Parameters: Input values
- Return Value: Output result
Function Call Stack
Example: Functions Implementation
#include <stdio.h>
// Function declaration (prototype)
int add(int a, int b);
void greet();
int factorial(int n);
float average(int arr[], int size);
int main() {
// Function calls
greet();
int sum = add(10, 20);
printf("Sum: %d\n", sum);
int num = 5;
printf("Factorial of %d is %d\n", num, factorial(num));
int numbers[] = {85, 90, 78, 92, 88};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Average score: %.2f\n", average(numbers, size));
return 0;
}
// Function definitions
// Simple void function (no return value)
void greet() {
printf("Welcome to Functions in C!\n");
}
// Function with parameters and return value
int add(int a, int b) {
return a + b;
}
// Recursive function
int factorial(int n) {
if (n == 0 || n == 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
// Function with array parameter
float average(int arr[], int size) {
int total = 0;
for (int i = 0; i < size; i++) {
total += arr[i];
}
return (float)total / size;
}
// Call by value vs Call by reference
void swapByValue(int a, int b) {
int temp = a;
a = b;
b = temp;
printf("Inside swapByValue: a=%d, b=%d\n", a, b);
}
void swapByReference(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
printf("Inside swapByReference: a=%d, b=%d\n", *a, *b);
}
06. 📚 Arrays in C
Arrays are collections of elements of the same type stored in contiguous memory locations. They allow you to work with multiple values efficiently.
Array Types
- One-dimensional arrays: Simple lists
- Multi-dimensional arrays: Matrices, tables
- Dynamic arrays: Size determined at runtime
Array Memory Layout
[0]
[1]
[2]
[3]
[4]
Contiguous memory blocks, each element accessible by index (0-based)
Example: Array Operations
#include <stdio.h>
#define SIZE 5
int main() {
// Array declaration and initialization
int numbers[SIZE] = {10, 20, 30, 40, 50};
// Accessing array elements
printf("First element: %d\n", numbers[0]);
printf("Third element: %d\n", numbers[2]);
printf("Last element: %d\n", numbers[SIZE - 1]);
// Modifying array elements
numbers[1] = 25;
printf("\nAfter modification: ");
for (int i = 0; i < SIZE; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
// Array traversal
printf("\nArray elements: ");
for (int i = 0; i < SIZE; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
// Calculating sum
int sum = 0;
for (int i = 0; i < SIZE; i++) {
sum += numbers[i];
}
printf("\nSum of array elements: %d\n", sum);
printf("Average: %.2f\n", (float)sum / SIZE);
// Finding maximum
int max = numbers[0];
for (int i = 1; i < SIZE; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
printf("Maximum value: %d\n", max);
// 2D Arrays (Matrix)
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
printf("\n2D Array (Matrix):\n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
// Array of characters (string)
char name[] = "C Programming";
printf("\nCharacter array: %s\n", name);
printf("Length: %zu\n", sizeof(name) - 1); // -1 for null terminator
return 0;
}
07. 🎯 Pointers Deep Dive
Pointers are variables that store memory addresses. They are one of the most powerful but challenging features of C programming.
Pointer Basics
& (address of operator): Gets memory address of a variable
* (dereference operator): Accesses value at a memory address
Pointers enable dynamic memory allocation, efficient array access, and complex data structures.
Pointer Visualization
int *ptr = &x;
x
*ptr gives the value 42
Example: Pointer Operations
#include <stdio.h>
int main() {
// Basic pointer usage
int num = 42;
int *ptr = #
printf("Value of num: %d\n", num);
printf("Address of num: %p\n", &num);
printf("Value of ptr: %p\n", ptr);
printf("Value pointed by ptr: %d\n", *ptr);
// Modifying value through pointer
*ptr = 100;
printf("\nAfter *ptr = 100:\n");
printf("Value of num: %d\n", num);
printf("Value pointed by ptr: %d\n", *ptr);
// Pointer arithmetic
int arr[] = {10, 20, 30, 40, 50};
int *arrPtr = arr; // Points to first element
printf("\nArray elements using pointer:\n");
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d at address %p\n", i, *(arrPtr + i), arrPtr + i);
}
// Pointers to pointers
int value = 5;
int *p = &value;
int **pp = &p;
printf("\nPointers to pointers:\n");
printf("value = %d\n", value);
printf("*p = %d\n", *p);
printf("**pp = %d\n", **pp);
// Pointer to function
printf("\nFunction pointers:\n");
int (*funcPtr)(int, int); // Declare function pointer
// Pointer compatibility
int a = 10;
float b = 3.14;
int *intPtr;
float *floatPtr;
intPtr = &a;
floatPtr = &b;
printf("\nType safety:\n");
printf("Integer pointer points to %d\n", *intPtr);
printf("Float pointer points to %.2f\n", *floatPtr);
// NULL pointer
int *nullPtr = NULL;
if (nullPtr == NULL) {
printf("\nnullPtr is NULL - safe to check\n");
}
return 0;
}
08. 📝 String Manipulation
In C, strings are arrays of characters terminated by a null character ('\0'). String manipulation is a fundamental skill for text processing.
String Functions (string.h)
- strlen(): Get string length
- strcpy(): Copy string
- strcat(): Concatenate strings
- strcmp(): Compare strings
- strstr(): Find substring
- strtok(): Tokenize string
Example: String Operations
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
// String declaration methods
char str1[] = "Hello";
char str2[20] = "World";
char str3[] = {'C', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', '\0'};
printf("String 1: %s\n", str1);
printf("String 2: %s\n", str2);
printf("String 3: %s\n", str3);
// String length
printf("\nLength of '%s' is %zu\n", str1, strlen(str1));
// String copy
char copy[20];
strcpy(copy, str1);
printf("Copied string: %s\n", copy);
// String concatenation
strcat(copy, " ");
strcat(copy, str2);
printf("Concatenated: %s\n", copy);
// String comparison
char password[] = "secret123";
char input[] = "secret123";
if (strcmp(password, input) == 0) {
printf("\nPassword correct!\n");
} else {
printf("Password incorrect\n");
}
// String searching
char text[] = "The quick brown fox jumps over the lazy dog";
char search[] = "fox";
char *result = strstr(text, search);
if (result != NULL) {
printf("\n'%s' found at position %ld\n", search, result - text);
}
// String tokenization
char data[] = "apple,orange,banana,grape";
char *token = strtok(data, ",");
printf("\nTokens:\n");
while (token != NULL) {
printf("- %s\n", token);
token = strtok(NULL, ",");
}
// Character functions
char mixed[] = "Hello World 123!";
printf("\nCharacter analysis:\n");
for (int i = 0; mixed[i] != '\0'; i++) {
printf("%c - ", mixed[i]);
if (isalpha(mixed[i])) {
printf("Alphabet");
if (isupper(mixed[i])) {
printf(" (Uppercase)");
} else {
printf(" (Lowercase)");
}
} else if (isdigit(mixed[i])) {
printf("Digit");
} else if (isspace(mixed[i])) {
printf("Whitespace");
} else {
printf("Other");
}
printf("\n");
}
// String reversal
char original[] = "Reverse Me";
char reversed[20];
int len = strlen(original);
for (int i = 0; i < len; i++) {
reversed[i] = original[len - 1 - i];
}
reversed[len] = '\0';
printf("\nOriginal: %s\n", original);
printf("Reversed: %s\n", reversed);
return 0;
}
09. 🏗️ Structures & Unions
Structures allow you to combine different data types into a single type. Unions share memory between members, storing only one value at a time.
Structures vs Unions
Structure: Each member has separate memory space
Union: All members share the same memory space
Unions are memory-efficient but only one member can contain a value at any time.
Structure Memory Layout
int id; // 4 bytes
char name[20]; // 20 bytes
float gpa; // 4 bytes
}; // Total: ~28 bytes
Example: Structures & Unions
#include <stdio.h>
#include <string.h>
// Structure definition
struct Student {
int id;
char name[50];
int age;
float gpa;
};
// Nested structure
struct Address {
char street[50];
char city[30];
char state[20];
int zipcode;
};
struct Person {
char name[50];
struct Address address;
};
// Union definition
union Data {
int i;
float f;
char str[20];
};
// Typedef for type alias
typedef struct {
char title[100];
char author[50];
int year;
float price;
} Book;
int main() {
// Structure variable declaration and initialization
struct Student student1;
// Assigning values
student1.id = 101;
strcpy(student1.name, "John Doe");
student1.age = 20;
student1.gpa = 3.8;
printf("Student Information:\n");
printf("ID: %d\n", student1.id);
printf("Name: %s\n", student1.name);
printf("Age: %d\n", student1.age);
printf("GPA: %.2f\n", student1.gpa);
// Structure initialization at declaration
struct Student student2 = {102, "Jane Smith", 21, 3.9};
// Array of structures
struct Student class[3] = {
{201, "Alice Johnson", 19, 3.7},
{202, "Bob Williams", 20, 3.5},
{203, "Charlie Brown", 21, 3.9}
};
printf("\nClass Roster:\n");
for (int i = 0; i < 3; i++) {
printf("%d. %s (GPA: %.2f)\n",
class[i].id, class[i].name, class[i].gpa);
}
// Nested structures
struct Person person1;
strcpy(person1.name, "Tom Smith");
strcpy(person1.address.street, "123 Main St");
strcpy(person1.address.city, "New York");
strcpy(person1.address.state, "NY");
person1.address.zipcode = 10001;
printf("\nPerson Details:\n");
printf("Name: %s\n", person1.name);
printf("Address: %s, %s, %s %d\n",
person1.address.street,
person1.address.city,
person1.address.state,
person1.address.zipcode);
// Union usage
union Data data;
data.i = 10;
printf("\nUnion data.i = %d\n", data.i);
data.f = 220.5;
printf("Union data.f = %.2f\n", data.f);
strcpy(data.str, "C Programming");
printf("Union data.str = %s\n", data.str);
// Typedef usage
Book book1 = {"The C Programming Language",
"Brian Kernighan & Dennis Ritchie",
1978, 49.99};
printf("\nBook Information:\n");
printf("Title: %s\n", book1.title);
printf("Author: %s\n", book1.author);
printf("Year: %d\n", book1.year);
printf("Price: $%.2f\n", book1.price);
// Structure pointer
struct Student *ptr = &student1;
printf("\nAccessing via pointer:\n");
printf("ID: %d\n", ptr->id);
printf("Name: %s\n", ptr->name);
printf("Age: %d\n", ptr->age);
// Size of structure
printf("\nSize of Student structure: %zu bytes\n", sizeof(struct Student));
printf("Size of Data union: %zu bytes\n", sizeof(union Data));
return 0;
}
10. 💾 File Input/Output
File I/O operations allow programs to read from and write to files, enabling persistent data storage.
File Operations
- Opening files: fopen()
- Closing files: fclose()
- Reading: fgetc(), fgets(), fread(), fscanf()
- Writing: fputc(), fputs(), fwrite(), fprintf()
- Navigation: fseek(), ftell(), rewind()
Example: File Operations
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *file;
char ch;
// Writing to a file
file = fopen("example.txt", "w");
if (file == NULL) {
printf("Error creating file!\n");
return 1;
}
fprintf(file, "This is line 1\n");
fprintf(file, "This is line 2\n");
fprintf(file, "Numbers: %d %.2f\n", 42, 3.14);
fclose(file);
printf("File written successfully.\n");
// Reading from a file - character by character
printf("\nReading file character by character:\n");
file = fopen("example.txt", "r");
if (file == NULL) {
printf("Error opening file!\n");
return 1;
}
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
}
fclose(file);
// Reading line by line
printf("\n\nReading file line by line:\n");
file = fopen("example.txt", "r");
char line[100];
while (fgets(line, sizeof(line), file) != NULL) {
printf("Line: %s", line);
}
fclose(file);
// Binary file operations
struct Student {
int id;
char name[50];
float marks;
};
struct Student students[3] = {
{1, "Alice", 85.5},
{2, "Bob", 90.0},
{3, "Charlie", 78.5}
};
// Write structures to binary file
file = fopen("students.dat", "wb");
if (file == NULL) {
printf("Error creating binary file!\n");
return 1;
}
fwrite(students, sizeof(struct Student), 3, file);
fclose(file);
// Read structures from binary file
struct Student readStudents[3];
file = fopen("students.dat", "rb");
if (file == NULL) {
printf("Error opening binary file!\n");
return 1;
}
fread(readStudents, sizeof(struct Student), 3, file);
fclose(file);
printf("\n\nStudents from binary file:\n");
for (int i = 0; i < 3; i++) {
printf("ID: %d, Name: %s, Marks: %.2f\n",
readStudents[i].id,
readStudents[i].name,
readStudents[i].marks);
}
// File positioning
file = fopen("example.txt", "r");
// Move to 10th byte from beginning
fseek(file, 10, SEEK_SET);
printf("\n\nFrom position 10: ");
while ((ch = fgetc(file)) != '\n' && ch != EOF) {
putchar(ch);
}
// Get current position
long position = ftell(file);
printf("\nCurrent position: %ld\n", position);
// Go back to beginning
rewind(file);
printf("\nAfter rewind, first 5 chars: ");
for (int i = 0; i < 5; i++) {
ch = fgetc(file);
putchar(ch);
}
fclose(file);
// Append to file
file = fopen("example.txt", "a");
fprintf(file, "This is appended text\n");
fclose(file);
printf("\n\nFile operations completed successfully!\n");
return 0;
}
11. 🧠 Memory Management
C provides manual memory management through dynamic allocation functions. Understanding this is crucial for efficient programs.
Memory Segments
Stack: Local variables, automatic allocation
Heap: Dynamic memory, manual allocation
Data Segment: Global and static variables
Code Segment: Program instructions
Memory Allocation Process
Example: Dynamic Memory Allocation
#include <stdio.h>
#include <stdlib.h>
int main() {
// malloc - memory allocation
int *ptr = (int *)malloc(5 * sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
printf("malloc example:\n");
for (int i = 0; i < 5; i++) {
ptr[i] = i * 10;
printf("ptr[%d] = %d\n", i, ptr[i]);
}
// Realloc - resize memory block
ptr = (int *)realloc(ptr, 10 * sizeof(int));
if (ptr == NULL) {
printf("Memory reallocation failed!\n");
return 1;
}
printf("\nAfter realloc (size 10):\n");
for (int i = 5; i < 10; i++) {
ptr[i] = i * 10;
}
for (int i = 0; i < 10; i++) {
printf("ptr[%d] = %d\n", i, ptr[i]);
}
// Free memory
free(ptr);
ptr = NULL; // Good practice
// calloc - contiguous allocation (initialized to 0)
int *arr = (int *)calloc(5, sizeof(int));
printf("\ncalloc example (initialized to 0):\n");
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
free(arr);
// Dynamic array of structures
struct Point {
int x;
int y;
};
int n;
printf("\nEnter number of points: ");
scanf("%d", &n);
struct Point *points = (struct Point *)malloc(n * sizeof(struct Point));
for (int i = 0; i < n; i++) {
points[i].x = i * 2;
points[i].y = i * 3;
}
printf("\nPoints:\n");
for (int i = 0; i < n; i++) {
printf("Point %d: (%d, %d)\n", i+1, points[i].x, points[i].y);
}
free(points);
// Memory leak example (commented out - DON'T DO THIS!)
/*
printf("\nMemory leak example (commented out):\n");
for (int i = 0; i < 1000; i++) {
int *leak = (int *)malloc(1000 * sizeof(int));
// Forgot to free - MEMORY LEAK!
}
*/
// Double free error (commented out - DON'T DO THIS!)
/*
int *error = (int *)malloc(sizeof(int));
free(error);
free(error); // ERROR: Double free
*/
// Use after free error (commented out - DON'T DO THIS!)
/*
int *dangling = (int *)malloc(sizeof(int));
*dangling = 42;
free(dangling);
printf("%d\n", *dangling); // ERROR: Use after free
*/
printf("\nMemory management best practices:\n");
printf("1. Always check if allocation succeeded\n");
printf("2. Free memory when done\n");
printf("3. Set pointer to NULL after freeing\n");
printf("4. Don't access freed memory\n");
printf("5. Don't free memory twice\n");
return 0;
}
12. 🏛️ Data Structures in C
Data structures organize and store data efficiently. Implementing them in C teaches fundamental computer science concepts.
Common Data Structures
- Linked Lists: Dynamic nodes connected by pointers
- Stacks: LIFO (Last In First Out)
- Queues: FIFO (First In First Out)
- Trees: Hierarchical structures
- Graphs: Nodes and edges
- Hash Tables: Key-value pairs
Linked List Visualization
Example: Linked List Implementation
#include <stdio.h>
#include <stdlib.h>
// Node structure for linked list
struct Node {
int data;
struct Node* next;
};
// Function to create a new node
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// Function to insert at beginning
void insertAtBeginning(struct Node** head, int data) {
struct Node* newNode = createNode(data);
newNode->next = *head;
*head = newNode;
}
// Function to insert at end
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;
}
// Function to display linked list
void displayList(struct Node* head) {
struct Node* temp = head;
printf("Linked List: ");
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
// Function to delete a node
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) {
printf("Key %d not found in list\n", key);
return;
}
prev->next = temp->next;
free(temp);
}
// Stack implementation using array
#define MAX 100
struct Stack {
int arr[MAX];
int top;
};
void initStack(struct Stack* s) {
s->top = -1;
}
int isFull(struct Stack* s) {
return s->top == MAX - 1;
}
int isEmpty(struct Stack* s) {
return s->top == -1;
}
void push(struct Stack* s, int value) {
if (isFull(s)) {
printf("Stack Overflow!\n");
return;
}
s->arr[++(s->top)] = value;
}
int pop(struct Stack* s) {
if (isEmpty(s)) {
printf("Stack Underflow!\n");
return -1;
}
return s->arr[(s->top)--];
}
int peek(struct Stack* s) {
if (isEmpty(s)) {
printf("Stack is empty!\n");
return -1;
}
return s->arr[s->top];
}
// Queue implementation
struct Queue {
int arr[MAX];
int front, rear;
};
void initQueue(struct Queue* q) {
q->front = q->rear = -1;
}
int isQueueEmpty(struct Queue* q) {
return q->front == -1;
}
int isQueueFull(struct Queue* q) {
return (q->rear + 1) % MAX == q->front;
}
void enqueue(struct Queue* q, int value) {
if (isQueueFull(q)) {
printf("Queue is full!\n");
return;
}
if (isQueueEmpty(q)) {
q->front = q->rear = 0;
} else {
q->rear = (q->rear + 1) % MAX;
}
q->arr[q->rear] = value;
}
int dequeue(struct Queue* q) {
if (isQueueEmpty(q)) {
printf("Queue is empty!\n");
return -1;
}
int value = q->arr[q->front];
if (q->front == q->rear) {
q->front = q->rear = -1;
} else {
q->front = (q->front + 1) % MAX;
}
return value;
}
// Binary Search Tree
struct TreeNode {
int data;
struct TreeNode* left;
struct TreeNode* right;
};
struct TreeNode* createTreeNode(int data) {
struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
struct TreeNode* insertBST(struct TreeNode* root, int data) {
if (root == NULL) {
return createTreeNode(data);
}
if (data < root->data) {
root->left = insertBST(root->left, data);
} else if (data > root->data) {
root->right = insertBST(root->right, data);
}
return root;
}
void inorderTraversal(struct TreeNode* root) {
if (root != NULL) {
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
}
int main() {
printf("=== LINKED LIST DEMO ===\n");
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtBeginning(&head, 5);
insertAtEnd(&head, 30);
displayList(head);
deleteNode(&head, 20);
displayList(head);
printf("\n=== STACK DEMO ===\n");
struct Stack s;
initStack(&s);
push(&s, 10);
push(&s, 20);
push(&s, 30);
printf("Top element: %d\n", peek(&s));
printf("Popped: %d\n", pop(&s));
printf("Top element after pop: %d\n", peek(&s));
printf("\n=== QUEUE DEMO ===\n");
struct Queue q;
initQueue(&q);
enqueue(&q, 10);
enqueue(&q, 20);
enqueue(&q, 30);
printf("Dequeued: %d\n", dequeue(&q));
printf("Dequeued: %d\n", dequeue(&q));
printf("\n=== BINARY SEARCH TREE DEMO ===\n");
struct TreeNode* root = NULL;
root = insertBST(root, 50);
insertBST(root, 30);
insertBST(root, 20);
insertBST(root, 40);
insertBST(root, 70);
insertBST(root, 60);
insertBST(root, 80);
printf("Inorder traversal (sorted): ");
inorderTraversal(root);
printf("\n");
// Clean up linked list
while (head != NULL) {
struct Node* temp = head;
head = head->next;
free(temp);
}
printf("\nData structures implemented successfully!\n");
return 0;
}
#include <stdio.h>
// TODO: Implement this function
// It should return 1 if number is prime, 0 otherwise
int isPrime(int n) {
// Your code here
if (n <= 1) return 0;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return 0;
}
return 1;
}
int main() {
printf("Prime numbers between 1 and 50:\n");
for (int i = 1; i <= 50; i++) {
if (isPrime(i)) {
printf("%d ", i);
}
}
printf("\n");
return 0;
}
Codcups
Master C Programming - Complete Course