40 Intermediate C Tutorials
1. Basic Pointers
Pointers store memory addresses for direct data access.
Example: Use a pointer to modify a variable.
#include
int main() {
int x = 10, *p = &x;
*p = 20;
printf("Value: %d\n", x);
return 0;
}
Value: 20
Note: Use & for address, * for dereference.
2. Pointer to Array
Pointers can access array elements efficiently.
Example: Iterate array using a pointer.
#include
int main() {
int arr[] = {1, 2, 3};
int *p = arr;
for (int i = 0; i < 3; i++) printf("%d ", *(p + i));
printf("\n");
return 0;
}
1 2 3
Note: Array name is a pointer to first element.
3. Dynamic Memory
Allocate memory at runtime with malloc.
Example: Allocate and use an array.
#include
#include
int main() {
int *arr = (int*)malloc(3 * sizeof(int));
arr[0] = 1; arr[1] = 2; arr[2] = 3;
printf("%d %d %d\n", arr[0], arr[1], arr[2]);
free(arr);
return 0;
}
1 2 3
Note: Always free allocated memory.
4. String Handling
Manipulate strings using standard library functions.
Example: Copy and concatenate strings.
#include
#include
int main() {
char s1[20] = "Hello", s2[10] = "World";
strcat(s1, s2);
printf("String: %s\n", s1);
return 0;
}
String: HelloWorld
Note: Include
5. Structures
Group related data using structs.
Example: Define and use a struct.
#include
struct Point { int x, y; };
int main() {
struct Point p = {3, 4};
printf("Point: (%d, %d)\n", p.x, p.y);
return 0;
}
Point: (3, 4)
Note: Access fields with dot operator.
6. File Writing
Write data to files using FILE pointers.
Example: Write text to a file.
#include
int main() {
FILE *f = fopen("output.txt", "w");
fprintf(f, "Hello, File!\n");
fclose(f);
printf("Written to file\n");
return 0;
}
Written to file
Note: Use "w" mode. Always close files.
7. File Reading
Read data from files using FILE pointers.
Example: Read text from a file.
#include
int main() {
FILE *f = fopen("input.txt", "r");
char buffer[20];
fgets(buffer, 20, f);
printf("Read: %s", buffer);
fclose(f);
return 0;
}
Read: [file content]
Note: Use "r" mode. Check file existence.
8. Function Pointers
Store function addresses for dynamic calls.
Example: Call function via pointer.
#include
int add(int a, int b) { return a + b; }
int main() {
int (*p)(int, int) = add;
printf("Sum: %d\n", p(2, 3));
return 0;
}
Sum: 5
Note: Match function signature.
9. Arrays of Pointers
Store multiple pointers in an array.
Example: Array of string pointers.
#include
int main() {
char *arr[] = {"Hello", "World"};
printf("%s %s\n", arr[0], arr[1]);
return 0;
}
Hello World
Note: Useful for dynamic data.
10. Linked List
Dynamic structure with linked nodes.
Example: Create and print list.
#include
#include
struct Node { int data; struct Node* next; };
int main() {
struct Node* head = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; head->next = NULL;
printf("%d\n", head->data);
free(head);
return 0;
}
1
Note: Free nodes to avoid leaks.
11. Stack Array
LIFO structure using an array.
Example: Push and pop elements.
#include
#define MAX 3
int stack[MAX], top = -1;
void push(int v) { if (top < MAX-1) stack[++top] = v; }
int main() {
push(1);
printf("Popped: %d\n", stack[top--]);
return 0;
}
Popped: 1
Note: Check for overflow/underflow.
12. Queue Array
FIFO structure using an array.
Example: Enqueue and dequeue.
#include
#define MAX 3
int queue[MAX], front = 0, rear = -1;
void enqueue(int v) { if (rear < MAX-1) queue[++rear] = v; }
int main() {
enqueue(1);
printf("Dequeued: %d\n", queue[front++]);
return 0;
}
Dequeued: 1
Note: Handle full/empty conditions.
13. Struct Pointers
Use pointers to access struct fields.
Example: Modify struct via pointer.
#include
struct Point { int x, y; };
int main() {
struct Point p = {1, 2}, *ptr = &p;
ptr->x = 3;
printf("X: %d\n", p.x);
return 0;
}
X: 3
Note: Use -> for pointer access.
14. Dynamic Strings
Allocate strings dynamically with malloc.
Example: Create dynamic string.
#include
#include
#include
int main() {
char *s = (char*)malloc(10 * sizeof(char));
strcpy(s, "Hello");
printf("%s\n", s);
free(s);
return 0;
}
Hello
Note: Include
15. Command Line Args
Access program arguments via main.
Example: Print arguments.
#include
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("Arg %d: %s\n", i, argv[i]);
}
return 0;
}
Arg 0: program
Arg 1: test
Note: argv[0] is program name.
16. Error Handling
Check for errors in file operations.
Example: Handle file open error.
#include
int main() {
FILE *f = fopen("no.txt", "r");
if (!f) printf("File not found\n");
else fclose(f);
return 0;
}
File not found
Note: Check pointers for NULL.
17. Binary Files
Read/write raw data to files.
Example: Write/read integer.
#include
int main() {
int x = 42;
FILE *f = fopen("data.bin", "wb");
fwrite(&x, sizeof(int), 1, f);
fclose(f);
f = fopen("data.bin", "rb");
fread(&x, sizeof(int), 1, f);
printf("Value: %d\n", x);
fclose(f);
return 0;
}
Value: 42
Note: Use "wb"/"rb" modes.
18. Enum Types
Define named integer constants.
Example: Use enums for states.
#include
enum State { OFF, ON };
int main() {
enum State s = ON;
printf("State: %d\n", s);
return 0;
}
State: 1
Note: Enums improve code readability.
19. Union Types
Store different types in same memory.
Example: Use union for int/char.
#include
union Data { int i; char c; };
int main() {
union Data d;
d.i = 65;
printf("Char: %c\n", d.c);
return 0;
}
Char: A
Note: Shares memory; use one field at a time.
20. Recursion
Functions that call themselves.
Example: Calculate factorial.
#include
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
int main() {
printf("Factorial 5: %d\n", factorial(5));
return 0;
}
Factorial 5: 120
Note: Ensure base case to avoid stack overflow.
21. String Tokenizing
Split strings into tokens.
Example: Tokenize a string.
#include
#include
int main() {
char str[] = "A,B";
char *token = strtok(str, ",");
printf("Token: %s\n", token);
return 0;
}
Token: A
Note: strtok modifies input string.
22. Dynamic 2D Array
Allocate 2D arrays dynamically.
Example: Create 2x2 array.
#include
#include
int main() {
int **arr = (int**)malloc(2 * sizeof(int*));
for (int i = 0; i < 2; i++) arr[i] = (int*)malloc(2 * sizeof(int));
arr[0][0] = 1;
printf("%d\n", arr[0][0]);
for (int i = 0; i < 2; i++) free(arr[i]);
free(arr);
return 0;
}
1
Note: Free each row and array.
23. Void Pointers
Generic pointers for any data type.
Example: Use void pointer.
#include
int main() {
int x = 10;
void *p = &x;
printf("Value: %d\n", *(int*)p);
return 0;
}
Value: 10
Note: Cast before dereferencing.
24. Const Qualifiers
Prevent modification of variables.
Example: Use const pointer.
#include
int main() {
const int x = 10;
const int *p = &x;
printf("Value: %d\n", *p);
return 0;
}
Value: 10
Note: Const ensures read-only access.
25. Static Variables
Retain value between function calls.
Example: Count function calls.
#include
void count() {
static int c = 0;
printf("Count: %d\n", ++c);
}
int main() {
count(); count();
return 0;
}
Count: 1
Count: 2
Note: Static retains value across calls.
26. Preprocessor Macros
Define constants or simple functions.
Example: Use macro for square.
#include
#define SQUARE(x) ((x) * (x))
int main() {
printf("Square: %d\n", SQUARE(5));
return 0;
}
Square: 25
Note: Parentheses prevent operator issues.
27. Bitwise Operators
Manipulate bits for efficient operations.
Example: Set a bit.
#include
int main() {
int x = 0;
x |= (1 << 2);
printf("Value: %d\n", x);
return 0;
}
Value: 4
Note: Use <<, |, & for bit operations.
28. File Positioning
Move file pointer for specific access.
Example: Seek and read.
#include
int main() {
FILE *f = fopen("input.txt", "r");
fseek(f, 2, SEEK_SET);
char c = fgetc(f);
printf("Char: %c\n", c);
fclose(f);
return 0;
}
Char: [third char]
Note: Use SEEK_SET, SEEK_CUR, SEEK_END.
29. Array Sorting
Sort arrays using standard library.
Example: Sort integers.
#include
#include
int cmp(const void *a, const void *b) { return (*(int*)a - *(int*)b); }
int main() {
int arr[] = {3, 1, 2};
qsort(arr, 3, sizeof(int), cmp);
printf("%d %d %d\n", arr[0], arr[1], arr[2]);
return 0;
}
1 2 3
Note: Define comparison function.
30. Linked List Insert
Insert nodes into linked list.
Example: Insert at head.
#include
#include
struct Node { int data; struct Node* next; };
int main() {
struct Node* head = (struct Node*)malloc(sizeof(struct Node));
head->data = 2; head->next = NULL;
struct Node* new = (struct Node*)malloc(sizeof(struct Node));
new->data = 1; new->next = head;
printf("%d\n", new->data);
free(new); free(head);
return 0;
}
1
Note: Update pointers carefully.
31. Struct Arrays
Store multiple structs in an array.
Example: Array of structs.
#include
struct Point { int x, y; };
int main() {
struct Point arr[2] = {{1, 2}, {3, 4}};
printf("Point 0: (%d, %d)\n", arr[0].x, arr[0].y);
return 0;
}
Point 0: (1, 2)
Note: Access with index and dot.
32. String Formatting
Format strings with sprintf.
Example: Create formatted string.
#include
int main() {
char buffer[20];
int x = 42;
sprintf(buffer, "Value: %d", x);
printf("%s\n", buffer);
return 0;
}
Value: 42
Note: Ensure buffer size is sufficient.
33. Pass by Reference
Modify variables using pointers.
Example: Swap two numbers.
#include
void swap(int *a, int *b) {
int temp = *a; *a = *b; *b = temp;
}
int main() {
int x = 1, y = 2;
swap(&x, &y);
printf("%d %d\n", x, y);
return 0;
}
2 1
Note: Use pointers for modification.
34. Dynamic Memory Free
Properly free allocated memory.
Example: Allocate and free.
#include
#include
int main() {
int *p = (int*)malloc(sizeof(int));
*p = 10;
printf("Value: %d\n", *p);
free(p);
return 0;
}
Value: 10
Note: Avoid dangling pointers.
35. Simple Stack
Implement stack with dynamic memory.
Example: Push to stack.
#include
#include
struct Stack { int *data; int top; };
int main() {
struct Stack s = {(int*)malloc(2 * sizeof(int)), -1};
s.data[++s.top] = 1;
printf("Top: %d\n", s.data[s.top]);
free(s.data);
return 0;
}
Top: 1
Note: Manage stack size dynamically.
36. Simple Queue
Implement queue with dynamic memory.
Example: Enqueue and dequeue.
#include
#include
struct Queue { int *data; int front, rear; };
int main() {
struct Queue q = {(int*)malloc(2 * sizeof(int)), 0, -1};
q.data[++q.rear] = 1;
printf("Dequeued: %d\n", q.data[q.front++]);
free(q.data);
return 0;
}
Dequeued: 1
Note: Track front and rear indices.
37. Nested Structures
Structures containing other structures.
Example: Nested struct access.
#include
struct Point { int x, y; };
struct Rect { struct Point topLeft; int width; };
int main() {
struct Rect r = {{1, 2}, 10};
printf("X: %d\n", r.topLeft.x);
return 0;
}
X: 1
Note: Use dot for nested access.
38. Array of Functions
Store function pointers in array.
Example: Call functions dynamically.
#include
int add(int a) { return a + 1; }
int main() {
int (*funcs[1])(int) = {add};
printf("Result: %d\n", funcs[0](5));
return 0;
}
Result: 6
Note: Match function signatures.
39. File Append
Add data to existing file.
Example: Append text.
#include
int main() {
FILE *f = fopen("output.txt", "a");
fprintf(f, "More text\n");
fclose(f);
printf("Appended\n");
return 0;
}
Appended
Note: Use "a" mode for append.
40. Basic Binary Tree
Tree with left and right nodes.
Example: Create simple tree.
#include
#include
struct Node { int data; struct Node *left, *right; };
int main() {
struct Node* root = (struct Node*)malloc(sizeof(struct Node));
root->data = 1; root->left = root->right = NULL;
printf("Root: %d\n", root->data);
free(root);
return 0;
}
Root: 1
Note: Free nodes to avoid leaks.