Conditional Statements
if-else Constructs
Key points when using if-else:
- Avoid adding semicolons directly after if statements
- Use braces when if or else controls multiple statements
- Nested if: else can combine with another if to form multiple conditions
- Dangling else ambgiuity: else pairs with the nearest preceding if
- An if-else pair counts as a single statement
Relational Operators
- Best practice: place constants on the left side when comparing with variables—this helps catch accidental assignment mistakes early
- Available operators:
>,<,>=,<=,==,!= - The equality operator
==differs from the assignment operator=—confusing them produces bugs - Avoid chaining relational operators; use logical operators like
&&instead
Conditional Operator
The ternary operator format: condition ? expression1 : expression2
Logic: if condition evaluates to true, expression1 executes and becomes the result; otherwise expression2 executes. This provides a compact alternative to simple if-else blocks.
int max = (a > b) ? a : b;
Logical Operators
!: logical NOT—reverses the truth value of an expression&&: logical AND—both operands must be true for the result to be true||: logical OR—at least one operand must be true for the result to be true- Short-circuit evaluation: if the left operand determines the result, the right operand is not evaluated
Example: determining leap years
#include <stdio.h>
int main() {
int year;
scanf("%d", &year);
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
printf("Leap year\n");
return 0;
}
switch Statement
Replaces multiple if-else chains with cleaner syntax:
switch (expression) {
case constant1:
statements;
break;
case constant2:
statements;
break;
default:
statements;
break;
}
Important notes:
- The expression must evaluate to an integer type
- Case labels require integer constant expressions
- Character types work because characters are integral types (ASCII values)
- Case order does not matter
- Omitting break causes execution to fall through to subsequent cases
Loop Constructs
while Loop
Standard while syntax:
while (condition) {
statement1;
statement2;
}
The do-while variant executes at least once:
do {
statement1;
} while (condition);
Execution flow: the condition is evaluated first; if true, the loop body executes, then control returns to re-evaluate the condition.
Example: reverse printing digits of a positive integer
#include <stdio.h>
int main() {
int num;
scanf("%d", &num);
while (num) {
printf("%d ", num % 10);
num /= 10;
}
return 0;
}
for Loop
Syntax structure:
for (initialization; condition; increment) {
statements;
}
- Initialization: sets up loop variables (executes once)
- Condition: checked before each iteration
- Increment: adjusts loop variables after each iteration
Execution flow: initialize once, then repeatedly check condition, execute body, and increment.
Example: printing numbers 1 through 10
#include <stdio.h>
int main() {
for (int i = 1; i <= 10; i++)
printf("%d ", i);
return 0;
}
Comparison: a while loop and for loop with equivalent behavior
// while version
init;
while (condition) {
body;
increment;
}
// equivalent for version
for (init; condition; increment) {
body;
}
break and continue
breakterminates the enclosing loop entirelycontinueskips remaining statements in current iteration and proceeds to the next one
Nested Loops
Loops can contain other loops. This is essential for problems requiring multi-dimensional iteration.
Example: finding prime numbers between 100 and 200
#include <stdio.h>
#include <math.h>
int main() {
for (int n = 100; n <= 200; n++) {
int isPrime = 1;
for (int d = 2; d <= sqrt(n); d++) {
if (n % d == 0) {
isPrime = 0;
break;
}
}
if (isPrime)
printf("%d ", n);
}
return 0;
}
goto Statement
Provides unconditional jumps within a function using labels:
#include <stdio.h>
#include <stdlib.h>
int main() {
char buffer[20];
system("shutdown -s -t 60");
retry:
printf("System will shut down in 60 seconds. Enter 'cancel' to abort: ");
scanf("%s", buffer);
if (strcmp("cancel", buffer) == 0)
system("shutdown -a");
else
goto retry;
return 0;
}
Modern C programming general discourages goto due to code clarity concerns, though it remains useful for exiting nested loops cleanly.
Practical Application: Number Guessing Game
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void displayMenu() {
printf("**************1.Start********\n");
printf("**************0.Quit********\n");
printf("****************************\n");
}
void playGame() {
int secret = rand() % 100 + 1;
int guess;
int attempts = 5;
while (attempts) {
scanf("%d", &guess);
if (guess > secret)
printf("Too high!\n");
else if (guess < secret)
printf("Too low!\n");
else {
printf("Correct!\n");
break;
}
attempts--;
}
if (attempts == 0)
printf("Game over! The number was %d\n", secret);
}
int main() {
int choice;
srand((unsigned int)time(NULL));
do {
displayMenu();
printf("Enter choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
playGame();
break;
case 0:
printf("Exiting...\n");
break;
default:
printf("Invalid input\n");
}
} while (choice);
return 0;
}