您的位置:首页 > 编程语言 > MATLAB

MATLAB学习(三)字符串、元胞&构架数组

2017-02-27 09:16 357 查看
第三阶段学习开始咯!字符串数组(Character String Array)、元胞数组(Cell array)、构架数组(Structure array)。


MATLAB采用了面向对象编程技术,内建数据类型5种以上,还有许多专门设计的类(如符号类、内联函数类、控制工具包中的线性时不变模型类、神经网络类等)。

字符串数组

串数组及其相应操作,为MATLAB文字表达、复杂字符的组织、数据的可视化以及MATLAB的宏定义提供了有力的支持。

1、字符串

【eg.1】字符串入门

>> a=12345.6789       %给变量a赋数值标量
>> class(a)           %a类别判断
>> a_s=size(a)        %数值数组a的大小
>> b='S'              %给变量b赋字符标量(即单个字符)
>> class(b)           %b类别判断
>> b_s=size(b)        %符号数组b的大小
>> whos               %观察变量a,b在内存中所占字节






图1 字符串

【eg.2】字符串的属性和标识

>> a='This is an example.'
>> size(a)
>> a14=a(1:4)             %提出一个字符串
>> ra=a(end:-1:1)         %字符串倒排
>> ascii_a=double(a)      %产生ASCII码
>> char(ascii_a)          %把ASCII码转换成字符串
>> %使字符串中字母全部大写
>> w=find(a>='a' & a<='z');       %找出字符串中小写字母的元素位置
>> ascii_a(w)=ascii_a(w)-32;      %大小写字母ASCII值差32.用数值加法改变部分码值
>> char(ascii_a)                  %把更新后的ASCII码翻成字符
>> A='这是一个算例.';             %创建中文字符串
>> A_s=size(A)           %串数组的大小
>> A56=A([5 6])          %取串的子数组
>> ASCII_A=double(A)     %获取ASCII码
>> char(ASCII_A)         %把ASCII码翻译成字符
>> b='Example"3.1.2-1"'








图2 字符串属性

2、复杂字符串

【eg.3】复杂串数组的创建

>> S=['This string array'
'has multiple rows']                               %多行串数组的直接输入
>> size(S)
>> S1=char('This string array','has two rows.')
>> S2=str2mat('这','字符','串数组','','由4行组成')  %“空串”会产生空格行
>> S3=strvcat('这','字符','串数组','','由4行组成')  %“空串”不会产生一个空格行
>> size(S3)






图3 复杂串数组的创建

【eg.4】int2str(把整数数组转换成串数组)、num2str(非整数转换串数组)、mat2str(常与eval指令配用,把数值数组换换成输入形态的串数组)

>> A=eye(2,4)             %生成一个(2*4)数值数组
>> A_str1=int2str(A)      %转换成(2*10)串数组,
>> size(A_str1)
>> rand('state',0)
>> B=rand(2,4);           %生成数值矩阵
>> B3=num2str(B,3)        %保持3位有效数字,转换成串
>> B_str=mat2str(B,4)     %保持4位有效数字,转换成“数组输入形式”串
>> Expression=['exp(-',B_str,')'];
>> eval(Expression)






图4 转换函数产生数码字符串
[align=left]【eg.5】MATLAB计算生成的图形上标出图名、最大值点坐标
[/align]
>> a=2;                    %衰减系数
w=3;                       %设置震荡频率
t=0:0.01:10;               %取自变量采样数组
y=exp(-a*t).*sin(w*t);     %计算函数值,产生函数数组
[y_max,i_max]=max(y);      %找最大值元素位置
t_text=['t=',num2str(t(i_max))];             %生成最大值点的横坐标字符串
y_text=['y=',num2str(y_max)];                %生成最大值点的纵坐标字符串
>> max_text=char('maximum',t_text,y_text);   %生成标志最大值点的字符串
>> %生成标志图名用的字符串
>> tit=['y=exp(-',num2str(a),'t)*sin(',num2str(w),'t)'];
>> plot(t,zeros(size(t)),'k')                   %画纵坐标为0的基准线
>> hold on                                      %保持绘制的先不被清除
>> plot(t,y,'b')                                %用蓝色画y(t)曲线
>> plot(t(i_max),y_max,'r.','MarkerSize',20)    %用大红点标最大值点
>> text(t(i_max)+0.3,y_max+0.05,max_text)       %用大红点标最大值点
>> title(tit),xlabel('t'),ylabel('y'),hold off  %书写图名、横坐标名、纵坐标名




图5 字符串运用

【eg.6】利用元胞数组(Cell Array)创建复杂字符串
元胞数组允许存放、并操作各种不同类型和不同大小的数据,但存放和操作复杂字符串是元胞数组的一个主要用途。
a='MATLAB R2015b';
b='includes new data types:';     %创建单行字符串a,b
c1='Multidimensional array';
c2='User-definable data structure';
c3='Cell arrays';
c4='Character array';
c5='Function handle';
c=char(c1,c2,c3,c4,c5);           %创建多行字符串c
C={a;b;c};                        %利用元胞数组存放长短不同的字符内容
disp([C{1:2}])                    %显示前两个元胞中的字符内容
disp('')                          %显示一行空白
disp(C{3})                        %显示第三个元胞中的字符内容




图6 元胞数组创建复杂字符串

3、串转换函数

表1 字符串转换函数
指令含义指令含义
abs把串翻译成ASCII码hex2dec十六进制串-->十进制整数
base2dec任意进制串-->十进制整数dex2num十六进制串-->浮点数
bin2dec二进制串->十进制整数int2str整数-->串
char任何类型-->串mat2str数值矩阵-->eval可调用的格式
dec2base十进制整数-->任意进制串num2str数值-->串
dec2bin十进制整数-->二进制串setstrASCII码-->串
dec2hex十进制整数-->十六进制串sprintf数值-->串(控制格式)
double任何-->双精度数值sscanf串-->数(控制格式)
fprintf把格式化数据写到文件或屏幕str2num串-->数值
【eg.】串转换函数:指令fprintf、sprintf、sscanf用法
与num2str、mat2str相比:fprintf、sprintf的转换格式更灵活。

rand('state',0);
a=rand(2,2);                 %产生(2*2)随机库
s1=num2str(a)                %数值数组-->串
s_s=sprintf('%.10e\n',a)     %10数位科学记述串,每写一个元素就换行
fprintf('%.5g\\',a)               %以5位数位最短形式显示,不能赋值用
s_sscan=sscanf(s_s,'%f',[3,2])    %浮点格式把串转换成(3*2)数值数组




图7 指令fprintf、sprintf、sscanf用法

4、串操作函数

blanks(n) :创建n个空格串、

char(s1,s2,...):把串s1、s2等逐个写成行,形成多行数组、

deblank(s):删去串尾部的空格符

eval(s):把串s当做MATLAB指令运行

eval(s1,sc):把串s1当做MATLAB指令运行,若s1运行发生错误,则运行sc

feval(f,x,y,...):对输入量x,y等计算函数f

findstr(s1,s2):在长串中找短串的起始字符的下标

ischar(s):s是字符串,则判“真”给出逻辑1

isletter(s):以逻辑1指示s里文字符的位置

isspace(s):以逻辑1指示s里空格符的位置

lasterr:发出的最新错误信息

lower(s):使串s里的英文字母全部小写

str2mat(s1,s2,...):把串s1、s2等逐个写成行,形成多行数组

strcat(s1,s2,...):把串s1、s2等连接成长串

strcmp(s1,s2):若串s1、s2相同,判断“真”给出逻辑1

strjust(s):字符串的对齐方式:右对齐/左对齐/对中

strmatch(s1,s2):逐行搜索串s2,给出以s1开头的那些行的行号

strncmp(s1,s2,n):若串s1、s2的前n个字符相同,则判断“真”给出逻辑1

strrep(s1,s2,s3):串s1中所有给出s2的地方替换成s3

strtok(s):找出第一个间隔符前的内容

strvcat(s1,s2,...):把 串s1、s2等逐个写成行,形成多行数组,并删除全空行

upper(s):使s里的英文字母全部大写

元胞数组

(1)元胞数组(Cell array)如同银行保险箱库,该数组基本组分(Element)是元胞(Cell)。每个元胞自身在数组中是平等的,只能以下标区分。

(2)元胞可以存放任何类型、任何大小的数组(任意维数数值数组、字符串数组、符号对象等),同一个元胞数组中各元胞中的内容可以不同。

(3)元胞数组对元胞编制方法:单下标编址&全下标编址。

单下标编址:第一行第一列第一页的元胞序号1,沿列而下,直到第一列的元胞全部编完;接下来,沿第二列而下;以此类推,直到第一页编完,直至第二页沿第一列而下...

全下标编址:编址中的序号1为行号;序号2为列号;序号3为页号。

1、元胞数组的创建&显示

【eg】元胞标识寻访&内容编址寻访

数值数组/字符串数组:同一数组各元素的数据类型相同。

元胞数组:元胞&元胞里的内容不同。两种寻访操作:元胞外标识(Cell Indexing)&元胞内编址(Content addressing)。“外标识的元胞元素”用“圆括号()”。“编址元胞元素内涵”用“花括号{}”。

eg:二维元胞数组A:

A(2,3):A元胞数组中第2行第3列元胞元素;

A{2,3}:A元胞数组第2行第3列元胞中所允许存或取的内容。

C_str=char('这是','元胞数组创建算例1');      %产生字符串
R=reshape(1:9,3,3);                          %产生(3*3)实数阵R
Cn=[1+2i];                                   %产生复数标量
S_sym=sym('sin(-3*t)*exp(-t)');              %产生符号函数量
%直接创建法一:外标识元胞元素赋值法
A(1,1)={C_str};
A(1,2)={R};
A(2,1)={Cn};
A(2,2)={S_sym};
A                                             %显示元胞数组
%直接创建方法二:编址元胞元素内涵的直接赋值法
B{1,1}=C_str;
B{1,2}=R;
B{2,1}=Cn;
B{2,2}=S_sym;
celldisp(B)                                   %显示元胞数组内容






图8 元胞标识寻访&内容编址寻访

2、元胞数组的扩充&收缩&重组

【eg】元胞数组的扩充、收缩、重组

利用cell指令:创建元胞数组;

指令cellplot:能用图形形象化表示元胞数组的内容,第二个输入量是用于显示色彩图例。用大白格:表示元胞;小方格:表示所存数组;色彩:表示数据属性。

C=cell(2);
C(:,1)={char('Another','text string');10:-1:1}    %对第一列元胞赋值
AC=[A C]                                          %空格(或逗号)利用来分隔列
A_C=[A;C]                                         %分号利用来分隔行
>> cellplot(A_C,'legend')       %cellplot能用图形形象化表示:元胞数组的内容
>> A_C(3,:)=[]                        %删除第3行,使得A_C成为(3*2)元胞数组
>> R_A_C=reshape(A_C,2,3)









                                                                                                               

图9 元胞数组的扩充、收缩、重组

3、元胞数组内容的调取

【eg】元胞数组内容的调取

%调取一个元胞
>> f1=R_A_C(1,3)                      %使用圆括号寻访得到元胞,不仅是内容
>> class(f1)
%调取一个元胞的内容
>> f2=R_A_C{1,3}                      %用花括号寻访内容
>> class(f2)
%调取元胞内的子数组
>> f3=R_A_C{1,1}(:,[1 2 5 6])         %注意3种括号的不同用途
%同时调取多个元胞内容
>> [f4,f5,f6]=deal(R_A_C{[1,3,4]})    %取3个元胞内容,赋值给3个变量






图10 元胞数组内容的调取

4、元胞数组转换数组

【eg】num2cell函数:把数值数组-->元胞数组

rand('state',0);
A=rand(2,3,2)           %生成(2*3*2)数值数组A
C1=num2cell(A)          %把数值数组A转换成维数大小相同的元胞数组C1
C2=num2cell(A,1)        %把“行”方向元素装入C2的一个元胞
C3=num2cell(A,[2,3])    %把“列、页”方向元素装入C3的一个元胞






图11 元胞数组转换数组

【eg】mat2cell:把矩阵分解-->元胞数组、cell2mat:把元胞数组-->矩阵

x=zeros(4,5);
x(:)=1:20                    %向数组x赋值
C4=mat2cell(x,[2,2],[3,2])   %把数组x转移到(2*2)元胞数组C4
%数组x的分块方式:
%(1)行维方向分成两块:第一块占2行,第二块占2行;
%(2)列维方向分成两块:第一块占3列,第二块占2列
celldisp(C4)
D=cell2mat(C4(1,:))          %C4的一个行子元胞数组转换成单个矩阵








图12 元胞数组<-->矩阵

架构数组

1、架构数组的创建&显示

(1)与元胞数组一样,架构数组(Structure array)也能在一个数组里存放各类数据,架构数组组织数据能力更强、更富变化。

(2)架构数组基本组分(Element)是架构(Structure),架构必须在划分“域”后才能使用。数据不能直接存放于架构,只能存放于域中。

(3)架构的域(Field),可以存放任何类型、任意大小的数组。

(4)架构数组对架构的编址方法:单下标编址&全下标地址。

表2架构数组&元胞数组的异同
 元胞数组架构数组
举例(3*4)元胞数组A(3*4)架构数组B,名为f1、f2两个域
基本组分(Element)元胞架构
对基本组分的编址全下标&单下标:A(1,2),A(4)全下标&单下标:B(1,2)、B(4)
可存放的数据类型任何类型任何类型
直接存放数据的场所元胞本身:元胞A(1,2)域:架构域B(1,2).f1
基本组分寻访方式被标识的元胞名:A(1,2)
被标识的架构名:B(1,2)
具体内容寻访方式“花括号{}”标识的元胞名:A{1,2}“带域名”标识架构名:B(1,2).f1
元胞数组 <-->架构数组cell2struct:元胞数组-->架构数组struct2cell:架构数组--> 元胞数组
【eg】单架构的创建:(1*1)数组、架构数组

>> g_h.name='一号房子';               %架构的域=(架构名).(域名)标识
g_h.volume='2000立方米';
g_h.parameter.temperature=[31.2 30.4 31.6 28.7
29.7 31.1 30.9 29.6]
g_h.parameter.humidity=[62.1 59.5 57.7 61.5 62.0 61.9 59.2 57.5]
g_h                                  %显示单架构结构内容
g_h.parameter
g_h.parameter.temperature
g_h(2,3).name='六号房';       %产生(2*3)架构数组
g_h                              %显示架构数组的结构:行列数+域
g_h(2,3)                            %显示元素架构的结构:域;是否有子域








图13 单架构、架构数组

【eg】利用构造函数struct创建架构数组

struct指令不能直接创建带子域的架构数组,子域需要另行创建。

a=cell(2,3);                                        %创建(2*3)空元胞数组
g_h_1=struct('name',a,'volume',a,'parameter',a(1,2))
g_h_2=struct('name',a,'volumn',[],'parameter',[])
g_h_3(2,3)=struct('name',[],'volumn',[],'parameter',[])
a1={'六号房'};a2={'3200立方米'};
g_h_4(2,3)=struct('name',a1,'volumn',a2,'parameter',[]);
T6=[31.2 30.4 31.6 28.7 29.7 31.1 30.9 29.6];
g_h_4(2,3).parameter.temperature=T6;
g_h_4










图14 利用构造函数struct创建架构数组

2、架构数组域中内容的调取&设置

调取&设置架构数组中的数据:fieldnames指令:查询域名、子域名(得到的fieldnames的类型是)。getfield、setfield指令:调取&设置架构域中的数据内容。

【说明】

(1)函数tf(num,den)中,输入量num是有理分式矩阵的“分子多项式系数矩阵”,den是有理分式矩阵的“分母多项式系数矩阵”。

(2)getfield(SSTF,'den',{2,1})的等价指令形式:SSTF.den(2,1)、getfield(SSTF.den(2,1))、getfield(SSTF,FN{2},{2,1})。

(3)SSTF=setfield(SSTF,'num',{2,1},{[1 3 1]})的等价指令:SSTF.num{2,1}=[1 3 1]、SSTF.num(2,1)={[1 3 1]}、SSTF=setfield(SSTF,FN(1),{2,1},{[0 1 3 1]})等。

【eg】调取&设置架构数组中的数据

Stf=tf({3,2;[4,1],1},{[1,3,2],[1,1,1];[1,2,2,1],[1,0]})
SSTF=struct(Stf)                 %把对象转换成架构,并显示架构的组成
FN=fieldnames(SSTF)              %获得域名元胞数组FN
class(FN)                        %检查FN的类别
FC=getfield(SSTF,'den',{2,1})    %相当于FC=SSTF.den(2,1)
FC{1}
poly2str(FC{1},'s')
SSTF.num{2,1}                   %显示被重新设置后的情况
SSTF=setfield(SSTF,'num',{2,1},{[1 3 1]})     %注意花括号的使用
SSTF.num{2,1}                   %显示被重新设置后的情况












图15 调取&设置架构数组中的数据

3、架构数组操作应用

【eg】架构数组的扩充&收缩

size(SSTF)                      %原架构是一个“单构架”
SSTF(2,2)=struct(tf(1,[1 1]))   %把1/(s+1)放在第2行第2列构架中
size(SSTF)
SSTF(1,:)=[]                    %收缩成为(1*2)构架
S22n=SSTF(1,2).num,S22d=SSTF(1,2).den   %取出第2架构num域和den域
printsys(S22n{1},S22d{1})       %显示成习惯的表达形式






图16 架构数组的扩充&收缩

【eg】添加&删除域

clear,for k=1:10;department(k).number=['No.',int2str(k)];end   %创建架构数组
department
department(1).teacher=40;department(1).student=300;
department(1).PC_computer=40;
department
department(2).teacher.male=35;department(2).teacher.female=13;
D2T=department(2).teacher
D1T=department(1).teacher
department(2).teacher=rmfield(department(2).teacher,'male');
department(2).teacher
department=rmfield(department,'student')                   %删除一个域
department=rmfield(department,{'teacher';'PC_computer'})   %删除2个域
n_ex=5;
for k=1:n_ex,ex(k).f=(k-1)*n_ex+[1:5];end                  %创建(1*5)架构数组
ex                                                         %显示构架数组的结构
disp([blanks(10),'架构域中 '])
for k=1:n_ex,dis(ex(k).f),end



       

   



  


[align=center]图17 添加&删除域
[/align]
【eg】数值运算操作&函数对架构数组的应用

n_ex=5;                                        %架构数组的长度
for k=1:n_ex,ex(k).f=(k-1)*n_ex+[1:5];end      %创建(1*5)架构数组
ex                                             %显示构架数组的结构
disp([blanks(10),'架构域中 '])                 %显示架构数组的域中内容
for k=1:n_ex,disp(ex(k).f),end
class(ex(1).f)                                 %检查域中内容的类型
sum_f=zeros(1,5);                              %对各架构域中数值数组相应位置的数据相加求和
for k=1:n_ex,sum_f=sum_f+ex(k).f;end,sum_f     %对架构数组域中各元素分别求平方根
disp([blanks(20),'ex,f的平方根值'])
for k=1:n_ex,disp(sqrt(ex(k).f)),end



    


图18 数值运算操作&函数对架构数组的应用

4、架构数组&元胞数组之间转换

由于架构数组&元胞数组一样,具有存放各种类型数据的能力,因此这两种类型的数组之间可以相互交换。转换指令:struct2cell、cell2struct

(1)struct2cell指令:架构数组的“域”转换为元胞数组的“行”。而元胞数组的第二、三等维分别是原架构数组的第一、二维。原架构数组中的子域,将仍被当做子域架构存放到新的元胞数组中。

(2)cell2struct指令:把元胞数组-->架构数组之前,选择“哪一维”-->“域”。在抉择确定后,给出域名字符串。

【eg】转换指令struct2cell、cell2struct的使用

%创建“带两个域的(1*5)架构数组
for k=1:5,ex(k).s=['No.',int2str(k)];ex(k).f=(k-1)*5+[1:5];end
%显示架构数组的内容
fprintf('%s\n','ex.s域的内容');fprintf('%s\n',blanks(4))
for k=1:5;fprintf('%s\n',[ex(k).s blanks(1)]);end
fprintf('%s\n',blanks(1)),fprintf('%s\b','ex.f域的内容')
for k=1:5;disp(ex(k).f);end
clc
C_ex=struct2cell(ex);                      %带2个域的架构数组-->(2*1*5)元胞数组
size(C_ex)
fprintf('%s\t',[C_ex{1,1,1},blanks(3)])    %显示C_ex第1页第1行第1列内容
fprintf('%5g\t',C_ex{2,1,1})               %显示C_ex第2页第1行第1列的内容
clc
%把元胞数组转换为架构数组之一
%选定C_ex“第一维'页'”转换为域,维度为2,因此取两个域名S_char、F_num。
FS={'S_char';'F_num'};                     %用元胞数组预建域名字符串
EX1=cell2struct(C_ex,FS,1)                 %元胞数组-->构架数组
EX1(1)                                     %观察新架构EX1第1构架的情况
clc
%把元胞数组转换为架构数组之二
%选定C_ex的“第2维”转换为域,由于第2维长度为1,取一个域名xxEX2=cell2struct(C_ex,'xx',2)
%把元胞数组转换为架构数组之三
%选定C_ex的“第3维”转换为域。由于第3维长度为5,取5个域名:y1,y2,y3,y4,y5YY=strvcat('y1','y2','y3','y4','y5');EX3=cell2struct(C_ex,YY,3)EX3(1) %观察第1架构的情况EX3(2) %观察第2架构的情况





  

  



        



      



    

        

图19
转换指令struct2cell、cell2struct的使用
【eg】带子域的架构数组-->元胞数组

>> %带子域的架构数组-->元胞数组
ex(1,1).s                     %原架构ex(1,1).s中的内容
%增设子域,并把ex架构数组扩充为(3*5)
ex(3,1).s.num=1/3;
ex(1,1).s                     %原架构ex(1,1).s中的内容
ex(3,1).s                     %经新赋值后,架构ex(3,1).s中的内容-
C_ex_sub=struct2cell(ex)      %架构-->元胞数组
size(C_ex_sub)                %观察新元胞数组的大小
C_ex_sub{1,1,1}               %观察第1元胞中的内容
C_ex_sub{1,3,1}               %观察(1,3,1)元胞中的内容






图20 带子域的架构数组-->元胞数组

第三阶段至此结束!学习了字符串&元胞&构架数组!

撒花!(*^__^*)


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: