Introduction to
Programming
Build your programming foundation: understand how computers think, write your first C program, and learn to solve problems like a software engineer.
Every app on your phone, every website you visit, every ATM you use — all powered by programming. When you learn C, you're learning the language that built UNIX, Linux, and most operating systems. You're learning how computers actually work at the metal level.
C is the grandfather of Python, Java, JavaScript, and C++. Master C, and everything else becomes easier.
Think of a computer like a human body: The brain = CPU, Memory = short-term memory (RAM), Disk = long-term memory, Keyboard = eyes/ears (input), Monitor = mouth (output).
Memory Hierarchy (Fastest → Slowest):
int a = 5;, variable 'a' lives in RAM. The CPU fetches it, does math in registers, stores result back in RAM.Write Source Code (.c file)
Your C program written in editorPreprocessor
Handles#include, #define — expands macrosCompiler (gcc)
Translates C code to assembly/machine codeLinker
Connects standard library functions, creates .exeExecute
CPU runs the machine code, program output appearsA variable is a named box in memory that stores a value. A data type tells the compiler: how many bytes to reserve and what kind of data goes in.
| Data Type | Size | Range | Format |
|---|---|---|---|
| int | 4 bytes | -2,147,483,648 to 2,147,483,647 | %d |
| float | 4 bytes | ±3.4 × 10⁻³⁸ to 10³⁸ | %f |
| double | 8 bytes | ±1.7 × 10⁻³⁰⁸ to 10³⁰⁸ | %lf |
| char | 1 byte | -128 to 127 (ASCII) | %c |
| long | 8 bytes | ±9.2 × 10¹⁸ | %ld |
#include<stdio.h> int main() { /* Variable Declarations */ int age = 20; float gpa = 8.75; char grade = 'A'; double salary = 75000.50; /* Constant — value CANNOT change */ const float PI = 3.14159; printf("Age: %d\n", age); printf("GPA: %.2f\n", gpa); printf("Grade: %c\n", grade); return 0; }
- Line 1#include <stdio.h> — includes Standard I/O library (printf, scanf live here)
- Line 4-7Variable declarations — tells compiler to reserve memory.
int age = 20reserves 4 bytes at some address and puts 20 in it. - Line 10const — PI can never be changed after declaration. Trying to do
PI = 3gives a compile error. - %.2fFormat specifier — prints float with exactly 2 decimal places
a = 5; int a; → Compile error! Always declare first.| Category | Operators | Example | Result |
|---|---|---|---|
| Arithmetic | + - * / % | 10 % 3 | 1 (remainder) |
| Relational | == != > < >= <= | 5 > 3 | 1 (true) |
| Logical | && || ! | 1 && 0 | 0 (false) |
| Bitwise | & | ^ ~ << >> | 5 << 1 | 10 (shift left) |
| Assignment | = += -= *= /= | a += 5 | a = a + 5 |
| Increment | ++ -- | a++ or ++a | adds 1 |
| Ternary | ? : | a > b ? a : b | max of a, b |
Type Conversion: C automatically converts smaller types to larger (implicit). You can force it with casting (explicit).
int a = 7, b = 2; /* Implicit: int ÷ int = int → TRUNCATES decimal */ printf("%d\n", a / b); // Output: 3 (NOT 3.5) /* Explicit Cast: force float division */ printf("%f\n", (float)a / b); // Output: 3.500000
int/int = int always! Beginner expects 3.5, gets 3. Always cast to float when you need decimal results.Algorithm = step-by-step instructions to solve a problem. Like a recipe. Write the algorithm BEFORE you code. Think first, code second!
Problem: Find largest of two numbers
START
Read inputs A and B
Check condition: if A > B
Go to step 4 if true, else step 5Print "A is largest"
Go to step 6Print "B is largest"
STOP
BEGIN
READ A, B
IF A > B THEN
PRINT "A is largest"
ELSE
PRINT "B is largest"
END IF
END
Time Complexity = how long an algorithm takes as input grows. Space Complexity = how much memory it uses. We use Big O Notation to express these.
| Notation | Name | Example | Speed |
|---|---|---|---|
| O(1) | Constant | Access array[0] | ⚡ Fastest |
| O(log n) | Logarithmic | Binary Search | 🚀 Very Fast |
| O(n) | Linear | Linear Search | Good |
| O(n²) | Quadratic | Bubble Sort (nested loop) | ⚠️ Slow |
| O(2ⁿ) | Exponential | Brute Force subsets | Very Slow |
#include <stdio.h> /* Step 1: Import I/O library */ int main() /* Step 2: Program starts here */ { int num; /* Step 3: Declare variable */ printf("Enter a number: "); /* Output */ scanf("%d", &num); /* Input (& = address of num) */ printf("You entered: %d\n", num); return 0; /* Step 4: Exit program */ }
- #includePreprocessor directive — pastes stdio.h content before compilation. Gives access to printf and scanf.
- int main()Every C program starts executing from main(). Returns int (0 = success, non-zero = error).
- printf()Prints text to screen. \n = newline character (go to next line).
- scanf()Reads user input. &num = address of num (where to store the value in memory).
- return 0Signals to OS that program ran successfully. 0 = no errors.
scanf("%d", num) instead of scanf("%d", &num) → CRASH! The & gives scanf the memory address to write into.int in C on a 32-bit system?& operator do in scanf("%d", &a)?printf("%d", 10/3);?Control
Structures
Master the logic that controls program flow — conditions, decisions, and loops. This unit is the core of ALL programming logic.
Decision making in code! Like traffic signals — if red, stop; else, go. The CPU evaluates a condition: if TRUE (non-zero), execute block. If FALSE (zero), skip it.
#include <stdio.h> int main() { int marks; printf("Enter marks (0-100): "); scanf("%d", &marks); if (marks >= 90) printf("Grade: O (Outstanding)\n"); else if (marks >= 75) printf("Grade: A+ (Excellent)\n"); else if (marks >= 60) printf("Grade: A (Very Good)\n"); else if (marks >= 50) printf("Grade: B (Good)\n"); else printf("Grade: F (Fail)\n"); return 0; }
🧠 Dry Run:
| marks | Condition Checked | Result | Output |
|---|---|---|---|
| 95 | marks >= 90 | TRUE | Grade: O |
| 78 | marks >= 90 → FALSE marks >= 75 → TRUE | 2nd condition true | Grade: A+ |
| 45 | All conditions FALSE | else executes | Grade: F |
if(a = 5) is assignment (always true!). if(a == 5) is comparison. This is the most common beginner bug!switch is a cleaner alternative to long if-else ladders. It matches a value to cases and executes. Perfect for menus, day names, grade display, etc. Works with int and char only — NOT float!
#include <stdio.h> int main() { int a, b, choice; char op; printf("Enter: a op b (e.g. 5 + 3): "); scanf("%d %c %d", &a, &op, &b); switch(op) { case '+': printf("Result = %d\n", a+b); break; case '-': printf("Result = %d\n", a-b); break; case '*': printf("Result = %d\n", a*b); break; case '/': if(b != 0) printf("Result = %d\n", a/b); else printf("Error: Divide by zero!\n"); break; default: printf("Invalid operator!\n"); } return 0; }
break, execution falls through to next case. This is called "fall-through" — often a bug unless intentional.for loop — use when you know exactly how many times to repeat. Has 3 parts: init, condition, update — all in one line.
/* Print 1 to 10 */ for (int i = 1; i <= 10; i++) { printf("%d ", i); } /* Output: 1 2 3 4 5 6 7 8 9 10 */ /* Sum of first n numbers */ int n=5, sum=0; for (int i=1; i<=n; i++) { sum += i; // sum = sum + i } printf("Sum = %d", sum); // Sum = 15
| i | Condition i≤5 | sum = sum+i | sum |
|---|---|---|---|
| 1 | TRUE | 0+1 | 1 |
| 2 | TRUE | 1+2 | 3 |
| 3 | TRUE | 3+3 | 6 |
| 4 | TRUE | 6+4 | 10 |
| 5 | TRUE | 10+5 | 15 |
| 6 | FALSE | Loop ends | 15 |
while loop — use when you DON'T know how many times. Checks condition BEFORE each iteration. If condition is false initially, loop body never executes.
/* Reverse digits of a number */ int n = 1234, rev = 0; while (n != 0) { int digit = n % 10; // get last digit rev = rev * 10 + digit; n = n / 10; // remove last digit } printf("Reversed: %d\n", rev); // 4321
| n | digit (n%10) | rev = rev*10+digit | n = n/10 |
|---|---|---|---|
| 1234 | 4 | 0*10+4 = 4 | 123 |
| 123 | 3 | 4*10+3 = 43 | 12 |
| 12 | 2 | 43*10+2 = 432 | 1 |
| 1 | 1 | 432*10+1 = 4321 | 0 |
| 0 | Loop ends → rev = 4321 | ||
do-while — loop body executes AT LEAST ONCE, THEN checks condition. Use for menus where user must see at least one option.
int choice; do { printf("1. Add 2. Sub 3. Exit\n"); printf("Enter choice: "); scanf("%d", &choice); // process choice... } while (choice != 3); // repeat until Exit
/* break — exits loop immediately */ for (int i=1; i<=10; i++) { if (i == 5) break; // stops at 5 printf("%d ", i); } // Output: 1 2 3 4 /* continue — skips current iteration */ for (int i=1; i<=10; i++) { if (i % 2 == 0) continue; // skip even printf("%d ", i); } // Output: 1 3 5 7 9
#include <stdio.h> int main() { int n, fact = 1; scanf("%d", &n); for (int i=1; i<=n; i++) fact *= i; // fact = fact * i printf("%d! = %d\n", n, fact); return 0; }
| i | fact = fact×i | fact |
|---|---|---|
| 1 | 1×1 | 1 |
| 2 | 1×2 | 2 |
| 3 | 2×3 | 6 |
| 4 | 6×4 | 24 |
| 5 | 24×5 | 120 |
#include <stdio.h> int main() { int n, isPrime=1; scanf("%d", &n); if (n < 2) isPrime = 0; for (int i=2; i*i<=n; i++) { if (n % i == 0) { isPrime = 0; break; } } if (isPrime) printf("%d is Prime\n", n); else printf("%d is Not Prime\n", n); return 0; }
/* Right Triangle Star Pattern */ #include <stdio.h> int main() { int n = 5; for (int i=1; i<=n; i++) { for (int j=1; j<=i; j++) printf("* "); printf("\n"); } } /* * * * * * * * * * * * * * * * */
#include <stdio.h> int main() { int n, a=0, b=1, c; scanf("%d", &n); printf("%d %d ", a, b); for (int i=2; i<n; i++) { c = a + b; printf("%d ", c); a = b; b = c; } return 0; } /* n=8: 0 1 1 2 3 5 8 13 */
Arrays &
Strings
Store multiple values, search, sort, and manipulate text. Arrays and strings are the building blocks of data handling in C.
Array = collection of same-type elements stored in contiguous (adjacent) memory. Instead of declaring 100 int variables, declare one array of 100 ints.
Key Rule: Array indexing starts from 0, NOT 1! An array of size n has indices 0 to n-1.
#include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; int n = 5, sum = 0; /* Traverse array */ for (int i=0; i<n; i++) { printf("arr[%d] = %d\n", i, arr[i]); sum += arr[i]; } printf("Sum = %d\n", sum); printf("Average = %.2f\n", (float)sum/n); return 0; }
#include <stdio.h> int main() { int arr[] = {15,30,5,72,18}; int n=5, key=72, found=-1; for (int i=0; i<n; i++) { if (arr[i] == key) { found = i; break; } } if (found != -1) printf("Found at index %d\n", found); else printf("Not found\n"); return 0; }
Time Complexity: O(n) worst case. Checks each element one by one.
#include <stdio.h> int main() { int arr[] = {64,34,25,12,22}; int n=5, temp; for (int i=0; i<n-1; i++) { for (int j=0; j<n-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; // swap arr[j] = arr[j+1]; arr[j+1] = temp; } } } /* Sorted: 12 22 25 34 64 */ return 0; }
2D array = matrix = array of arrays. Think of it as rows and columns. int mat[3][3] = 3 rows, 3 columns.
#include <stdio.h> int main() { int a[2][2]={{1,2},{3,4}}; int b[2][2]={{5,6},{7,8}}; int c[2][2]; /* Matrix Addition */ for (int i=0; i<2; i++) { for (int j=0; j<2; j++) { c[i][j] = a[i][j] + b[i][j]; printf("%d ", c[i][j]); } printf("\n"); } return 0; } /* Output: 6 8 10 12 */
String in C = char array ending with null character '\0'. C has no built-in String type — it's just an array of characters.
#include <stdio.h> #include <string.h> /* For string functions */ int main() { char name[50]; printf("Enter name: "); gets(name); /* Read string with spaces */ printf("Hello, %s!\n", name); printf("Length: %d\n", strlen(name)); /* String functions */ char s1[20]="Hello", s2[20]="World", s3[50]; strcat(s1, s2); /* Concatenate: "HelloWorld" */ strcpy(s3, s1); /* Copy s1 to s3 */ strcmp(s1, s2); /* 0 if equal */ strupr(s1); /* Convert to uppercase */ strlwr(s1); /* Convert to lowercase */ return 0; }
| Function | Header | What it does | Returns |
|---|---|---|---|
| strlen(s) | <string.h> | Length of string | int (count) |
| strcpy(d,s) | <string.h> | Copy s into d | dest string |
| strcat(d,s) | <string.h> | Append s to d | dest string |
| strcmp(s1,s2) | <string.h> | Compare strings | 0 if equal |
| strupr(s) | <string.h> | UPPERCASE conversion | modified string |
| strlwr(s) | <string.h> | lowercase conversion | modified string |
Pointers &
User-Defined Types
Master the most powerful — and feared — concept in C. Pointers let you talk directly to memory. Structures let you create your own data types.
Pointer = a variable that stores a memory ADDRESS instead of a regular value. Instead of storing 42, it stores where 42 lives in memory.
Real-world analogy: A pointer is like a Google Maps pin — it doesn't contain the restaurant, it contains its LOCATION.
#include <stdio.h> int main() { int a = 42; // Normal variable int *p; // Pointer variable (stores address) p = &a; // p = address of a printf("Value of a = %d\n", a); // 42 printf("Address of a = %p\n", &a); // 0x1004 (some hex) printf("p holds = %p\n", p); // 0x1004 (same!) printf("Value via p = %d\n", *p); // 42 (dereference) *p = 100; // Change a's value THROUGH pointer printf("a is now = %d\n", a); // 100! return 0; }
- int *pDeclares pointer — p can hold address of any int. The * means "this is a pointer"
- p = &a& = address-of operator — gets the memory address where a lives
- *pDereferencing — "go to the address in p, and give me the value there". * in this context = "value at"
- *p = 100Modifying via pointer — changes a's value without using a directly!
Pointer Arithmetic — when you do p++, pointer moves by the SIZE of the data type (4 bytes for int).
int arr[] = {10, 20, 30}; int *p = arr; // p points to arr[0] printf("%d\n", *p); // 10 (arr[0]) p++; // move to next int (4 bytes ahead) printf("%d\n", *p); // 20 (arr[1]) p++; printf("%d\n", *p); // 30 (arr[2])
int *p = NULL; means "points to nothing". Using an uninitialized pointer causes undefined behavior or crash.struct = custom data type that groups different data types together. Instead of separate name, age, gpa variables for each student, bundle them in one structure.
#include <stdio.h> /* Define structure */ struct Student { int rollno; char name[50]; float gpa; }; int main() { /* Create structure variable */ struct Student s1 = {101, "Ravi Kumar", 8.75}; /* Access using dot operator */ printf("Roll: %d\n", s1.rollno); printf("Name: %s\n", s1.name); printf("GPA: %.2f\n", s1.gpa); /* Array of structures */ struct Student class[60]; // 60 students! return 0; }
Union = like struct, but ALL members share the SAME memory location. Size = size of largest member. Only ONE member can hold a valid value at a time.
union Data { int i; // 4 bytes float f; // 4 bytes char str[20]; // 20 bytes — union size = 20 }; /* All share the same memory! */
Functions &
File Handling
Break programs into reusable blocks. Store and retrieve data from files. These are the hallmarks of professional C programming.
Function = reusable block of code that does a specific task. Write once, call many times. Like a machine in a factory — give it input, it produces output.
Functions prevent code repetition (DRY = Don't Repeat Yourself).
#include <stdio.h> /* ── Step 1: Function Declaration (Prototype) ── */ int add(int a, int b); int factorial(int n); /* ── Step 2: main() ── */ int main() { int result = add(5, 3); // Function Call printf("5+3 = %d\n", result); printf("5! = %d\n", factorial(5)); return 0; } /* ── Step 3: Function Definitions ── */ int add(int a, int b) { // a,b are parameters return a + b; } int factorial(int n) { if (n == 0 || n == 1) return 1; // base case return n * factorial(n-1); // recursive call }
- PrototypeFunction declaration — tells compiler: function name, return type, parameter types. Must come BEFORE main().
- add(5,3)Function call — 5,3 are ARGUMENTS. Values are passed to parameters a and b.
- return a+bReturn value — sends computed result back to caller. return type must match declaration.
- RecursionFunction calling itself — needs a base case to stop. factorial(5) calls factorial(4) calls... factorial(1) which returns 1.
void counter() { static int count = 0; // initialized ONCE count++; printf("Count = %d\n", count); } int main() { counter(); // Count = 1 counter(); // Count = 2 counter(); // Count = 3 }
File handling = permanent data storage. Unlike variables (lost when program ends), files persist on disk. Used in real software: logs, databases, config files.
Open File — fopen()
Creates/opens a file. Returns FILE pointer. Check for NULL (file open failure).Read/Write — fprintf(), fscanf(), fgets()
Write to or read from the file.Close File — fclose()
ALWAYS close after use! Saves buffer, frees resources.#include <stdio.h> int main() { FILE *fp; /* ── WRITE to file ── */ fp = fopen("student.txt", "w"); // "w" = write mode if (fp == NULL) { printf("Error opening file!\n"); return 1; } fprintf(fp, "Name: Ravi Kumar\n"); fprintf(fp, "Roll: 101\n"); fclose(fp); // close after writing /* ── READ from file ── */ fp = fopen("student.txt", "r"); // "r" = read mode char line[100]; while (fgets(line, 100, fp) != NULL) { printf("%s", line); } fclose(fp); return 0; }
| Mode | Meaning | If file doesn't exist |
|---|---|---|
| "r" | Read only | Returns NULL (error) |
| "w" | Write (overwrite) | Creates new file |
| "a" | Append (add to end) | Creates new file |
| "r+" | Read + Write | Returns NULL |
| "w+" | Write + Read (overwrite) | Creates new file |
Call by Value — copy of argument passed. Changes in function DON'T affect original.
Call by Reference (using pointers) — address passed. Changes DO affect original.
/* Swap using pointers (call by reference) */ void swap(int *x, int *y) { int temp = *x; *x = *y; *y = temp; } int main() { int a=10, b=20; swap(&a, &b); // pass ADDRESSES printf("a=%d b=%d\n", a, b); // Output: a=20 b=10 } /* Arrays are ALWAYS passed by reference (pointer) */ void printArray(int arr[], int n) { for (int i=0; i<n; i++) printf("%d ", arr[i]); }