1 字符常量
C的字符常量是用单撇号括起来的一个字符。如'a','x','D','?','$'等都是字符常量。注意,'a'和'A'是不同的字符常量。
除了以上形式的字符常量外,C还允许用一种特殊形式的字符常量,就是以一个“\”开头的字符序列。例如,前面已经遇到过的,在printf函数中的'\n’,它代表一个“换行”符。这是一种“控制字符”,在屏幕上是不能显示的。在程序中也无法用一个一般形式的字符表示,只能采用特殊形式来表示。
常用的以“\”开头的特殊字符见表3.3。
表3.3中列出的字符称为“转义字符”,意思是将反斜杠(\)后面的字符转换成另外的意义。如'\n'中的“n”不代表字母n而作为“换行”符。
表 3.3中最后第2行是用ASCII码(八进制数)表示一个字符,例如'101'代表 ASCII码(十进制数)为65的字符“A”。'\012'(十进制ASCII码为10)代表“换行”。用'376’代表图形字符“■”。用表3.3中的方法可以表示任何可输出的字母字符、专用字符、图形字符和控制字符。请注意'\0'或'\000'是代表ASCI码为0的控制字符,即“空操作”字符,它将用在字符串中。
例3.5 转义字符的使用。
main()
{printf("_ab_c\t_de\rf\tg\n");
printf("h\ti\b\bj _k");
}
程序中没有设字符变量,用printf函数直接输出双引号内的各个字符。请注意其中的“转义字符”。第一个printf函数先在第一行左端开始输出“_ab_c”,然后遇到“\t”,它的作用是“跳格”,即跳到下一个“制表位置”,在我们所用系统中一个“制表区”占8列。“下一制表位置”从第9列开始,故在第9~11列上输出“_de”。下面遇到“\r”,它代表“回车”(不换行),返回到本行最左端(第1列),输出字符“f”,然后遇“\t”再使当前输出位置移到第9列,输出“g”。下面是“\n”,作用是“使当前位置移到下一行的开头”。第二个 printf函数先在第1列输出字符“h”,后面的“\t”使当前位置跳到第9列,输出字母“i”,然后当前位置应移到下一列(第10列)准备输出下一个字符。下面遇到两个“\b”,“\b”的作用是“退一格”,因此“\b\b”的作用是使当前位置回退到第8列,接着输出字符“j_k”。
程序运行时在打印机上得到以下结果:
fab_c___gde
h ______ jik
注意在显示屏上最后看到的结果与上述打印结果不同,是:
f_______gde
h______ j_k
这是由于“\r”使当前位置回到本行开头,自此输出的字符(包括空格和跳格所经过的位置)将取代原来屏幕上该位置上显示的字符。所以原有的“_ab_c____”被新的字符“f_______ g”代替,其后的“de”未被新字符取代。换行后先输出“h_______ i”,然后光标位置移到i右面一列处,再退两格后输出“j_k”,j后面的“_”将原有的字符“i”取而代之。因此屏幕上看不到“i”。实际上,屏幕上完全按程序要求输出了全部的字符,只是因为在输出前面的字符后很快又输出后面的字符,在人们还未看清楚之前,新的已取代了旧的,所以误以为未输出应输出的字符。而在打印机输出时,不像显示屏那样会“抹掉”原字符,留下了不可磨灭的痕迹,它能真正反映输出的过程和结果。
2 字符变量
字符型变量用来存放字符常量,请注意只能放一个字符,不要以为在一个字符变量中可以放一个字符串(包括若干字符)。
字符变量的定义形式如下:
char cl,c2;
它表示c1和c2为字符型变量,各可以放一个字符,因此在本函数中可以用下面语句
对c1、c2赋值:
e1='a';c2-'b';
在所有的编译系统中都规定以一个字节来存放一个字符,或者说一个字符变量在内存中占一个字节。
3 字符数据在内存中的存储形式及其使用方法
将一个字符常量放到一个字符变量中,实际上并不是把该字符本身放到内存单元中去,而是将该字符的相应的ASCI代码放到存储单元中。例如字符'a'的ASCII 代码为97,'b'为 98,在内存中变量c1、c2的值如图3.8(a)所示。实际上是以二进制形式存放的,如图 3.8(b)所示。
既然在内存中,字符数据以ASCII码存储,它的存储形式就与整数的存储形式类似。这样使字符型数据和整型数据之间可以通用。一个字符数据既可以以字符形式输出,也可以以整数形式输出。以字符形式输出时,需要先将存储单元中的 ASCII码转换成相应字符,然后输出。以整数形式输出时,直接将ASCII码作为整数输出。也可以对字符数据运算。此时相当于对它们的ASCII码进行算术。
例3.6 向字符变量赋以整数。
main()
{char c1,c2;
c1=97;
c2=98;
printf(" %c %c\n" ,c1,c2);
printf(" %d %d\n",cl,c2);
}
cl、c2被指定为字符变量。但在第3和第4行中,将整数97和 98分别赋给c1和c2,它的作用相当于以下两个赋值语句:
c1='a';c2='b';
因为'a'和'b'的ASCII码为97和98。在程序的第3和第4行是把97和98两个整数直接存放到c1和c2的内存单元中。而cl='a'和c2='b'则是先将字符'a'和'b'化成 ASCII 码97和98,然后放到内存单元中。二者的作用和结果是相同的。第5行输出两个字符a和 b。“%c”是输出字符时必须使用的格式符。程序第6行输出两个整数97和98.程序运行时输出如下:
a b
97 98
可以看到:字符型数据和整型数据是通用的。它们既可以用字符形式输出(用%c),也可以用整数形式输出(用%d),见图3.9。但是应注意字符数据只占一个字节,它只能存放0~255范围内的整数。
例3.7 大小写字母的转换。
main()
{char cl,c2;
c1='a';
c2='b';
c1=c1-32;
c2=c2-32;
printf(" %c %c",c1,c2);
}
运行结果为
A B
程序的作用是将两个小写字母a和b转换成大写字母A 和 B。'a'的 ASCII码为 97,而'A'为 65,'b'为 98,'B'为 66。从 ASCI代码表中可以看到每一个小写字母比它相应的大写字母的ASCII码大32.C语言允许字符数据与整数直接进行算术运算,即'A'+32会得到整数 97,'a'-32会得到整数65。
C语言对字符数据作这种处理使程序设计时增大了自由度。例如对字符作各种转换就比较方便,而在BASIC语言中,为了将小写字母a转换成大写字母A,需要用两个字符处理函数:用ASC函数将字符转换成其相应的ASCII码,再用CHR$函数将ASCII码转换为字符:
PRINT CHR $ (ASC("a")-32)
这样来回转换,既增加程序的复杂性,又增加计算时间的开销。
字符数据与整型数据可以互相赋值。如:
int i;
char c;
i='a';
c=97;
是合法的。如果用格式符“%d”将i的值输出,可得到97。用“%c”输出c,可得字符'a'。
如果在上面语句之后执行以下语句:
printf(" %c,%d\n",c,c);
printf(" %c,%d\n",i,i);
输出:
a,97
a,97
说明:有些系统(如PDP,VAX-11,TurboC)将字符变量中的最高位作为符号位,也就是将字符处理成带符号的整数,即signed char型。它的取值范围是一128~127。如果使用ASCII码为0~127间的字符,由于字节中最高位为0,因此用%d输出时,输出一个正整数。如果使用ASCII 码为128~255间的字符,由于在字节中最高位为1,用%d 格式符输出时,就会得到一个负整数。例如
char c=130;
printf(*%d". c);
得到一126。如果不想按有符号处理,可以将字符变量定义为unsigned char 类型,这时其取值范围是0~255。signed char 和unsigned char的含义及用法与signed int和 unsigned int相仿,但它只有一个字节。
4 字符串常量
前面已提到,字符常量是由一对单撇号括起来的单个字符。C语言除了允许使用字符常量外,还允许使用字符串常量。字符串常量是一对双撇号括起来的字符序列。如,
"How do you do.","CHINA"."a"," $123.45"
都是字符串常量。可以输出一个字符串,如
printf("How do you do." );
不要将字符常量与字符串常量混淆。'a'是字符常量,"a"是字符串常量,二者不同。假设c被指定为字符变量:
char c;
c='a';
是正确的。而
c="a";
是错误的。
c="CHINA"
也是错误的。不能把一个字符串赋给一个字符变量。
有人不能理解'a'和"a"究竟有什么区别?C规定:在每一个字符串的结尾加一个“字符串结束标志”,以便系统据此判断字符串是否结束。C规定以字符'0’作为字符串结束标志。\0’是一个ASCI码为0的字符,从ASCII代码表中可以看到ASCI1 码为0的字符是“空操作字符”,即它不引起任何控制动作,也不是一个可显示的字符。如果有一个字符串"CHINA”,实际上在内存中是
C H I N A \0
它占内存不是5个字节,而是6个字节,最后一个字节为'\0’。但在输出时不输出'\0’。例如在prinf("how do you do.")中,输出时一个一个字符输出,直到遇到最后的'\0'字符,就知道字符串结束,停止输出。注意,在写字符串时不必加0’,否则会画蛇添足\0’字符是系统自动加上的。字符串"a",实际上包含2个字符:'a'和'\0',因此,把它赋给只能容纳一个字符的字符变量c:
c="a";
显然是不行的。
在C语言中没有专门的字符串变量(BASIC中的字符串变量形式为A$、B$等),如果想将一个字符串存放在变量中,以便保存,必须使用字符数组,即用一个字符型数组来存放一个字符串,数组中每一个元素存放一个字符。