欢迎光临散文网 会员登陆 & 注册

第 6 讲:数据类型(三):字符和字符串

2021-03-22 09:52 作者:SunnieShine  | 我要投稿

字符和字符串是 C# 里广泛使用的一种专用表示“只用来呈现原封不动的数据”的数据类型。字符是 char 关键字表示的,它的 BCL 名称是 System.Char,表示一个单独的字符;而字符串是表示一系列字符构成的序列,用 string 关键字表示,它的 BCL 名称是 System.String

下面我们来看一下基本的赋值方式和书写格式。

Part 1 字符字面量和字符串字面量

我们先来说字符。字符就是一个单独的原始数据。

C# 里使用单引号来表达 a 是一个字符。

当然,一个数字字符和一个数字是有区别的。比如说 '3'3 是有区别的。因为字符 3 仅用来呈现结果,所以它并不应当参与任何数值上的计算;而数字 3 是可以进行运算的。运算的功能我们将在下一章(运算符)里讲到。

虽然,如下的写法都是可以输出一个字符 3 的:

但显然,它们的区别在于,一个是呈现字符本身,一个则是将数字当成字符呈现(绕了一步)。因此它们是有区别的。

和 C 语言不同,C# 的字符是包含中文汉字、日语假名等等符号的。比如说:

在 C 语言里,一个字符是只占一个字节的,因此它只能表达一个很简单的字符;汉字、日文甚至别的一些符号并不属于标准 ASCII 码里的内容,因此无法用一个字符来表示。但 C# 里是可以的。

这就是为什么,字符没办法参与计算了。

顺带一说,这里以单引号引起来的内容称为字符字面量(Character Literal)。

Part 2 字符串字面量

显然,一个单独的字符并不能表达很多的信息,因此大多数时候我们都会使用字符串(String)来表示一个字符序列,以达到描述复杂信息的功能。

我们可以通过双引号,来表述一组字符信息。把它们串起来,表示一个整体。以双引号引起来的字符序列就称为字符串字面量(String Literal),当然,有些时候也简称字符串或者

C# 贴心地为我们提供了 Console.WriteLine 方法,可以让我们使用前面的所有类型,全部内嵌到小括号里参与输出,因此,这些字符串依然可以写进去。

由于字符串可以任意伸缩长度,因此,一个空字符串(Empty String)也是可以的:

这样的话,emptyString 就是一个空的字符串,里面没有任何字符。当然,空字符串你也可以写成 String.Emptystring.Empty

前文稍微提到过,string 是关键字,而 String 是 BCL 名称。它们的区别仅仅是“BCL 名需要引入 System 命名空间,而关键字不需要考虑命名空间的事情,编译器会自动导入”。初学的话,可能你不会愿意记很多复杂的东西,因此我建议你使用关键字,这样就不用引入命名空间了。

Part 3 原义字符串和转义字符

由于双引号在编程的时候有特殊用途(表示字符串字面量的开头和结尾),所以很明显,我们并不能在字符串字面量里使用引号。如果偏要输出引号的话,我们必须在左边添加反斜杠:\"。这个行为称为转义(Escape)。那么理所应当地,这里带反斜杠的字符就是转义字符(Escape Character)了。

在这个例子里,双引号内嵌到字符串里作为输出的一部分,就需要添加反斜杠标记。

在 C 语言里,\"\' 都是转义字符,即双引号里不可以直接出现单引号;但 C# 里是允许的。

转义字符除了上面说的双引号以外,还有一些别的。比如说制表符。制表符占据 8 个空格的空间。如果是写入字符串的时候,我们可以直接插入制表符:“ ”,但这样显得很不正常,因此 C# 里提供了一个字符写法:\t,这就表示一个制表符:

最后,由于反斜杠本身作为转义字符的开始,因此我们单纯要输出一个反斜杠的时候,必须双写它。

我们目前就只需要接触这几个就可以了。后续用到新的转义字符的时候,我们再作出说明。

但是有些时候,我们要写一大段的文字(很有可能自带换行)。这个时候,字符串怎么写呢?我们采用的办法是通过原义字符串(Verbatim String)来搞定。

为了避免字符串里出现的特殊字符,C# 提供了一种字符串:

如果是一个很普通的字符串,就必须双写反斜杠来表示一个反斜杠字符。当我们在字符串最开头追加原义标记 @ 后,字符串就成了原义字符串。原义字符串的内部除了双引号以外的其它所有字符都可以随便用了:不管你怎么写,原义字符都不作处理。

如果原义字符串里需要表示一个双引号的话,由于原义字符串会把反斜杠当成一个很普通的反斜杠,因此 \" 这种写法会失效。所以,此时用到的是双写:""。我们双写双引号,就表示原义字符串里的一个双引号字符。

对比两种写法(普通字符串和原义字符串),你可以看到区别。

总结一下:

  • 普通字符串里,\\ 表示一个反斜杠字符,\" 表示一个双引号字符,\t  表示制表符(还有别的,这里不作介绍);

  • 原义字符串里,"" 表示一个双引号字符。

Part 4 字符串的长度

由于字符串是不定长的,因此它拥有长度(Length)的概念。字符串可以很长,它的长度是所有字符的总数。比如说,"こんにちは、お元気ですか。" 字符串里,有 9 个假名、2 个日语汉字和 2 个标点符号,因此长度是 13。

当然了,空字符串长度为 0,这个是不用多说的。

Part 5 字符串的基本操作

说起字符串,就不得不提一下字符串的基本操作。

不得不说,这些内容有点超纲,但是既然重要我们就得先说。超纲内容也不一定难,可能仅仅就是超前说明而已。

5-1 获取字符串长度

我们直接使用 .Length 的语法来表示和获取字符串的具体长度:

这样的话,输出和显示的就是 s.Length 这个东西。s 是字符串,后直接跟上 .Length 则会得到字符串的长度。前文说过,字符串的长度就是所有字符总数,因此这个字符串是 10 个字符,因此结果是 10,输出的内容也是 10。

顺带一提,s.Length 的结果是一个数字,那么它会是什么类型的呢?对了,int 类型的。因为 int 在 C# 里起到很重要的作用,因此很多地方都会使用 int,即使我们知道长度是不可能为负数的,按道理应该用 uint,但因为为了兼容性(底层,比如说和 C 语言以及别的没有无符号数据类型的语言进行交互的时候),int 是最合适的一种类型。

5-2 获取特定位置上的字符

我们采用类似 C 语言的中括号语法,可以获取一个字符串里指定位置上的字符是什么。

我故意拆开写的。我们使用 [] 语法来确定和获取 s 字符串里的字符信息。中括号的数字是 n,那么就取的是第 (n + 1) 个字符。换句话说,n 最小是 0,而不是 1。

这个例子里,s[3] 就相当于取的是 s 这个字符串里的第四个字符('l'),因此,c 变量得到的结果就是 'l',最后输出的也是这个字符。

但请注意,你不能修改字符串的内容。虽然 C 语言里,你可以使用索引器来接受一个字符,以达到修改的目的,但 C# 里,整个字符串一旦声明后,就无法修改:

这个写法是不允许的。编译器会直接告诉你“索引器不存在 set 方法”;这个句子换句话说就是,你没办法赋值一个新字符进去。

5-3 拼接字符串

有些时候我们可能需要拼接多个字符串,然后把这些字符串合并成一个字符串。我们需要用到的是一个叫 Concat 的方法。

这个例子应该比较好理解。我们使用 string.Concat 方法,把所有需要拼接在一起的字符串挨个顺次写进去,用逗号隔开;然后最后得到的结果就是整体的结果了。此时,用 result 变量接受结果。显示出来就是 Hello, Mike!

5-4 查看字符串是不是包含一个字符或字符串

如果一个字符串较长,我们可能会去查找里面的字符。比如说一个电话号码(用字符串表示后),我们需要查看是不是包含 666 这个序列。那么,我们可以这么写:

我们在字符串字面量(或变量)的后面追加 .Contains("666") 来表示我们需要看这个字符串是不是包括 666 这个序列。最后,这个整体得到一个 bool 的结果,赋值给 contains666 变量。

看到了吧,这里就用上了 bool 类型。

当然,小括号里不一定非得是序列,也可以是一个单独的字符:

这样就表示,是否字面量里包含字符 9 的信息。

5-5 查看字符串开头和结尾是不是固定的序列

如果我们要查看一个用字符串表达的电话号码里是不是以 13 开头的话,我们需要追加 .StartsWith("13") 来表示:

同理,如果要看字符串结尾是不是固定的序列,则使用 .EndsWith(序列) 表示:

这个依然也可以判断一个单独的字符:

5-6 比较字符串的具体序列是不是完全一样

如果要比较字符串是不是完全一致的话,我们用的是 string.Equals

5-7 查看字符串里指定字符(或字符串序列)的具体位置

比如说,如果我想看一个身份证号里的年份信息在具体哪个位置的话,我们会直接在字符串变量(或字面量)后面追加 .IndexOf(内容)

我想,理解起来应该不难。这个结果是 6,也就是说,从第 7 个字符(从 0 开始叫第一个字符,n 就是第 (n + 1) 个字符,所以结果 6 代表第 7 个字符)开始,就可以找到 1996 这个序列。如果整个字符串没有我们要找的序列的话,结果就是 -1。为什么不是 0 呢?因为 0 表示第一个字符。

5-8 删掉一个字符或字符串

要想把字符串里的一部分完整序列去掉,我们用的是 .Remove(位置)

这表示从第 3 个位置的字符开始,后面的字符我们都不要了。所以 t 变量的结果是 "He"

如果你要删掉一系列的字符的话,光有个位置还不行,还得加上删除长度:

.Remove(2, 2) 表示从第 3 个字符开始删,删掉 2 个字符。所以最后 t 结果是 "Heo"

5-9 替换掉一个字符或字符串

要想替换掉序列的话,我们可以用 .Replace(字符, 字符).Replace(字符串, 字符串)

可以从例子看到,u 变量结果自然就是 "今儿天气好"

这样就变成了 "明儿天气好" 了。

5-10 取字符串的一部分

要想取一部分字符,我们用 .Substring(开始位置, 取的长度) 来获取:

t 从第 1 个字符开始取,取 4 个字符,所以 t 结果是 "Hell"

行,那么字符串的操作我们就介绍到这里。字符串还有别的操作,但是因为用不上,或者需要高阶的知识点,所以我们就不作介绍了。

Part 6 不可变的字符串

我们看到前面的这些操作,我们发现共同点:我们发现怎么去操作字符串,最后原始的字符串都是没有变动的:即使要修改字符串,变动的结果也会通过赋值给到新的变量上去,但原始的字符串并没有变化。这是 C# 里字符串的一大特殊性质:不可变(Immutable)。

比如这个例子,我们已经删掉了 s 的字符,但代码运行起来后,我们可以看到的是,s 还是 "Hello",而 t 才是 "He"

Part 7 总结

本节我们学习了字符和字符串的内容,以及操作。再怎么说,我们都不必考虑类似 C 语言那样字符串操作的复杂细节。所以从这个角度来说,C# 还是比较简单的。


第 6 讲:数据类型(三):字符和字符串的评论 (共 条)

分享到微博请遵守国家法律