Control Flow
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Written against MATLAB R2026b. The sessions below were run in GNU Octave 11.3.0 (MATLAB code that Octave also accepts) and show Octave’s output, whose layout may differ from MATLAB’s. Everything on this page has been in MATLAB for decades (the documentation pages give "Introduced before R2006a"), so no release is singled out. Statements that Octave does not share, such as the exact text of MATLAB error messages, are marked "not run here".
Control flow decides which statements run and how often. MATLAB has the usual four constructs: if for a choice between blocks, switch for a choice among values, for for a known sequence of iterations and while for repetition until a condition fails. break, continue and return change the course from inside a block, and try and catch handle errors. All of them end with end. Two things differ from many languages and explain most surprises: the condition of if and while can be an array (see Logical Type and Conditions), and for iterates over the columns of its argument.
The page closes with the heatflow time-stepping loop, the one place in this section where a loop is the right tool because each step needs the result of the previous one. The stencil it uses is written with the range indexing of Indexing; the scenario is introduced on the section home page.
if, elseif and else
if expression
statements
elseif expression
statements
else
statements
end
An expression is true when its result is non-empty and every element is nonzero. The elseif and else blocks are optional, and an if can have several elseif blocks. Only the first block whose expression is true runs. The documentation of if states the rule for arrays: an expression such as A > 0 is true only when every element of the result is nonzero, so test with any or all (or isequal for whole-array equality) when you mean one of those.
Combine scalar conditions with && and ||. They short-circuit, which is what makes if exist("x", "var") && x > 0 safe. The documentation adds that inside the condition of an if (or while) the operators & and | also short-circuit, but it recommends && and || in conditions anyway; see Operators and Precedence.
T = 350;
if T > 400
disp("hot")
elseif T > 300
disp("warm")
else
disp("cool")
end
Octave 11.3.0 output: warm.
switch, case and otherwise
switch switch_expression
case case_expression
statements
case case_expression
statements
otherwise
statements
end
switch tests the cases in order and runs the first one that matches, then leaves the block. A case matches when:
-
for numbers,
case_expression == switch_expression; -
for character vectors and strings,
strcmp(case_expression, switch_expression)is true, so the comparison is case sensitive; -
for a cell array, at least one element matches, which is how several values share one block;
-
for objects that support
eq, the result ofeqis true.
The switch expression must be a scalar or a character vector, and a case expression a scalar, a character vector or a cell array of scalars or character vectors. otherwise is optional and runs only when no case matched.
kind = "Neumann";
switch kind
case "Dirichlet"
disp("fixed value")
case {"Neumann", "Periodic"}
disp("zero flux or wrap")
otherwise
disp("unknown")
end
n = 2;
switch n
case 1
disp("one")
case {2, 3}
disp("two or three")
end
switch "dirichlet"
case "Dirichlet"
disp("matched")
otherwise
disp("case matters")
end
Octave 11.3.0 output:
zero flux or wrap
two or three
case matters
There is no fall-through. Unlike C, only the first matching case runs and then the switch ends, so no break is needed and none is wanted: the documentation points out that break leaves the enclosing for or while loop, not the switch. Because exactly one case runs, a variable defined in one case is not available in another; define whatever a case needs inside it. The documentation also advises against relational operators in a case expression (case x < 5 does not do what it appears to); test inequalities with if, elseif and else.
The switch is the natural way to branch on the heatflow boundary kind: the Dirichlet, Neumann and Periodic members of +heatflow.BoundaryKind (an enumeration, introduced on Enumerations) each get a case, and otherwise raises an error for an unknown kind.
for loops
for index = values
statements
end
values has one of three forms, according to the documentation:
-
initVal:endValincrements the index by 1 until it is greater thanendVal; -
initVal:step:endValincrements bystep, or decrements whenstepis negative; -
valArraymakesindexequal to a column ofvalArrayon each iteration,valArray(:,1)on the first, for as many iterations as there are columns.valArraycan be of any data type, including a character vector, a cell array or a struct.
So the loop goes over columns. For a row vector, which is the usual range, every column is one element and the loop looks like a loop over elements. For a matrix, the loop variable is a whole column. For a cell array the loop variable is a cell (a 1-by-1 cell array holding the contents, not the contents themselves), so you write c = e{1} to open it (see Cell Arrays). To iterate over the elements of a column vector, transpose it first, as the documentation advises.
for k = 1:3
fprintf("%d ", k);
end
fprintf("\n");
for v = [1 2; 3 4]
disp(v')
end
for e = {1, "ab", [1 2 3]}
disp(class(e))
end
count = 0;
for k = 1:0
count = count + 1;
end
disp(count)
for t = 1:-0.25:0
fprintf("%.2f ", t);
end
fprintf("\n");
Octave 11.3.0 output:
1 2 3
1 3
2 4
cell
cell
cell
0
1.00 0.75 0.50 0.25 0.00
The second loop shows the columns [1;3] and [2;4] (printed transposed). The cell loop shows that e is a cell on every iteration. The empty range 1:0 runs zero times, which is why for k = 1:numel(v) is safe for an empty v, and numel is the safer length for a vector.
The loop variable. Do not assign to it. The documentation states that for overrides any change made to the index inside the loop; the next iteration takes the next column regardless, and the assignment only affects the rest of that iteration.
for x = [10 20 30]
x = x + 1;
fprintf("%d ", x);
end
fprintf("\n");
Octave 11.3.0 output: 11 21 31. Each pass started from the original value, so the assignments had no effect on the sequence.
Three more rules about ranges:
-
Floating-point steps. A step such as
0.1is not exactly representable, so the values of a range are rounded, and with other bounds the last element can be missing or present by a hair. When the number of iterations matters, loop over an integer count and compute the value (t = (k-1)*dt), which also avoids accumulated rounding. This is exactly what the time-stepping loop below does, with a counter and a computed time. -
iandj. They are functions that return the imaginary unit. A loopfor i = 1:ncreates a variable that shadows the function, so a later3 + 2*iin the same workspace uses the last loop value and silently gives a real number. A literal such as2ior1iis part of the number syntax and always means the imaginary unit, whatever variables exist. Use names such asrow,colorkfor counters, and write the imaginary unit as1i. -
Growing an array in a loop (
result(end+1) = ...) reallocates it each time; preallocate withzeros, as described on Vectorization and Preallocation.
The parfor loop runs iterations in parallel on workers; running them in parallel needs the Parallel Computing Toolbox (see Toolboxes and Add-On Products), and the statement is not used in this section.
while, break, continue and return
while expression, statements, end repeats the statements for as long as the expression is true, with the same rule as if: non-empty and every element nonzero. Test the condition before every pass, so the body may never run.
-
breakleaves the innermost enclosingfororwhileloop at once. It does not leave aswitch, and in nested loops it leaves only the inner loop. -
continueskips the rest of the current pass and begins the next one (for awhile, the condition is tested again). -
returnis stronger: it ends the whole script or function and returns control to the caller, or to the command prompt if the script was called directly. The documentation warns to be careful when using it inside a conditional block or a loop, because it does not just exit the loop. See Functions.
n = 0;
while true
n = n + 1;
if mod(n,2) == 0, continue, end
if n > 7, break, end
fprintf("%d ", n);
end
fprintf("\n");
Octave 11.3.0 output: 1 3 5 7. Even values were skipped by continue, and the loop stopped when n reached 9. A while true loop with a break is the standard form when the exit test sits in the middle of the body; if you start a loop that never ends by mistake, stop it with Ctrl+C.
try and catch in brief
try
statements
catch exception
statements
end
If any statement in the try block raises an error, control goes immediately to the catch block, where the optional exception variable holds an MException object with fields such as identifier and message. The two blocks can contain nested try statements. A one-line form is common in short sessions.
try, error("heatflow:badStep", "dt %g too large", 0.5), catch err, disp(err.identifier), disp(err.message), end
Octave 11.3.0 output:
heatflow:badStep
dt 0.5 too large
Catch the specific errors you can handle and rethrow the rest; an empty catch that ignores everything hides real bugs. Identifiers, rethrow, MException, warning and onCleanup are on Errors, Warnings and Exceptions.
Source: MATLAB documentation: try, catch
Loops versus vectorization
A loop over array elements is correct but often slower and longer than the equivalent array expression, because MATLAB is designed to apply operators and functions to whole arrays. The rule of thumb in this section: vectorize operations that are independent from element to element (sums, masks, the five-point stencil on the grid), and use a loop for work that is sequential, where each pass needs the previous one, as in time stepping. Preallocate whatever the loop fills. The trade-offs, with timings, are on Vectorization and Preallocation and Profiling and Timing; measure before rewriting working code.
The heatflow time-stepping loop
Explicit time stepping of the heat equation updates the interior of the plate from the previous temperature field with the five-point stencil, and repeats until the largest change in a step falls below a tolerance. The scheme is stable only if dt <= dx^2/(4*alpha), so the script checks that before it starts. The loop has two exits, convergence and a step limit, so it is a while loop with a compound condition; after it, an if tells the caller which exit was taken.
The code below is a complete script. It uses a 21-by-21 grid on a unit plate, a diffusivity of 1e-4, a time step of 80% of the stability limit and a left edge held at 100 degrees. The updates use whole-array indexing for the stencil, and the loop is over time. The grid and the values are illustrative; the final temperature field belongs to the example, not to a physical plate.
alpha = 1e-4;
n = 21;
dx = 1/(n-1);
dt = 0.2*dx^2/alpha;
assert(dt <= dx^2/(4*alpha))
T = zeros(n,n);
T(:,1) = 100;
tol = 1e-6;
maxSteps = 20000;
step = 0;
delta = Inf;
while delta > tol && step < maxSteps
step = step + 1;
Tn = T;
Tn(2:end-1,2:end-1) = T(2:end-1,2:end-1) + alpha*dt/dx^2 * ...
(T(1:end-2,2:end-1) + T(3:end,2:end-1) ...
+ T(2:end-1,1:end-2) + T(2:end-1,3:end) ...
- 4*T(2:end-1,2:end-1));
delta = max(abs(Tn(:) - T(:)));
T = Tn;
end
if delta > tol
warning("heatflow:notConverged", "no convergence in %d steps", maxSteps);
else
fprintf("converged after %d steps, delta %.2e\n", step, delta);
end
fprintf("T center %.4f\n", T(11,11));
Octave 11.3.0 output:
converged after 1304 steps, delta 9.96e-07
T center 24.9999
Points to notice. delta starts at Inf so that the first test passes. The condition uses && on two scalars. A new array Tn is built from the old T, and T is replaced only at the end of the pass, which is what an explicit scheme needs; updating T in place would mix old and new values. The assertion stops the run with an error if the step is unstable; a failed assert without a message argument raises the error identifier MATLAB:assertion:failed (not run here). Pass an identifier and message, assert(dt <= dx^2/(4*alpha), "heatflow:unstableStep", "dt %g exceeds the stability limit", dt), to give the caller something more specific to catch. The other three edges stay at zero because the update touches only the interior and the left edge was set once, which is a fixed-value (Dirichlet) boundary. Other boundary kinds would be a switch over the boundary kind, as shown above. The 1304-step count and the centre value are the numbers Octave printed for this grid and tolerance; MATLAB follows the same IEEE 754 arithmetic, but treat them as an example output, not a reference value.
Pitfalls
-
ifon an array is true only if all elements are nonzero and the array is not empty. Useany,all,isemptyorisequalto say what you mean. -
Text in
switchis compared withstrcmp, so it is case sensitive. Normalize withlowerfirst if the input is not controlled. -
Expecting fall-through (or a
breakin each case): there is none, andbreakin a case leaves the enclosing loop, not theswitch. -
Relational operators in a
case: useif,elseif,else. -
Assigning to the loop variable does not change the sequence.
-
Looping over a cell array gives a cell, not its contents.
-
Reading past the end of an array in a loop (
x(k)withk > numel(x), often from a hard-coded bound) is an error with the identifierMATLAB:badsubscript(not run here). Usenumel(x)orsize(x,dim)as the bound. -
Looping over the rows of a matrix with
for r = Agives columns. Loop over1:size(A,1)and indexA(r,:), or transpose. -
Shadowing
iandj. -
Floating-point loop counters: loop over integers and compute the value.
-
A convergence loop without a step limit may never end. Always combine the tolerance with a maximum number of steps, and report which exit was taken.
-
returninside a loop ends the function or script, not just the loop. -
A comparison of floating-point values with
==in a condition: use a tolerance (see Logical Type and Conditions).
Where older books differ
The if, switch, for, while, break and continue statements are unchanged in the books of the older generation, and what they teach about them is still correct. What has changed is the style around them: the books show element-by-element loops where current code often uses an array expression or a function such as sum, cumsum or max, and they use i and j freely as loop counters. They use character vectors in switch and case (switch lower(kind)), which still works, and strings in double quotes are matched the same way, with strcmp. They rarely mention that a switch accepts a cell array of values in one case. Older code may read the last error with lasterr instead of catching an MException object, which is the current form (see Errors, Warnings and Exceptions).