6.3.4 字符数组的输入/输出

在printf里,输出一个字符串,用%s格式符。看看如下范例:

运行起来,看到输出结果为"China"。

上一节讲到过,printf向屏幕输出结果时,遇到'\0'就会停止输出。而当把这个字符串"China"赋给字符数组变量c的时候,系统自动在"China"的末尾增加'\0'代表字符串结束标记。有几点说明:

(1)printf输出的字符串中并不包含'\0',而且'\0'也不是个可显示字符。

(2)“printf("%s\n",c);”,这里用%s输出的时候,输出项是字符数组名,不可以是数组元素如c[0]、c[1]等,因为c[0]、c[1]代表的是字符,输出字符要用printf的%c格式字符来输出。

(3)即便数组定义时的长度大于字符串实际长度,也只输出到'\0'结束。看如下代码:

输出依旧是"China",虽然字符数组c的长度是100(定义时的长度),可以设置断点调试看一看数组c所代表的内存中的内容,所以,字符串结束标记的用处正在于标记一个字符串内容的结束。

(4)如果一个字符数组里包含多个'\0'(例如通过手工给多个数组元素赋值成'\0'来实现),那么printf遇到第一个'\0'时就停止输出。

看看下面这个范例,输入一个字符串,用scanf来完成:

这里注意以下几点:

①scanf函数中,c是字符数组名。

②从键盘上输入的字符串内容应该短于已定义的字符数组长度,并且不要忘记,输入字符串后,还要给'\0'留个存储位置,否则会造成程序隐患,甚至导致程序当时或者不定时崩溃。例如定义如下长度为6的字符数组,则最多只能输入5个字符的一个字符串,输入多了,就可能造成程序隐患,导致程序运行崩溃,不一定是当时(运行到该行时)崩溃,但执行到某个时刻可能崩溃。

③若要输入多个字符串,则可以以空格分隔。看如下代码:

程序开始执行后,输入howare you,然后按下Enter键,可以加断点跟踪看输入完成后的每个数组中所存的内容,但是,如果修改为如下代码:

程序开始执行后,如果输入howare you,则跟踪调试发现str里只得到了“how\0”,“areyou”都没得到,这说明scanf输入函数在遇到第一个空格时会把空格之前的字符串内容放入到变量str中,然后从“are”开始有第二个变量就放入到第二个变量,没有,就直接把“areyou”都舍弃掉了。

④以往学习scanf的时候会加一个“&”。回忆一下以往的代码:

当时说过,&a表示变量a的地址。地址就是一个数字,在计算机上一般显示为0xXXXXXXXX这种十六进制数字(0x开头代表十六进制数字),可以在程序中任意设置一个断点看一看地址的样子,如图6.14所示。调试过程中,当执行流程停到所设置的断点行时可以直接用鼠标双击str1这个字符串名并将其拖动到地址栏中,然后按下Enter键查看该字符串对应的地址中代表的内存内容。

图6.14 地址的样子,形如0x00a0fd58,调试时也可以看到该地址开头的内存中内容

但在这里的代码:

str前面并没有增加“&”,因为str是字符数组名,数组名代表的正是数组的起始地址(首地址),所以就不需要加“&”了。当然通过测试不难发现,写成&str也可以,估计是当代C或C++语言把str和&str在这种场合下等同看待,都认为是数组的起始地址了。

可以把地址以十进制数形式输出(因为上面说过地址本身就是一个数字)。看如下代码:

总之,在C语言中,一维字符数组可以看成是字符串变量(专门用来保存字符串的变量)。另外,scanf函数并不常用,尤其是在实际项目中,几乎不会用到,了解一下即可。