C 语言重拾【二】字符串
1 |
|
运行程序,输入结果如下:
Hi! What’s your first name?
Christine
Christine, what’s your weight in pounds?
154
Well, Christine, your volume is 2.47 cubic feet.
Also, your first name has 9 letters, and we have 40 bytes to store it.
该程序包含以 下新特性。
- 用数组(array)储存宇符串(character string)。在该程序中,用户输入的名被储存在数组中,该数组占用内存中 40 个连续的字节,每个字节储存一个字符值。
- 使用名
%s
转换说明来处理字符串的输入和输出。注意,在scanf()
中,name 没有&
前缀,而weight
有(稍后解释,&weight
和name
都是地址)。 - 用 C 预处理器把字符常量
DENSITY
定义为 62.4。 - 用 C 函数
strlen()
获取字符串的长度。
char 类型数组和 null 字符
C 语言没有专门用于储存字符串的变量类型,字符串都被储存在 char
类型的数组中。数组由连续的存储单元组成,字符串中的宇符被储存在相邻的存储单元中,每个单元储存一个字符,如下图:
注意上图中数组末尾位置的字符 \0
。这是空字符(null character),C 语言用它标记字符串的结束。
空字符不是数字 0,它是非打印字符,其 ASCII 码值是(或等价于)0。C 中的字符串一定以空字符结束,这意味着数组的容量必须至少比待存储字符串中的字符数多 1。因此,程序清单中有 40 个存储单元的字符串,只能储存 39 个字符,剩下一个字节留给空字符。
那么,什么是数组?可以把数组看作是一行连续的多个存储单元。用更正式的说法是,数组是同类型数据元素的有序序列。程序清单通过以下声明创建了一个包含 40 个存储单元(或元素)的数组,每个单元储存一个 char
类型的值:
1 | char name [40]; |
name
后面的方括号表明这是一个数组,方括号中的 40 表明该数组中的元素数量。char 表明每个元素的类型,见下图。
字符串看上去比较复杂!必须先创建一个数组,把字符串中的字符逐个放入数组,还要记得在末尾加上一个 \0
。还好,计算机可以自己处理这些细节。
字符串和字符
字符串常量 "x"
和字符常量 'x'
不同。区别之一在于,'x'
是基本类型(char),而 "x"
是派生类型(char数组);区别之二是 "x"
实际上由两个字符组成:'x'
和空字符 \0
,见下图:
strlen() 和 sizeof
sizeof
运算符报告,name
数组有 40 个存储单元。但是,只有前 11 个单元用来储存 serendipity
,所以 strlen()
得出的结果是 11。 name
数组的第 12个单元储存空字符,strlen()
并未将其计入。下图演示了这个概念。
对于 PRAISE,
1 |
用 strlen()
得出的也是字符串中的字符数(包括空格和标点符号)。然而,sizeof
运算符给出的数更大,因为它把字符串末尾不可见的空字符也计算在内。该程序并末明确告诉计算机要给字符串预留多少空间,所以它必须计算双引号内的字符数。
另外,还要注意一点:上一章的 sizeof
使用了圆括号,但本例没有。圆括号的使用时机否取决于运算对象是类型还是特定量?运算对象是类型时,圆括号必不可少,但是对于特定量,可有可无。也就是说,对于类型,应写成 sizeof(char)
或 sizeof (float)
;对于特定量,可写成 sizeof name
或 sizeof 6.28
。尽管如此,还是建议所有情况 下都使用圆括号,如 sizeof(6.28)
。
常量和 C 预处理器
#define
1 |
编译程序时,程序中所有的 TAXRATE
都会被替换成 0.015。 这一过程被称为编译时替换(compile-timesubstitution)。在运行程序时,程序中所有的替换均己完成(见下图)。通常,这样定义的常量也称为明示常量(manifest constant)
。
请注意格式,首先是 #define
,接着是符号常量名(TAXRATE),然后是符号常量的值(0.015)(注意,其中并没有 =
符号)。所以,其通用格式如下:
1 |
实际应用时,用选定的符号常量名和合适的值来替换 NAME
和 value
。注意,末尾不用加分号,因为这是一种由预处理器处理的替换机制。为什么 TAXRATE
要用大写?用大写表示符号常量是 C 语言一贯的传统。这样,在程序中看到全大写的名称就立刻明白这是一个符号常量,而非变量。大写常量只是为了提高程序的可读性,即使全用小写来表示符号常量,程序也能照常运行。尽管如此,初学者还是应该养成大写常量的好习惯。
另外,还有一个不常用的命名约定,即在名称前带 c_
或 k_
前缀来表示常量(如,c_level
或 k_line
)。
符号常量的命名规则与变量相同。可以使用大小写字母、数字和下划线宇符,首字符不能为数字。
const 限定符
C90 标准新增了 const
关键字,用于限定一个变量为只读。其声明如下:
1 | const int MONTHS = 12; // MONTHIS 在程序中不可更政,值为 12 |
这使得 MONTHS
成为一个只读值。也就是说,可以在计算中使用 MONTHS
,可以打印 MONTHS
,但是不能更改 MONTHS
的值。const
用起来比 #define
更灵活。(详细内容将在接下来的博客中推出。)
参考文献
- C Primer Plus