$$ \newcommand{\Oof}[1]{\mathcal{O}(#1)} \newcommand{\F}{\boldsymbol{F}} \newcommand{\J}{\boldsymbol{J}} \newcommand{\x}{\boldsymbol{x}} \renewcommand{\c}{\boldsymbol{c}} $$

While loops

Matlab also has another standard loop construction, the while loop, doing iterations with a loop index very much like the for loop. To illustrate what such a loop may look like, we consider another modification of ball_plot.m in the chapter A Matlab program with vectorization and plotting. We will now change it so that it finds the time of flight for the ball. Assume the ball is thrown with a slightly lower initial velocity, say \( 4.5\hbox{ ms}^{-1} \), while everything else is kept unchanged. Since we still look at the first second of the flight, the heights at the end of the flight become negative. However, this only means that the ball has fallen below its initial starting position, i.e., the height where it left the hand, so there is no problem with that. In our array y we will then have a series of heights which towards the end of y become negative. Let us, in a program named ball_time.m find the time when heights start to get negative, i.e., when the ball crosses \( y=0 \). The program could look like this

g = 9.81;
v0 = 4.5;                  % Initial velocity
t = linspace(0, 1, 1000);  % Acceleration of gravity
y = v0*t - 0.5*g*t.^2;     % Generate all heights

% At this point, the array y with all heights is ready

i = 1;
while y(i) >= 0
   i = i + 1; 
end

% Having the index, we may look up the time in the array t
fprintf('The time (switch from positive to negative): %f\n', t(i));

% We plot the path again just for comparison
plot(t, y);
xlabel('Time (s)');
ylabel('Height (m)');

If you type and run this program you should get

y=0 at 0.917417417417
The new thing here is the while loop only. The loop will run as long as the boolean expression y(i) >= 0 evaluates to true. Note that the programmer introduced a variable (the loop index) by the name i, initialized it (i = 1) before the loop, and updated it (i = i + 1) in the loop. So for each iteration, i is explicitly increased by \( 1 \), allowing a check of successive elements in the array y.

Compared to a for loop, the programmer does not have to specify the number of iterations when coding a while loop. It simply runs until the boolean expression becomes false. Thus, a loop index (as we have in a for loop) is not required. Furthermore, if a loop index is used in a while loop, it is not increased automatically; it must be done explicitly by the programmer. Of course, just as in for loops and if blocks, there might be (arbitrarily) many code lines in a while loop. Any for loop may also be implemented as a while loop, but while loops are more general so not all of them can be expressed as a for loop.

A problem to be aware of, is what is usually referred to as an infinite loop. In those unintentional (erroneous) cases, the boolean expression of the while test never evaluates to false, and the program can not escape the loop. This is one of the most frequent errors you will experience as a beginning programmer. If you accidentally enter an infinite loop and the program just hangs forever, press Ctrl+c to stop the program.

Reading from and writing to files

Input data for a program often come from files and the results of the computations are often written to file. To illustrate basic file handling, we consider an example where we read \( x \) and \( y \) coordinates from two columns in a file, apply a function \( f \) to the \( y \) coordinates, and write the results to a new two-column data file. The first line of the input file is a heading that we can just skip:

% x and y coordinates
1.0  3.44
2.0  4.8
3.5  6.61
4.0  5.0
The relevant Matlab lines for reading the numbers and writing out a similar file are given in the file file_handling.m

filename = 'tmp.dat';
infileID = fopen(filename, 'r');   % Open file for reading
fgetl(infileID);                   % Read and skip first line

% First read file to count number of lines with data
no_of_lines = 0;
while ~feof(infileID)
    no_of_lines = no_of_lines + 1;
    fgetl(infileID); 
end
fclose(infileID);

% Can now define arrays x and y of known length
x = zeros(no_of_lines, 1);
y = zeros(no_of_lines, 1);

% Re-open the file for reading
infileID = fopen(filename, 'r');   % Open file for reading
fgetl(infileID);                   % Read and skip first line

% Read x and y coordinates from the file and store in arrays
i = 1;
while i <= no_of_lines
    x(i) = fscanf(infileID, '%f', 1);
    y(i) = fscanf(infileID, '%f', 1);    
    i = i + 1;
end
fclose(infileID);

% Next, we treat the y-coordinates and write to file

F = @(y) log(y);
y = F(y);    % Overwrite y with new values

filename = 'tmp_out.dat';
outfileID = fopen(filename, 'w');   % Open file for writing
i = 1;
while i <= no_of_lines
    fprintf(outfileID, '%10.5f %10.5f', x(i), y(i));
    i = i + 1;
end
fclose(outfileID);

Such a file with a comment line and numbers in tabular format is very common so Matlab has functionality to ease reading and writing. Here is the same example (file file_handling_easy.m):

filename = 'tmp.dat';
data = load(filename);
x = data(:,1);
y = data(:,2);
data(:,2) = log(y); % insert transformed y back in array
filename = 'tmp_out.dat';
outfile = fopen(filename, 'w'); % open file for writing
fprintf(outfile, '%% x and y coordinates\n');
fprintf(outfile, '%10.5f %10.5f\n', data);
fclose(outfile);