PSYCHTOOLBOX工具箱及MATLAB编程实例
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.6 过程控制

过程控制用于控制程序的流程,如不同条件下执行的代码片段不同,常用的过程控制结构有如下几种。

3.6.1 if条件语句

对于简单的if 条件语句,可采用如下形式(如果条件表达式expression 为值,则执行statements语句)

if expression, statements, end

对于复杂的if条件语句,可采用下面的形式(更具有可读性)。如果表达式expression1为真,则执行statements1语句并结束判断。如果表达式expression1为假,则判断表达式expression2是否为真,如果为真,则执行statements2语句并结束判断;如果表达式expression2为假,以此类推,如果所有带if字样的分支都不满足,则执行else后面的语句statements3(如果有else的话)。

if expression1
  statements1
elseif expression2
  statements2
else
  statements3
end

程序示例:根据学生编号的奇偶平衡反应按键。

if mod(subid,2) %被试编号存储在变量subid中
    correctKey=KbName('f'); %如果是奇数,正确按键为F键
else
    correctKey=KbName('j'); %否则,如是偶数,正确按键为J键
end

或者写成

if mod(subid,2),correctKey=KbName('f');else,correctKey=KbName('j');end

程序示例:根据IQ进行等级划分

if iq>=130
    desc='超常';
elseif iq>=120
    desc='优秀';
elseif iq>=110
    desc='良好';
elseif iq>=100
    desc='中上';
elseif iq>=90
    desc='中等';
elseif iq>=70
    desc='中下';
else
    desc='较差';
end

在上面的例子中,需要注意分界值应按一定顺序给出,否则可能会得不出正确结果。例如,下面代码中交换了分界值100和110的位置,当iq=115时,变量desc的值为“中上”。

if iq>=130
    desc='超常';
elseif iq>=120
    desc='优秀';
elseif iq>=100
    desc='中上';
elseif iq>=110
    desc='良好';
elseif iq>=90
    desc='中等';
elseif iq>=70
    desc='中下';
else
    desc='较差';
end

if条件语句还可以嵌套。假如,一个2×2实验设计,两个自变量的水平值分别用1和2来表示,我们通过if语句来设置需要呈现的图片名称(当然有更简单的方法实现),程序示例如下(其中v1和v2为两个自变量):

if v1==1
    if v2==1
      filename='f1.bmp';
    else
      filename='f2.bmp';
    end
else
    if v2==1
      filename='f3.bmp';
    else
      filename='f4.bmp';
    end
end

上面语句也可以利用关系运算符改写为如下形式:

if v1==1 && v2==1
    filename='f1.bmp';
elseif v1==1 && v2==2
    filename='f2.bmp';
elseif v2==1 && v2==1
    filename='f3.bmp';
else
    filename='f4.bmp';
end

3.6.2 switch条件语句

switch条件语句的结构如下:

switch switch_expr
 case case_expr
    statement1, ..., statement2
  case {case_expr1, case_expr2, case_expr3, ...}
    statement3, ..., statement4
  otherwise
    statement5, ..., statement6
end

根据表达式switch_expr的值转入对应的条件分支,即如果表达式switch_expr的值符合case_expr条件,则执行语句statement1, … statement2;如果符合case_expr1,case_expr2,case_expr3中任何一个条件,则执行语句statement3, …, statement4;当上述条件均不满足,并且有otherwise关键词时,则执行其后的语句statement5, …, statement6。在判断的过程中,按照case语句顺序,只要符合当前的case语句,则后面的case语句及otherwise语句均略过。

程序示例:根据月份字符判断季度

switch month_expr
    case {'Jan','Feb','Mar'}
      disp('First Season');
    case {'Apr','May','Jun'};
      disp('Second Season');
    case {'Jul','Aug','Sep'};
      disp('Third Season');
  case {'Oct','Nov','Dec'};
      disp('Fourth Season');
end

如果变量month_expr的值为“Jul”,则输出显示为:Third Season,可以在命令窗口中先对变量赋值,然后将上述代码粘贴至命令窗口中查看执行结果。

程序示例:假设一5点量表,根据其等级显示对应的文本描述

switch select
    case 1
      option='完全不同意';
    case 2
      option='基本不同意';
    case 3
      option='中立';
    case 4
      option='基本同意';
    case 5
      option='完全同意';
otherwise
      option='未做选择';
end

3.6.3 for循环语句

for循环结构如下:

for index = values
program statements
        :
end

其中values可以取以下三种形式:

(1)initval:endval,initval代表初始值,endval代表结束值,中间用冒号(:)隔开;

(2)initval:step:endval,step代表步长,前一种形式每次递增值为1,此处可以指定每次递增值,如果为负值,则递减;

(3)valArray,循环按列遍历数组中的值。注意:使用break可以提前中止for循环。

程序示例:计算1~100的和

sums=0;
for i=1:100
    sums=sums+i;
end
disp(sums);

程序示例:计算1~100间所有奇数之和

sums=0;
for i=1:2:100
    sums=sums+i;
end
disp(sums);

程序示例:计算1~100间5的倍数之和

sums=0;
for i=100:-5:1
    sums=sums+i;
end
disp(sums);

程序示例:数组值累加

sums=0;
for i=[27 34 18 19 52 25]
    sums=sums+i;
end
disp(sums);

程序示例:数组值累加

sums=0;
a=rand(3,5)
for i=a
    sums=sums+i;
end
disp(sums);

结果如下:

a =
    0.7513   0.6991   0.5472   0.2575   0.8143
    0.2551   0.8909   0.1386   0.8407   0.2435
    0.5060   0.9593   0.1493   0.2543   0.9293
    3.0694
    2.3689
    2.7981

程序示例:显示10以内的偶数

for i=1:10
    if mod(i,2)
      continue; %如果是奇数,则跳过,如果for循环存在嵌套,使用continue语句作用于
                  包含该语句的内层循环
    end
    disp(i);
end

3.6.4 while循环语句

while循环结构如下,只要条件表达式成立,就执行中间的语句,直至条件表达式不成立,循环中间需要改变表达式的值或使用循环中断指令(break),否则将有可能限于死循环。

while expression
program statements
        :
end

程序示例:循环显示文件信息,文件命名规则为,主文件名后加1, 2, 3, …, n后缀,通过函数exist判断文件是否存在,如果存在,则利用函数imfinfo显示文件信息;如果不存在,则中止循环。

filename='a1.bmp';
index=1;
while exist(filename,'file')
    imfinfo(filename)
    index=index+1;
    filename=['a' num2str(index) '.bmp'];
end

程序示例:计算1~100的累加和

i=1;
sums=0;
while i<=100
    sums=sums+i;
    i=i+1;
end
disp(sums);

程序示例:随机数累加,直至产生的随机数大于0.7

sums=0;
while 1
    a=rand
    if a>0.7
      break; %如果产生的随机数大于0.7,则跳出while循环,与continue类似,如果存在
              循环嵌套,则跳出包含该语句的内层的循环
    end
    sums=sums+a;
end
disp(sums);

3.6.5 try错误控制语句

结构如下,在处理程序代码program statements部分时如果发生异常,则由error-handling statements处的程序代码来处理。

try
  program statements
        :
catch exception
  error-handling statements
        :
end

程序示例:当读取图片文件出错时,处理是否因文件扩展名使用有误所造成的。

function d_in = read_image(filename)(文件位于Psyfeng\Little_Examples目录下)
[path name ext] = fileparts(filename); %将文件拆分为路径、前缀和后缀
try %尝试打开文件
  fid = fopen(filename, 'r');
  d_in = fread(fid);
catch exception %如果文件打开失败
  if ~exist(filename, 'file') %判断是否是因为未找到文件所致
      % 尝试改变文件的扩展名
      switch ext
      case '.jpg'   % Change jpg to jpeg
        altFilename = strrep(filename, '.jpg', '.jpeg')
      case '.jpeg'  % Change jpeg to jpg
        altFilename = strrep(filename, '.jpeg', '.jpg')
      case '.tif'   % Change tif to tiff
          altFilename = strrep(filename, '.tif', '.tiff')
      case '.tiff'  % Change tiff to tif
          altFilename = strrep(filename, '.tiff', '.tif')
      otherwise
        rethrow(exception);
      end
      %更改文件扩展名后再进一步尝试打开文件
      try
        fid = fopen(altFilename, 'r');
        d_in = fread(fid);
      catch
       %如果仍然无法打开文件,则抛出异常,由系统来处理
        rethrow(exception)
      end
    else %如果文件存在,但无法打开
      d_in=-1;
      return; %return语句可以提前返回(中止)某脚本或函数,其后的语句不管有多少均不再执行
    end
end