This chapter introduces advanced control structures and data types in C programming, including switch statements, pointers, structures, and variable scope rules.
Learn how to use switch statements for efficient multi-way conditional branching, often preferred over multiple if-else statements.
From the vending machine example, it can be analyzed that:
#include <stdio.h>
int main() {
int choice;
printf("Please select an item:\n");
printf(" 1. Coke\n");
printf(" 2. Sprite\n");
printf(" 3. Orange Juice\n");
printf(" 4. Water\n");
printf("Enter your choice (1-4): ");
scanf("%d", &choice);
// Execute different actions based on the user's choice
switch (choice) {
case 1:
printf("A can of Coke is dispensed.\n");
break;
case 2:
printf("A can of Sprite is dispensed.\n");
break;
case 3:
printf("A bottle of Orange Juice is dispensed.\n");
break;
case 4:
printf("A bottle of Water is dispensed.\n");
break;
default:
printf("Invalid selection! Please choose 1-4.\n");
break;
}
return 0;
}
The switch statement evaluates an expression and matches it to case labels.
switch (expression) {
case constant1:
// statements to execute if expression equals constant1
break;
case constant2:
// statements to execute if expression equals constant2
break;
// more cases...
default:
// statements to execute if expression doesn't match any case
break;
}
By default, once a matching case is found, all subsequent cases are executed until a break statement or the end of the switch block.
switch (grade) {
case 'A':
printf("Excellent! ");
case 'B':
printf("Good! ");
case 'C':
printf("Average. ");
case 'D':
printf("Below average. ");
case 'F':
printf("Failed.\n");
}
If grade is 'B', the output would be: "Good! Average. Below average. Failed."
switch (grade) {
case 'A':
printf("Excellent!\n");
break;
case 'B':
printf("Good!\n");
break;
case 'C':
printf("Average.\n");
break;
case 'D':
printf("Below average.\n");
break;
case 'F':
printf("Failed.\n");
break;
default:
printf("Invalid grade.\n");
break;
}
Learn how to work with pointers - variables that store memory addresses rather than values.
From the pointer example, it can be analyzed that:
#include <stdio.h>
int main() {
// Declare a regular integer variable
int my_number = 42;
// Declare a pointer variable that can store the address of an integer
int *ptr_to_number;
// Assign the memory address of 'my_number' to 'ptr_to_number'
ptr_to_number = &my_number;
printf("Value of my_number: %d\n", my_number);
printf("Address of my_number: %p\n", &my_number);
printf("Value stored in ptr_to_number: %p\n", ptr_to_number);
printf("Value pointed to by ptr_to_number: %d\n", *ptr_to_number);
// Change the value through the pointer
*ptr_to_number = 100;
printf("After changing through pointer, my_number is: %d\n", my_number);
return 0;
}
Pointers are special variables that store memory addresses.
// Syntax: data_type *pointer_name;
int *ptr; // declares a pointer to an integer
float *fptr; // declares a pointer to a float
char *cptr; // declares a pointer to a character
int value = 10;
int *ptr;
ptr = &value; // Assign address of 'value' to 'ptr'
// Now ptr contains the address of 'value'
int value = 10;
int *ptr = &value;
printf("%d", *ptr); // Outputs the value at ptr's address (10)
*ptr = 20; // Changes the value at ptr's address
printf("%d", value); // Outputs 20 (value was changed)
#include <stdio.h>
int main() {
int numbers[5] = {10, 20, 30, 40, 50};
int *ptr = numbers; // Points to the first element of the array
printf("Using array notation: %d\n", numbers[0]);
printf("Using pointer: %d\n", *ptr); // Same as numbers[0]
// Moving the pointer to the next element
ptr++; // Now points to numbers[1]
printf("Second element: %d\n", *ptr); // Same as numbers[1]
// Accessing array elements using pointer arithmetic
for(int i = 0; i < 5; i++) {
printf("Element %d: %d\n", i, *(numbers + i));
}
return 0;
}
Learn how to pass variables to functions by reference using pointers, allowing functions to modify the original variables.
Comparison between pass-by-value and pass-by-pointer:
#include <stdio.h>
// Function to swap two integers using pointers (pass-by-pointer)
void swap(int *ptr_a, int *ptr_b) {
int temp = *ptr_a; // Store value at address pointed to by ptr_a
*ptr_a = *ptr_b; // Copy value at address pointed to by ptr_b to address pointed to by ptr_a
*ptr_b = temp; // Copy temp value to address pointed to by ptr_b
}
int main() {
int x = 10, y = 20;
printf("Before swap: x = %d, y = %d\n", x, y);
swap(&x, &y); // Pass addresses of x and y
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
}
#include <stdio.h>
void increment_fail(int a) {
a = a + 1; // Only modifies the copy, not the original
}
int main() {
int num = 5;
printf("Before: %d\n", num); // Output: 5
increment_fail(num);
printf("After: %d\n", num); // Output: 5 (unchanged!)
return 0;
}
#include <stdio.h>
void increment_success(int *ptr) {
*ptr = *ptr + 1; // Modifies the value at the pointer's address
}
int main() {
int num = 5;
printf("Before: %d\n", num); // Output: 5
increment_success(&num); // Pass address of num
printf("After: %d\n", num); // Output: 6 (changed!)
return 0;
}
Learn how to define and use structures to group different data types together into a single entity.
Structures allow us to create custom data types:
#include <stdio.h>
#include <string.h> // For strcpy
// Define a structure for a student
struct Student {
char name[50];
int id;
float gpa;
};
int main() {
// Declare a variable of type struct Student
struct Student student1;
// Assign values to the struct members
strcpy(student1.name, "Alice Johnson");
student1.id = 12345;
student1.gpa = 3.85;
// Access and print struct members
printf("Name: %s\n", student1.name);
printf("ID: %d\n", student1.id);
printf("GPA: %.2f\n", student1.gpa);
return 0;
}
Structures (structs) allow grouping of related variables of different types under a single name.
struct structure_name {
data_type member1;
data_type member2;
// ... more members
};
struct Student {
char name[50];
int id;
float gpa;
};
struct Student s1, s2; // Declare two Student variables
struct Student s3 = {"Bob", 67890, 3.50}; // Initialize with values
strcpy(s1.name, "John"); // Assign to name member
s1.id = 11111; // Assign to id member
s1.gpa = 3.90; // Assign to gpa member
printf("Name: %s", s1.name); // Access member
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int id;
float gpa;
};
int main() {
// Array of structures
struct Student class[3] = {
{"Alice", 101, 3.85},
{"Bob", 102, 3.20},
{"Charlie", 103, 3.95}
};
// Print all students
for(int i = 0; i < 3; i++) {
printf("Student %d: %s (ID: %d, GPA: %.2f)\n",
i+1, class[i].name, class[i].id, class[i].gpa);
}
return 0;
}
struct Address {
char street[100];
char city[50];
int zip;
};
struct Student {
char name[50];
struct Address addr; // Nested structure
};
Learn how to use pointers to access structure members efficiently, especially when passing structures to functions.
Two ways to access struct members via pointers:
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int id;
float gpa;
};
// Function that takes a pointer to a struct
void printStudent(struct Student *s) {
printf("Name: %s\n", s->name); // Arrow operator
printf("ID: %d\n", s->id);
printf("GPA: %.2f\n", s->gpa);
}
int main() {
struct Student student1 = {"Alice", 12345, 3.85};
struct Student *ptr = &student1;
// Access members using arrow operator
printf("Using arrow operator:\n");
printf("Name: %s\n", ptr->name);
printf("ID: %d\n", ptr->id);
printf("GPA: %.2f\n", ptr->gpa);
// Pass pointer to function
printf("\nIn function:\n");
printStudent(ptr);
return 0;
}
#include <stdio.h>
#include <string.h>
struct Monster {
char name[50];
int hp;
int attack;
};
// Function to perform attack using pointers
void performAttack(struct Monster *attacker, struct Monster *target) {
printf("%s attacks %s!\n", attacker->name, target->name);
target->hp -= attacker->attack;
if (target->hp < 0) target->hp = 0;
printf("%s takes %d damage. Remaining HP: %d\n",
target->name, attacker->attack, target->hp);
if (target->hp == 0) {
printf("%s has been defeated!\n", target->name);
}
}
int main() {
struct Monster T1000 = {"Violent T1000", 80, 15};
struct Monster T800 = {"T800 the Arnold", 100, 10};
printf("Battle Start!\n");
printf("T1000: HP=%d, Attack=%d\n", T1000.hp, T1000.attack);
printf("T800: HP=%d, Attack=%d\n", T800.hp, T800.attack);
// Battle rounds
performAttack(&T1000, &T800); // T1000 attacks T800
performAttack(&T800, &T1000); // T800 attacks T1000
return 0;
}
Understand the scope and lifetime of variables in C, including local, global, and static variables.
Three types of variable scope:
#include <stdio.h>
// Global variable - accessible everywhere
int global_var = 10;
void demo_function(int param) {
// Local variable - only accessible in this function
int local_var = 20;
printf("Inside function:\n");
printf(" global_var = %d\n", global_var);
printf(" param = %d\n", param);
printf(" local_var = %d\n", local_var);
// Modifying global variable affects it everywhere
global_var = 88;
}
int main() {
int arg = 5;
printf("Before function call:\n");
printf(" global_var = %d\n", global_var);
printf(" arg = %d\n", arg);
demo_function(arg);
printf("\nAfter function call:\n");
printf(" global_var = %d\n", global_var); // Changed by function
printf(" arg = %d\n", arg); // Unchanged (pass-by-value)
return 0;
}
Static variables retain their value between function calls:
#include <stdio.h>
// Function with a local variable
void counter_local() {
int count = 0; // This is reinitialized each time
count++;
printf("Local count: %d\n", count);
}
// Function with a static variable
void counter_static() {
static int count = 0; // Initialized only once
count++;
printf("Static count: %d\n", count);
}
int main() {
printf("Calling counter_local three times:\n");
for(int i = 0; i < 3; i++) {
counter_local();
}
printf("\nCalling counter_static three times:\n");
for(int i = 0; i < 3; i++) {
counter_static();
}
return 0;
}
Output would be:
Calling counter_local three times:
Local count: 1
Local count: 1
Local count: 1
Calling counter_static three times:
Static count: 1
Static count: 2
Static count: 3
Analysis: The calculator should take an operator as input and perform the corresponding operation on two numbers.
#include <stdio.h>
int main() {
char operator;
double num1, num2, result;
printf("Enter operator (+, -, *, /): ");
scanf(" %c", &operator);
printf("Enter two numbers: ");
scanf("%lf %lf", &num1, &num2);
switch(operator) {
case '+':
result = num1 + num2;
printf("%.2lf + %.2lf = %.2lf\n", num1, num2, result);
break;
case '-':
result = num1 - num2;
printf("%.2lf - %.2lf = %.2lf\n", num1, num2, result);
break;
case '*':
result = num1 * num2;
printf("%.2lf * %.2lf = %.2lf\n", num1, num2, result);
break;
case '/':
if(num2 != 0) {
result = num1 / num2;
printf("%.2lf / %.2lf = %.2lf\n", num1, num2, result);
} else {
printf("Error: Division by zero!\n");
}
break;
default:
printf("Error: Invalid operator!\n");
break;
}
return 0;
Analysis: Define a book structure and implement a function that accesses the structure through a pointer.
#include <stdio.h>
#include <string.h>
struct Book {
char title[100];
char author[50];
int year;
};
void printBook(struct Book *b) {
printf("Title: %s\n", b->title);
printf("Author: %s\n", b->author);
printf("Year Published: %d\n", b->year);
}
int main() {
struct Book book1 = {
"The C Programming Language",
"Brian Kernighan and Dennis Ritchie",
1978
};
printf("Book Details:\n");
printBook(&book1);
return 0;
Analysis: Create a swap function that takes pointers to two integers and exchanges their values.
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
printf("Before swap: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
This demonstrates the difference between pass-by-value and pass-by-pointer. The original variables x and y are modified because we're passing pointers to their memory addresses, rather than copies of their values.