MATLAB: Index exceeds matrix dimensions

fgetsfopentxt file

Hi, I'm trying to read the raw data from a txt file and making plot.The codes read the file as an array of strings. Then transfer string to num and get the year data. But it shows that the index exceeds matrix dimensions at line 9. And I don't know why z is a 1×1 cell. Shouldn't it be an array? By the way, I don't know if my code work for the plot. The txt file is attached, any comment is helpful. Thanks.
filename = input('Please enter the file name: ');
fid01 = fopen(filename,'r');
for i = 14 : 66
line = fgets(fid01);
z = strread(line,'%s');
year = str2num(z{1});
for j = 2:13
monthly_entry = str2num(z{j});
if (monthly_entry == -99.99)
monthly_entry = [ ];
x = year + 1/12;
y = monthly_entry;
end
end
end
plot( x, y)

Best Answer

You have an empty lines in the input, and lines that have only blanks. fgets() is going to return each line including the line terminator. The strread() with '%s' format is going to return an empty cell array on those lines.
I would remind you that
for i = 14 : 66
line = fgets(fid01);
...
end
contains no instructions to MATLAB that the line to be fetched is the line number the corresponds to "i".
What you should do is, before the "for i = 14" loop, add a loop
for i = 1 : 13
line = fgets(fid01);
end
to read through (and ignore) lines 1 to 13. Then each time you read a line in "for i = 14 : 66" the line number will implicitly synchronize with the value of the "i" variable.
Additional notes:
The 14th input line of your file contains a number of tabs and the word 'Annual'. When you strread() that line with '%s' format, you are going to get the 'Annual' . str2num('Annual') is going to return [] so year would be empty. Then you would try to extract fields 2 through 13 of that line that contains 'Annual' but those fields do not exist, so you would get an index out of range error.
The 15th input line of your file contains a tab and then a series of tab-delimited fields with month names. When you strread() that line with '%s' format, the first result will be 'Jan', and converting that with str2num() will return empty. There are fields 2 through 13 on that line, namely the rest of the month names and the word 'Average'; converting those will give [] as well.
I would therefor suggest to you that your file does not contain 13 header lines but instead 15 header lines, so you should use
for i = 1 : 15
line = fgets(fid01);
end
for i = 16 : 66
line = fgets(fid01);
...
end
The 66 would not change; you got the final value right but not the initial value.
Another note: your code has
if (monthly_entry == -99.99)
that comparison will rarely be true. IEEE 754 Binary Double Precision is not able to exactly represent 1/10 or 1/100 in a finite number of bits, exactly the same way that in decimal, 1/7 cannot be exactly represented in any finite number of decimal places. When -99.99 is encountered on input, the exact value it is converted to will depend upon very small details of what was being calculated. You can never be sure that the calculation path is exactly the same, never be sure if the exact value stored will be -99.9899999999999948840923025272786617279052734375 or -99.9899999999999664623828721232712268829345703125 or -99.9900000000000233058017329312860965728759765625 . This is a general problem for floating point numbers, not just -99.99 .
Because you can never be sure exactly what was stored for any calculation where literal "-99.99" appears, you should never compare for exactly -99.99 . Instead you should compare to see if your value is sufficiently close to -99.99 to be "close enough". For example,
if abs(monthly_total - (-99.99)) < 1e-12
In your particular situation since the valid values are all non-negative, you could instead simply test
if monthly_total < 0
and not have to worry about the exact bit pattern.