MATLAB教学__03Script Writing,Structured Programming and User-defined Function-撰写脚本,结构化编程和用户自定义函数


前言

大家好,我是Lau师傅,今天继续和大家分享知识。

本文是学习郭老师的MATLAB教程第三节过程中所做的笔记,内容涉及撰写脚本结构化编程用户自定义函数三个重要板块。

郭彦甫老师上课使用的版本:MATLAB R2014a

我学习时使用的版本:MATLAB R2022b


一、Script Writing-撰写脚本程式

1.MATLAB Script-MATLAB脚本程式

  • MATLAB脚本程式是一个包含一系列MATLAB命令的文档。

  • 更像是一个C/C++程序。

  • 脚本不用经过编译就可以执行(逐行读取执行),但是必须保存为.m格式的文件才能执行。

2.Start A Script(.m)File-新建脚本文档(.m)

点击左上角“新建脚本”,创建了一个脚本编辑器-untitled,然后拖动untitled窗口可以使之单独显示。

在这里插入图片描述
在这里插入图片描述

3.Script Editor-脚本编辑器

复制如下代码粘贴到脚本编辑器中:

for i = 1:10
    x = linspace(0,10,101);
    plot(x,sin(x+i));
    print(gcf,'-deps',strcat('plot',num2str(i),'.ps'));
end

在这里插入图片描述

脚本执行方法有两种:

  • (1)单击编辑器选项卡中的“运行”:

    在这里插入图片描述

  • (2)按下键盘上的“F5”键。

选择上述两种方法之一后,软件强制弹出如下脚本储存窗口,需要完成路径选择和命名工作,这里使用默认名称untitled。

在这里插入图片描述

若弹出如下窗口,选择“更改文件夹”即可。

在这里插入图片描述

脚本执行结果如下图所示。

在这里插入图片描述

思考:代码中的每个函数的分别是什么意思?

4.常用功能介绍

  1. 首先是查找function的功能:因为郭老师使用的是2014a版本,该功能键在界面上方,而我使用的是2022b版本,该功能键已经改变了位置,放到了命令行窗口的“fx”中,如下图所示。

    在这里插入图片描述

    以查找“cos”为例,点击“fx”,选择“数学——初等数学——三角学——cos”,如下图所示,显示cos函数的使用简介,然后双击cos即可输入cos。

    在这里插入图片描述

  2. 注释:如果有某些行的代码不需要执行,那么可以将它们注释掉,使用百分比符号%进行注释。方法:

    (1)选中代码后右键选择注释;

    (2)选中代码后按下快捷键Ctrl+R;

    (3)选中代码后鼠标单击编辑器-代码的注释按钮。

    在这里插入图片描述

    在这里插入图片描述

    取消注释也都有对应的方法:

    (1)选中注释后右键选择取消注释;

    (2)选中注释后按下快捷键Ctrl+Shift+R;

    (3)选中注释后鼠标单击编辑器-代码的取消注释按钮。

    注意编辑器-代码:

    在这里插入图片描述

  3. 分节:将代码分为几个部分称为节,在调试(debug)时非常有用。使用两个百分比符号+空格进行分节。方法:

    (1)在需要分节的地方单击右键,选择分节符;

    (2)在需要分节的地方按下快捷键Ctrl+Alt+Enter;

    (3)在需要分节的地方鼠标单击编辑器-节的分节符。

    在这里插入图片描述

    注意编辑器-节:

    在这里插入图片描述

  4. 调试(debug):对程序进行错误排查、修复、解决故障。

    断点(breakpoint):可以在调试过程中使用的方法,设置断点后,程序运行到断点行就暂停执行。

    在2022b版本当中,单击代码前的数字就可以设置断点。如下图所示,在第4行设置断点。

    在这里插入图片描述

    运行后效果如下图所示。

    在这里插入图片描述

    在这里插入图片描述

    再单击代码前的数字将断点取消,点击继续,则debug取消,全部运行。

    在这里插入图片描述

  5. 智能缩进、增加缩进、减少缩进

    在这里插入图片描述

脚本可以保存执行的程序指令,而命令行指令不能,所以建议以后都使用脚本进行程序编写,可以储存为文档随时查看使用。

5.Script Flow-脚本流程

通常来说,脚本从第一行运行到最后一行。

在这里插入图片描述

使用结构化编程(包括子进程、循环、条件等)能够让程序看起来更加简洁。


二、Structured Programming-结构化编程

1.Flow Control-流程控制

(1)Review

下表是MATLAB中使用的一些语法结构的review。

StructureMeaning
if,elseif,else如果条件为true,则执行语句
for按指定的次数执行语句
switch,case,otherwise执行几组语句中的一组
try,catch执行语句并捕获生成的错误
while在条件为true时,重复执行语句
TerminalMeaning
break终止 for 或 while 循环的执行
continue将控制权传递给 for 或 while 循环的下一个迭代
end终止代码块,或指示最后一个数组索引
pause暂时停止执行
return将控制权返回给调用函数
(2)Relational(Logical) Operators-关系(逻辑)运算符

我们把对逻辑关系进行判断的运算如a>10,a==10,a<10,a>=10,a<=10称为relational operation,即关系运算或者逻辑运算,其中用作逻辑判断的运算符号>,<,==等称为relational(logical) operator,即关系运算符或逻辑运算符。这些运算属于布尔逻辑体系,运算结果有2种,分别用1和0代指true(是)和false(非)。

如下表所示,是MATLAB中的常用的8种逻辑运算符。

Operator-运算符Meaning-含义
<小于
<=小于或等于
>大于
>=大于或等于
==等于
~=不等于
&&
l l或(两根竖线)

注意:

(1)a=10,这里单独的等号是assignment赋值运算。

(2)MATLAB的不等于是~=,而C语言的不等于是!=,二者写法不一样。

2.常用的结构化编程语法

所有结构化编程的语法都必须配有相应的结束指令terminal,如if用end(end of some structured programming command)结束。

注意:一般将if,switch称为分支结构,将for,while称为循环结构。

(1)if,elseif,else

在这里插入图片描述

如果条件1为true,那么执行语句1;如果条件1不为true,那么检查条件2,条件2为true则执行语句2;如果所有条件都不符合即条件1和2都不为true,则执行语句3;最后执行end结束指令。

“elseif”和“else”都是可选择的。

请练习下列代码:

a = 3; % a赋值实数3
if rem(a,2) == 0 % rem取余数,判断a/2的余数是否为0,为0则true,为1则false
    disp('a is even') % a/2的余数为0则显示a is even
else % a/2的余数不为0即为1时
    disp('a is odd') % a/2的余数不为0时显示a is odd
end % 结束指令

执行结果在命令行窗口显示:

在这里插入图片描述

可以发现,结构化编程能够跳过某行指令,直接执行后面的指令。

(2)switch

switch与if else的不同在于它不是条件判断true/false,而是判断数值,依据数值选择执行几组语句中的某一组。

在这里插入图片描述

判断expression的数值,如果值为value1,则执行语句1,如果值为value2,则执行语句2,…,如果以上值都不满足,则执行最后的语句,然后执行end结束指令。

请练习如下代码:

input_num = 1; % input_num赋值为实数1
switch input_num % 判断input_num数值
    case -1 % 如果input_num数值为1
        disp('negative -1'); % 则执行,显示negative -1
    case 0 % 如果input_num数值为0
        disp('zero'); % 则执行,显示zero
    case 1 % 如果input_num数值为1
        disp('positive 1'); % 则执行,显示positive 1
    otherwise % 如果input_num数值不为1,0,-1
        disp('other value'); % 则执行,显示other value
end % 结束指令
(3)while

在这里插入图片描述

当条件表达式expression为true时,执行语句,当条件不为true时,执行end结束指令。

请练习下列代码:

n = 1; % n赋值为实数1
while prod(1:n) < 1e100 % prod返回数组元素的乘积,判断数组元素的乘积是否小于1e100,即prod(1:n)=prod([1 2 3 ... n])=1x2x3x...xn=n!
    n = n + 1; % n!小于1e100时,n递增1
end % n!不小于1e100时跳出循环,结束指令,n有最大值

结果如下图,可知,最大69!<1e100

在这里插入图片描述

Exercise-练习
  • 使用while循环计算1+2+3+…+999的和

    % 我练习写的代码
    n=1;
    sum=0;
    while n<1000
        sum=sum+n;
        n=n+1;
    end
    disp(sum);
    
(4)for

在这里插入图片描述

在变量从start到end以increment为间隔变化时,执行commands语句,最后执行end结束指令。

请练习下列代码,思考若n取1、3、5、7、9时应如何修改:

for n =1:10 % 变量n从1到10变化,步长为1。见“冒号运算符”
    a(n) = 2^n; % n每次变化,求a(n) = 2^n
end % 结束指令
disp(a); % 显示a

在这里插入图片描述

当n取1、3、5、7、9时,若修改如下:

for n =1:2:10 % n取1、3、5、7、9
    a(n) = 2^n; % a(1)、a(3)、a(5)、a(7)、a(9)
end
disp(a);

在这里插入图片描述

显然不是我们所想要的结果,a(2)、a(4)、a(6)、a(8)自动补零了,思考如何修改?

我的修改如下:

clear;
for n = 1:2:10
    a((n+1)/2) = 2^n;
end
disp(a);

在这里插入图片描述

或者

clear;
for n = 1:5
    a(n) = 2^(2*n-1);
end
disp(a);

或者

clear;
i = 1;
for n =1:2:10
    a(i) = 2^n; 
    i=i+1;
end
disp(a);
Exercise-练习

如下图示,使用结构化编程完成:

  1. 将矩阵A的元素复制给矩阵B;

  2. 如果矩阵A中的相应元素为负数,则更改矩阵B中的值。

提示:使用for循环就可以完成。

在这里插入图片描述

下面是我练习写的代码:

clear;
A = [0 -1 4;9 -14 25;-34 49 64]; % 创建矩阵A
B = A % 把A复制给B
for n = 1:9 % 遍历A的每一个元素
    if A(n)<0 % A某元素为负时
        B(n)=-B(n); % 将B对应的元素变为正
    end
end
disp(B); % 显示更改后的B

运行结果:

在这里插入图片描述

(5)终止符
1)break

break可以终止执行for或while循环,不执行循环中在break语句之后显示的语句,可以用来避免电脑宕机、陷入死循环等情况。

在这里插入图片描述

如上图所示,当条件error>error_threshold成立时,执行while循环内的语句。通常我们还会在循环内加入其它的判断,当k>100成立时,执行break直接跳到end终止while循环而不执行循环中break之后显示的语句。

3.Pre-allocating Space to Variables-给变量预分配空间

在之前的例子中,我们没有预先分配空间给a,而是让MATLAB在每次迭代时调整其大小,那么哪种方法更快?

下图中,A方法无预分配,B有预分配,那么哪种方法更快?

在这里插入图片描述

如何得知MATLAB的程序执行花费的时间?这里使用了tic(开始计时)和toc(结束计时)来计算执行用时。

clear;
tic; % 开始计时
for ii = 1:2000
    for jj = 1:2000
        A(ii,jj) = ii + jj;
    end
end
toc; % 结束计时
clear;
tic; % 开始计时
A = zeros(2000,2000); % 创建2000x2000的全零数组
for ii = 1:size(A,1) % size(A,1)返回A的第1个维度的长度即2000
    for jj = 1:size(A,2) % size(A,2)返回A的第2个维度的长度即2000
        A(ii,jj) = ii + jj;
    end
end
toc; % 结束计时

结果如下图所示:

在这里插入图片描述

可以看到,分别运行两节时的时间相差还是很大的,显然预分配节省了很多时间,建议自己练习感受一下。

因此,建议在能够得知变量大小的情况下尽量进行预分配空间的操作

4.Tips for Script Writing-对于撰写脚本的建议

  • (1)在脚本开头,使用指令

    • clear all来清除之前的变量

    • close all来关闭所有图形窗口

  • (2)在命令末尾使用分号 ; 来禁止不需要的输出

  • (3)当指令过长时,可以使用省略号 … (起到换行的作用)来使脚本更具可读性

    在这里插入图片描述

  • (4)如果出现宕机,按快捷键 Ctrl+C 在结束前终止脚本

  • (5)使用clc来清除命令行窗口历史


三、User-defined Function-用户自定义函数

脚本和函数都是包含MATLAB指令的.m文件,有时我们经常使用某些指令,把这些指令写成函数就能使工作方便很多。

ScriptsFunctions
无输入参数有输入参数
无输出参数有输出参数
在全局工作区中操作数据在本地工作区中操作数据

1.Concent of MATLAB Built-in Functions-MATLAB内置函数的内容

我们求平均用到的mean就是一个函数function,这是MATLAB内置的函数。

在命令行窗口输入edit(which('mean.m')可以打开mean函数的.m文件,查看mean函数的内容。

在这里插入图片描述

在第一行看到function y = mean(x,dim,flag,flag2),蓝色的function是关键字,括号内的x,dim,flag,flag2为输入参数,y为输出参数,mean是函数名称。

在这里插入图片描述

所以,函数格式如上图所示,keyword output = function_name(input)关键字 输出参数 = 函数名(输入参数),其中function_name函数名和file_name文件名相同,然后下面是注释和代码。

呼叫mean函数时,首先执行下面的代码,然后将数值给到yy再给到命令行窗口或者其他呼叫mean函数的脚本中。

Some Observation-一些观察
  • 关键字:function

  • 函数名称和文件名称相匹配

  • 目录:MATLAB需要找到这个函数

  • 输入和输出变量可选

  • 本地变量:dimflag不能被访问

2.User Define Functions-用户定义函数

(1)

写一个计算自由落体运动的位移x的函数,给定初始位移 x0、初始速度 v0 和下落持续时间 t ,那么初始位移 x0、初始速度 v0 和下落持续时间 t是输入参数,待计算的位移x是输出参数,函数名称是freebody

在这里插入图片描述

function x = freebody(x0,v0,t)
% calculation of free falling
% x0: initial displacement in m
% v0: initial velocity in m/sec
% t: the elapsed time in sec
% x: the depth of falling in m
x = x0 + v0.*t + 1/2*9.8*t.*t;

在新建脚本中输入这些代码,然后保存,默认会保存文件名和函数名相同。

此时,我们注意到代码中使用了点乘.*(见MATLAB教学02),为什么要用点乘?

我们知道计算不同角度(1,2,3,4,5)的cos值可以使用cos([1,2,3,4,5]),那么计算不同x0v0t也可以同理,即使用freebody([0 1],[0 1],[10 20])同时计算了x0=0v0=0t=10x0=1v0=1t=20两种情况的结果,这是使用点乘的情况。但是如果不使用点乘,只使用乘法即x = x0 + v0.*t + 1/2*9.8*t*t则运行freebody([0 1],[0 1],[10 20])会出错,t*t计算不出来,如下图所示。

在这里插入图片描述

(2)Functions with Multiple Inputs and Outputs-具有多个输入和输出的函数

粒子的加速度和作用在它身上的力如下图所示。要求写一个计算粒子的加速度a和作用在它身上的力F的函数,输入参数为末速度v2、初速度v1、末时间t2、初时间t1、质量m,输出参数为加速度a和力F,函数名称是acc

在这里插入图片描述

输出参数有2个,如何读取到呢?用中括号[]括起来。注意,这里我们使用了点除./和点乘.*

function [a F] = acc(v2,v1,t2,t1,m)
a = (v2-v1)./(t2-t1);
F = m.*a;

使用时要写2个输出如[Acc Force] = acc(20,10,5,4,2)

Exercise-练习

在这里插入图片描述

写一个函数,要求输入温度(以华氏温度°F为单位),然后计算对应的摄氏温度(C=(F-32)*5/9),最后显示换算的摄氏温度是多少。这个函数应当保持执行直到没有可供转换的数。你可能会使用到这些函数:inputisemptybreakdispnum2str。效果如下图所示。这个练习有一定难度,请一定要经过自己的思考

在这里插入图片描述

下面是我练习写的代码:

function [] = F2C(~)
% F2C无输入、无输出
% tem_F表示华氏温度,tem_C表示摄氏温度
while 1 % 表示无限循环,重复执行
    prompt = "Temperature in F is "; % prompt是显示给用户的提示文本
    tem_F = input(prompt); % 要求用户输入,输入记为tem_F
    if isempty(tem_F) % isempty判断数组是否为空,即判断tem_F是否为空
        break % tem_F为空时,跳出while循环
    end % 终止if
    tem_C = (tem_F-32)*5/9; % 华氏度到摄氏度的转换公式
    Tem_C = ['==>Temperature in C is ',num2str(tem_C)]; % num2str将数字tem_C转换成字符串放在Tem_C中,再用在disp中
    disp(Tem_C); % 显示Tem_C的内容
end % 终止while
end % 终止function

执行结果:

在这里插入图片描述

3.Function Default Variables-函数默认变量

VariableMeaning
inputname函数输入的变量名
mfilename当前执行函数的文件名
nargin函数输入参数的数量
nargout函数输出参数的数量
varargin变量长度输入参数列表
varargout变量长度输出参数列表

在这里插入图片描述

如上图所示,函数pillar,当nargin=2输入参数2个时,默认height=1

4.Function Handles-函数句柄

函数句柄是一种表示函数的 MATLAB 数据类型,一种创建匿名函数的方法,即不必在m文档中定义的一行表达式函数。函数句柄还是一种指针pointer。

在这里插入图片描述

命令行窗口执行后在工作区查看变量f,类型为function_handle。将f指向exp(-2*x)f的输入为x。即输入的x为向量,输出的f(x)x的数学函数也是向量,可以plot出来。

在这里插入图片描述


总结

以上就是本节课程的全部内容,如有错误望指出。之后陆续上传后面章节的笔记和PDF版本,欢迎大家关注。

MATLAB教程地址

我最常用的写作开源软件Marktext的介绍、下载、安装与设置

MATLAB教学__01学习导览
MATLAB教学__02MATLAB as A Calculator and Array Operation-计算器与矩阵操作
MATLAB教学__03Script Writing,Structured Programming and User-defined Function-撰写脚本,结构化编程和用户自定义函数

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lau师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值