5.2.1单个字符
字符(char)是文本的最基本单元。在 MATLAB 中,单个字符使用单引号引起来,例:'a'、'0'、'我'。(一定要是英文输入法下的单引号,中文的会报错)下面我们介绍两个简单的函数,它能实现字符和对应的Unicode 编码的转换。
- double 函数可以获取字符对应的 Unicode 编码(十进制)。
- char函数可以将Unicode编码(十进制)转换为对应的字符。
A = 'a'
double(A) % 97
B = '我'
double(B) % 25105
C = 97
char(C) % 'a'
D = 25105
char(D) % '我'
'a' + 'b' % 195
'a' - 'A' % 32
'A' + 32 % 97
'A' > 'a' %logical 0
'A' == 65 %logical 1
% 用户输入一个英文字母,如果该字母是大写,则输出它的小写;如果是小写,则输出它的大写。
% 大写字母: 65至90代表 'A' 至 'Z'
% 小写字母: 97至122代表 'a' 至 'z'
A = input('请输入英文字母:','s');
if A >=65 & A <= 90B = char(A + 32);
elseB = char(A - 32);
end
disp(B)
5.2.2字符向量
我们了解到单个字符(即字符标量)是使用单引号引起来的。当我们将多个字符连续放置在同一对单引号中,就创建了一个字符向量,例如:'abc、'001'、"我喜欢你'字符向量中的每个元素都是字符标量,类似于数值向量中的每个元素都为数值标量。在第三章,我们提到了向量(在不引起混淆的情况下,数值向量我们通常简称为向量)是由中括号括起来的。其中,向量中元素如果由逗号或空格隔开,构成的是行向量;如果由分号或回车键隔开,构成的是列向量。对字符向量而言,生成方式也是类似的。通常,行字符向量可用于表示单词、句子等文本,我们将多个字符放置在同一对单引号中的本质就是生成了一个行字符向量,因此它的应用场景比列字符向量更为广泛。后续章节中,在不引起混淆的情况下,我们通常将行字符向量简称为字符向量。我们可以对字符向量使用double函数,这样可以得到该字符向量中各字符元素对应的Unicode 编码(十进制),返回的是一个数值向量。
A1 = ['A','p','p','l','e'] % 行字符向量
A2 = ['x';'y';'z'] % 列字符向量
A3 = ['Apple']
A1 == A3 % 1 1 1 1 1B = 'aAbB';
double(B) % 97 65 98 66C = 65:90
char(C) %'ABCDEFGHIJKLMNOPQRSTUVWXYZ''A':'Z' %'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'A':2:'Z' % 'ACEGIKMOQSUWY'
'0':'9' % '0123456789'
'Z':-1:'A' %'ZYXWVUTSRQPONMLKJIHGFEDCBA'
'0':'z' % '0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz'
double('0':'z') % 48到122
D = [65;66;67];
char(D)
- 和单个字符类似,字符向量也能进行算术运算和关系运算。注意,第三章中我们介绍了MATLAB支持的五种算术运算的兼容模式,字符向量的计算也要满足这五种兼容模式,否则MATLAB 就会报错。
c1 = 'abc'; c2 = 'ABC'; c1 - c2 c2 + 32 char(c2 + 32) c1 c3 = ['a';'b']; c3 c1 - c3 % 算术运算的兼容模式 c1 > c3 % 也可以进行关系运算
- 和数值向量类似,字符向量也能通过索引的方式进行引用、修改和删除。
c1 = '我喜欢你,真的不骗你'; c1(2:3) % 引用c1中2、3位置上的字符 c1(end-4:end) % 引用c1中最后五个字符 c1(4) = '她'; % 修改c1的第四个位置的字符 c1(4:end-1) = []; % 删除指定位置的字符 c1(2:3) = '想'; % 右侧可以是单个字符 c1 = c1(end:-1:1); % 颠倒字符向量的顺序 c1(2:3) = '不爱';
- 此外,我们还可以对字符向量进行拼接、重复、排序、翻转等操作,这些操作和第三章中介绍的对数值向量的操作非常相似
c1 = 'Good '; c2 = 'Morning'; % 横向(水平)拼接字符向量,以下三种方法均可 [c1,c2] cat(2,c1,c2) % dim=2表示沿着列方向拼接 horzcat(c1,c2)c3 = 'abc'; repmat(c3,1,3) % 重复堆叠1×3次 c4 = 'abc'; repelem(c4, 3) % 重复字符向量中的元素3次c5 = 'efcd0Agba'; sort(c5) % 按照Unicode数值大小排序 sort(c5,'descend')c6 = '1':'9'; % '123456789' % 对字符向量左右翻转 flip(c6) fliplr(c6) c6(end:-1:1)
(1)字符向量中有单引号怎么办
我们知道,字符向量是使用单引号引起来的,如果字符向量中也出现了单引号,就需要使用两个连续的单引号来表示它
(2)字符向量中如何添加换行符换行符对应的 Unicode 编码为 10,因此我们可以使用 char(10)得到一个换行符。
(3)计算字符向量中字符的数量
和数值向量类似,我们可以使用length函数或umel 函数计算字符向量中字符的数量,如果使用 size 函数,那么将同时返回字符向量的行数和列数。
(4)比较两个字符向量是否相同 在第三章中介绍过,我们可以使用关系运算符==来比较两个数值向量的元素是否相同,两个数值向量的大小必须满足算术运算中介绍的五种兼容模式才能进行比较,并返回一个逻辑数组。要比较两个字符向量的元素是否相同也可以使用==,它们的大小也必须满足五种兼容模式。
c2 = 'I''m Li Hua.' %句中有单引号的用两个单引号表示,有双引号的用四个单引号表示c = '春眠不觉晓,处处闻啼鸟。';%换行可以用newline或者char(10)
char(10)
c1 = c(1:6)
c2 = c(7:end)
c_new = [c1, char(10), c2]
c_new = [c1, newline, c2]c = 'abcdefg';
numel(c)
length(c)
size(c)
c1 = 'pool';
c2 = 'moon';
c1 == c2
c3 = '你说你喜欢我,希望你没说谎';
ind = (c3 == '你')
num = sum(ind) % c3中'你'出现的次数c4 = 'abc';
c5 = ['a';'b';'c']; % 列字符向量
c4 == c5
(5) strcmp 比较字符向量是否相同(区分大小写)
strcmpi 比较字符向量是否相同(不区分大小写)
strncmp 比较字符向量的前 n 个字符是否相同(区分大小写)
strncmpi 比较字符向量的前 n 个字符是否相同(不区分大小写)
c1 = 'pool';
c2 = 'moon';
strcmp(c1,c2)
c3 = 'abc';
c4 = 'abcd';
strcmp(c3,c4)
c5 = 'abc';
c6 = ['a';'b';'c']; % 列字符向量
strcmp(c5,c6) % 比较时会区分字符向量的方向
c7 = 'apple';
c8 = 'Apple';
strcmp(c7,c8) % 比较时会区分大小写字母
A1 = 'abc'
A2 = 'ABC'
a1 = strcmp(A1,A2) % 0
a2 = strcmpi(A1,A2) % 1
B1 = 'wxYz'
B2 = 'wxy012'
b1 = strncmp(B1,B2,2) % 1
b2 = strncmp(B1,B2,3) % 0
B3 = strncmpi(B1,B2,3) % 1
练习题
练习题1:将C = '我会Matlab、Python、Spss等软件!'中的小写字母变成大写,其余不变。
%练习题1:将C = '我会Matlab、Python、Spss等软件!'中的小写字母变成大写,其余不变。
% 97至122代表小写字母 'a' 至 'z'
% 65至90代表大写字母 'A' 至 'Z'
%方法一:
C = '我会Matlab、Python、Spss等软件!';
C1 = double(C);
ind = (C1 >=97 & C1 <= 122);
C1(ind) = C1(ind) - 32
CC = char(C1)
%方法二:
C = '我会Matlab、Python、Spss等软件!';
ind = (C1 >=97 & C1 <= 122)
C(ind) = C(ind) - 32;
CC = char(C)
%方法三:
C = '我会Matlab、Python、Spss等软件!';
CC = upper(C)
练习题2:实现内置函数strcmp的功能(仅考虑比较的两个文本都是字符向量的类型)
% 练习题2:实现内置函数strcmp的功能(仅考虑比较的两个文本都是字符向量的类型)
C1 = 'abc';
C2 = 'Abcd';
flag = all(size(C1) == size(C2)) && ... 三个点 ... 用来表示行的延续all(C1 == C2) % 实际上这一行代码是上一行中没写完的部分
练习题3:统计字符向量中元音字母出现的频率(元音是指aeiouAEIOU)
% 练习题3:统计字符向量中元音字母出现的频率(元音是指aeiouAEIOU)
%方法一:
A = 'aeiouAEIOU';
C = 'I wish you and your family good health, and all the best.';
C1 = ismember(C,A);
P = sum(C1) / numel(C)
%方法二:
S = [];
for i1 = Cfor i2 = Aif i1 == i2S = [S,1];endend
end
P = sum(S) / numel(C)
%方法三:
A = 'aeiouAEIOU';
C = 'I wish you and your family good health, and all the best.';
P = (sum(A' == C,"all")) / numel(C)
练习题4:凯撒密码加密
% 练习题4:凯撒密码加密
% 凯撒密码加密程序
% 输入:明文字符向量 C
% 偏移量设置为 +3
C = 'Retreat to the countryside tomorrow morning.';
offset = 3 %设置偏移量
CC = C; %初始化暗文
for i = 1:numel(C)if C(i) >= 'A' && C(i) <= 'Z'CC(i) = char(mod(C(i) - 'A' + offset,26) + 'A');elseif C(i) >= 'a' && C(i) <= 'z'CC(i) = char(mod(C(i) - 'a' + offset,26) + 'a');end
end
disp(CC)
练习题5:编写程序将用户输入的十进制正整数转换为对应的二进制字符向量。
% 练习题5:编写程序将用户输入的十进制正整数转换为对应的二进制字符向量。
A = input('请输入你要转换的数字'); %要转换成二进制的十进制数
AA = ''; %初始化二进制数为空的字符向量
while A > 0Y = mod(A,2);AA = [num2str(Y),AA];A = floor(A/2);
end
disp(AA)
% dec2base函数可以将十进制转换成任意进制
dec2base(856,2) %'1101011000'
5.2.3字符矩阵
行字符向量,它可以用来表示一段文本。如果我们想在同一个变量中表示多段文本,那么就可以使用字符矩阵。例如我们想保存两个单词:good和fine:
c1 = ['g','o','o','d';'f','i','n','e']
c2 = ['good';'fine']
strcmp(c1,c2)
上面两种写法生成的字符矩阵c1和c2是完全一样的,可以使用strcmp函数验证c1和c2是否完全相同,执行strcmmp(c1.c2)会返回逻辑值1。第一种写法和我们第三章介绍的数值矩阵一致:同行元素(这里是单个字符)之间用逗号或者空格分隔,行与行之间用分号或回车键分隔。这种写法可以清楚的看到各个位置上对应的字符元素。第二种写法通常更符合我们的需求,我们可以将矩阵的每一行看成一段文本。为什么这种写法可行呢?在第三章介绍的数值矩阵中,如果a和b两个矩阵的列数相同,我们可以使用[a; b]的语法在竖直方向纵向拼接a和b两个矩阵,而这里的"good和"fine'是两个长度相同的行字符向量,因此使用“good;fine"可以将它们拼接到一个字符矩阵中,这种拼接方法等价于使用 cat或者 vertcat函数,因此我们也可以写成 vertcat(good",fine)或 cat(1,good,fine”),返回的结果也是一样的(复习:cat 函数的第一个输入参数表示维度 dim,dim 等于1表示沿着行方向从上往下进行拼接,即纵向拼接)。
思考:如何在字符矩阵中表示good和great这两个单词?
MATLAB 的 char 函数自动拼接。char函数可以将 Unicode 编码转换为对应的字符,下面介绍它的另一种用法:C = char(A1,A2,...,An)将输入的数组 A1,A2,...,An(通常是字符向量、字符矩阵,也能支持数值向量、数值矩阵等)转换为单个字符数组,输入的 A1,A2,...,An 会变为C中的行。char 函数会自动在每一行最后使用空格填充来保证每行字符数量相同,如果任何输入数组是空字符数组,则C中相应的行是一行空格 。
char('good',' ','great','perfect')
A1 = [65 66; 67 68];
A2 = 'abcd';
C = char(A1,A2)
strvcat('good','','great','perfect') %strvcat 函数会自动删除空行,建议不要使用这个函数
练习题
练习题1.将十进制数1至100转换为二进制数,判断转换后的二进制数中有哪些是回文数?要求输出一个字符矩阵,矩阵每一行的字符向量的格式为:'十进制数:转换后的二进制数,可以在每一行字符向量的末尾加上空格保证长度相等。(提示:转换后的二进制数为字符向量类型,将这个字符向量反转顺序,如果和原来的一样就是回文数。例如'101'、'1001'都是二进制回文数)
S = '';
for i = 1:100n = dec2base(i,2);nn = n(end:-1:1);if strcmp(n,nn)s = [num2str(i),':',n];S = char(S,s);end
end
S(1,:) = ''; %第一行是空行所以删除掉
S
拓展:
c = [' 你好棒! ',newline,'还在学习 ! ']
deblank(c)
strtrim(c)
strip(c,'both')
strip(c)
strip(c,'left')
strip(c,'right') c = 'aabcdaefgasaaa';
strip(c,'both','a') % 同时删除两侧的'a'
strip(c,'a')
strip(c,'left','a') % 删除左侧的'a'
strip(c,'right','a') % 删除右侧的'a'
strip(['aaa',char(9)],'right',' ')
strip(['aaa',char(9)],'right')
拓展二、strjust函数
c = char('good','great','wonderful');
disp(c)
c1 = strjust(c,'right'); % 右对齐
disp(c1)
c2 = strjust(c,'center'); % 居中对齐
disp(c2)
练习题2.格式化输出一个乘法口诀表
cfb = [];
for i = 1:9tem = ''for ii = 1:item = [tem,num2str(i),'x',num2str(ii),'=',num2str(i*ii),' '];endcfb = char(cfb,tem);
end
cfb = strjust(cfb,'center')
disp(cfb)