Help improve SovranCode?

Google Analytics can measure anonymous usage after you choose Allow. Essential account and progress features work either way.

SovranCode
C: Foundations for Systems Programming Conditions and Loops
This device
Course contentsConditions and Loops · 15 titles

C foundations

What C Is and How C Programs RunYour First C ProgramVariables, Types, and OperatorsInput and Output with printf and scanfConditions and Loops

Program structure and data

Functions, Headers, and ScopeArrays and StringsPointers and Memory AddressesStructures, Enumerations, and UnionsFiles and Command-Line Arguments

Memory, tooling, and practice

Dynamic Memory AllocationPreprocessor Directives and Separate CompilationErrors, Debugging, and Undefined BehaviorBuild Tools and MakefilesProject: Command-Line Inventory Manager
C: Foundations for Systems Programming15 complete lessons

C foundations

What C Is and How C Programs RunYour First C ProgramVariables, Types, and OperatorsInput and Output with printf and scanfConditions and Loops

Program structure and data

Functions, Headers, and ScopeArrays and StringsPointers and Memory AddressesStructures, Enumerations, and UnionsFiles and Command-Line Arguments

Memory, tooling, and practice

Dynamic Memory AllocationPreprocessor Directives and Separate CompilationErrors, Debugging, and Undefined BehaviorBuild Tools and MakefilesProject: Command-Line Inventory Manager
PREVIOUS LESSONInput and Output with printf and scanf
NEXT UP · PLANNEDFunctions, Headers, and Scope
C fundamentals 115 min

Conditions and Loops

A program becomes useful when it can choose a response and repeat a reliable action. Learn to turn program state into precise comparisons, order multi-branch decisions, and repeat only while a clear stopping rule remains true. You will trace what happens at exact boundaries—not merely memorize C syntax.

What you will leave with

You will be able to read comparison and logical operators, explain why = and == are not interchangeable, order an if/else if/else chain, choose between for and while, trace exact boundary values, validate a small numeric input range, and identify the update that proves a loop can finish.

Use state, a question, and a next step

Evaluate a conditionTurn the current numeric state into a true or false decision with a readable comparison.
Select one branchKeep mutually exclusive outcomes in an ordered if/else if/else chain with braces.
Repeat deliberatelyUse a for loop for a known count and a while loop for a changing state.
Prove terminationName the condition, changing value, boundary, and moment the condition becomes false.

A condition asks one small, testable question

In C, 0 acts as false and a nonzero numeric value acts as true. Most beginner conditions are clearer when they state a relationship directly: completed < total, score >= pass_mark, or attempts != limit. Read such a condition as a sentence before deciding what the program should do next.

01Store state

Variables hold facts such as a score, remaining count, or current loop index.

02Compare

A relational or equality operator turns those facts into a true or false result.

03Choose work

if runs its body only when the condition is true; else handles the alternative.

04Change state

A loop update changes the value that the next condition will examine.

Read a condition in three passes

Do not begin by looking at the braces. First identify the values being read, then state the comparison in ordinary language, and only then choose the branch. For completed < total, the values are completed and total; the question is “are there lessons left?”; the true branch is the work for an unfinished path. This habit makes conditions easier to test and easier to change.

completed = 3

State

A variable stores the current fact. Its name should tell you what the number means before you see an operator.

total = 4

Reference point

Another value establishes the target, limit, or boundary that makes the first value meaningful.

completed < total

Question

The comparison is true because 3 is less than 4. It is a question, not an instruction to change data.

true → keep learning

Consequence

The branch should say what the program does when the answer to the question is true.

Prefer an explicit comparison

C treats 0 as false and every nonzero number as true, so if (attempts) is legal. In beginner code, if (attempts > 0) is often clearer because it tells the reader exactly why the branch is allowed to run.

Compare values; do not accidentally replace them

Equality needs two characters. A single = assigns a value to a variable; == compares two values. Write the comparison first, then use braces even when a branch currently has one statement. Braces make a later edit less likely to quietly change which code is controlled.

==

Equal to

True when both numeric values are the same.

!=

Not equal to

True when two numeric values differ.

< / <=

Less than

Use <= when the endpoint belongs in the range.

> / >=

Greater than

Use >= when the passing boundary belongs in the range.

&&

Both true

Logical AND requires the condition on each side to be true.

|| / !

Either or inverse

Logical OR accepts either side; ! reverses a true or false result.

Read the operator before running code

if (completed = total) changes completed; it does not ask whether the values match. Compilers often warn about this pattern, but a warning is not a safety net. Use == when you mean equality.

Choose exactly one response with if and else

The branch below has a complete rule: a learner needs both a passing score and a submitted project. The && operator means both parts must be true. Change the values, predict which message will appear, and run the program. Try a score below 70, then keep the score high and change project_submitted to 0.

C FUNDAMENTALS RUNNER

Select one completion message

The safe runner evaluates numeric comparisons, &&, ||, and ! without evaluating arbitrary browser code. Edit one value at a time and trace the selected branch.

#include <stdio.h>

int main(void) {
  int score = 82;
  int project_submitted = 1;

  if (score >= 70 && project_submitted) {
    puts("Module complete.");
  } else {
    puts("Review the missing requirement.");
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Add an int named attendance_ok and require it in the condition before the module can be complete.

if (condition) { ... }

if

The body runs only if the condition evaluates to true. The braces visibly mark the controlled statements.

else { ... }

else

This alternative body runs only if the directly preceding if condition is false.

score >= 70 && ready

Logical AND

Every required condition must hold. Keep each part independently meaningful and easy to test.

count < 0 || count > limit

Range rejection

Either impossible boundary makes the full condition true, so one branch can reject invalid data.

Order a multi-branch decision from most specific to least specific

An if/else if/else chain asks questions from top to bottom and runs the first true body only. It does not run every true condition. That makes order part of the rule: a distinction score is also a passing score, so the distinction test must appear before the broader pass test. The final else is the one remaining outcome after all earlier questions are false.

C FUNDAMENTALS RUNNER

Classify a score with an ordered decision

The runner checks the branches from top to bottom and stops at the first true condition. Change score to 85, 70, 50, and 49; predict the label before you run it.

#include <stdio.h>

int main(void) {
  int score = 72;

  if (score >= 85) {
    puts("Distinction");
  } else if (score >= 70) {
    puts("Pass");
  } else if (score >= 50) {
    puts("Resit required");
  } else {
    puts("Review the foundation");
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Add a new top branch for scores of 95 or more, then choose a label that makes the new rule clear.

  1. 01
    Start with score = 72

    The first question is score >= 85. It is false, so C moves to the next else if.

  2. 02
    Test the next boundary

    score >= 70 is true. The program enters that body and prints Pass.

  3. 03
    Skip every later alternative

    The 50-point condition and final else are not tested as separate outcomes after one branch has already been chosen.

  4. 04
    Test the exact edges

    Use 85, 70, 50, and 49. Boundaries reveal whether >= and your branch order match the rule you meant to write.

Combine questions without hiding the rule

Use && when every requirement must hold and || when any invalid state should trigger the same response. C evaluates ! before comparisons, comparisons before &&, and && before ||. You do not need to rely on that order for a complicated rule: parentheses can make the intended grouping visible.

(score >= 70) && submitted

All requirements

Parentheses separate the score question from the submission flag. Both must be true to complete the full condition.

completed < 0 || completed > total

Invalid range

Either impossible side makes the condition true, so a single branch rejects data that is too small or too large.

!(choice == 1)

Negation

Read this as “choice is not 1.” Prefer choice != 1 when it says the same thing more directly.

(a || b) && ready

Group intentionally

Without parentheses, && binds more tightly. The parentheses make “either a or b, and ready” explicit.

Use for when the count is visible from the start

A for loop places its three moving parts together: initialization runs once, the condition is checked before every cycle, and the update runs after the body. This structure fits numbered lessons, days, pages, retries with a fixed limit, and any task whose number of repetitions is known before the loop begins.

C FUNDAMENTALS RUNNER

Trace a counted practice loop

The loop starts day at 1, runs while day is at most total_days, then changes day with day++. Change total_days and trace the exact number of terminal lines.

#include <stdio.h>

int main(void) {
  int total_days = 3;

  for (int day = 1; day <= total_days; day++) {
    printf("Practice day %d\n", day);
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Change the start value to 0 and update the label so the first printed day still makes sense.

  1. 01
    Initialize once

    int day = 1 creates the starting index before the first condition check.

  2. 02
    Test before the body

    day <= total_days decides whether another cycle is allowed.

  3. 03
    Run one cycle

    The body prints one labeled practice day using the current index.

  4. 04
    Update toward the stop

    day++ adds one, so eventually the condition becomes false.

Trace the first, last, and forbidden loop values

Most loop bugs are boundary bugs. A loop has to agree on whether its index is zero-based or one-based and whether its ending value belongs in the range. The starter below prints four lines even though there are only three lessons: it starts at 0 and includes the endpoint 3. Run it, then repair it in either of these consistent ways: start at 1 and keep <= total_lessons, or start at 0 and use lesson < total_lessons.

C FUNDAMENTALS RUNNER

Repair an off-by-one loop

This code runs, but its numbering and count do not match a three-lesson path. Change one part of the loop header, predict the output, then run it again.

#include <stdio.h>

int main(void) {
  int total_lessons = 3;

  for (int lesson = 0; lesson <= total_lessons; lesson++) {
    printf("Lesson %d\n", lesson);
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Make the output contain exactly Lesson 1, Lesson 2, and Lesson 3. In your own words, explain why the final condition stops.

Boundary checklist

Before trusting a counted loop, name the first value, the last allowed value, the number of intended cycles, and the value that appears immediately after the last update. For a one-based three-lesson loop, those values are 1, 3, 3 cycles, and 4. The condition 4 <= 3 is false, so the loop ends.

Let the inner loop finish before the outer loop advances

A nested loop means one repetition happens inside another. In the program below, the outer loop chooses a week. For that one week, the inner loop runs through every day. Only after days 1 through 3 are printed does the outer loop advance to the next week. With weeks = 2 and days = 3, expect 2 * 3, or six lines of output.

C FUNDAMENTALS RUNNER

Trace a two-level practice schedule

Run the program and notice that the day counter resets to 1 each time a new week begins. Change weeks or days and calculate the total lines before running it.

#include <stdio.h>

int main(void) {
  int weeks = 2;
  int days = 3;

  for (int week = 1; week <= weeks; week++) {
    for (int day = 1; day <= days; day++) {
      printf("Week %d, day %d\n", week, day);
    }
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Change days to 2 and add a final line that says how many day entries you expect before you run the program.

Nested loops are useful for grids, schedules, groups and items, or every pair of values. They are also easy to make hard to read. Give each index a meaningful name such as week and day, keep the body small, and calculate the total work before adding a large nested loop to a real program.

Use while when the changing state defines the stop

A while loop is best when the work should continue until some state changes: tasks remaining, bytes read, a menu choice, or a retry count. Its condition appears at the top, so it may run zero times. That is often the correct behavior when there is no work to do.

C FUNDAMENTALS RUNNER

Make a while loop finish

remaining controls the loop and remaining-- changes that same value each cycle. Remove the update to see the runner explain the missing stopping progress.

#include <stdio.h>

int main(void) {
  int remaining = 3;

  while (remaining > 0) {
    printf("%d task(s) remain.\n", remaining);
    remaining--;
  }
  puts("All tasks are complete.");
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Start with 5 tasks, then change the body so it labels even and odd remaining counts using an if branch.

Every loop needs a progress story

Before running a loop, identify the condition and the statement that can make it false. This browser runner stops either loop after 1,000 cycles to protect the page, but a real program needs a correct condition and update of its own.

Trace a while loop before you write it

For the example above, start with remaining = 3. The condition remaining > 0 is true, so the body prints 3 and then remaining-- changes the state to 2. The next two passes use 2 and 1. After the body prints 1, the update makes remaining zero; 0 > 0 is false, so the body does not run again and the completion message prints.

remaining = 0

Zero-cycle case

The initial condition is already false, so the loop body runs zero times. The statement after the loop still runs.

remaining = 1

One-cycle case

The body runs once, then the update changes the value to the stopping boundary.

remaining = 3

Typical case

Each cycle has the same shape: test, print the current fact, decrement, and test again.

remove remaining--

Failure case

The condition keeps reading the same positive value. The program has no reason to stop.

That repeated fact is called a loop invariant: at the start of every pass, remaining is the number of tasks that have not yet been reported. A good invariant helps you choose the right condition and makes a debugging trace much less mysterious.

Use do-while when one attempt must happen first

A do/while loop puts the condition after its body. That means its body runs at least once, even when the condition is false after that first pass. It is useful for a prompt that must appear once before a user can choose to stop, but use it only when that “at least once” rule is genuinely part of the problem.

C FUNDAMENTALS RUNNER

Run a first check before testing again

The body prints once before checks < 2 is evaluated. Change checks to 2 before the loop and see why the program still prints the first check.

#include <stdio.h>

int main(void) {
  int checks = 0;

  do {
    printf("Check %d\n", checks + 1);
    checks++;
  } while (checks < 2);
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Change the condition so the program prints exactly three checks, then explain why a do-while differs from a while when the starting value is already at the stop.

Use break and continue sparingly and trace their target

break leaves the nearest loop immediately. continue skips the rest of the current cycle; a for loop still performs its update before testing again, and a while loop returns directly to its condition. They are useful for an exceptional case inside otherwise regular repetition, but a plain loop condition is still the clearest normal stopping rule.

C FUNDAMENTALS RUNNER

Skip one cycle and stop after a found result

Attempt 2 uses continue, so it never reaches the normal check. Attempt 4 uses break, so attempts 5 and later never start. Trace each outcome before running it.

#include <stdio.h>

int main(void) {
  int attempt = 0;

  while (attempt < 5) {
    attempt++;

    if (attempt == 2) {
      puts("Skip attempt 2.");
      continue;
    }

    printf("Check attempt %d\n", attempt);
    if (attempt == 4) {
      puts("A valid result appeared.");
      break;
    }
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Change the skipped attempt to 3 and the successful attempt to 5. Explain which statement changes the loop counter before continue can take effect.

Keep loop exits explainable

A reader should be able to answer “why can this loop stop?” by looking at its condition and update. When you add break or continue, make the exceptional case narrow, name the current state clearly, and test the cycles immediately before and after it.

Validate numeric input before relying on it

The previous lesson showed that scanf converts input only when the provided text matches the requested format. A production C program should also check its conversion count. The complete local pattern is if (scanf("%d", &completed) != 1) { /* recover or stop */ }. The browser lesson runner deliberately keeps function-call results out of conditions; it stops on invalid numeric input instead of imitating a full C runtime. You can still validate a successfully read value with range checks such as completed < 0 || completed > total.

Validate the shape and the meaning

A conversion check answers “did the input look like an integer?” A range check answers “is this integer valid for this program?” Reliable input paths need both answers before they update important state.

  1. 01
    Read one value

    Ask scanf to convert input into the type your variable was declared to hold.

  2. 02
    Check conversion locally

    If the conversion count is not the expected value, do not treat the variable as trustworthy program state.

  3. 03
    Check the domain rule

    For a completed lesson count, reject values below zero and values above the total.

  4. 04
    Only then repeat work

    The later loop can rely on a value that has both the correct type and a meaningful range.

Debug one-character mistakes with a precise rule

This program looks like an equality check but uses an assignment operator in the condition. Run it first, read the runner message, and replace only the one character that changes the rule. Then change one of the values and observe the other branch.

C FUNDAMENTALS RUNNER

Repair an equality condition

The runner makes the = versus == distinction explicit so you can connect a small syntactic difference to a different program behavior.

#include <stdio.h>

int main(void) {
  int completed = 4;
  int total = 4;

  if (completed = total) {
    puts("Every lesson is complete.");
  } else {
    puts("Keep going.");
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: After repairing the condition, set completed to 3 and explain why the else branch now runs.

Debug control flow with evidence, not guesses

A condition or loop can be syntactically valid and still describe the wrong rule. When output surprises you, reduce the problem to one known state and trace it in order. Do not change several operators at once: that hides which change fixed the behavior.

  1. 01
    Write down the input state

    Record the exact values before the decision: for example completed = 3 and total = 4.

  2. 02
    Evaluate the condition aloud

    Replace variable names with values and decide whether the question is true or false before looking at output.

  3. 03
    Mark the branch or one loop cycle

    Name the exact body that should run, then record the update and the next condition result.

  4. 04
    Test the boundaries

    Use the value below a limit, the exact limit, and the value above it. These tests expose most < versus <= mistakes.

Compile local control flow with warnings enabled

Save a program as conditions.c and compile with warnings enabled. A compiler can catch many suspicious constructs, including a likely assignment in a condition, but it cannot decide whether your chosen boundary or stopping rule matches the program you meant to write. Trace at least one true and one false path by hand before trusting the terminal output.

macOSCompile with Clang and inspect warnings before executing.clang -Wall -Wextra -Wpedantic -Wconversion conditions.c -o conditions./conditions
LinuxBuild with GCC or Clang and test both sides of each decision.gcc -Wall -Wextra -Wpedantic -Wconversion conditions.c -o conditions./conditionsUse small boundary inputs: zero, the exact limit, one below it, and one above it.
WindowsCompile in a configured Developer Command Prompt.cl /W4 conditions.cconditions.exeConfirm that each path and loop stopping condition produces the result you can explain.

Independent lab: print a learning-path status

Use the starter to read a completed-lesson count and print one line for every lesson. It already rejects an impossible value and marks each lesson as complete or next. Change the total, labels, or valid range to fit a learning path you care about. Then try the boundary inputs 0, the exact total, and one value outside the valid range.

C FUNDAMENTALS RUNNER

Build a guarded learning-path report

This lab combines numeric input, a range check, a while loop, a nested if branch, and an explicit return status.

#include <stdio.h>

int main(void) {
  int completed;
  int total_lessons = 4;
  int lesson = 1;

  scanf("%d", &completed);

  if (completed < 0 || completed > total_lessons) {
    puts("Completed lessons must be between 0 and 4.");
    return 1;
  }

  while (lesson <= total_lessons) {
    if (lesson <= completed) {
      printf("Lesson %d: complete\n", lesson);
    } else {
      printf("Lesson %d: next\n", lesson);
    }
    lesson++;
  }
  return 0;
}
TERMINAL OUTPUT
Edit the program, predict its output, then run it.

This safe browser runner supports the lesson subset: scalar and fixed-size int/double arrays, character strings, indexed reads and numeric writes, arithmetic, printf/puts, numeric scanf into scalar or bounded array-element addresses, comparisons, bounded if/else, for/while loops, and return.

Try this next: Change total_lessons to 6, update the valid range message, and make the output describe your own topic instead of lessons.

Milestone 01

Make input safe

Keep the conversion and range decision before the loop. Test -1, 0, and a value greater than the total.

Milestone 02

Trace both branches

Use an input of 2 and explain why two lines are complete while the remaining lines are next.

Milestone 03

Change one rule

Add a clear status category—such as “review”—by changing the condition and its label, not by duplicating the loop.

Milestone 04

Prove the boundary

With a total of 6, test 0 and 6. Explain the exact final loop value that makes the condition false.

Extension after the core lab works

Turn the report into a weekly practice tracker. Keep the same safe structure: validate the total first, choose a label with a condition, then repeat one predictable line per day. Your extension should preserve a named counter and an obvious update.

Lesson review

Conditions turn data into a choice; loops repeat work while that choice allows another cycle. Clear control flow uses descriptive state, a visible comparison, ordered branches, braces around every branch, and a named update that moves a loop toward its stopping point. When input is involved, confirm both conversion and meaning before the program relies on it.

  • I can read ==, !=, <, <=, >, and >= as precise comparisons instead of vague symbols.
  • I can explain the difference between assignment with = and comparison with ==, and I use braces around every if and else body.
  • I can order an if/else if/else chain from the most specific boundary to the remaining alternative, knowing that only the first true branch runs.
  • I can choose for for a known count and while for a state-driven stop, then trace initialization, condition, body, and update.
  • I can test a loop's first value, last allowed value, number of cycles, and the value immediately after the final update.
  • I can explain why an inner loop completes all of its work before an outer loop advances, and estimate the total work in a nested loop.
  • I can name the value that changes inside a loop and prove why the condition will eventually become false, including the zero-cycle case.
  • I can distinguish a successful scanf conversion check from a separate range check on the value that was read.
KNOWLEDGE CHECK

Trace a decision and its repeated work

Read the condition first, then follow the selected branch or each loop cycle in order. The goal is to explain why the program stops, not only recognize its syntax.

01Which expression compares score with 10 instead of assigning a new value?
02Which loop is usually clearest when you know in advance that a task must happen five times?
03How many times does this body run: for (int day = 1; day <= 3; day++)?
04What does && mean in a C condition?
05What is missing from this loop? while (attempt < 3) { puts("Try again"); }
PREVIOUS LESSONInput and Output with printf and scanf
NEXT UP · PLANNEDFunctions, Headers, and Scope
ON THIS PAGEConditions and LoopsLesson mapConditionsRead a conditionComparisonsif and elseElse-if chainsLogical operatorsfor loopsLoop boundariesNested loopswhile loopsWhile tracingdo-whilebreak and continueInput validationRepair an assignmentDebugging flowCompile locallyIndependent labLesson reviewKnowledge check
Course contents