Unit 2 - Notes
CSE101
Unit 2: Control structures and Input/Output functions
1. Decision Making and Branching
Control structures dictate the flow of program execution. Branching statements allow the program to skip execution of a code block or execute it based on the validity of a specific condition.
1.1 The if Statement
The simplest form of decision control. It executes a block of code only if the specified condition evaluates to true (non-zero).
Syntax:
if (condition) {
// Code to execute if condition is true
}
Example:
int x = 10;
if (x > 5) {
printf("x is greater than 5");
}
1.2 The if...else Statement
Provides an alternative path. If the condition is true, the if block executes; otherwise, the else block executes.
Syntax:
if (condition) {
// Code for true
} else {
// Code for false
}
Example:
int num = 4;
if (num % 2 == 0) {
printf("Even Number");
} else {
printf("Odd Number");
}
1.3 The else if Ladder
Used to test multiple conditions in sequence. The program checks conditions from top to bottom; the first true condition triggers its associated block, and the rest are skipped.
Syntax:
if (condition1) {
// statement 1
} else if (condition2) {
// statement 2
} else {
// default statement
}
1.4 The switch Case Statement
A multi-way branch statement that provides an easy way to dispatch execution to different parts of code based on the value of an expression. It is often a cleaner alternative to long else if ladders when comparing a single variable against constants.
Key Rules:
- The expression must evaluate to an integer or character.
caselabels must be constants.breakis strictly necessary to prevent "fall-through" (executing subsequent cases).defaultexecutes if no cases match.
Syntax:
switch (expression) {
case constant1:
// code
break;
case constant2:
// code
break;
default:
// default code
}
Example:
char grade = 'B';
switch(grade) {
case 'A': printf("Excellent"); break;
case 'B': printf("Good"); break;
case 'C': printf("Fair"); break;
default: printf("Invalid Grade");
}
2. Loop Control Structures (Iteration)
Loops allow a block of code to be executed repeatedly until a specific condition is met.
2.1 The while Loop (Entry-Controlled)
The condition is evaluated before the loop body executes. If the condition is initially false, the loop body never runs.
Syntax:
while (condition) {
// Code to repeat
// Increment/Decrement logic
}
Example:
int i = 0;
while (i < 5) {
printf("%d ", i);
i++;
}
2.2 The do...while Loop (Exit-Controlled)
The condition is evaluated after the loop body executes. This guarantees the loop body runs at least once.
Syntax:
do {
// Code to repeat
} while (condition); // Note the semicolon
Example:
int i = 10;
do {
printf("%d", i); // Prints 10 even though 10 is not < 5
i++;
} while (i < 5);
2.3 The for Loop
The most compact loop structure, typically used when the number of iterations is known. It combines initialization, condition testing, and increment/decrement in one line.
Syntax:
for (initialization; condition; update) {
// Code to repeat
}
Example:
for (int i = 0; i < 5; i++) {
printf("%d ", i);
}
3. Jump Statements
These statements transfer control unconditionally to another part of the program.
3.1 break
- Usage: Used in
switchstatements and loops. - Action: Immediately terminates the nearest enclosing loop or switch structure. Control passes to the statement following the loop/switch.
3.2 continue
- Usage: Used only in loops.
- Action: Skips the remaining code in the current iteration and jumps to the next iteration check (update/condition step).
3.3 goto
- Usage: Unconditional jump to a labeled statement.
- Note: Generally discouraged ("spaghetti code") as it reduces readability, but useful in specific system programming contexts (e.g., breaking out of deep nested loops).
Example:
for(int i=0; i<10; i++) {
if(i == 5) goto cleanup;
}
cleanup:
printf("Jumped out of loop");
3.4 return
- Usage: Used in functions.
- Action: Terminates the execution of a function and optionally returns a value to the caller.
4. Type Conversion and Modifiers
4.1 Type Modifiers
Modifiers alter the meaning of base data types (int, char, double) to yield a new type or change the storage range.
signed: Default forintandchar. Holds positive and negative values.unsigned: Holds only zero and positive values. Doubles the positive range of the variable.short: Reduces memory usage (usually 2 bytes for int).long: Increases memory usage/range (usually 4 or 8 bytes).
Example:
unsigned int age = 25; (Age cannot be negative).
4.2 Type Conversion (Type Casting)
Converting a value from one data type to another.
1. Implicit Conversion (Coercion):
Performed automatically by the compiler. Usually happens when a smaller type is assigned to a larger type (e.g., int to float).
int i = 10;
float f = i; // 10.0
2. Explicit Conversion (Casting):
Forced by the programmer. Essential when losing precision is a risk or doing integer division.
Syntax: (type_name) expression
Example:
int a = 5, b = 2;
float result;
result = a / b; // Result is 2.0 (integer division)
result = (float)a / b; // Result is 2.5 (explicit cast)
5. Input and Output Functions
C uses standard library functions defined in <stdio.h> for I/O operations.
5.1 Formatted I/O Functions
These functions allow data to be read or written in a specific format defined by the user using format specifiers.
printf() (Print Formatted)
Used to output data to the standard output (console).
- Format Specifiers:
%d(int),%f(float),%c(char),%s(string),%lf(double). - Escape Sequences:
\n(newline),\t(tab).
Example:
int age = 20;
printf("Age is: %d\n", age);
printf("Price: %.2f", 99.999); // Width formatting (2 decimal places) -> 100.00
scanf() (Scan Formatted)
Used to read data from standard input (keyboard).
- Address Operator (
&): Required for primitive types (int, float, char) to tellscanfwhere to store the input in memory. Strings (arrays) do not need&.
Example:
int id;
char name[20];
printf("Enter ID and Name: ");
scanf("%d %s", &id, name); // Reads integer and string (up to whitespace)
5.2 Unformatted I/O Functions
These functions deal with characters or strings directly without format specifiers. They are generally faster but less flexible.
Character I/O
getchar(): Reads a single character from standard input.putchar(char): Writes a single character to standard output.getch()/getche(): (Non-standard, usually in<conio.h>). Reads a character without pressing enter.getcheechoes the character;getchdoes not.
String I/O
gets(str): Reads a line of text (including spaces) until a newline is found.- Warning: Deprecated in modern C due to buffer overflow risks. Uses
fgetsis preferred in production, thoughgetsis often covered in academic syllabi.
- Warning: Deprecated in modern C due to buffer overflow risks. Uses
puts(str): Writes a string to standard output and automatically appends a newline character.
Example:
char str[50];
puts("Enter text:");
gets(str); // Reads spaces, unlike scanf("%s")
puts("You typed:");
puts(str);
6. Designing Structured Programs in C
Structured programming is a paradigm aimed at improving the clarity, quality, and development time of a computer program by making extensive use of the control structures described above.
Key Principles
- Top-Down Design: Breaking a complex problem into smaller, manageable sub-problems (modules/functions).
- Modularity: Writing code in distinct, independent blocks (functions) that perform specific tasks.
- Standard Control Flow: Avoiding
goto(spaghetti code) in favor of:- Sequence: Linear execution.
- Selection:
if,switch. - Iteration:
for,while.
Steps to Design a Structured Program
- Problem Definition: Clearly understand the inputs and desired outputs.
- Algorithm Design: Create a step-by-step logic (pseudocode or flowchart).
- Coding: Implement the logic using structured control statements.
- Testing and Debugging: verify logical correctness using test cases.
Benefits:
- Maintainability: Easier to update specific modules without breaking the whole system.
- Readability: Logic follows a natural flow.
- Reusability: Functions can be reused in other programs.