C语言剖解(06)
我想,我得想法敲打一下学生,激发一下学生的斗志,让学生更积极的去学习,因此,我对学生一番苦口婆心,我给学生讲解了今年的整体就业形势,我告诉学生目前的竞争环境的恶略。我拿出今年一些招聘会的现场场景,来告诉学生,如果我们不珍惜这来之不易的工作,不知道努力自觉的学习,会是什么样一个情况,我曾亲口听一个同学给我说了这么一个事情。
他到一个招聘会现场,跟着招聘会的牌子走,首先看到的牌子是:
A专业的请往右走。
B专业的请往左走。
然后,他顺着A的方向走去,一段路之后,又有一个牌子:
获得**证书的请往左走,
没获得**证书的请往右走;
于是,他往右走。又过了一会,前面又一个牌子,上面写:
在公司实习过的,请往左走,
没在公司实习过的,请往右走。
于是他往右走。又到了一个牌子,上写:
一本学校请往右走
二本学及其他学校请往左走。
于是他往左走,当他和一群人跨过一个大门的时候,他发现自己已经身处会场之外,眼前是川流不息的汽车。他们互相看了一下,调侃又无奈的傻笑了一下,就回学校去了。
由此可知,当前社会就业竞争有多夸张。连获得一个面试机会都这么难,我们如果侥幸争取到了一个机会,难道还要白白浪费一次么?
好了,大家笑完,我估计心情也有一些沉重吧。我们继续我们的讲课,今天我们说字符型数据类型。
“什么是字符型数组呢?为什么会有字符型数组呢?”我首先向学生引出了这个话题,当然,学生难以回答。难以回答就对了,好,我继续说:
“我想用C语言来表示键盘上的回车,想表示键盘上的Tab键,想表示键盘上的退格键等等,该怎么表示呢?”
“很显然,这是一个难题。当然类似的情况还有很多,于是那些牛叉的科学家想出了如此奇怪的表示方法,这个方法显然不能是整型。”我边说,写下如下代码:
char a = '\t';
char b = ‘1’;
“这就是字符数据类型,这样,英文中的26个字母,以及常用的阿拉伯数字就能很方便的表述出来了。”
然后我又写如下一行代码:
printf(“%d\n”,b);
我问学生,打印出来的结果是什么?
“1”;
“我呸!你们也太打击老师了吧,竟然没人下去往后看书。”
我便说,边将程序编译并运行。结果是:49;
“为啥?”有学生问道。
“对,为啥呢?”,
“ASCII码”,显然,有的学生知道。
“对,ASCII码,那为啥会有ASCII码呢?”
我自问自答道:
“大家都知道,计算机是美国家发明的,而他是个说英语的国家,英语只有26个字母,即便加上阿拉伯数字,也不过36个,但是,全世界很多国家,很多语言,如果想让这些国家使用电脑,那必须得能够顺利的现实出一些特殊的字符,比如说小日本那种贪婪的民族等。因此就有了ASCII码的产生。”
当然,我的表述并不完全正确,我只是想让大家理解,字符时以ASCII码的形式存储的。能让他们深刻记下这些,我有依据的杜撰一些内容,又有何不可?
“因为当初对字符的设计,只想到用一个字节表示,因此ASCII码只有0~127个,可后来发现,这远远不够,所以后续又在一个字节的基础上,添加上无符号字符,因此你看到的第364也就有256个了。”
“这么多内容,我并不要求你们死记,但常用的我们得知道,常用的是那些呢?大小写英文字母52个,数字10个,键盘上常用的字符16个,因此共78个需要大家熟知,当然,一些重要的转移字符,我们是必须记忆的,因此,翻至书本的第48页,转义字符表格中的内容”。
“那么怎么才能正确的打印出1这个字符呢?”
printf(“%c\n”,b);
在学生的一片呼喊中,我打出了上面的代码,这再简单不过了,但
“为什么可以用%d来打用char定义的内容呢?”
大家又不说话了。
“很简单,因为char占1个字节,而int占四个字节,因此,char是Int的一个子集,因此,可以使用%d打印出字符对应的ascii码。”
就这样,我边举例子边说明了字符型数据的声明定义和打印,那字符型数据的存储方法又是怎么样的呢?一句话:和整型数据一样,在内存中是以补码的形式存放的。只不过是,它只占一个字节。
数据越界是最为常见的编程错误之一,那上课我也不可能一字不提,因此。在基本讲授完字符数组之后,顺手给出如下代码,但说实在,这代码是经过我推演之后的代码我总得找一些具有代表性的内容,而不能随便举例子,我写的代码如下:
char a = 306;
printf(“%c\n”,a);
然后我问学生,
“打印结果是什么?”
很少有人回答出结果,也有不少人回答306的,这足以说明,一部分学生,根本不动脑子。
针对回答306的,我会鄙视一番;
“毛,我刚刚说过,字符型数据占几个字节?”
“一个字节”
“一个字节的最大值是多少?”
“255”
“毛,你说的是无符号吧,所有数据类型,默认都是有符号的,是多少?”
“127”
“多少?”
“-128~~ 127”
“对了,刚说过了嘛,有符号有符号,当然有正负了”
“那这个打印出来时多少呢?”我继续指着我写的代码问学生。
这下没一个人回答了,我编译并运行程序,显示结果如下:
“2”,学生看到这个结果,开始窃窃私语了。
“为什么会是2呢?我们来看一下,306转换为2进制是多少”
“0001 0011 0010”,
“而char占一个字节,因此,截取高字节内容为00110010”,
转换为十进制为“50”。
“那为啥打印出来是2,而不是50呢?”
学生还在发蒙着。
“笨哪,50的ASCII码是多少,翻到P364也附录A去看一下。”
“哦,2”。明白了吧。
“明白了”
“那这个结果是多少呢?”我边问边写
Char a = 307;
Printf(“%d\n”,a);
“3”;
“多少?”
“3”。
“哎,鄙视你们活该,看一下运行结果是多少”
很显然,结果是51;
“哦,是%d。”
“悲催呀,竟然没一个看出我改为%d了。注意了,认真踏实。明白不?”
明白了这个,我就开始讲字符串常量了。
这地方其实没什么可讲的,没什么可将的主要原因是因为暂时还是用不到他,讲了学生也容易忘记,因此,我索性只说了一句话。
“字符串是常量,只能做常量,他和字符常量不同。我们可以这么写”
Char a = ‘a’;
但我们不能这么写:
Char a = “a”;
原因很简单,字符串常量系统会为其后面补一个\0;这也是一个字符,这样就是两个字符了,但char只能是一个字符。其他我并不多讲。
而变量的赋值我几乎不讲,因为我前面的所有举例中,都带有变量的赋值。
我唯一强调一点:
初始化和赋值实际上是不同的。
比如;
我们可以这么写;
Int a, b, c,d;
a = b = c = d= 0;
但我们不能这么写:
Int a = b = c= d = 0;
编译器不允许你这么做。
而,这并不足以完全说明初始化和赋值的区别,所以,我会写一个数组;
我们可以这么做:
Char a[2] = {‘0’,’a’};
但我们不能这么做;
Char a[2];
a[2] = {‘0’, ‘a’};
讲到这里,我希望让大家着重知道一下,对于字符型数据,他的打印,我们一定要认真,区分什么时候打印%d,什么时候打印%c,即,完全明白转换。