Search code examples
matlabsyntaxswitch-statementboolean-expression

MATLAB only runs first case in a switch-case block


I am trying to separate data from a csv file into "blocks" of data that I then put into 10 different categories. Each block has a set of spaces at the top of it. Each category contains 660 blocks. Currently, my code successfully puts in the first block, but only the first block. It does correctly count the number of blocks though. I do not understand why it only puts in the first block when the block count works correctly, and any help would be appreciated. The csv file can be downloaded from here. https://archive.ics.uci.edu/ml/machine-learning-databases/00195/

    fid = fopen('Train_Arabic_Digit.txt','rt');
traindata = textscan(fid, '%f%f%f%f%f%f%f%f%f%f%f%f%f', 'MultipleDelimsAsOne',true, 'Delimiter','[;', 'HeaderLines',1);
fclose(fid);
% Each line in Train_Arabic_Digit.txt or Test_Arabic_Digit.txt represents 
% 13 MFCCs coefficients in the increasing order separated by spaces. This 
% corresponds to one analysis frame. Lines are organized into blocks, which
% are a set of 4-93 lines separated by blank lines and corresponds to a 
% single speech utterance of an spoken Arabic digit with 4-93 frames.
% Each spoken digit is a set of consecutive blocks.
% TO DO: how get blocks...split? with /n?
% In Train_Arabic_Digit.txt there are 660 blocks for each spoken digit. The
% first 330 blocks represent male speakers and the second 330 blocks 
% represent the female speakers. Blocks 1-660 represent the spoken digit 
% "0" (10 utterances of /0/ from 66 speakers), blocks 661-1320 represent
% the spoken digit "1" (10 utterances of /1/ from the same 66 speakers 
% 33 males and 33 females), and so on up to digit 9.
 content = fileread( 'Train_Arabic_Digit.txt' ) ;
  default = regexp(content,'\n','split');
  digit0=[];
  digit1=[];
  digit2=[];
  digit3=[];
  digit4=[];
  digit5=[];
  digit6=[];
  digit7=[];
  digit8=[];
  digit9=[];
  blockcount=0;
  a=0;
  for i=1:1:length(default)
      if strcmp(default{i},'            ')
          blockcount=blockcount+1;
      else
          switch blockcount % currently only works for blockcount=1 even though
              %it does pick up the number of blocks...
              case blockcount>0 && blockcount<=660 %why does it not recognize 2 as being<660
                  a=a+1;
                  digit0=[digit0 newline default{i}];
              case blockcount>660 && blockcount<=1320
                  digit1=[digit1 newline default{i}];
              case blockcount<=1980 && blockcount>1320
                  digit2=[digit2 newline default{i}];
              case blockcount<=2640 && blockcount>1980
                  digit3=[digit3 newline default{i}];
              case blockcount<=3300 && blockcount>2640
                  digit4=[digit4 newline default{i}];
              case blockcount<=3960 && blockcount>3300
                  digit5=[digit5 newline default{i}];
              case blockcount<=4620 && blockcount>3960
                  digit6=[digit6 newline default{i}];
              case blockcount<=5280 && blockcount>4620
                  digit7=[digit7 newline default{i}];
              case blockcount<=5940 && blockcount>5280
                  digit8=[digit8 newline default{i}];
              case blockcount<=6600 && blockcount>5940
                  digit9=[digit9 newline default{i}];
          end
      end
  end

Solution

  • That's because you have somehow confused if-else syntax with switch-case. Note that an expression like blockcount>0 && blockcount<=660 always returns a logical value, meaning it's either 0 or 1. Now, when blockcount is equal to 1, first case expression also results 1 and the rest result 0, so, 1==1 and first block runs. But when blockcount becomes 2, the first case expression still results 1 and 2~=1 so nothing happens!

    You can either use if-else or change your case expressions to cell arrays containing ranges of values. According to docs:

    The switch block tests each case until one of the case expressions is true. A case is true when:

    • For numbers, case_expression == switch_expression.

    • For character vectors, strcmp(case_expression,switch_expression) == 1.

    • For objects that support the eq function, case_expression == switch_expression. The output of the overloaded eq function must be either a logical value or convertible to a logical value.

    • For a cell array case_expression, at least one of the elements of the cell array matches switch_expression, as defined above for numbers, character vectors, and objects.

    It should be something like:

    switch blockcount
      case num2cell(0:660)
        digit0 ...
      case num2cell(661:1320)
        digit1 ...
      ...
    end
    

    BUT, this block of code will take forever to complete. First, always avoid a = [a b] in loops. Resizing matrices is time consuming. Always preallocate a and do a(i) = b.