Professional Documents
Culture Documents
校计算机技术“十二
3.5 程序调试 五”规划教材
用户也可以结合自己的工作需要,开发自己的函数程序或工具箱
3.1 M 文件建立
1. M 文件 Matlab 语言编写的程
序
① Matlab 命令和函数组合构成,可完成某操作和算法
② 存储文本文件,扩展名为 .m 的 M 文
件;
③ 文本编辑器: M 文件编辑器
windows 的记事本
word 文件
④ M 文 件 分 Script 脚本文 Function 函数文
件 件
类:
2.M 文件建立和打开 M 文件编辑器
(1) 新建 M 文件 ( 2 )打开 M 文件
命令按钮 : 快捷键
菜单操作 : 新建 打开
3 . M 文件保存和搜索路径
M 文件应保存在搜索路
显示 M 文件路径:which filename
径或当前目录,才能在
命令窗口调用运行
设定当前目录: cd d:\myfile
删除 rmpath(' folder
path')
4. 显示 M 文件内容
调用格式: type M 文件 命令窗口显示
r=22; % 半径,程序中赋值
s=pi*r*r ; % 计算圆面积 s文件主体 实现脚本文件功能的指令组成;
运行后所有变量驻留在基本工作空间( base
workspace )
3. 数据输入
① 编程中直接赋值给输入变量值
clear >> rsp % 调用程序结果
r=33 % 程序中赋值输入变量 s = 3.4212e+003
s=pi*r*r 保存 p = 207.3451
p=2*pi*r rsp
② 程序运行中从键盘敲数据给输入变量
Input 在程序运行中从键盘输入数据给变量
r=input('r=') % 从键盘赋值输入变 >> rspi % 调用程序结果
量 r=33
s=pi*r*r 保存 rspi s = 3.4212e+003
p=2*pi*r p = 207.3451
此程序编写只针对一个标量运算,所以运算符无
所谓矩阵运算符还是数组运算符
保存 rspi
r=input(‘r=’);
r=input('r=');
s=pi*r.*r ; % 数组运算
s=pi*r*r ; 修改为
p=2*pi*r;
p=2*pi*r;
批量重复运算应为是数组运算
>> rspis % 调用程序
结果
>> rspi % 调用程序结果
r=1:2:6;
r=33
>> p
s = 3.4212e+003
p = 6.2832 18.8496
p = 207.3451
31.4159
数值运算大部分为数组运算 >> s
s = 3.1416 28.2743
78.5398
数据输入格式 从键盘给变量 A 输入数据
编程命令行末加‘;’, 运行结果:
结果不显示在命令窗, >> rspid
但存在内存空间 r=22
s=1520.5308,p=138.2301
5. 命令窗口格式化数据输出 fprintf
将变量 A 按指定格式 format 输到命令窗口显
示
fprintf( format, 程序 rspif:
r=input('r=');
A) : 指定数据输出格式 , 必须有 %
format s=pi*r.*r;
%d 整数 p=2*pi*r;
%e 实数:科学计算法形式 fprintf('%e',s);
%f 实数:小数形式
%g 由系统自动选取上述两种格式之一 fprintf('%f',s);
%s 输出字符串 运行结果:
A :要输出的数据变量 >>rspif
r=22
1.520531e+03
例
例 创建一个字符矩阵并存入磁盘,
再读出赋值给另一个矩阵。
>> a='string';
>> fid=fopen('d:\char1.txt','w');
>> fprintf(fid,'%s',a);
>> fclose(fid);
>> fid1=fopen('d:\char1.txt','rt');
>> b=fscanf(fid1,'%s')
6. 脚本文件特点
① 一串命令行简单叠加的集合;
② 自动按顺序执行文件的命令;
特征向量 v 和特征
③ 不需要输入和输出量; 值 d [v,d]=eig(a)
④ 变量一旦生成,一直保留 workspace 工
作空间中(内存空间),除非 clear 和退
出;
⑤ 所有变量均为全局变量。
3.3 函数文件格式
求半径为 r 的圆的面积和周长
例 编写函数文件格式
function [s,p]=fcircle(r) 函数定义行
% FCIRCLE calculate the area and perimeter of a circle of radii r
H1 注释行 调用、运行、工作
%r 圆半径 空间、变量及存储截然
不同于脚本文件
%s 圆面积
帮助文本区
%p 圆周长
% 2017 年 7 月 30 日编 函数文件 fcircle
s=pi*r.*r; % 计算圆面积 s
函数体
p=2*pi*r; % 计算圆周长 p 脚本文件 fcircle
end
常用开发应用程序
3.3 函数文件 和扩充 MATLAB 函
数库
3.3.1 函数文件
3.3.2 全局变量和局部变量
3.3.3 子函数与主函数
3.3.4 函数句柄和匿名函数
Matlab 提供内部函数以及各种工具箱,都是利用 Matlab 语言开发的 M 函
数文件
3.3.1 编写函数文件
1. function 定义行
function 输出形参数 = 函数名 ( 输入形参
数)
第一行 function 引导词,表示是函数文件 ;
列出函数与外界联系的全部输入 / 输出形参数;
输出多个参数应写作行向量,用方括号 [v1,v2] ;
输入 / 输出量可有可
无
① 全部输入输出量 另存
function [s,p]=fcircle (r) fcirlce
s=pi*r.*r; 运行结果
p=2*pi*r; >> [s,p]=fcircle(22)
s = 1.5205e+03
end p = 138.2301
② 少部分输出量
function p=fcircle1(r)
s=pi*r.*r; 另存 fcirlce1
p=2*pi*r;
运行结果
end >> pp=fcircle1(22)
pp = 138.2301
输出量可有可无
function ex_18(a,b)
x=a:0.1:b; 1.45
y1=sin(x); 1.4
y2=cos(x); 1.35
y=y1-y2; 1.3
plot(x,y) 1.25
end 1.2
1.15
1.1
2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3
2. 函数调用
① 调用格式:[ 输出实参数 ]= 函数名 ( 输入实参
数)
编写函数 function [s,p]=fcircle(r)
函数调用时实参数名与函数定义时形参数名可以一致
函数调用时,先将实参传递给相应的形参,从而实现参数传递,然后再执行函数的功
能。
② 函数调用特点
I. 函数调用时实参数名可以与函数定义时形参数名一致,也可以不一致
输入个数 nargin(‘ 函数
名’ )
输出个数 nargout(‘ 函数
名’ )r = roots(c)
nargin('roots')
ans = 1
nargout('roots')
输入个数不确定
ans = 1
显示负值
nargin(‘plot') ans = -1
function [x,n]=jacobi(A,b,x0,eps)
if nargin= =3
eps=1.0e-6; % 迭代精度 >> nargin('jacobi')
例 elseif nargin<3 ans = 4
error >> nargout('jacobi')
return
ans = 2
end
Jacobi D=diag(diag(A)); % 求系数矩阵 A 的对角矩阵
L=-tril(A,-1); % 求 A 的下三角阵
迭代法
U=-triu(A,1); % 求 A 的上三角阵
求解线 B=D\(L+U);
性方程 f=D\b; %b 常数列向量
x=B*x0+f; % 迭代解 运行结果
的函数
n=1; % 迭代次数 >> A=[10,-1,0;-1,10,-2;0,-2,10];
文件 : b=[9,7,6]';
while norm(x-x0)>=eps [X,n]=jacobi(A,b,[0,0,0]',1.0e-6)
x0=x; X =0.9958
x=B*x0+f; 0.9579
n=n+1; % 迭代次数 0.7916
end n = 11
④ 脚本文件和函数文件的区别
脚本式 M 文件 函数式 M 文件
无函数定义行; 有函数定义行;
无输入和输出量 可有输入和输出变量
在 base workspace 中数据操作,中间变量存在临时工作空间,
运行后变量驻留其中; 它随函数结束而删除;
全局变量。 局部变量,除特别声明。
3.3.2. 全局变量和局部变量
1. 全局变量:
① 所有变量驻留在基本工作空间中,即全程有效;
② 所有函数都可对其进行存取和修改;
③ 定义全局变量是函数之间传递信息的手段。
实际编程时,尽量
避免使用全局变
量,不安全
2. 局部变量
① 仅在函数工作空间存在中间变量,影响仅限于函数本
身;
② 函数文件变量不能直接访问 workspace 中的全局变
量,它只能读取通过参数传入的变量;
③ 函数文件中定义的变量不能被另一个函数文件引用;
④ 如果在若干函数中,把某个变量定义为全局变量,那么
这些函数可以共用这个变量。
在 matlab 中,函数内部定义的变量除特殊声明外均为局部变量
3. 定义全局变量 global
调用格式: global 变量名 全局变量名一般大写字母;
(1) 编写矩阵元素和的均值程 变量之间以空格分隔
序
function avgs=test4(A)
( 2 )调用 test4 :
global S SS % 定义全
局变量 例 >> A=[4 3 5;6 7 8;3 5 7;1 3 4];
[m,n]=size(A); >> test4(A)
ans = 4.6667
for i=1:m
s(i)=sum(A(i,:)) % 每行 ( 3 )命令窗口中定义 S 和 SS 为全局变
量:
的和 >> global S SS
end >> ss
ss=sum(s) % 矩阵和 ss = 56
avgs=ss/(m*n) % 矩阵和 >> s
的平均值 s = 12 21 15 8
6/29/22 04:40 PM 31
end
如需某个变量在几个函数或 MATLAB 命令窗口中被使用,则用 global 在函数
编程和 MATLAB 命令窗口中都要声明该变量为全局变量。
3.3.3 主函数与子函数
一个 M 文件可含多个函数 , 第一个主函数 , 其它子函
数;
主函数必须在最前面,子函数次序可随意调整;
function
子函数仅被主函数或同一文件其它子函数所调用;
c=test(a,b) % 主函数
c=test1(a,b)*test2(a,b);
end 例
function c=test1(a,b) % 子函数 1
c=a+b;
end
function c=test2(a,b) % 子函数 2
c=a-b; 子函数则只能在主
end 函数文件中编辑
6/29/22 04:40 PM 32
3.3.4 函数句柄和匿名函数
1. 函数句柄 : 携带函数路径的函数,反复调用方便,
像变量调用。 x
函数表达式 y x 10
① 两种创建句柄: function fv=fun(x)
fv=x-10.^x ;
end 定义函数文
hfun=@+ 函数名 件
>> hfun=@fun
>> hfun=str2func(‘fun’)
hfun=str2func(‘fun’)
>>class(hd)
ans =function_handle
② 函数句柄调用:
直接调用: 调用与函数一样,句柄变量名取代函数名
[y1, y2, ..] = hfun( x1, ..., xn)
格式: f= @ (xlist)expression
① 以 @ 符号开头;
② xlist 为输入参数列表 yyy=@(x)x-10^x
③ expression 为表达式的函数体
调用和函数句柄一样: ff=@(x)x-10^x
>> ff(2) 或者 >> feval(ff,2)
x=0:0.1:1;
y1=sin(x);
y2=cos(x);
3.4 y=y1-y2;
最简单的程序结构,自动按 plot(x,y)
顺序结构 顺序执行文件的命令
程
序
控 3.4.1 条件(选择)结构
制
结 3.4.2 循环结构
构
3.4.3 try-catch 结构
3.4.1 选择(条件)结构
选择结构 : 根据给定条件成立与否,执行不同语句
选择结构的语句 :
if 语句 根据逻辑条件判断执行语句
switch 语句 根据条件值选择执行语句
1. if 条件语句
(1) 单分支结构
if expression (条件表达式:关系和逻辑运算
符)
statements (语句组 A )
end
(2) 双分支结构
if expression (条件)
statements1 (语句组 A )
else
statements2 (语句组 B )
end
x
2
x0
例计算分段函数值
例 y e
2
ln( x 1 x ) 0 > x
x=input(' 请输入 x 的值 :');
if x<=0
y=(x+sqrt(pi))/exp(2);
else
y=log(x+sqrt(1+x*x))/2;
end
fprintf('y=%e',y) %e 科学计算法形式实数输出
(3) 多分支结构
if expression1 (条件 1 )
statements1 (语句组 1 )
先
后
elseif expression2 (条件 2 ) 顺
序
依
statements2 (语句组 2 ) 次
进
行
... ...
elseif expressionm (条件 n )
statementsm (语句组 n )
else
statements (语句组 n+1 )
end
用条件语句 if 编写分段函数计算程序 , 分别求 (1)x=- 2 (2)x=
例 数 f 的值
x 2 3* x 5 x0
2
分段函 f ( x) x 2 * x 6 0 x 5
数 x 2 5* x 6 5x>5
x
解: (1) 编写 M 文件
x=input(' 请输入 x 的值 :');
if x<=0
(2) 调用函数的运行结果:
y=x^2+3*x-5 请输入 x 的值 :-2
elseif x<=5 &x>0 y = -7
y=x^2-2*x+6; y=-7.000000e+000
else 请输入 x 的值 :5
y=2.100000e+001
y=x^2-5*x-6;
end
fprintf('y=%e',y)
2. switch 开关语句 数控的多路开关
1. switch 语句结构
switch expression (开关表达式) 2. switch 语句特点
case value1 (表达式 1 )
statement1 (语句组 1 )
先按给定的变量计算开关表达
case value2 (表达式 2 ) 式 expression 的条件值,这
statement2 (语句组 2 ) 个值可以是标量也可以字符串
... ... 依次与各 case 指令比
case valuem (表达式 m ) 较。 Case 指令可以是标量或
statementm (语句组 m ) 字符串,
otherwise
还可以单元数组(元胞数组)
statement (语句组 n )
比较结果为真时,执行相应语
end
句,再跳出 switch 结构。
条件值
如多条 case 语句为真,也只执
行所第一条为真的语句。
结果都为假,执行 otherwise
后的语句,再跳出 switch 。
根据评分原则:大于等于 90 分为 A ,大于等于 80 分为 B,
大于等于 70 分为 D ,大于等于 60 分为 C ,小于 60 分不
例 合格 (E2 ) switch 语句编
例 ( 1 ) if 语句编
写
function result=grade(per)
写
k=floor(per/10) % 开关表达式 function result=grade(x)
switch k if x>=90
case {9,10} floor 向负无穷取整 result='A';
result='A'; elseif x>=80
case 8 result='B';
result='B'; elseif x>=70
case 7 result='C';
result='C'; elseif x>=60
case 6 result='D';
result='D'; else
otherwise Case 语句表示数的result='E';
result='E'; end
end 范围采用 {}
( 3 ) switch 语句 per=input(' 输入成绩 ')
k=floor(per/10)
编写
switch k
第二种方法 case {9,10}
disp('A')
case 8
disp('B')
case 7
disp('C')
case 6
disp('D')
otherwise
disp('E')
end
3.4.2 循环结构
循环结构 : 按照给定的条件,重复执行指定的语
句。 Jacobi 迭代法求解线性方程的函数文件
循环结构的语 function [x,n]=jac(A,b,x0,eps)
if nargin==3
句: eps=1.0e-6; % 迭代精度
elseif nargin<3
for 语句 error
return
end
D=diag(diag(A)); % 求 A 的对角矩阵
L=-tril(A,-1); % 求 A 的下三角阵
U=-triu(A,1); % 求 A 的上三角阵
while 语句 B=D\(L+U);
f=D\b;
常用累计求和 x=B*x0+f; % 迭代解
n=1; % 迭代次数
求迭代等 while norm(x-x0)>=eps
x0=x;
x=B*x0+f;
n=n+1;
1. for 循环
figure(1) 0.6
figure(2) 0.4
0
0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5
4
x 10
3.break 和 continue
它们一般与 if 配合使用。
break 终止循环,即跳出该层循环 ;
continue 结束本次循环,进行该层下次循环 .
例
例
求 [100 , 1000] 之间第一个能被 21 整除的整数。
for n=100:1000
if rem(n,21)~=0
continue Rem 除法求余
end
break
end
n
3. while 循环 < 逻辑判断语句
>
while expression ( < 逻辑变量 > )
statement (执行语句的循环体)
end
例 编程: 求 n 为多少
n=0; 时, 2^n>100, 其
while 2^n<100
值多少
s=2^n; 运行结果
n=n+1 ; >>Ss = 128
end n= 7
Ss=2*s >> s
n s = 64
function [x,n]=jaco(A,b,x0,eps)
if nargin==3
eps=1.0e-6; % 迭代精度
elseif nargin<3
error
return
end
D=diag(diag(A)); % 求 A 的对角矩阵
L=-tril(A,-1); % 求 A 的下三角阵
U=-triu(A,1); % 求 A 的上三角阵
B=D\(L+U);
f=D\b;
x=B*x0+f;
n=1; % 迭代次数
while norm(x-x0)>=eps Jacobi 迭代法的
x0=x; MATLAB 函数文件
x=B*x0+f; Jacobi.m
n=n+1;
end
4.for 和 while 循环语句区别
for 适用已知到循环次数,而不知循环运算目标;
while 适用已知循环运算目标,而循环次数未知 ;
6/29/22 04:40 PM 55
63
计算级数 :S=1+2+2 +2 +···+2 =
n
例 2 3 2 63
例 n 0
6/29/22 04:40 PM
56
从键盘输入若干个数,当输入 0 时结束输入,求
例
例 这些数的平均值和它们之和。
sum=0;
cnt=0;
val=input('Enter a number (end in 0):');
while val~=0
sum=sum+val;
cnt=cnt+1;
val=input('Enter a number (end in 0):');
end
if cnt > 0
sum
mean=sum/cnt
end
总结
3.4.3 try-catch 语句
语句格式 Try
try ① 检测程序代码是否出
语句组 1
错;
catch
语句组 2 ② 先试探语句组 1 ,如出
end 现错误,则将错误信息
赋给 lasterr 保留;
lasterr % 显示出错原因
③ 并转去执行语句组 2 。
矩阵乘法运算要求两矩阵维数相容,否则会出错。先
例
例
求两矩阵的乘积,若出错,则自动转去求两矩阵的点
乘。
编程: 运行结果:
A=[1,2,3;4,5,6]; B=[7,8,9;10,11,12]; C = 7 16 27
try 40 55 72
C=A*B; ans = 错误使用 *
catch 内部矩阵维度必须一
C=A.*B; 致。
end
C
lasterr % 显示出错原因
Matlab实用教程(高等院校精品教材) 周明华 主
3.5 程序调试 编
出版社 : 浙江大学出版社 出版时间 :2013-12-01
3.5.1 人机交互命令
编程或调试程序中常用到能实现特殊功能的
命令,实现交互式调试方式,主要有
echo 、 keyboard 、 return 、 pause
等。
1. echo M 文件命令执行时可见
执行 M 文件时,通常在命令窗口是看
不到 M 文件命令和执行过程的,但在调试程序时
需要执行 M 文件同时在命令窗口显示每条命令。
这时可以用 echo 命令实现这样的功能。
Echo 常用的命令
echo 命令
脚本文件
函数文件
脚本文件显示 函数文件显示
>> echo on
>> ed % 调用脚本文件 例如:
例如: for for n=100:1000
n=100:1000 if rem(n,21)~=0
function [c,d]=abcd(a,b)
if continue c=a+b 解释执行
rem(n,21)~= if rem(n,21)~=0 d=sin(c)
0 continue
e=log(d)
continue if rem(n,21)~=0
end continue end 保存函数文件 abcd
break if rem(n,21)~=0 >> echo abcd on
continue >> abcd(2,3)
end if rem(n,21)~=0 function
n continue [c,d]=abcd(a,b)
if rem(n,21)~=0 c=a+b
保存脚本 end c= 5
ed break d=sin(c)
end 编译执行 d = -0.9589
n e=log(d)
e = -0.0419 +
n= 3.1416i
end
105 ans = 5
function [x,n]=jaco(A,b,x0,eps)
if nargin==3
eps=1.0e-6; % 迭代精度
elseif nargin<3
error
return
end
D=diag(diag(A)); % 求 A 的对角矩阵
L=-tril(A,-1); % 求 A 的下三角阵
U=-triu(A,1); % 求 A 的上三角阵
B=D\(L+U);
echo jacw on
f=D\b;
[xx,nn]=jacw([10,-1,0;-1,10,-2;0,-2,10],[9,7,6]',[0;0;0])
x=B*x0+f;
n=1; % 迭代次数
while norm(x-x0)>=eps
x0=x;
x=B*x0+f;
n=n+1;
end
2. keyboard 便于程序调试和运行中修改变量
function [x,n]=jaco(A,b,x0,eps)
if nargin==3
eps=1.0e-6; % 迭代精度
elseif nargin<3
error
return % 错退出程序
end
D=diag(diag(A)); % 求 A 的对角矩阵
L=-tril(A,-1); % 求 A 的下三角阵
Jacobi 迭代法的
U=-triu(A,1); % 求 A 的上三角阵
MATLAB 函数
B=D\(L+U);
文件 Jacobi.m
f=D\b;
x=B*x0+f;
n=1; % 迭代次数
while norm(x-x0)>=eps
x0=x;
x=B*x0+f;
n=n+1;
end
4. 程序的暂停 pause
pause(n) 或
pause
n 是延迟时间,以秒为单位;
缺省,将暂停程序,直到用户按任意键后继续
若想强行终止程序的运行,可以使用 Ctrl+c
例 一般程序:
例 function
[e]=abcde(a,b)
c=a+b
d=sin(c) 暂停命令的程序:
e=log(d) function
end [e]=abcdep(a,b)
c=a+b 运行结果:
d=sin(c) >> abcdep(3,4)
pause c= 7
e=log(d) d = 0.6570
end 任意键
e = -0.4201
3.5.2 编程中注意事项
M 文件错误种类:
语法错误:函数参数输入类型,括号, matlab 直接指出
运算逻辑错误 :运行过程死机或溢出,与程序本身有关。
第一个可执行语句前
红点即设置断点。
( 4 )单击图中红点,会发现红点被取消,此时
回复到初始状态。
( 5 )命令窗口依次输入 dbstop if error 和 调
用 ttt(magic(3))
指向出错的程序行
Dbquit 退出