六、Structure
这里举个例子,有一个学生structure,包含姓名、邮箱、学号、成绩,应该如何创建这个structure
图6-1 学生structure
下面给出代码
图6-2 学生structure代码
structure的作用可不止这么点,学生不止一个人,假设又多了一个学生,我们应该怎么做呢?
图6-3 多个学生structure
下面给出代码
图6-4 多个学生structure代码
其实就是在定义的structure名字后面用括号括起来加个数字
问题总是接踵而至,现在如果我让你显示名字为“Ann Lane”的学生的第三个成绩,也就是“90”,应该如何做?
直接给出代码,读者看一下就明白了
student(2).grade(7)或student(2).grade(1,3)
structure暂时就讲到这里,可以提一句的是,一个structure里面可以再包含另一个structure,反过来说就是,一个structure作为字段存储在另一个structure里,这都是可以的,还有很多对于structure进行操作的函数,比方说删除studen这个structure里的id字段,就可以执行rmfield(student,’id’),这些就不在这里讲解了,读者若有需要可以去google
七、cell array
cell 有点类似于我们讲的矩阵,但是矩阵的每个位置都是存储数值,而cell的每个位置可以用来存储不同类型的值,比方说,一个cell A,A(1,1)的位置存储一个3×3的矩阵,A(1,2)的位置存储一个string类型的字串,A(1,3)的位置存储一个复数3+7i,A(1,4)的位置存储一个1×3的矩阵,见下图
图7-1 cell array
而cell定义的代码又有点类似于structure,有两种定义方式,下面给出代码
图7-2 第一种定义cell
图7-3 第二种定义cell
从上面两图可以看到,无论是哪种定义方式,都必须要用“{}”,花括号是至关重要的,定义cell必不可少
下面再想一想,如果我要显示A(1,1)存储里面的内容,应该输入什么代码?
图7-4 展示cell内容
在这里我把通过花括号和圆括号展示cell内容的代码都写出来,好让读者区分,圆括号只会告诉你cell这个位置存储的是个什么类型的值,而花括号会给你展示这里面的值的内容
问题又来了,我们如何获取矩阵当中的值“3”?其实读者想一想就明白了,A虽然是个cell类型,但是A{1,1}展示的是个矩阵,也就是说A{1,1}这个整体,其实就可以看作是一个矩阵,如果要获取矩阵内的值,应该如何获取?所以问题就迎刃而解了,直接输入A{1,1}(1,3)或A{1,1}(7),就会显示”3”了
Matlab还是提供了很多函数,除了structure有很多函数可以用以外,cell也有,下面稍微讲几个比较常用特殊的函数,剩下的读者有需要再去google
1.num2cell函数
num2cell函数的作用是讲一个矩阵转换为相同行列数的cell类型,下面举个例子,我们先用magic函数创建一个魔方阵(每行、列以及对角线的数之和相等。该和的值为1+2+3+.....+n^2的和再除以n,n必须为大于或等于3的整数)
图7-5 num2cell函数
2.mat2cell函数
如果说我不想一个一个将矩阵内的值存转换成cell,而是想一块一块的转换,比方说,我想以行为单位,一行一行的转换成cell,还是上面的矩阵,转换成三行一列的cell,应该怎么做呢?下面给出代码
图7-6 mat2cell函数
3.cat函数
之前我们讲的所有内容都只涉及到一维或者二维,那么在这里讲的涉及到的就是三维,如何创建一个三位的矩阵或者cell,就用cat函数,下面我们先看一个例子
图7-7 两个矩阵
图7-8 cat函数
图7-9 三维矩阵
当然,cat也能创建二维矩阵,有两种方式,一种是将矩阵一列一列排下去,一种是一行一行排下去,代码和结果见下图
图7-10 列排
图7-11 行排
4.reshape函数
reshape函数的作用是将一个i×j的矩阵转换为inew×jnew的矩阵,前提条件是i*j = inew*jnew,下面看个例子
图7-12 cell array
这是一个2×2的cell array,现在我要将它变成一个1×4的array,具体操作见下图
图7-13 1×4array
可以看到,reshape函数里面带三个参数,第一个是需要转换的矩阵的名字,第二个是需要转换的行数,第三个是需要转换的列数
八、file access
我们有时候需要把计算完的workspace里的data存储为档案,或者是将存储的档案读取到workspace里,所以我们这里涉及到两个操作,load和save
图8-1 file access
8.1 save
save函数的含义是:Save(all)workspace data to a file
这里我们首先创建一个4*4的矩阵,然后通过save函数将他存储起来,见下图
图8-2 save
当我们输入代码之后,workspace里的所有数据都被保存了指定的文件夹下,现在我们做一个操作,看看能不能通过记事本打开data1
图8-3 记事本打开1
通过记事本打开,我们发现里面的内容并不是矩阵的数值,而是一些相关信息,那如果我们想保存为记事本也能打开的格式,应该怎么输入呢?
>> savedata2.mat -ascii
在代码后面加上-ascii就可以了,然后我们将新保存的文件再通过记事本打开
图8-4 记事本打开2
多说一句,如果不是想保存所有的workspace里的变量,只是想保存某一个或者某一些,只要鼠标右键这个变量,另存为即可
8.2 load
有保存,就有读取,读取的方式见下图
图8-5 load
这都没什么好说的,读者将代码记住就行了,有一点要注意的是,如果你保存的时候加了-ascii,那么读取的时候也要加上,否则是读不进来的
8.3 xlsread
现在我们要讲的是如何读取excel中的数据
图8-6 excel数据
我这里有一个excel,里面有一些数据,我想把他读取到matlab里面,应该怎么做?下面给出代码
>>Score = xlsread(‘04Score.xlsx’)
那么matlab就会把整个excel内的数据全部读进来?不对,其实matlab在读excel内的数据时会将数值和string类型的字符串分开来,只会读数值
图8-7 xlread1
再思考一个问题,excel里面是有坐标的,每个值都有其位置,比方说94,它的位置就是B2,那我们如何选定一个区域进行读取呢?可以,下面给出代码
>>Score = xlsread(‘04Score.xlsx’,’C3:D4’)
这样,我们就只选择C3到D4之间的数据读入,其他部分的值是不会读入的,如果想要连同标题一起读入,我们这么写>>Score = xlsread(‘04Score.xlsx’);,你可以试一下,这么写还是只有数字,为什么?因为我们知道matlab矩阵里面是只能有数值类型的变量,所以他不会把string类型的字符串也读进来,那我们应该怎么做?我们可以把他们分开来读
>>[Score Header] = xlsread(‘04Score.xlsx’);
图8-8 xlread2
8.4 xlswrite
有从excel中读取数据的办法,就有从matlab中写入数据的办法,xlswrite函数的作用就是写入excel,我们以一个例子来讲,下面我们要做的是把刚刚从excel中读入进来的数据,算他们每个人的平均数,然后再写入他们每个人的成绩的后一列。一步步来,首先是算平均数,算平均数的函数是mean,我们之前讲到过了,mean这个函数算平均数的时候,是一列一列算的,但是我们应该一行一行算,因为一个人的三个成绩在同一行,所以我们的代码应该是这样
>>mean(score’)
光这样就可以了吗?仔细想想,创建一个矩阵,他默认是一行多列的,但是我们现在需要的是多行一列,所以我们还需要在mean函数的后面再次转置mean(score’)’,然后再写入excel,下面给出完整代码
>>M = mean(score’)’;
>>xlswrite(‘04Score.xlsx’,M,1,’E2:E4’);
注意一点,在写入的时候,excel是不能开着的,下面我们看一下excel是否写入了
图8-9 xlwrite
我们顺便在上面加个标题mean好了,不然别人不知道这一列的数字有什么含义
>>xlswrite(‘04score.xlsx’,{‘mean’},1,’E1’);
总结一下xiswrite函数的格式:xlswrite(‘filename’,’variable’,sheet,’location’),”sheet“的含义是excel的第几页
*8.5 file I/O function
这一部分的内容打上*星号,因为比较深入,如果你有一定的c语言或者别的编程语言基础,可能会比较容易懂,但是如果没有,可能就比较难懂
我们上面讲了,如何读取excel,如何写入excel,现在我们要讲的是对于一个普通的file格式的文档,如何去操作
一开始我们先不讲各种函数的使用,我们先分析,操作一个文件,需要哪些步骤,举个例子,我这里有矩阵x,矩阵y是sin(x),我想把它保存到一个文本文档里,应该如何操作
1.Open a file
2.Write x,y into the file
3.close the file
我们一个一个说,首先是第一步,打开档案,打开档案我们需要用到的函数是fopen,其调用格式为:[fid,errmsg]=fopen(‘filename’,’permission’);
参数说明:
1.fid:函数返回值类型,为整数类型。打开文件成功时,返回以整数,用来标识该文件;打开不成功时fid=-1。三个标准文件则自动获得标识,不需要打开。fid=0,标准输入文件(键盘)。fid=1,标准输出文件(屏幕)。fid=2,标准出错信息文件
2.errmsg:打开文件不成功时返回的出错信息,字符串类型变量
3.filename:待操作的文件名,字符串类型变量
4.permission:对文件的允许使用方式见下表
参数 | 允许使用方式 |
---|---|
r | 为输入数据打开一个文件。如果指定的文件不存在,则返回值为-1 |
w | 为输入数据打开一个文件。如果指定的文件不存在,则创建一个新文件,再打开它;如果存在,则打开该文件,并清空原有内容 |
a | 打开一个文件,随后的操作可在该文件末尾添加数据 |
r+ | 为输入和输出数据打开一个文件 |
w+ | 为输入和输出数据打开一个文件。如果指定的文件不存在,则创建一个新文件,再打开它,如果存在,则打开该文件,并清空原有内容 |
a+ | 为输入和输出数据打开一个文件,随后的操作可在该文件末尾添加数据 |
第一步做完了,我们进行第二步将数据写入文件,写入文件需要用到一个函数fprintf,其调用格式为:fprintf(fid,format,variables)
参数说明:
1.fid为文件句柄,若缺省,则输出到屏幕
2.format用来指定数据输出时采用的格式,具体格式见下表
参数 | 说明 |
---|---|
%d | 整数 |
%e | 科学计数法 |
%f | 小数 |
%g | 系统自动选取上述两种格式之一 |
%s | 输出字符串 |
最后,我们只需要关闭文档即可,使用函数fclose,其调用格式为:status=fclose(‘fid’)或fclose(‘fid’)
图8-9 ”写“文档操作
既然是I/O操作,有input也就有output,接下来我们讲解的就是如何读取一个文本当中的数据,读取和写入其实是相类似的,就是换了个函数使用而已,我们也可以把读取分成几个部分:
1.Open the file
2.If it isn’t the end of file
3.Read
4.Close the file
我们还是一个一个来看,第一步就不必多说了,与写入是一样的,第二步要解释一下,我们如果要把文档的内容全部读出来,我们需要用一个while循环,那么循环停止的条件是什么呢?是否达到了文件尾(end of file),所以这里我们需要一个用于判断的函数feof,其调用格式为:feof(fid);
第三步,读取,需要用的函数是fscanf,其调用格式为:[a,count]=fscanf(fid,format,size)
参数内容:
1.a读出的数据放入内存的变量名
2.count返回值。0:失败、n>0:成功,n是读出数据个数
3.size a的数据的维度
最后关闭文档,我还是用一个例子来讲
图8-10 04asciiData.txt
下面给出代码
图8-1 ”读“文档操作