Index exceeds the number of array elements (0).

Hi,
I'm struggling with a piece of code to extract information from a text file. It keeps coming up with the error message 'Index exceeds the number of array elements (0).'. I think this is something to do with the format of my data but I'm not super experienced when it comes to extracting data.
My code:
% Enter BETR text file name and location
fid = fopen('filename);
% read the file and split it into lines
data = textscan(fid, '%s', 'delimiter', '\n');
data = data{1}; % extract cell array from textscan output
% close the file
fclose(fid);
% Initialize empty arrays for hours, M1, M2, and M3
hours = [];
m1 = [];
m2 = [];
m3 = [];
% Loop through each line of the data
for i = 1:length(data)
% If the line starts with a number, assume it's the hours
if isstrprop(data{i}(1), 'digit') && isempty(hours)
hours = str2double(strsplit(data{i}));
% If the line starts with 'M1', extract the points of interest for M1
elseif startsWith(data{i}, 'M1')
m1_points = extractBetween(data{i}, 'M1 - ', '\n');
m1_points = strsplit(m1_points, ', ');
m1_points(cellfun('isempty', m1_points)) = [];
m1 = [m1; m1_points];
% If the line starts with 'M2', extract the points of interest for M2
elseif startsWith(data{i}, 'M2')
m2_points = extractBetween(data{i}, 'M2 - ', '\n');
m2_points = strsplit(m2_points, ', ');
m2_points(cellfun('isempty', m2_points)) = [];
m2 = [m2; m2_points];
% If the line starts with 'M3', extract the points of interest for M3
elseif startsWith(data{i}, 'M3')
m3_points = extractBetween(data{i}, 'M3 - ', '\n');
m3_points = strsplit(m3_points, ', ');
m3_points(cellfun('isempty', m3_points)) = [];
m3 = [m3; m3_points];
end
end
The data in the .txt file looks like this, and I'm looking to extract the time, alongside the position (307, 327 etc.) for each sample (M1,M2,M3):
General: xxx
CC: 2000
M1 - 277,2209g, OW I.D.xxx, no distinctive features, (160, 220, 295 ?)
M2 - 312,4254g, OW I.D.xxx, no distinctive features,
M3 - 277,7087g, OW I.D.xxx, no distinctive features, (230 ?)
15 10 hours (270)
M1 - 276,9280g, 307, 327, 2mm, 376, 378, 388, 400
M2 - 314,5424g, 366, 371, 393, 398, 3x2, 401
M3 - 278,5357g, 362, 380, 399, 411
16 50 hours (320)
M1 - 277,1215g, 307, 327, 2mm, 360, 376, 378, 389, 400
M2 - 314,6405g, 351, 357, 366, 370, 1mm, 375, 379, 384, 387, 394, 6x5, 401, 403, 409
M3 - 280,6355g, 318, 344, 362, 374, 376, 383, 398, 409, 1x1
Any support on why this code isnt working would be appreciated.
Many thanks

1 Comment

If it depends on the format of your data, then we will need that. Please attach your file to your post using the paperclip icon.
Also, please share the complete error message (all the red text).

Sign in to comment.

 Accepted Answer

If your file contains the same spaces as what you show in your description of the data, then the issue is that not every line contains data. So when you try to index an empty line, you will get this error.
You'll want to either delete empty lines, or check the length of your data row before indexing into it.
data = data(~cellfun('isempty',data))

3 Comments

Hi Cris,
Thanks for this answer, that definetly is one of the problems but now im getting a second error message.
Error using strsplit (line 80)
First input must be either a character vector or a string scalar.
Error in Extracting_BETR_Text_File (line 29)
m1_points = strsplit(m1_points, ', ');
I've attached the .txt file.
Thanks for the support.
Again, your variable is empty so you get an error.
It might be helfpul to visualize what MATLAB is 'seeing' when the error occurs. You can use the debugging tools in MATLAB for this purpose.
fid = fopen("Filename.txt");
data = textscan(fid, '%s', 'delimiter', '\n');
data = data{1}; % extract cell array from textscan output
fclose(fid);
data = data(~cellfun('isempty',data))
data = 101×1 cell array
{'General: xxx' } {'CC: 2000' } {'M1 - 277,2209g, OW I.D.xxx, no distinctive features, (160, 220, 295 ?) '} {'M2 - 312,4254g, OW I.D.xxx, no distinctive features, ' } {'M3 - 277,7087g, OW I.D.xxx, no distinctive features, (230 ?)' } {'01 10 hours' } {'M1 - 277,4901g, No optical changes' } {'M2 - 312,7474g, No optical changes' } {'M3 - 278,4185g, No optical changes' } {'02 50 hours (60)' } {'M1 - 276,9283g, No optical changes' } {'M2 - 312,6089g, No optical changes' } {'M3 - 279,9373g, NO optical changes' } {'03 10 hours (70)' } {'M1 - 276,9147g, No optical changes' } {'M2 - 312,9180g, No optical changes' } {'M3 - 280,1907g, No optical changes' } {'04 10 hours (80)' } {'M1 - 276,8916g, No optical changes' } {'M2 - 312,6759g, No optical changes' } {'M3 - 277,9216g, No optical changes' } {'05 10 hours (90)' } {'M1 - 277,0002g, No optical changes' } {'M2 - 312,8696g, No optical changes' } {'M3 - 277,9567g, No optical changes' } {'06 10 hours (100)' } {'M1 - 276,9059g, No optical changes' } {'M2 - 312,6947g, No optical changes' } {'M3 - 280,1065g, No optical changes' } {'07 50 hours (150)' }
i=3 % when your error occurs
i = 3
m1_points = extractBetween(data{i}, 'M1 - ', '\n')
m1_points = 0×1 empty cell array
The textscan function is not reading in newline characters, so nothing is getting extracted.
I would recommend moving away from using cells, and move towards strings. There are some great new functions for working with text that can simplifiy your code.
  • readlines instead of textscan
  • extractAfter instead of extractBetween
  • split instead of strsplit
  • startWith instead of isstrprop
clearvars
% read the file and split it into lines
data = readlines("Filename.txt", 'EmptyLineRule','skip','LineEnding','\r\n')
data = 101×1 string array
"General: xxx" "CC: 2000" "M1 - 277,2209g, OW I.D.xxx, no distinctive features, (160, 220, 295 ?) " "M2 - 312,4254g, OW I.D.xxx, no distinctive features, " "M3 - 277,7087g, OW I.D.xxx, no distinctive features, (230 ?)" "01 10 hours" "M1 - 277,4901g, No optical changes" "M2 - 312,7474g, No optical changes" "M3 - 278,4185g, No optical changes" "02 50 hours (60)" "M1 - 276,9283g, No optical changes" "M2 - 312,6089g, No optical changes" "M3 - 279,9373g, NO optical changes" "03 10 hours (70)" "M1 - 276,9147g, No optical changes" "M2 - 312,9180g, No optical changes" "M3 - 280,1907g, No optical changes" "04 10 hours (80)" "M1 - 276,8916g, No optical changes" "M2 - 312,6759g, No optical changes" "M3 - 277,9216g, No optical changes" "05 10 hours (90)" "M1 - 277,0002g, No optical changes" "M2 - 312,8696g, No optical changes" "M3 - 277,9567g, No optical changes" "06 10 hours (100)" "M1 - 276,9059g, No optical changes" "M2 - 312,6947g, No optical changes" "M3 - 280,1065g, No optical changes" "07 50 hours (150)"
% Initialize empty arrays for hours, M1, M2, and M3
hours = [];
m1 = [];
m2 = [];
m3 = [];
% Loop through each line of the data
for i = 1:length(data)
% If the line starts with a number, assume it's the hours
if startsWith(data(i), digitsPattern) && isempty(hours)
hours = str2double(split(data(i)));
% If the line starts with 'M1', extract the points of interest for M1
elseif startsWith(data(i), 'M1')
m1_points = extractAfter(data(i), 'M1 - ');
m1_points = split(m1_points, ', ');
m1 = [m1; m1_points];
% If the line starts with 'M2', extract the points of interest for M2
elseif startsWith(data(i), 'M2')
m2_points = extractAfter(data(i), 'M2 - ');
m2_points = split(m2_points, ', ');
m2 = [m2; m2_points];
% If the line starts with 'M3', extract the points of interest for M3
elseif startsWith(data(i), 'M3')
m3_points = extractAfter(data(i), 'M3 - ');
m3_points = split(m3_points, ', ');
m3 = [m3; m3_points];
end
end
m1
m1 = 174×1 string array
"277,2209g" "OW I.D.xxx" "no distinctive features" "(160" "220" "295 ?) " "277,4901g" "No optical changes" "276,9283g" "No optical changes" "276,9147g" "No optical changes" "276,8916g" "No optical changes" "277,0002g" "No optical changes" "276,9059g" "No optical changes" "276,8935g" "No optical changes" "277,0127g" "328?" "1mm" "276,8668g" "328 x1mm" "276,9018g" "328 x1mm" "389" "" "276,9222g"
m2
m2 = 200×1 string array
"312,4254g" "OW I.D.xxx" "no distinctive features" "" "312,7474g" "No optical changes" "312,6089g" "No optical changes" "312,9180g" "No optical changes" "312,6759g" "No optical changes" "312,8696g" "No optical changes" "312,6947g" "No optical changes" "314,7507g" "No optical changes" "314,6013g" "377?" "378?" "312,9095g" "377?" "378?" "315,0064g" "377?" "378?" "314,9719g" "378 x2mm" "399"
m3
m3 = 166×1 string array
"277,7087g" "OW I.D.xxx" "no distinctive features" "(230 ?)" "278,4185g" "No optical changes" "279,9373g" "NO optical changes" "280,1907g" "No optical changes" "277,9216g" "No optical changes" "277,9567g" "No optical changes" "280,1065g" "No optical changes" "278,7136g" "No optical changes" "278,5384g" "380?" "278,0906g" "380" "278,3670g" "304 x4mm" "380 " "280,4222g" "304 x4mm" "380" "404? " "278,1214g"
Awesome, I understand now that strings are better for textfiles. Many thanks.

Sign in to comment.

More Answers (1)

data = textscan(fid, '%s', 'delimiter', '\n');
The %s format always uses cell array of character vectors, never string(), so here data will be a cell with a single entry that contains a cell array of character vectors
data = data{1}; % extract cell array from textscan output
You strip off the outer layer so data will be a cell array of character vectors.
m1_points = extractBetween(data{i}, 'M1 - ', '\n');
data{i} would be one particular character vector. Now what is m1_points after this call?
newStr is a string array if str is a string array. Otherwise, newStr is a cell array of character vectors.
We showed that data{i} is not a string array, so newStr (the output from extractBetween) is going to be a cell array of character vectors even if only one match is found . Note that extractBetween() will find and extract multiple matches if they exist, even if the input is a single character vector, so the fact that you have a single character vector input is not enough to be sure that extractBetween will only find a single match.
Your code is obviously expecting that m1_points will be a character vector, rather than the cell array of character vectors that it actually is.

Products

Release

R2020b

Community Treasure Hunt

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

Start Hunting!