MATLAB中定义了15种数据类型,基本数据类型是双精度数据类型和字符类型,如图2-1所示。MATLAB的不同数据类型的变量或对象占用的内存空间不同,不同的数据类型的变量或对象也具有不同的操作函数。本节将讨论这些数据类型及其用法。
图2-1 基本数据类型
在MATLAB中可能会遇到对字符和字符串的操作。字符串能够显示在屏幕上,也可以用来构成一些命令,这些命令在其他命令中用于求值或被执行。字符串在数据的可视化、应用程序的交互方面起到非常重要的作用。
一个字符串是存储在一个行向量中的文本,这个行向量中的每一个元素代表一个字符,每一个字符占用两个字节的内存。实际上,元素中存放的是字符的内部代码,也就是ASCII码。当在屏幕上显示字符变量的值时,显示的是文本,而不是ASCII数字。由于字符串是以向量的形式来存储的,所以可以通过它的下标对字符串中的任何一个元素进行访问。字符矩阵也可以这样,但是它的每行字符数必须相同。
1.字符串的创建方法
创建字符串时,只要将字符串的内容用单引号包括起来即可。
【例2-1】 创建字符串。
>> a=127 a = 127 >> class(a) ans = double >> size(a) ans = 1 1 >> b='127' b = 127 >> class(b) ans = char >> size(b) ans = 1 3
若需要在字符串内容中包含单引号,则在键入字符串内容时,连续键入两个单引号即可。
使用char函数创建一些无法通过键盘输入的字符,该函数的作用是将输入的整数参数转变为相应的字符。
【例2-2】 使用char函数创建一些无法通过键盘输入的字符。
>> S1=char('Good','Job.') S1 = Good Job. >> S2=char('祝','老师','教师节','','快乐') S2 = 祝 老师 教师节 快乐
2.字符串的基本操作
1)字符串元素索引
字符串实际上也是一种MATLAB的向量或数组,一般利用索引操作数组的方法都可以用来操作字符串。
2)字符串拼接
字符串可以利用“[]”运算符进行拼接。
若使用“,”作为不同字符串之间的间隔,相当于扩展字符串成为更长的字符串向量;若使用“;”作为不同字符串之间的间隔,则相当于扩展字符串成为二维或多维的数组,这时不同行上的字符串必须具有同样的长度。
3)字符串和数值的转换
使用char函数可以将数值转变为字符;使用double函数可以将字符转变成数值。
4)字符串操作函数
表2-1 字符串操作函数
【例2-3】 使用Blanks创建空字符串。
>> a=blanks(4) a =
图2-2 创建的空字符串
【例2-4】 使用deblank去掉字符串尾部空格。
>> a='Hello! ' a = Hello! >> deblank(a) ans = Hello! >> whos Name Size Bytes Class a 1x9 18 char array ans 1x6 12 char array Grand total is 15 elements using 30 bytes
【例2-5】 使用ischar判断变量是否为字符类型。
>> a='Hello!' a = Hello! >> ischar(a) ans = 1 >> b=12; >> ischar(b) ans = 0
strcat可以水平组合字符串,构成更长的字符向量。
strvcat函数允许将不同长度的字符串组合成为字符矩阵,并且将短字符串扩充为与长字符串相同的长度。
【例2-6】 分别使用strcat和strvcat对字符串a和b进行比较。
>> a='Hello'; >> b='MOTO!'; >> c=strcat(a,b) c = HelloMOTO! >> d=strvcat(a,b ,c) d = Hello MOTO! HelloMOTO! >> whos Name Size Bytes Class a 1x5 10 char array b 1x5 10 char array c 1x10 20 char array d 3x10 60 char array Grand total is 50 elements using 100 bytes
strcmp:比较字符串,判断字符串是否一致。
strncmp:比较字符串前n个字符,判断是否一致。
【例2-7】 分别使用strcmp和strncmp对字符串a和b进行比较。
>> a='The first string'; >> b='The second string'; >> c=strcmp(a,b) c = 0 >> d=strncmp(a,b,4) d = 1
findstr:在较长的字符串中查寻较短的字符串出现的索引。
strfind:在第一个字符串中查寻第二个字符串出现的索引。
【例2-8】 分别使用findstr和 strfind对字符串S1和S2进行查询操作。
>> S1='A friend in need is a friend indeed'; >> S2='friend'; >> a=findstr(S2,S1) a = 3 23 >> b=strfind(S2,S1) b = [] >> c=strfind(S1,S2) c = 3 23
【例2-9】 对字符串a、b、c进行排列操作。
>> a='Hello'; >> b='MOTO!'; >> c=strcat(a,b) c = HelloMOTO! >> d=strvcat(a,b,c) d = Hello MOTO! HelloMOTO! >> e=strjust(d) e = Hello MOTO! HelloMOTO!
【例2-10】 使用strrep将字符串S1中的firend替换为friend。
>> S1='A firend in need is a firend indeed' S1 = A firend in need is a firend indeed >> S2=strrep(S1,'firend','friend') S2 = A friend in need is a friend indeed
【例2-11】 使用strmatch查询字符串a和b中分别匹配max的字符串。
>> a=strmatch('max',strvcat('max','minimax','maximum')) a = 1 3 >> b=strmatch('max',strvcat('max','minimax','maximum'),'exact') b = 1 upper和 lower
5)字符串转换函数
在MATLAB中使用不同的函数可以允许不同类型的数据和字符串类型的数据之间进行转换;在MATLAB中直接提供了相应的函数对同样类型的数据进行数制的转换。
数字和字符之间的转换函数如表2-2所示。
表2-2 数字和字符之间的转换函数
不同数值之间的转换函数如表2-3所示。
表2-3 不同数值之间的转换函数
函数str2num在使用时需要注意,被转换的字符串仅能包含数字、小数点、字符“e”或“d”、数字的正号或负号、复数的虚部字符“i”或“j”,使用时要注意空格。
【例2-12】 使用str2num函数将字符串转换为数字。
>> A=str2num('1+2i') A = 1.0000 + 2.0000i >> B=str2num('1 +2i') B = 1.0000 0 + 2.0000i >> C=str2num('1 + 2i') C = 1.0000 + 2.0000i >> whos Name Size Bytes Class A 1x1 16 double array (complex) B 1x2 32 double array (complex) C 1x1 16 double array (complex) Grand total is 4 elements using 64 bytes
也可以使用str2double函数避免上述问题,但str2double函数只能转换标量,不能转换矩阵或数组。
使用函数num2str将数字转换成为字符串时,可以指定字符串所表示的有效数字位数。
【例2-13】 使用num2str函数将数字转换成为字符串。
>> A=num2str(rand(2,2),4) A = 0.8913 0.4565 0.7621 0.0185 >> B=num2str(rand(2,2),6) B = 0.921813 0.176266 0.738207 0.405706
6)格式化输入输出
MATLAB可以进行格式化的输入、输出,用于C语言的格式化字符串都可以用于MATLAB的格式化输入输出函数,如表2-4所示。
表2-4 MATLAB的格式化输入输出函数
在MATLAB中,有两个函数用来进行格式化的输入和输出。
(1)sscanf(读取格式化字符串)
A=sscanf(s,format) A=sscanf(s,format,size)
(2)sprintf(格式化输出数据到命令行窗口)
S=sprintf(format,A,……)
【例2-14】 分别使用sscanf(s,format)、sscanf(s,format,size)、sprintf(format,A,……)对字符串S1、S2、S3进行格式化输出。
>> S1='2.7183 3.1416'; >> S2='2.7183e3 3.1416e3'; >> S3='0 2 4 8 16 32 64 128'; >> A=sscanf(S1,'%f') A = 2.7183 3.1416 >> B=sscanf(S2,'%e') B = 1.0e+003* 2.7183 3.1416 >> C=sscanf(S3,'%d') 0 2 4 8 16 32 64 128 >> S1='0 2 4 8 16 32 64 128'; >> A=sscanf(S3,'%d') A = 0 2 4 8 16 32 64 128 >> B=sscanf(S3,'%d',1) B = 0 >> C=sscanf(S3,'%d',3) C = 0 2 4 >> A=1/eps;B=-eps; >> C=[65,66,67,pi]; >> D=[pi,65,66,67]; >> S1=sprintf('%+15.5f',A) S1 = +4503599627370496.00000 >> S2=sprintf('%+.5e',B) S2 = -2.22045e-016 >> S3=sprintf('%s%f',C) S3 = ABC3.141593 >> S4=sprintf('%s%f%s',D) S4 = 3.141593e+00065.000000BC
A=input(prompt):参数prompt为提示用的字符串。
A=input(prompt,'s'):若有s,则输入的数据为字符串;没有s,则输入的数据为双精度数据。
【例2-15】 input函数的使用方法。
>> A=input('随便输入数字:') 随便输入数字:264 A = 264 >> B=input('随便输入数字:','s') 随便输入数字:264 B = 264 >> whos Name Size Bytes Class A 1x1 8 double array B 1x3 6 char array Grand total is 4 elements using 14 bytes
MATLAB的基本数值类型变量或对象主要用来描述基本的数值对象。
MATLAB还存在的一些数据:常量数据、空数组或空矩阵等。常量数据是指在使用MATLAB过程中由MATLAB提供的公共数据,数据可以通过数据类型转换的方法转换常量到不同的数据类型,还可以被赋予新的数值;空数组或空矩阵,在创建数组或矩阵时,可以使用空数组或空矩阵辅助创建数组或矩阵。
1.基本数值类型
基本数据类型如表2-5所示。
表2-5 基本数值类型
class函数可以用来获取变量或对象的类型,也可以用来创建用户自定义的数据类型。
【例2-16】 class函数的使用样例。
>> A=[1 2 3]; >> class(A) ans = double >> whos Name Size Bytes Class A 1x3 24 double array ans 1x6 12 char array Grand total is 9 elements using 36 bytes >> B=int16(A); >> class(B) ans = int16 >> whos Name Size Bytes Class A 1x3 24 double array B 1x3 6 int16 array ans 1x5 10 char array Grand total is 11 elements using 40 bytes
MATLAB和C语言在处理数据类型和变量时的区别:在C语言中,任何变量在使用之前必须声明,然后赋值,在声明变量时就指定了变量的数据类型;在MATLAB中,任何数据变量都不需要预先声明,MATLAB将自动将数据类型设置为双精度类型。
在进行数据类型转换时,若输入参数的数据类型就是需要转换的数据类型,则MATLAB忽略转换,保持变量的原有特性。
2.整数类型数据运算
整数类型数据的运算函数如表2-6所示。
表2-6 整数类型数据的运算函数
注意
参与整数运算的数据都必须大于0。
【例2-17】 使用bitand函数对数据A和B进行与操作。
>> A=86;B=77; >> C=bitand(A,B) C = 68 >> a=uint16(A);b=uint16(B); >> c=bitand(a,b) c = 68 86的补码: 01010110 77的补码: 01001101 "与"运算的结果: 01000100 >> whos Name Size Bytes Class A 1x1 8 double array B 1x1 8 double array C 1x1 8 double array a 1x1 2 uint16 array b 1x1 2 uint16 array c 1x1 2 uint16 array Grand total is 6 elements using 30 bytes
【例2-18】 使用bitset函数对数据A进行操作。
>> A=86; >> dec2bin(A) ans = 1010110 >> B=bitset(A,6) B = 118 >> dec2bin(B) ans = 1110110 >> C=bitset(A,7,0) C = 22 >> dec2bin(C) ans = 10110
bitset(A,B,C)函数根据输入的第二个参数设置相应的数据位的数值,若不指定第三个参数,则将相应的数据位设置为“1”,否则,根据输入的第三个参数设置相应的数据位。
用法:bitget(A,B),根据输入的第二个参数获取指定的数据位的数值。
【例2-19】 使用bitget函数获取数据A指定数据位的值。
>> A=86; >> dec2bin(A) ans = 1010110 >> bitget(A,6) ans = 0 >> bitget(A,3) ans = 1 >> A=86; >> bitget(A,6) ans = 0 >> bitget(A,3) ans = 1
用法:bitshift(A,B),函数第二个参数为正,则左移,第二个参数为负,则右移。
【例2-20】 使用bitshift函数对数据进行移位操作。
>> A=86; >> dec2bin(A) ans = 1010110 >> D=bitshift(A,4); >> dec2bin(D) ans = 10101100000 >> E=bitshift(A,-4); >> dec2bin(E) ans = 101 →(0000101) >> A=86; >> D=bitshift(A,4) D = 1376 >> E=bitshift(A,-4) E = 5
3.MATLAB的常量
MATLAB的常量如表2-7所示。
表2-7 MATLAB的常用常量
注意
eps、realmax、realmin三个常量具体的数值与运行MATLAB的计算机相关,不同的计算机系统可能具有不同的数值。
MATLAB的常量是可以赋予性的数值的,一旦被赋予了新的数值,则常量代表的就是新值,而不是原有的值,只有执行clear命令后,常量才会代表原来的值,下例将进行演示。
【例2-21】 使用clear命令将 pi恢复原值。
>> pi=100 pi = 100 >> clear >> pi ans = 3.1416
将inf应用于函数,计算结果可能为inf或NaN。进行数据转换时,inf将获取相应数据类型的昀大值,而NaN返回相应整数数据类型的数值0,浮点数类型则仍然为NaN。
【例2-22】 inf或NaN的使用样例。
>> A=Inf; >> class(A) ans = Double >> B=int16(A) B = 32767 >> C=sin(A) C = NaN >> sin(C) ans = NaN >> class(C) ans = double >> int64(C) ans = 0 >> int32(C) ans = 0
4.空数组
空数组不意味着什么都没有,空数组类型的变量在MATLAB的工作空间中是存在的。
【例2-23】 创建空数组。
>> A=[] A = [] >> B=ones(2,3,0) B = Empty array: 2-by-3-by-0 >> C=randn(2,3,4,0) C = Empty array: 2-by-3-by-4-by-0 >> whos Name Size Bytes Class A 0x0 0 double array B 2x3x0 0 double array C 4-D 0 double array Grand total is 0 elements using 0 bytes
使用空数组,可以将大数组删除部分行或列,亦可以删除多维数组的某一页。
【例2-24】 使用空数组对大数组进行列删除操作。
>> A=reshape(1:24,4,6) A = 1 5 9 13 17 21 2 6 10 14 18 22 3 7 11 15 19 23 4 8 12 16 20 24 >> %删除第2.3.4列 >> A(:,[2 3 4])=[] A = 1 17 21 2 18 22 3 19 23 4 20 24
思考:如何删除第2、3行?
>> ???
A =
1 5 9 13 17 21
4 8 12 16 20 24
函数句柄(Function handle)是MATLAB的一种数据类型。引入函数句柄是为了使feval及借助于它的泛函指令工作更可靠;特别在反复调用情况下更显效率;使“函数调用”像“变量调用”一样方便灵活;提高函数调用速度,提高软件重用性,扩大子函数和私用函数的可调用范围;迅速获得同名重载函数的位置、类型信息。MATLAB中函数句柄的使用使得函数也可以成为输入变量,并且能很方便地调用,提高函数的可用性和独立性。
函数句柄可以将其理解成一个函数的代号,就像一个人的名字,这样在调用时可以调用函数句柄而不用调用该函数。
创建函数句柄需要用到操作符@,创建函数句柄的语法如下。
fhandle = @function_filename
调用函数时就可以调用该句柄,可以实现同样的功能。
例如,
fhandle = @sin
就创建了sin的句柄,输入fhandle(x)其实就是sin(x)的功能。
逻辑运算又称布尔运算。布尔用数学方法研究逻辑问题,成功地建立了逻辑演算。它用等式表示判断,把推理看作等式的变换,这种变换的有效性不依赖人们对符号的解释,只依赖于符号的组合规律,这一逻辑理论常被称为布尔代数。20世纪30年代,逻辑代 数在电路系统上获得应用,随后,由于电子技术与计算机的发展,出现各种复杂的大系 统,其变换规律也遵守布尔所揭示的规律。逻辑运算(logical operators)通常用来测试真假值。最常见的逻辑运算就是循环处理,用来判断是否该离开循环或继续执行循环内的 指令。
关系的基本运算有两类:一类是传统的集合运算(并、差、交等);另一类是专门的关系运算(选择、投影、连接、除法、外连接等),有些查询需要几个基本运算的组合,要经过若干步骤才能完成。
1.逻辑数据类型
在MATLAB中逻辑类型包含true和false,分别由1和0表示。在MATLAB中用函数logical()将任何非零的数值转换为true(即1),将数值0转换为false(即0)。逻辑类型的数据只能通过数值类型转换,或者使用特殊的函数生成相应类型的数组或矩阵。逻辑类型的数组每一个元素仅占用一个字节的内存空间。
创建逻辑类型数据的函数如表2-8所示。
表2-8 创建逻辑类型数据的函数
【例2-25】 逻辑数据类型logical、True、False的使用样例。
>> A=eye(3) A = 1 0 0 0 1 0 0 0 1 >> B=logical(A) B = 1 0 0 0 1 0 0 0 1 >> C=true(size(A)) C = 1 1 1 1 1 1 1 1 1 >> C=true(3,3) >> D=false([size(A),2]) D(:,:,1) = 0 0 0 0 0 0 0 0 0 D(:,:,2) = 0 0 0 0 0 0 0 0 0 >> whos Name Size Bytes Class A 3x3 72 double array B 3x3 9 logical array C 3x3 9 logical array D 3x3x2 18 logical array Grand total is 45 elements using 108 bytes
在使用true或false函数创建逻辑类型数组时,若不指明参数,则创建一个逻辑类型的标量。
在MATLAB中有些函数以is 开头,这类函数用来完成某种判断功能的函数。
例如,
【例2-26】 isnumeric与islogical的使用方法。
>> a=true a = 1 >> b=false b = 0 >> c=1 c = 1 >> isnumeric(a) ans = 0 >> isnumeric(c) ans = 1 >> islogical(a) ans = 1 >> islogical(b) ans = 1 >> islogical(c) ans = 0
2.逻辑运算
能够处理逻辑类型数据的运算叫逻辑运算。参与逻辑运算的操作数不一定是逻辑类型的变量或常量,其他类型的数据也可以进行逻辑运算,但运算结果一定是逻辑类型的数据。
MATLAB的逻辑运算符及其作用如表2-9所示。
表2-9 MATLAB的逻辑运算符及其作用
具有短路作用的逻辑“与”操作(&&)和“或”操作(||),在进行a && b && c && d运算时,若a为假(0),则后面的三个变量都不再被处理,运算结束,并返回运算结果逻辑假(0);同样,进行a || b || c || d运算时,若a为真(1),则后面的三个变量都不再被处理,运算结束,并返回运算结果逻辑真(1)。
注意
它们仅能处理标量!
【例2-27】 对数据a、b、c、d进行“与”操作(&&)和“或”操作(||)。
>> a=0;b=1;c=2;d=3; >> a&&b&&c&&d ans = 0 >> a=0;b=2;c=6;d=8; >> a&&b&&c&&d ans = 0 >> a=10;b=1;c=2;d=3; >> a||b||c||d ans = 1 >> a=10;b=0;c=7;d=9; >> a||b||c||d ans = 1 >> whos Name Size Bytes Class a 1x1 8 double array ans 1x1 1 logical array b 1x1 8 double array c 1x1 8 double array d 1x1 8 double array Grand total is 5 elements using 33 bytes
函数any和all是针对矩阵中每一列进行处理。Any对每列元素有非零值,则返回逻辑真;All对每列元素均为非零值,则返回逻辑真。
【例2-28】 使用any和all分别对数据a、b、c进行操作。
>> a=[1 2 3 0]; >> any(a) ans = 1 >> all(a) ans = 0 >> b=[0 0 0 0]; >> any(b) ans = 0 >> all(b) ans = 0 >> c=[1 2 3 4]; >> any(c) a n s = 1 >> all(c) ans = 1 >> a=[1 0 2;3 0 0;1 3 0;1 1 1] a = 1 0 2 3 0 0 1 3 0 1 1 1 >> any(a) ans = 1 1 1 >> all(a) ans = 1 0 0
3.关系运算
MATLAB的关系运算符如表2-10所示。
表2-10 MATLAB的关系运算符
参与关系运算的操作数可以是各种数据类型的变量或常数,其运算结果是逻辑类型的数据,标量可以和数组(或矩阵)进行比较,比较时自动扩展标量,返回的结果是和数组同维的逻辑类型数组,若比较的是两个数组,则数组必须是同维的,且每一维的尺寸必须一致。
利用“()”和各种运算符相结合,可以完成复杂的关系运算。
【例2-29】 灵活运用“()”进行运算操作。
>> A=reshape(-4:4,3,3) A = -4 -1 2 -3 0 3 -2 1 4 >> A>=0 ans = 0 0 1 0 1 1 0 1 1 >> B=~(A>=0) B = 1 1 0 1 0 0 1 0 0 >> whos Name Size Bytes Class A 3x3 72 double array B 3x3 9 logical array ans 3x3 9 logical array Grand total is 27 elements using 90 bytes >> C=(A>0)&(A<3) C = 0 0 1 0 0 0 0 1 0 >> A>0 ans = 0 0 1 0 0 1 0 1 1 >> A<3 ans = 1 1 1 1 1 0 1 1 0 A = -4 -1 2 -3 0 3 -2 1 4
逻辑索引:将逻辑类型的数据应用于索引就构成了逻辑索引,利用逻辑索引可以方便地从矩阵或数组中找到某些符合条件的元素。
(1)括号()
(2)数组转置(. ),数组幂(.^ ),矩阵转置( ’ ),矩阵幂(^)
(3)一元加(+),一元减(–),逻辑非(~)
(4)数组乘法(. * ),数组右除(./ ),数组左除(.\ ),矩阵乘法(*),矩阵右除(/),矩阵左除(\)
(5)加法(+),减法(–)
(6)冒号运算符( :)
(7)小于(<),小于等于(<=),大于(>),大于等于(>=),等于(==),不等于(~=)
(8)元素与(&)
(9)元素或(|)
(10)短路逻辑与(&&)
(11)短路逻辑或(||)
结构是包含一组记录的数据类型,记录是存储在相应的字段中,结构的字段可以是任意一种MATLAB数据类型的变量或对象,结构类型的变量可以是一维的、二维的或多维的数组,在访问结构类型数据的元素时,需要使用下标配合字段的形式。
1.结构的创建
结构的创建有两种方法:直接赋值和利用struct函数创建。
(1)直接赋值创建结构
创建时直接用结构的名称,配合操作符“.”和相应的字段名称完成创建,创建是直接给字段赋具体的数值。
【例2-30】 Student结构的创建。
>> Student.name='Way'; >> Student.age=26; >> Student.grade=uint16(1); >> whos Name Size Bytes Class Student 1x1 388 struct array Grand total is 8 elements using 388 bytes >> Student Student = name: 'Way' age: 26 grade: 1
MATLAB会自动扩展结构数组的尺寸,对于没有赋值的字段,则直接创建空数组。
【例2-31】 空结构数组的创建。
>> Student(2) ans = name: [] age: [] grade: [] >> Student(3).age ans = []
(2)利用struct函数创建结构
struct函数的基本语法如下。
【例2-32】 使用struct函数创建Student结构。
>> Student=struct('name','Way','age',26,'grade',uint16(1)) Student = name: 'Way' age: 26 grade: 1 >> whos Name Size Bytes Class Student 1x1 388 struct array Grand total is 8 elements using 388 bytes >> Student=struct('name',{'Deni','Sherry'},'age',{22,24},'grade',{2,3}) Student = 1x2 struct array with fields: name age grade >> whos Name Size Bytes Class Student 1x2 604 struct array Grand total is 20 elements using 604 bytes >> Student=struct('name',{},'age',{},'grade',{}) Student = 0x0 struct array with fields: name age grade >> whos Name Size Bytes Class Student 0x0 192 struct array Grand total is 0 elements using 192 bytes
可以使用repmat函数,给结构制作复本。
【例2-33】 使用repmat函数给Student结构制作复本。
>>Student=repmat(struct('name','Way','age',26,'grade',uint16(1)),1,2) Student = 1x2 struct array with fields: name age grade >> Student=repmat(struct('name','Way','age',26,'grade',uint16(1)),1,3) Student = 1x3 struct array with fields: name age Grade >> Student(1) ans = name: 'Way' age: 26 grade: 1 >> Student(2) ans = name: 'Way' age: 26 grade: 1
2.结构的基本操作
对于结构的基本操作其实是对结构数组元素包含记录的操作,其中,包括结构记录数据的访问和字段的增加和删除。
(1)访问结构数组元素包含的记录的方法。
可以直接使用结构数组的名称和字段的名称及操作符“.”完成相应的操作,也可以使用“动态”字段的形式利用动态字段形式访问结构数组元素,便于利用函数完成对结构字段数据的重复操作。
基本语法结构如下。
【例2-34】 直接使用结构数组的名称(Student)和字段的名称访问其中的元素。
>>Student=struct('name',{'Deni','Sherry'},'age',{22,24},'grade',{2,3}, 'score',{rand(3) *10,randn(3) *10}); >> Student Student = 1x2 struct array with fields: name age grade score >> Student(2).score ans = -4.3256 2.8768 11.8916 -16.6558 -11.4647 -0.3763 1.2533 11.9092 3.2729
利用动态字段的形式可以通过编写函数对记录的数据进行统一的运算操作。
【例2-35】 使用动态字段对Student中的数据进行统一操作。
>> Student(2).score(1,:) ans = -4.3256 2.8768 11.8916 >> Student.name ans = Deni ans = Sherry >> Student.('name') ans = Deni ans = Sherry
(2)对结构数据进行计算。
若对结构数组的某一个元素的字段代表的数据进行计算,则和使用MATLAB普通的变量操作相同;若对结构数组的某一个字段的所有数据进行同一种操作,则需要使用[]符号将该字段包含起来。
【例2-36】 对Student的数据求平均值。
>> mean(Student(1).score) % Mean函数是用来求解列向量的平均值 ans = 6.1736 6.1210 7.5269 >> mean([Student.score]) ans = 6.1736 6.1210 7.5269 -6.5761 1.1071 4.9294
(3)内嵌结构。
当结构的字段记录了结构时,则称其为内嵌结构,创建内嵌结构可以使用直接赋值的方法,也可以使用struct函数完成。
【例2-37】 使用直接赋值的方法创建内嵌结构。
>>Student=struct('name',{'Deni','Sherry'},'age',{22,24}, 'grade',{2,3},'score',{rand(3) *10,randn(3) *10}); >> Class.numble=1; >> Class.Student=Student; >> whos Name Size Bytes Class Class 1x1 1188 struct array Student 1x2 932 struct array Grand total is 83 elements using 2120 bytes >> Class Class = numble: 1 Student: [1x2 struct]
【例2-38】 使用struct函数创建内嵌结构。
>>Class=struct('numble',1,'Student',struct('name',{'Way','Deni'})) Class = numble: 1 Student: [1x2 struct]
(4)结构操作函数,如表2-11所示。
表2-11 结构操作函数
【例2-39】 使用fieldnames函数获取S结构的字段名称。
>> fieldnames(S) ans = 'name' 'ID'
【例2-40】 用getfield函数获取S结构的字段数据。
>> A=getfield(S,{2,2},'name') A = Way >> B=getfield(S,{2,2},'ID') B = 1
【例2-41】 用orderfields函数对S3结构字段排序。
>> S3=orderfields(S) S3 = 2x2 struct array with fields: ID name
【例2-42】 用rmfield函数删除S4的ID字段。
>> S4=rmfield(S,'ID') S4 = 2x2 struct array with fields: name
【例2-43】 使用isfield函数判断name和id字段是否分别属于结构A和B。
>> A=isfield(S,'name') A = 1 >> B=isfield(S,'id') B = 0
【例2-44】 使用isstruct函数判断数据S是否为结构类型。
>> isstruct(S) ans = 1
deal函数处理标量时,将标量的数值依次赋值给相应的输出。
【例2-45】 使用deal函数依次给Y1、Y2、Y3赋值。
>> X=3; >> [Y1,Y2,Y3]=deal(X) Y1 = 3 Y2 = 3 Y3 = 3
deal函数处理元胞数组时,将元胞数组中的元胞依次赋值给相应的输出。
【例2-46】 使用deal函数依次给元胞数组赋值并输出。
>> X={rand(3),'2',1}; >> [Y1,Y2,Y3]=deal(X{:}) Y1 = 0.9501 0.4860 0.4565 0.2311 0.8913 0.0185 0.6068 0.7621 0.8214 Y2 = 2 Y3 = 1
元胞数组是MATLAB的一种特殊数据类型,可以将元胞数组看作为一种无所不包的通用矩阵(广义矩阵),组成元胞数组的元素可以是任何一种数据类型的常数或常量。数据类型可以是字符串、双精度数、稀疏矩阵、元胞数组、结构或其他MATLAB数据类型。每一个元胞数据可以是标量、向量、矩阵、N维数组,每一个元素可以具有不同的尺寸和内存空间,每一个元素的内容可以完全不同,元胞数组的元素叫作元胞。元胞数组的内存空间是动态分配的,它的维数不受限制。访问元胞数组的元素可以使用单下标方式或全下标方式。
元胞数组和结构数组的异同,如表2-12所示。
表2-12 元胞数组和结构数组的异同
1.元胞数组的创建
(1)使用运算符花括号{},将不同类型和尺寸的数据组合在一起构成一个元胞数组。
【例2-47】 构造元胞数组A。
>> A={zeros(2,2,2),'Hello';17.35,1:100} A = [2x2x2 double] 'Hello' [ 17.3500] [1x100 double] >> whos Name Size Bytes Class A 2x2 1122 cell array Grand total is 118 elements using 1122 bytes
对于内容较多的元胞,显示的内容将为元胞的数据类型和尺寸。
(2)将数组的每一个元素用{}括起来,然后用数组创建的符号[]将数组的元素括起来构成一个元胞数组。
【例2-48】 创建由数组元素构成的元胞数组。
>> B=[{zeros(2,2,2)},{'Hello'};{17.35},{1:100}] B = [2x2x2 double] 'Hello' [ 17.3500] [1x100 double] >> whos Name Size Bytes Class A 2x2 1122 cell array Grand total is 118 elements using 1122 bytes
(3)用{}创建一个元胞数组,MATLAB能够自动扩展数组的尺寸,没有明确赋值的元素作为空元胞数组存在。
【例2-49】 用{}创建一个元胞数组。
>> C={1} C = [1] >> whos Name Size Bytes Class C 1x1 68 cell array Grand total is 2 elements using 68 bytes >> C(2,2)={3} C = [1] [] [] [3] >> whos Name Size Bytes Class C 2x2 144 cell array Grand total is 6 elements using 144 bytes
(4)用函数cell创建元胞数组,该函数可以创建一维、二维或多维元胞数组,但创建的数组都为空元胞。
【例2-50】 用函数cell创建元胞数组。
>> A=cell(1) A = {[]} >> B=cell(2,3) B = [] [] [] [] [] [] >> C=cell(2,2,2) C(:,:,1) = [] [] [] [] C(:,:,2) = [] [] [] [] >> whos Name Size Bytes Class A 1x1 4 cell array B 2x3 24 cell array C 2x2x2 32 cell array Grand total is 15 elements using 60 bytes
元胞数组的每个空元胞占用四个字节的内存空间,元胞数组占用的内存空间和元胞数组的内容有关,不同的元胞数组占用的内存空间不同。
2.元胞数组的基本操作
元胞数组的基本操作包括对元胞数组元胞和元胞数据的访问、修改,元胞数组的扩展、收缩或重组。操作数值数组的函数也可以应用在元胞数组上。
(1)元胞数组的访问
使用圆括号()直接访问元胞数组的元胞,获取的数据也是一个元胞数组。
【例2-51】 使用圆括号()直接访问元胞数组的元胞。
>> A=[{zeros(2,2,2)},{'Hello'};{17.35},{1:100}] A = [2x2x2 double] 'Hello' [17.3500] [1x100 double] >> B=A(1,2) B = 'Hello' >> class(B) ans = Cell >> whos Name Size Bytes Class A 2x2 1122 cell array B 1x1 70 cell array ans 1x4 8 char array Grand total is 128 elements using 1200 bytes
使用花括号{}直接访问元胞数组的元胞,获取的数据是字符串。
【例2-52】 使用花括号{}直接访问元胞数组的元胞。
>> A=[{zeros(2,2,2)},{'Hello'};{17.35},{1:100}] A = [2x2x2 double] 'Hello' [ 17.3500] [1x100 double] >> C=A{1,2} C = Hello >> class(C) ans = Char >> whos Name Size Bytes Class A 2x2 1122 ell array C 1x5 10 char array ans 1x4 8 char array Grand total is 127 elements using 1140 bytes
【例2-53】 将花括号{}和圆括号( )结合起来使用访问元胞元素内部的成员。
>> A=[{zeros(2,2,2)},{'Hello'};{17.35},{1:10}] A = [2x2x2 double] 'Hello' [ 17.3500] [1x10 double] >> D=A{1,2}(2) D = E >> E=A{2,2}(5:end) E = 5 6 7 8 9 10 >> class(E) ans = Double >> F=A{4}([1 3 5]) F = 1 3 5 >> whos Name Size Bytes Class A 2x2 402 cell array D 1x1 2 char array E 1x6 48 double array F 1x3 24 double array ans 1x6 12 char array Grand total is 44 elements using 488 bytes
(2)元胞数组的扩充(其方法和数值数组大体相同)
【例2-54】 元胞数组的扩充样例。
>> A=[{zeros(2,2,2)},{'Hello'};{17.35},{1:10}] [2x2x2 double] 'Hello' [ 17.3500] [1x10 double] >> B=cell(2) B = [] [] [] [] >> B(:,1)={char('Hello','Welcome');10:-1:5} B = [2x7 char ] [] [1x6 double] [] >> C=[A,B] C = [2x2x2 double] 'Hello' [2x7 char ] [] [ 17.3500] [1x10 double] [1x6 double] [] >> D=[A,B;C] D = [2x2x2 double] 'Hello' [2x7 char ] [] [ 17.3500] [1x10 double] [1x6 double] [] [2x2x2 double] 'Hello' [2x7 char ] [] [ 17.3500] [1x10 double] [1x6 double] [] >> whos Name Size Bytes Class A 2x2 402 cell array B 2x2 204 cell array C 2x4 606 cell array D 4x4 1212 cell array Grand total is 208 elements using 2424 bytes
(3)元胞数组的收缩和重组(和数值数组大体相同)
【例2-55】 元胞数组的收缩。
D = [2x2x2 double] 'Hello' [2x7 char ] [] [ 17.3500] [1x10 double] [1x6 double] [] [2x2x2 double] 'Hello' [2x7 char ] [] [ 17.3500] [1x10 double] [1x6 double] [] >> D(2,:)=[] D = [2x2x2 double] 'Hello' [2x7 char ] [] [2x2x2 double] 'Hello' [2x7 char ] [] [ 17.3500] [1x10 double] [1x6 double] []
【例2-56】 元胞数组的重组。
>> E=reshape(D,2,2,3) E(:,:,1) = [2x2x2 double] [17.3500] [2x2x2 double] 'Hello' E(:,:,2) = 'Hello' [2x7 char] [1x10 double] [2x7 char] E(:,:,3) = [1x6 double] [ ] [ ] [ ]
(4)元胞数组的操作函数,如表2-13所示。
表2-13 元胞数组的操作函数
表2-14 在ceIIfun函数中可用的函数
【例2-57】 对元胞数组的元素(元胞)分别指定不同的函数。
>> A={rand(2,2,2),'Hello',pi;17,1+i,magic(5)} A = [2x2x2 double] 'Hello' [ 3.1416 ] [ 17] [1.0000+ 1.0000i] [5x5 double] >> B=cellfun('isreal',A) B = 1 1 1 1 0 1 >> C=cellfun('length',A) C = 2 5 1 1 1 5
cellfun函数还有以下两种用法。
【例2-58】 获取元胞数组A元素第1维的尺寸并判断元胞数组A的数据类型。
A = [2x2x2 double] 'Hello' [ 3.1416 ] [17 ] [1.0000+ 1.0000i] [5x5 double] >> D=cellfun('size',A,1) D = 2 1 1 1 1 5 >> E=cellfun('size',A,2) E = 2 5 1 1 1 5 >> F=cellfun('isclass',A,'double') F = 1 0 1 1 1 1
【例2-59】 使用celldisp函数显示元胞数组A的内容。
>> A={rand(2,2,2),'Hello',pi;17,1+i,magic(5)} A = [2x2x2 double] 'Hello' [ 3.1416] [ 17] [1.0000+ 1.0000i] [5x5 double] >> celldisp(A) A{1,1} = (:,:,1) = 0.1389 0.1987 0.2028 0.6038 (:,:,2) = 0.2722 0.0153 0.1988 0.7468 A{2,1} = 17 A{1,2} = Hello A{2,2} = 1.0000 + 1.0000i A{1,3} = 3.1416 A{2,3} = 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
【例2-60】 使用cellplot函数显示元胞数组A。
cellplot函数实例如图2-3所示。
>> A={rand(2,2,2),'Hello',pi;17,1+i,magic(5)} A = [2x2x2 double] 'Hello' [ 3.1416] [ 17] [1.0000+ 1.0000i] [5x5 double] >> cellplot(A)
图2-3 cellplot函数实例
【例2-61】 cell2mat函数样例。
>> A = {[1] [2 3 4]; [5; 9] [6 7 8; 10 11 12]} A = [1] [1x3 double] [2x1 double] [2x3 double] >> B = cell2mat(A) B = 1 2 3 4 5 6 7 8 9 10 11 12 >> a={[1 2 3;5 6 7],[4;8];[9 10 ],[11 12]} a = [2x3 double] [2x1 double] [1x2 double] [1x2 double] >> b= cell2mat(a) b = 1 2 3 4 5 6 7 8 9 10 11 12 >> C={[1 2;5 6],[3 4];[9 10],[7 8;11 12]} C = [2x2 double] [1x2 double] [1x2 double] [2x2 double] >> D= cell2mat(C) ??? Error using ==> cat CAT arguments dimensions are not consistent. Error in ==> C:\MATLAB6p5p1\toolbox\MATLAB\datatypes\cell2mat.m On line 85 ==> m{n} = cat(2,c{n,:});
【例2-62】 使用mat2cell函数将矩阵X转变为元胞数组。
>> X = [1 2 3 4; 5 6 7 8; 9 10 11 12] X = 1 2 3 4 5 6 7 8 9 10 11 12 >> Y = mat2cell(X,[1 2],[1 3]) Y = [ 1] [1x3 double] [2x1 double] [2x3 double]
【例2-63】 使用num2cell函数将数值数组X转变为元胞数组。
>> X = [1 2 3 4; 5 6 7 8; 9 10 11 12] X = 1 2 3 4 5 6 7 8 9 10 11 12 >> Y = num2cell(X) Y = [1] [ 2] [ 3] [ 4] [5] [ 6] [ 7] [ 8] [9] [10] [11] [12] >> Y = num2cell(X,2) Y = [1x4 double] [1x4 double] [1x4 double] >> Z = num2cell(X,1) Z = [3x1 double] [3x1 double] [3x1 double] [3x1 double] >> M = num2cell(X,[1,2]) M = [3x4 double] 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12