3. Matlab编程基础:数据类型

3. Matlab编程基础:数据类型

借林肯公园的摇滚乐《Numb》烘托一下气氛



林肯公园Numb歌词
Linkin Park - Numb
I'm tired of being what you want me to be
Feeling so faithless lost under the surface
Don't know what you're expecting of me
Put under the pressure of walking in your shoes
(Caught in the undertow just caught in the undertow)

Every step I take is another mistake to you
(Caught in the undertow just caught in the undertow)
I've become so numb I can't feel you there
I've become so tired so much more aware
I've becoming this all I want to do
Is be more like me and be less like you


Can't you see that you're smothering me
Holding too tightly afraid to lose control
Cause everything that you thought I would be
Has fallen apart right in front of you
(Caught in the undertow just caught in the undertow)


Every step that I take is another mistake to you
(Caught in the undertow just caught in the undertow)
And every second I waste is more than I can take
I've become so numb I can't feel you there
I've become so tired so much more aware
I've becoming this all I want to do
Is be more like me and be less like you
And I know
I may end up failing too
But I know
You were just like me with someone disappointed in you


I've become so numb I can't feel you there
I've become so tired so much more aware
I've becoming this all I want to do
Is be more like me and be less like you
I've become so numb I can't feel you there
Is everything what you want me to be
I've become so numb I can't feel you there
Is everything what you want me to be



今天讲讲逻辑。

先从一个最简单的问题开始:
1 + 1 = ?

这还用问吗?你脑子进水了,这不肯定等于2吗?
那一片云 + 一片云呢?

这... ...




再来一个问题:

你觉得无所不在无所不能的神存在吗?



无神论的观点是,根本不存在神,所以这是个伪命题,连神都没有,自然无所不在无所不能的神是不存在。你是无神论,在这个问题上你赢了!

我在一个虔诚的基督教徒递给我的宣传册上看到这么一句话,“神是无所不在无所不能的... ...” 她建议我一定看一下这个册子,我看到这句话,我就想起我看过的一场很精彩的有神论和无神论之间的辩论:

一个哲学教授问传道者,”你相信神无所不在无所不能吗?“

传道者说:”我当然相信!“。很坚定,因为按照基督教的理解上帝就是全能的。

教授继续问,”上帝能不能造一块他自己搬不动的石头?“

“这……这个……”

我把这个上帝能不能造的问题抛给了这位虔诚的信徒(现在想起来我特别后悔,人家本来有信仰挺好的)。结果可想而知,我让她陷入了冲突好几天没缓过来... ...



在学习Matlab的过程中,经常会出现这样的情况,“这代码明明是对的,怎么就出错了呢?” 或者,“这机器是不是有问题啊?” ------每次我都会心平气和且苦口婆心地劝道,“计算机是不会错的,只有人才犯错,要淡定... ...”,然而并没有卵用。

计算机遵循的是人的指令,如果你的指令是符合逻辑的,机器是肯定不会报错的;出现问题,唯一有可能的就是你自己在哪个地方出错了,你所要做的事情就是把这个错误找出来并且予以修正(debug)。

人是会撒谎的动物!讲逻辑,是第一步,它可以帮助我们克服人性的弱点!
在学习Matlab的时候,我们完全不用担心逻辑的问题,因为计算机不像人,它是完全按照逻辑执行命令的。


什么是变量和变量名

我们在之前反复提到了“变量”,却一直没有给出它的定义。所谓的变量,在百度百科里边是这么定义的:



变量是指是一段有名字的连续存储空间。 而这个所谓的名字就是变量名。




如果把存储单元进一步放大,本质上它就是一些由 0和1组成的格子。


变量有不同的类型,不同的类型又对应不同的存储空间的大小,本质上就是0和1组成的格子数不一样。简单一点,它可以是一个整数;复杂一点,它可以指向一张图片,一首歌曲;再复杂一点它可以指向一个动态变化的应用程序。


在介绍变量的不同数据类型之前,我们先来看看Matlab的关键字都有哪些?

关键字

'break'

'case'

'catch'

'classdef'

'continue'

'else'

'elseif'

'end'

'for'

'function'

'global'

'if'

'otherwise'

'parfor'

'persistent'

'return'

'spmd'

'switch'

'try'

'while'

这些关键字,可以在命令窗口中输入 iskeyword打印出来。


然后,我们再来看看Matlab默认的常量有哪些?

常量




逻辑型变量

最简单的变量类型应该就是逻辑型变量,这种变量的值只有两种:一种是 true,另外一种是 false。

比如,你的房间里有一盏灯,它要么是开着的,要么是关着的,你可以用一个变量表征它的开关的状态。

>> State_KaiG = true

State_KaiG =

1


>> State_KaiG = false

State_KaiG =

0
这时候你会很神奇的发现,为什么变量是true的时候,其显示为啥是1,而变量是false的时候,其显示的是0呢?

如果这个时候,你随便设置另外两个变量:

>> Variable_A = 1

Variable_A =

1

>> Variable_B = 0

Variable_B =

0

这个时候,我们的工作空间里边显示了3个变量,其中State_KaiG前边显示的是一个打钩,而Variable_A和Variable_B前边则显示的是田字格,它们分属于不同的变量类型,所以它们前边的图标也是不一样的(它们所占的格子数,也就是存储空间的大小自然也是不一样的。所以并不是你让一个变量等于0或者1,它就是逻辑型变量,尽管显示的时候我们看到的都是0或者1)。如果这个时候你比较好奇,强行把State_KaiG + Variable_A 会有什么后果呢?


>> State_KaiG + Variabl_A

ans =

2


我们发现ans前边的图标也是田字格。Matlab存在一种操作,服从弱肉强食自然法则,它会强制将逻辑型变量转换为数值来进行计算。



当然,我们尚处在社会主义初级阶段,贫富差异还有点太过明显,可能有人说了,我是土豪,我住的房间大,一盏灯怎么够,我要十盏灯。(土豪我们做朋友吧)

土豪说他还是单身,晚上睡觉空虚寂寞冷,需要把前边五盏灯关掉,后边五盏灯开着(有钱人的一些癖好比较怪,不需要懂)... ... 我们试试看这种情况下应该怎么写才能满足土豪的特殊要求:

>> Light_Array = 1:10

Light_Array =

1 2 3 4 5 6 7 8 9 10


>> State_KaiG_Array = Light_Array > 5

State_KaiG_Array =

0 0 0 0 0 1 1 1 1 1


第一次出现冒号‘:’,它是什么意思呢?
Light_Array = 1:10 完整的写法应该是这样的:Light_Array = 1:1:10,如果你缺省中间那个1,Matlab会自动把这个位置默认为是1,也就是你从初始1到最后的10,每次递增(或者递减)的step是1。

在这里,冒号‘:’的功能是生成等间距的序列。冒号还有其他几种用法,先按下不表。

Light_Array > 5 算是关系运算,它又遵循什么样的规则呢?
在Matlab中,关系运算符主要有6个,请看下边的表格:


在程序中,对数据进行了关系运算,可采用关系运算符,也可以采用对应的函数。需要注意的是,进行比较的两个操作数(也可能是其他对象)维数必须相同。


逻辑运算

既然讲到了逻辑型变量,自然是要理解逻辑运算符的,包括:

逻辑与(and),逻辑或(or), 和逻辑非(not)。
它们的运算符分别是: & | ~

“与”:两者都为真时,运算结果才为真;只要其中一个是假,其运算结果就是假。
“或”:两者只要有一个是真,运算结果就是真;只有两者都是假,运算结果才是假。
“非”:一个真事件的非运算结果是假,假事件的非运算结果是真。

除了逻辑与和逻辑或之外,还有一个快速逻辑与(&&)和快速逻辑或(||)。
&&运算符在参与运算的第一个操作数为假时,直接返回假,不再计算第二个操作数。
||运算符在参与运算的第一个操作数为真的时候,直接返回真,不再计算第二个操作数。

>> a = true -> a = 1 %定义变量a,其值为逻辑型真
>> b = false -> b = 0 %定义变量b,其值为逻辑型假
>> a && b -> ans = 0 %a是真,b是假,a且b为假
>> a || b -> ans = 1 %a是真,b是假 a或b为真
>> ~a -> ans = 0 %a是真,非a为假

自从有了逻辑型数据类型之后,Matlab的开发者们就开始着手进行各种判断语句的编写工作,首当其冲的自然是if条件判断语句的编写:

它基本的格式是这样的:


if 条件判断语句
执行语句
end


如果稍微复杂一点,可以写成:
if 条件判断语句
执行语句1
else
执行语句2
end



如果再复杂一点,可以写成:
if 条件判断语句1

执行语句1
elseif 条件判断语句2

执行语句2
else

执行语句3
end



if条件判断语句,简单说就是提供了一种逻辑判断的方式,即如果一种条件成立,则进行一种操作;如果该条件不成立,则进行另外的操作。举个例子,

if 考试成绩<60
告诉学生:尼玛考试不及格!
else
告诉学生:尼玛考试还及格了!
end

这里就是一个逻辑判断的过程,如果成绩小于60分,返回逻辑值1,执行 "告诉学生尼玛考试不及格";否则就告诉学生另外一句话"告诉学生:尼玛考试还及格了!"。对于之前学习过C语言的欧巴奴娜们,这很容易理解。

完整的Matlab程序应该是这样的:

  Test_Score = input('input your test score:');
  if Test_Score<60
      fprintf('告诉学生:尼玛考试不及格!\n')
      fprintf('告诉学生:尼玛考试还及格了!\n')
  end

这里专门用了两个新的函数,一个是input()函数,用来获取输入的数值并且赋给Test_Score这个变量;另外一个就是fprintf()函数,用来显示反馈语句。也可以用disp()函数,功能都是一样的。\n 则是换行的意思。


人往往是抗拒批评的。人往往是非常自恋的,都会认为自己没有错,问题出在其他人或者其他事物上。这是一种防御机制,选择Matlab有很多正视自己的人性的弱点的机会。错不可怕,错了改过来就好了。有勇气勇敢面对自己的人,真诚面对自己内心的人,都是很难得的。在这个世界上,敢于真诚面对自己内心的人,才有机会触碰伟大O(∩_∩)O~



数值型

先上个图,概括一下Matlab数值型数据都有哪些类型:

Matlab默认的数值型是双精度double

再上一个表格,表示整数数据能够表示的数的大小范围:


•单精度数据需要4字节的存储空间,其空间分配如下表:

单精度数据的字节位功能


单精度浮点型的表示范围也可以用函数查询,realmax和-realmax分别得到

其可以表示的最大正数和最小负数,单精度类型用single表示


•MATLAB中数值的默认类型是双精度浮点型,其构造规则和单精度相同。

双精度数据的字节位功能


双精度类型用double表示,其范围查询函数和单精度一样。


取整函数:

floor(x)向下取整

ceil(x)向上取整

round(x)四舍五入

fix(x)向0取整


字符串


有那么一个精神病人,整天穿着一身黑雨衣打着把伞蹲在院子里潮湿黑暗的角落,就那么蹲着,一整天一动不动。医院的护士架走他他也不反抗不挣扎,不过一旦有机会那是会穿着那一身行头打着花伞原位蹲回去。


很多精神病医生和专家都来看过,折腾了好几天连句回答都没有。于是大家最后都放弃了,说这个病人没救了。



有一天,来了个北师大的学心理的专家,她不问对方任何问题,只是穿着和病人一样的衣服,也打了把花伞跟他蹲在一起,连着好几天都是如此。就这样过了一个礼拜,终于有一天,那个病人主动开口了,他悄悄地爬到心理专家身边,低声问道:“你也是蘑菇?”


这是我从《天才在左 疯子在右》这本书里边摘出来改编的 O(∩_∩)O~ 这个段子的原型是一个笑话,就像作者说的,当你开始理解这个奇妙的世界的时候,你会不再觉得这是个笑话。

疯子的世界,你不会懂的,除非你能摆脱自我中心,学会换位思考。

我的小姑妈在别人看来也是个疯子,不怎么喜欢与人交流,看起来神经兮兮的,总生活在自己的世界。我的奶奶最夸张的时候曾经架着她的脖子,一边往墙上撞一边喊着“你怎么这样啊 ... ...” 。


我隐约记得,我的小姑妈有一种很神奇的能力,你随便报一个年份,比如,1863年,她能够马上告诉你,这一年的生肖是什么;另外,我也有印象,有一天我的小姑妈拿起一个魔方玩,没多久六面就玩出来了。


现在想起来,这是典型的自闭症。牺牲掉几个点的social方面的能力,在数学和视觉空间能力方面会表现得很好。

一般人,如果有点奇葩,会很招人恨,如果不小心生了个自闭症,真的想死的心都会有的。为什么会这样?为什么他们总是活在自己的世界里边,一个正常人都是能跟人愉快顺畅的交流,自闭症怎么就不能?我们所要做的努力就是学会去接纳他们,文明发展的水平越高对异类的接纳程度就会越高。




Diversity,一个民族越多元化,这个民族就会越强。日本人和美国人怕我们,不会是因为我们的千篇一律(更不会是因为我们不怕死,不怕死你死好了),而是我们的兼容并包,尊重人的个性。疯子和天才,才是推动社会进步的动力(乔布斯是个疯子,爱因斯坦是个天才)。也许在一个更包容的世界,天才就有机会得到专门的教化,能够在他们所擅长的领域把人类知识的边界进一步推向极限之外。




这个章节会借助乔布斯(Steve Jobs)和爱因斯坦(Albert Einstein)为线索,讲解如何进行字符串处理。以下首先会介绍字符串的属性(知己知彼百战百胜);然后再讲解字符串的常见操作(想象着字符串就是你砧板上的食材,要杀要剐任凭你处置);最后会探讨字符串的执行(从普通人升格为超级赛亚人,它本来就是一串卑微的字符串,居然可以升格为命令控制命令窗口,所以不要因为对方弱小就太嚣张,有的时候你都不知道谁会不会成长为大Boss)。



字符串是指1*N的字符数组,它是我们砧板上的一条鱼,它有它的内容,为了操作它的内容我们至少要知道刀得从哪个位置下去我们得知道它的属性(它有多长),让我们让我们以乔布斯说过的"Stay hungry. Stay foolish." 开始剖析字符串:


wStr = 'Stay hungry. Stay foolish.' % wStr w意思是 wisdom, Str是String的缩写


我们想知道它有多长,主要借助size()函数和length()函数


>> wStr = 'Stay hungry. Stay foolish.'

wStr =

Stay hungry. Stay foolish.

>> size(wStr)

ans =

1 26

>> length(wStr)

ans =

26

从这个例子也可以看出,函数size()是有两个返回参数的,不像length()函数。size返回的是行数和列数,而length则干脆只返回长的那个维度的长度(字符串是1*N的字符数组,也就是字符串的长度)

为了让各位对size()函数的操作能够更好的理解,我们写得更全一点试试:
>> [rowNum colNum] = size(wStr)

rowNum =
1

colNum =
26


这样直接取 colNum就是字符串的长度了。


字符串的常见操作函数


聚合字符串的操作


字符串最常见的操作是 聚合 ,这里要特别隆重地推出我们的明星函数 sprintf()
在Matlab里边,我们之前讲过一定要养成拷贝当前路径到工作目录编辑框的习惯,那么怎么获取这个工作目录的路径信息呢?比如,我想在当前工作目录里边新建两个文件夹,一个叫做Steve Jobs;另外一个叫做Albert Einstein


% how to get the current working path
CurrentWorkingPath = fileparts(mfilename('fullpath')); %通过fileparts()和mfilename()两个函数的嵌套就可以获取当前工作目录,这里mfilename(‘fullpath’)获取的是当前运行.m文件的全路径,而fileparts()获取的则是里边参数去掉文件名剩下的路径。


jobsFolderName = 'Steve Jobs';
einsteinFolderName = 'Albert Einstein';


% sprintf()函数来了,来感受一下它的魅力吧
jobsFolderPath = sprintf('%s\\%s', CurrentWorkingPath, jobsFolderName);
einsteinFolderPath = sprintf('%s\\%s', CurrentWorkingPath, einsteinFolderName);


% 新建一个文件夹的函数是 mkdir() ,mkdir是make directory的缩写,so 让我们新建两个文件夹试试
mkdir(jobsFolderPath);
mkdir(einsteinFolderPath);


稍等片刻,应该能在你Matlab的左边的'资源管理器',或者windows自带的资源管理器相应的工作目录中观察到对应的文件夹Steve Jobs和文件夹Albert Einstein。

一开始,可能会对sprintf()函数的这种特殊的写法不太适应,因为它在一开始的时候需要先指代(%s指代字符型变量,%d指代数值型变量,中间可以加任意的字符串,'\\'就是字符串,第一个'\'是标识这是一个特殊的字符,比如'\t'就是制表符的意思,'\n'就是换行的意思,‘\\’就是斜杠的意思,上级目录和下级目录之间都会有这么一个斜杠\),然后再在后边把变量一一列出来,为什么要采用这种形式呢?我一开始也适应了一段时间,在后来用的时候越来越觉得这种形式比直接拼接的形式有诸多优点,至于你什么时候会跟我有相同的感觉,那你准备写代码吧,当你写到2万行代码的时候,应该就会产生跟我一样的感觉。


我在这里举一个简单的例子说明sprintf()函数这种指代的思想为什么比那种拼接的思想要更优秀的原因:
我们学校为了方便管理,需要给每个学生一个id的,也就是我们的学号。比如,我们周星驰同学的学号是8号(008),假如我们想给每个同学都新建一个文件夹,里边有他们每个人的各种文档。这个过程应该怎么实现?


我们可以试着新建36个同学的文档:
CurrentWorkingPath = fileparts(mfilename('fullpath'));
% LOOP: index is i
for i = 1:36
tmpFolderPath = sprintf('%s\\StudentID%d', CurrentWorkingPath, i);
mkdir(tmpFolderPath);
end









故意停顿10秒钟,











O(∩_∩)O~ 上面这段代码有个问题,处女座会说,它没对齐!!!
处女座你太有才了,您说的没错,上面这36个文件夹是没有对齐的
StudentID1
StudentID2
.
.
.
StudentID11
.
.
.
StudentID36

为了让文件夹的名字更好看,满足处女座的需求,我们需要稍微做一个判断:

% filename is:: generate36folders.m
% clear
clc; clear; close all;
% get the current working path
CurrentWorkingPath = fileparts(mfilename('fullpath'));
% LOOP: index is i
for i = 1:36
     if i < 10
             tmpFolderPath = sprintf('%s\\StudentID0%d', CurrentWorkingPath, i);
             mkdir(tmpFolderPath);
             tmpFolderPath = sprintf('%s\\StudentID%d', CurrentWorkingPath, i);
             mkdir(tmpFolderPath);
end


在资源管理器中会是这般:

StudentID01
StudentID02
.
.
.
StudentID11
.
.
.
StudentID36

掌握以上这段代码,立马能够高大上,为啥?你想象一下,你的公司有几十个人,和几万个人,本质上是一样的,在Matlab的世界里边,i从36改成36000也就多了几个0。学习Matlab,我们就是要提高我们的驾驭数据的能力(这与管理能力绝对是正相关的)。

当然,要提高管理能力,还涉及到数据矩阵的整体操作的能力的提升,随着教程的慢慢铺开你会慢慢感受到一股暖流从丹田这地方慢慢向上,向上,向上,最后冲破你的任督二脉。


分久必合,合久必分讲完字符串的 聚合 ,我们讲讲字符串的 切割




切割字符串的操作

我们在这里借助regexp()函数的'split' 模式来实现字符串切割操作。这个regexp()函数的一般语法如下:
strCells = regexp(myStr, char, 'split')

其中myStr是待分割的字符串,char是作为分隔符的字符(可以使用正则表达式),分割出的结果存在myStr中:

以下面这样一串字符为例

myStr = 'Hello Albert Einstein' %也可以写成myStr = ['Hello Albert Einstein'] 本质是一样的

% 首先去除字符串尾部的多余空格
myStr = deblank(myStr);


% 去除字符串两端的多余空格

myString = strtrim(myStr);


%如果这几个字符串是以制表符分隔的,可以这样来做:
strCells = regexp(str, '\t', 'split');


%如果这些字符串是以一个或多个空格分隔的,可以用正则表达式来描述:
strCells = regexp(str, '\s+', 'split');


这样,strCells(1)=’Hello’,strCells(2)=’Albert’,strCells(3)=’Einstein’。

注意,上面得到的结果strCells是一个cell型变量(也叫做元胞数组,是Matlab里边比较好用,兼容并包的一种格式,在这里都是字符串类型),它的每个元素比如strCell(1)仍然是cell型的,只能用来display,不能直接用来进行字符串操作(比如获取其中的某个字符),所以我们在使用需要执行一次:

pString = char(S(1))

这样的pString才是一个真正的字符串,可以进行后续的操作。

>> myStr = 'Hello Albert Einstein'

myStr =

Hello Albert Einstein

>> strCells = regexp(myStr, ' ', 'split') % 第二个参数 ‘ ’ 中间是一个空格

strCells =

'Hello' 'Albert' 'Einstein'

>> strCells(1)

ans =

'Hello'

>> strCells{1}

ans =

Hello

理论上,如果我们要直接获取元胞数组的字符串信息,也可以用 {} 来直接提取其中的字符串内容。

所以,strCells(N)提取的是第N个元胞数组的信息,这个元素仍然是元胞数组类型;strCells{N}提取的是第N个元胞数组中的字符串的内容,这个元素的格式已经是字符串的了。


替换字符串的操作



字符串可以聚合,可以切割,自然也是可以 替换 的。

str1 = 'I am a Genius';

如果我们要把这句话中的 Genius 替换成 Psycho 可以这样操作

str2 = strrep(str1, 'Genius', 'Psycho')


>> str1 = 'I am a Genius';

>> str2 = strrep(str1, 'Genius', 'Psycho')

str2 =

I am a Psycho

有的时候,天才和疯子只有一步之遥,这一步就是 strrep()函数 O(∩_∩)O~


字符串的执行


Matlab提供了一个eval()函数,用来执行'字符串'程序。

比如,我们要生成魔方矩阵 magic(3),最简单的写法是这样的
tmpMatrix = magic(3)


这个是很简单的,假如我要生成多个 magic(N)矩阵呢?


这个时候,要么一个一个输入
tmpMatrix1 = magic(3)
tmpMatrix2 = magic(4)
tmpMatrix3 = magic(5).
.
.
tmpMatrix10 = magic(10)

这种叫做硬编程,计算机本来的优势就在于它能够循环反复执行,这么写代码有点“太累了”的感觉。

用eval()函数吧,它可以省时省力还不伤手!

for n = 3:10
tmpLine = sprintf('tmpMatrix%d = magic(%d)', n, n);
eval(tmpLine) % 故意少一个分号,这样方便在命令窗口中看到显示的情况
end

执行的结果如下

>> for n = 3:10
tmpLine = sprintf('tmpMatrix%d = magic(%d)', n, n);
eval(tmpLine)
end

tmpMatrix3 =

8 1 6
3 5 7
4 9 2


tmpMatrix4 =

16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1


tmpMatrix5 =

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

.
.
.

tmpMatrix10 =

92 99 1 8 15 67 74 51 58 40
98 80 7 14 16 73 55 57 64 41
4 81 88 20 22 54 56 63 70 47
85 87 19 21 3 60 62 69 71 28
86 93 25 2 9 61 68 75 52 34
17 24 76 83 90 42 49 26 33 65
23 5 82 89 91 48 30 32 39 66
79 6 13 95 97 29 31 38 45 72
10 12 94 96 78 35 37 44 46 53
11 18 100 77 84 36 43 50 27 59



在现实生活里边,'人有多大胆,地有多大产'绝对是忽悠人的话;但是,在Matlab的世界里边,因为eval()函数的存在,思想有多远,你就可以走多远!




结构体

创建结构体的两种方法:

第一种是“直接输入”的方法,

student(1).name = 'Zhang Fei';

student(1).age = 28;

student(1).gender = 'Male';

student(2).name = 'Zhao Yun';

student(2).age = 23;

student(3).gender = 'Male';


第二种是“采用struct()函数”的方法,

S1 = struct(‘type’, {‘big’, ‘little’}, ‘color’, {‘red’, ‘blue’}, ‘data’, {[1 2 3; 4 5 6], [1:6]});


结构体操作函数举例(结构体中有字段,也有记录)

比如,用rmfield()函数可以删除结构体中的字段,如下图所示:


对于结构体来说,最实用的莫过于,获取一个文件夹中所有文件的信息的操作:


给代码来段截图,关键是带dir函数那句:

这个时候,Matlab的工作空间中会看到这样的信息:


我们可以点开这个变量,会看到这样的信息:


每个bmp文件,都包含name,date,bytes,isdir和datenum等字段的信息。

结构体这种数据类型,用来表示一种对象的属性特别合适。


元胞数组

•元胞(Cell)是MATLAB7.0中出现的一个重要的数据类型,元胞可以包含不同类型和大小的数据,包括数值数组、逻辑类型、字符串及元胞类型,这样使得不同类型的相关数据可以集中在一个单一的变量中表示,给用户的数据存储和操作带来了方便。

元胞数组的创建有三种方法:

A. 直接输入

B. 直接赋值法

C. 函数生成法


A. 直接输入

创建一个元胞数组方法是直接输入元胞数组的各个元胞。

•例:生成一个2X2的元胞数组,其中包含4个元胞,元素类型分别是标量、整型数组、字符串和元胞数组,代码如下:

>>a={8, ones(2); ’cell array’, cell(2,2)} %元胞数组包含4个不同类型的元胞

a=

[ 8] [2x2 double]

‘cell array’ {2x2 cell}


B. 直接赋值法

元胞索引法

>> a(1,1) = {8};

>> a(1,2) = {ones(2)};

>> a(2,1) = {‘cell array’};

>> a(2,2) = {cell (2,2)}

a=

[ 8] [2x2 double]

‘cell array’ {2x2 cell}


内容索引法

>> a{1,1} = 8;

>> a{1,2} = ones(2);

>> a{2,1} = ‘cell array’;

>> a{2,2} = cell(2,2);

a=

[ 8] [2x2 double]

‘cell array’ {2x2 cell}


特别需要强调的是:{ } 用来访问元胞的值,而( )只用来标识元胞行列位置。


C. 函数生成法

•函数生成法:即用cell函数预先生成一个空元胞数组,然后再向其中添加所需的数据。

•例:创建一个2x2的元胞数组。

•(1)生成一个2x2的空元胞数组。

•>> a = cell(2,2)

• a =

• [] []

• [] []

•(2)调用元胞或内容赋值法对空元胞数组的元胞进行赋值生成

• a=

• ‘中国’ ‘China’

• [ 1*6 double] [ 100]

•(3)调用cellplot函数,对元胞数组的结构进行图形显示,以增强对其结构和内容的了解,显示结果 Output_Cell = cellplot(a, ‘legend’)

调用函数cellplot() 绘制了单元型变量的结构


元胞数组的操作

元胞数组的操作和数值数组的操作基本相同,都是针对元胞本身进行操作,而不涉及元胞的内容。下面仅介绍元胞数组的扩充和删减。

•元胞数组的扩充

–以之前2x2数组a为例,如果给其添加a(1,3),系统将会在a(2,3)处自动生成一个空数组[]。形成一个2x3的新元胞数组。

–>>a(1,3)={‘addition’}

–a=

– [ 8] [2x2 double] ‘addition’

– ‘cell array’ {2x2 cell} []

•元胞数组的删减

–若要删减一个元胞数组的行或列,可以把需要删除的部分设置为空数组,如,要删除数组a的第3列,代码如下

–>>a(:,3)=[]

–a=

– [ 8] [2x2 double]

– ‘cell array’ {2x2 cell}



采用元胞数组,最实用的莫过于,从text文件中读取单词列表,赋给一个元胞数组。

代码如下:


% filename is:: print12SXiaoWYY.m
% clear
clc; clear;