This is actually a two-fer: padding a number with a variable number of leading zeros or spaces and updating text in the Command Window without creating a bunch of new lines.
Variable number padding
sprintf function includes in its documentation the instructions for padding a number with leading zeros.
myNumber = 4 paddedNumber = sprintf('%02d', myNumber) paddedNumber = 04
But what do you do when you don't know how many zeros you'll want to use? You need another variable. The syntax looks like this:
paddedNumber = sprintf('%0*d', numDigits, myNumber)
If I specify
numDigits, I can pad
myNumber with any number of zeros I choose. Of course, I need to define
numDigits somehow. In the FrameCounter function below, I want to have enough leading zeros that my last frame has no zeros out front. So if my last frame is 123, I should get two leading zeros for numbers less than 10, one leading zero for numbers up to 99, and then no leading zeros for the rest. Here's how I like to do it:
numDigits = length(sprintf('d', lastNumber));
This is to say, I write out the number as a string and calculate how many characters that is (i.e. the length of the string). That's how many digits I need to do the padding. Simple.
Updating text in the Command Window
I was using a program in MATLAB that took a long time to run and had an unfortunate tendency to crash1. I wanted to know which frame it had been working on before it failed, and in general I wanted to have some idea how much progress it had made. At the time, I wasn't aware of the built-in progress bar, and then I learned that that can actually slow down whatever process it is you're trying to keep tabs on, so I wrote my own. It just printed the current frame number to the Command Window every ten frames or so, which was enough to narrow down the range of the failed frame. Every time a new frame was printed to the Command Window, though, it made a new line, and after thousands of successful frames, I had a Command Window full of numbers. What I wanted was a way to update the number in place, without printing a new line.
In 2011, I went to the CPLC Summer School at UIUC (which was pretty fun and enlightening) and I saw what I wanted in action in an analysis program. I didn't have a chance to look at the source, though, so I asked how it worked. The student I was working with said he didn't recall for sure, but he thought it had something to do with backspaces. That clue was enough for me to figure it out on my own.
Here's how it works:
- Print the text you want to display to the Command Window using
- Print enough backspace characters (again, with
fprintf) to delete each of the characters that need to change.
- Print the new text.
Getting it to work as a separate function took a little thinking, but turned out to be pretty simple. The result is below. I hope you find it (or its components) as useful as I have over the years.
function FrameCounter(first_num, last_num, current_num, show_text) %% Determine the number of digits in the number num_digits = length(sprintf('%d',last_num)); text = 'Frame '; if nargin < 4 show_text = 0; end %% Before displaying the first number if current_num == first_num if show_text == 1 %% % Display "Frame " before the numbers fprintf(text) end for aaa = 1:num_digits %% Prime the counter with spaces fprintf(' ') end end %% Remove the previous number for bbb = 1:num_digits fprintf('\b') end %% Display the current number fprintf('%0*d', num_digits, current_num) %% Last number if current_num == last_num if show_text == 1 char_num = length(sprintf(text)); else %if show_text == 0 char_num = 0; end backspaces = char_num + num_digits; pause(.1) % Without this pause, the last number sometimes doesn't display properly. %% Remove last number and "Frame " text for ccc = 1:backspaces fprintf('\b') end end end
1: The source of the crash was a read/write conflict with the Windows 7 indexing system. More on that conflict here if you're interested.