MATLAB Answers

Why do I receive "exceeds matrix dimensions" after reading a fixed numbered format?

1 view (last 30 days)
Kenneth Lamury
Kenneth Lamury on 26 Jul 2016
Edited: dpb on 27 Jul 2016
When I ask MATLAB to read 5 variables up to 20 times it gives an error message I cannot understand. Can anybody see the error on the first read (mm=1)?
fmt_num1b='%7f%7f%7f%7f%7f'; % 5F7.0
for mm=1:20 % up to 20 body Mach table, table(20)
fgetl(fid);
XY=fscanf(fid,fmt_num1b,1);
BMACH(mm)=XY(1); % body Mach number table
CLBIO(mm)=XY(2); % lift coefficient due to body interference effects NOTE: line 521
CLBIA(mm)=XY(3); % slope of CLBIO
CMBIO(mm)=XY(4); % mom coefficient due to body interference effects
CMBIA(mm)=XY(5); % slope of CMBIO
if BMACH(mm) < 0,end;
end;
Index exceeds matrix dimensions.
Error in CNSMTX (line 521)
CLBIO(mm)=XY(2); % lift coefficient due to body interference effects

  0 Comments

Sign in to comment.

Answers (2)

dpb
dpb on 26 Jul 2016
What does
size(XY)
return? Looks like probably only got one return value; w/o any data to compare to, just guessing as crystal ball is in the shop (yet again :( ).
BTW, you don't need to loop to read a file; also are you intending to only read/parse every other line in the file; that's what the fgetl is going to cause to happen.
Also, the if BMACH(mm)<0 clause is doing nothing useful; was it intended perhaps to terminate a loop as the file uses a single entry <0 as a flag? If that were to be the case, that'd certainly be a reason for the failure trying to address the second element of XY

  3 Comments

Kenneth Lamury
Kenneth Lamury on 26 Jul 2016
Thanks for your support.
With MATLAB stopping at the last read position, I need a new line to start at the beginning, otherwise it read false data beyond last read.
I want to limit my loop to .LE. 20 reads. I suppose I could use a while loop, but I will have to give BMACH(1) a value before reading it.
I cannot visualize reading 5 variables without giving them separate names.
dpb
dpb on 26 Jul 2016
Again, need to see the input file (a short sample should do) and what it is you want to read and the answer to the previous questions.
" cannot visualize reading 5 variables without giving them separate names."
That's what arrays are for--and in Matlab with its vectorized operations, generally what one strives to use if at all possible instead of multiple variables.
Again, what would work best in your situation depends on the details you've not divulged...
Kenneth Lamury
Kenneth Lamury on 26 Jul 2016
Sample input
.10 .0096 .00214 -.0480 .00480 CFM-BIV6 1
.30 .0096 .00214 -.0480 .00480 CFM-BIV6 2
.40 .0068 .00214 -.0480 .00480 CFM-BIV6 3
.55 .0007 .00209 -.0469 .00383 CFM-BIV6 4
.70 -.0092 .00190 -.0459 .00258 CFM-BIV6 5
.80 -.0198 .00230 -.0470 .00100 CFM-BIV6 6
.85 -.0145 .00294 -.0561 .00437 CFM-BIV6 7
.90 -.0176 .00340 -.0590 .00739 CFM-BIV6 8
.95 -.0244 .00270 -.0334 .00307 CFM-BIV6 9
.96 -.0244 .00270 -.0334 .00307 CFM-BIV6 10
-1.0 BLANK
BMACH,CLBIO,CLBIA,CMBIO,CMBIA are the five variables up to 20 times. This setup should stop reading after 10 entries. A different setup will stop reading after 13 entries.

Sign in to comment.


dpb
dpb on 27 Jul 2016
Edited: dpb on 27 Jul 2016
>> fmt=[repmat('%f',1,5) '%*[^\n]']; % 5 floats, skip rest of line
>> fid=fopen('lamury.dat','r'); % open the file
>> data=cell2mat(textscan(fid,fmt,'collectoutput',1)) % read data/cast to array
data =
0.1000 0.0096 0.0021 -0.0480 0.0048
0.3000 0.0096 0.0021 -0.0480 0.0048
0.4000 0.0068 0.0021 -0.0480 0.0048
0.5500 0.0007 0.0021 -0.0469 0.0038
0.7000 -0.0092 0.0019 -0.0459 0.0026
0.8000 -0.0198 0.0023 -0.0470 0.0010
0.8500 -0.0145 0.0029 -0.0561 0.0044
0.9000 -0.0176 0.0034 -0.0590 0.0074
0.9500 -0.0244 0.0027 -0.0334 0.0031
0.9600 -0.0244 0.0027 -0.0334 0.0031
-1.0000 NaN NaN NaN NaN
>> data(end,:)=[]; % clean up the EOF data record
This makes use of no a priori knowledge of the file other than the 5 fields/record needed; simply throw away that last record.
Alternatively, if you do know the number of records in the file going in, you can simply read that many--
>> frewind(fid) % reposition to beginning to save close/reopen
>> data=cell2mat(textscan(fid,fmt,10,'collectoutput',1)) % read 10 records
data =
0.1000 0.0096 0.0021 -0.0480 0.0048
0.3000 0.0096 0.0021 -0.0480 0.0048
0.4000 0.0068 0.0021 -0.0480 0.0048
0.5500 0.0007 0.0021 -0.0469 0.0038
0.7000 -0.0092 0.0019 -0.0459 0.0026
0.8000 -0.0198 0.0023 -0.0470 0.0010
0.8500 -0.0145 0.0029 -0.0561 0.0044
0.9000 -0.0176 0.0034 -0.0590 0.0074
0.9500 -0.0244 0.0027 -0.0334 0.0031
0.9600 -0.0244 0.0027 -0.0334 0.0031
>> fid=fclose(fid);
>>
You can assign the columns to different variables, but consider carefully what it is you're going to be doing with the data and whether it couldn't be vectorized by at least selectively leaving those with similar operations in the array.
Again, Matlab is not C nor Fortran nor other conventional language--its power is in that it is vectorized; learn to use (and revel in :) ) that facility.
ADDENDUM
For the sample file you posted, one way to read the section you gave above...
>> fid=fopen('ZLS918.dat','r'); % open the file
>> l=fgetl(fid); % read first record
>> while isempty(strfind(l,'BLANK')), l=fgetl(fid);end
>> l % display the last record written --looks like what were looking for
l =
-1.0 BLANK
>> data=cell2mat(textscan(fid,fmt,10,'collectoutput',1)) % now read the data
data =
0.1000 0.0096 0.0021 -0.0480 0.0048
0.3000 0.0096 0.0021 -0.0480 0.0048
0.4000 0.0068 0.0021 -0.0480 0.0048
0.5500 0.0007 0.0021 -0.0469 0.0038
0.7000 -0.0092 0.0019 -0.0459 0.0026
0.8000 -0.0198 0.0023 -0.0470 0.0010
0.8500 -0.0145 0.0029 -0.0561 0.0044
0.9000 -0.0176 0.0034 -0.0590 0.0074
0.9500 -0.0244 0.0027 -0.0334 0.0031
0.9600 -0.0244 0.0027 -0.0334 0.0031
>> fid=fclose(fid);
This uses the fact that the 'BLANK' comment first occurs in the file in the record ahead of the particular section of interest. That's fortuitous and probably not terribly robust and won't work without modification in finding a later subsection.
More robust (at the expense of more i/o, but "there is no free lunch") would be to count records while looking for the comment identifying the section itself (the 'CFM-BIV6' string), and when find it then frewind and use that count as the 'headerlines' count since there isn't a neat way to revert to the beginning of the record just read. For pretty small files such as this, it won't be a noticeable overhead, anyway.
Alternatively, you could just read the whole file into memory as character array and then do the lookup in memory to find the array row(s) of interest and use textscan on the memory image instead of reading the file directly. Many ways to "skin the cat" here.
BTW, isn't this the same file of some earlier thread(s) on trying to convert a Fortran app to Matlab? Surely looks similar if not identical but I don't recall the poster's name...
ADDENDUM 2
Well, shoot, while at it might as well just demo the "find a given section" approach as well...it's pretty simple
>> fid=fopen('ZLS918.dat','r');
>> l=fgetl(fid);
>> nSkip=0;while isempty(strfind(l,'CFM-BIV6')),l=fgetl(fid);nSkip=nSkip+1;end
>> l
l =
.10 .0096 .00214 -.0480 .00480 CFM-BIV6 1
>> nSkip
nSkip =
116
>> frewind(fid);
>> data=cell2mat(textscan(fid,fmt,10,'collectoutput',1,'headerlines',nSkip))
data =
0.1000 0.0096 0.0021 -0.0480 0.0048
0.3000 0.0096 0.0021 -0.0480 0.0048
0.4000 0.0068 0.0021 -0.0480 0.0048
0.5500 0.0007 0.0021 -0.0469 0.0038
0.7000 -0.0092 0.0019 -0.0459 0.0026
0.8000 -0.0198 0.0023 -0.0470 0.0010
0.8500 -0.0145 0.0029 -0.0561 0.0044
0.9000 -0.0176 0.0034 -0.0590 0.0074
0.9500 -0.0244 0.0027 -0.0334 0.0031
0.9600 -0.0244 0.0027 -0.0334 0.0031
>>
QED
You can, of course, combine the above with searches and reads of other sections by simply repeating the above with a different keyword and the appropriate format string for the section of interest. You also don't have to frewind and continue from the beginning every time altho it has some simplification over picking up from the present location as noted in there not being a record-oriented file structure in Matlab to do an equivalent of Fortran BACKSPACE (which often ends up in the actual code as REWIND and N READs anyway). In this case, you'd read the current line from memory and then concatenate the remainder of the section scanned from the file before then going on to the next section of interest.

  2 Comments

Kenneth Lamury
Kenneth Lamury on 27 Jul 2016
Doesn't frewind take you to beginning of input deck (which is 200 lines)? (See attachment.)
fid=fopen('ZLS918_919_KCR_Test_Up_O.m','r'); %File for flap up maneuvers
is one of the first calls in my script file.
I still get "Index exceeds matrix dimensions."
dpb
dpb on 27 Jul 2016
Of course it does; that was for the demo purpose only, however, as noted. I only included that to read the file the second time from the command line...you read the file once only, with/without the count, your choice.
As for the error, again must see what you got in context of what you actually did. As shown, I read the file successfully twice; once with, once without a count with no such error either time.
OK, that's a totally different file than what was given above; use 'headerlines' option if you know how many lines are in the file before the section of interest. Otherwise, you'll have to read/parse lines until you do find that you're looking for.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by