3.2数据的表现形式及其运算
3.2.1 常量和变量
1.常量:
1)整型常量
2)实型常量.1.十进制小数形式,由数字和小数点组成.2.指数形式
3)字符常量.1.普通字符,用单撇号括起来的一个字符.2.转义字符.
转义字符 | 字符值 | 输出结果 |
\' | 一个单撇号(') | 具有此八进制码的字符 |
\" | 一个双撇号(") | 输出此字符 |
\? | 一个问号(?) | 输出此字符 |
\\ | 一个反斜线(\) | 输出此字符 |
\a | 警告(alert) | 产生声音或视觉信号 |
\b | 退格(backspace) | 将当前位置后退一个字符 |
\f | 换页(form feed) | 将当前位置移到下一页的开头 |
\n | 换行 | 将当前位置移到下一行的开头 |
\r | 回车(carriage return) | 将当前位置移到本行的开头 |
\t | 水平制表符 | 将当前位置移到下一个tab位置 |
\v | 垂直制表符 | 将当前位置移到下一个垂直制表对齐点 |
\o,\oo或\ooo 其中o代表一个八进制数字 |
与该八进制码对应的ASCII符 | 与该八进制码对应的字符 |
\xh[h···] 其中h代表一个十六进制数字 |
与该十六进制码对应的ASCII符 | 与该十六进制码对应的字符 |
4)字符串常量.用双撇号把若干字符括起来,字符串常量是双撇号中的全部字符(不包括双撇号本身).单撇号内只能包含一个字符,双撇号内可以包含一个字符串.(这个地方和JS不同,JS用单双都可以)
5)符号常量.用#define指令,指定用一个符号名称代表一个常量.
#define PI 3.1416 //注意行末没有分号
经过以上的指定,本文件从此行开始所有PI都代表3.1416.在对程序进制编译前,预处理器先对PI进行处理,把所有的PI全部置换为3.1416.
在预编译后,符号常量已全部变成字面常量(3.14159).
使用符号常量的好处:含义清楚,在需要改变时"一改全改".
注意:要区别符号常量和变量,不要把符号常量误认为变量.符号常量不占内存,只是一个临时符号,在预编译后这个符号就不存在了,故不能对符号常量赋以新值.为与变量名相区别,习惯上符号常量用大写表示.
2.变量
变量代表一个有名字的,具有特定属性的一个存储单元.它用来存放数据,也就是存放变量的值.在程序运行期间,变量的值是可以改变的.
变量必须先定义,后使用.
在定义时指定该变量的名字和类型.一个变量应该有一个名字,以便引用.请注意区别变量各和变量值这两个不同的概念.变量名实际上是以一个名字代表的一个存储地址.在对程序编译连接时由编译系统给每一个变量名分配对应的内存地址.从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据.
3.常变量
const int a=3;
表示a被定义为一个整形变量,指定其值为3,而且在变量存在期间其值不能改变.
常变量与常量的异同:常变量具有变量的基本属性:有类型,占存储单元,只是不允许改变其值.可以说,常变量是有名字的不变量,而变量是没有名字的不变量.有名字就便于在程序中被引用.
4.标识符
在计算机高级语言中,用来对变量,符号常量名,函数,数组,类型等命名的有效字符序列统称为标识符.标识符就是一个对象的名字.
C语言规定标识符只能由字母,数字和下划线3种字符组成,且第1个字符必须为字母或下划线.
一般变量名用小写,增加可读性,大小写是不同的字符.
3.2.2 数据类型
所谓类型,就是对数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式.不同的类型分配不同的长度和存储形式.
基本类型和枚举类型变量的值都是数值,统称为算术类型.
算数类型和指针类型统称为纯量类型,因为其变量的值是以数字来表示的.
枚举类型是程序中用户定义的整数类型.
数组类型和结构体类型统称为组合类型,共用体类型不属性组合类型,因为在同一时间内只有一个成员具有值.
函数类型用来定义函数,描述一个函数的接口,包括函数返回值的数据类型和参数的类型.
不同类型的数据在内存中占用的存储单元长度是不同的.
3.2.3 整型数据
1.整型数据的分类
1)基本整型(int型)
编译系统分配给int数据2个字节或4个字节.在存储单元的存储方式是:用 整数的补码形式存放.一个正数的补码是此数的二进制形式,一个负数的补码是:先将它绝对值写成二进制形式,然后对其后面所有各十进位接位取反,再加1.
在存放整数的存储单元中,最左边一位是用来表示符号的,如果该位为0,表示数值是正,如果该位为1,表示数值为负.
2)短整型(short int)
类型名为short或short int.如用Visual C++ 6.0,编译系统分配给int数据4个字节,短整型2个字节.
3)长整型(long int)
类型名为long int 或long.如用Visual C++ 6.0,编译系统分配给long数据4个字节.
4)双长整型(long long int)
类型名为long long int或long long.一般分配8个字节,新增类型,许多C编译系统尚未实现.
C标准没有具体规定各种类型数据所占用存储单元的长度,这是由各编译系统自行决定的.
sizeof(short)<=sizeof(int)<=sizeof(long)<=sizeof(long long)
sizeof是测量类型或变量长度的运算符.
2.整型变量的符号属性
有些数据的范围常常只有正值,可以将变量定义为"无符号"类型,在前面加上修饰符unsigned,表示指定该变量为"无符号整数类型".如果加上修改符signed,则是"有符号类型".
如果既未指定为signed也未指定为unsigned,默认为"有符号类型".
说明:
1)只有整型(包括字符型)数据可以加signed或unsigned修饰符,实型数据不能加.
2)对无符号整型数据用"%u"格式输出.%u表示用无符号十进制数的格式输出.
在将一个变量定义为无符号 整型后,不应向它赋予一个负值,否则会得到错误的结果.
3.2.4 字符型数据
1.字符和字符代码
并不是任意写一个字符,程序都能识别,只能使用系统字符集中字符,大数系统采用ASCII字符集.
各种字符集的甘醇集都包括127个字符,包括:字母(大写,小字英文字母),数字0~9,专门符号29个:! " # & ' ( ) * + , - · / : ; < = > ? [ \ ] ^ _ { | } ~, 空格符:空格,水平制表符(tab),垂直制表符,换行,换页(form feed).不能显示的字符:空(null)字符(以'\0'表示),警告(以'\a’表示),退格(以’\b’表示),回车(以'\r'表示)等.
所有127个字符都可以用7个二进位表示,所以在C中,指定用1个字节(8位)存储一个字符.此时,字节中的第1位置为0.
注意:字符'1'和整数1是不同的概念,字符'1'只是代表一个形状为'1'的符号,在需要时按原样输出,在内存中ASCII码形式存储,占1个字节.而整数1是以整数存储方式(二进制补码方式)存储的,占2个字节或4个字节.
2.字符变量
字符变量是用类型符char定义的字符变量.
#include#include int main() { char c='?'; printf("%d %c\n",c,c); return 0; }
输出63 ?,'?'的ASCII代码是63,系统把整数63赋给变量c.c是字符变量,实质上是一个字节的整形变量,由于它常用来存放字符,所以称为字符变量.可以把0~127之间的整数赋给一个字符变量.在输出字符变量的值时,可以选择以十进制整数形式输出,或以字符形式输出.
3.2.5 浮点型数据
浮点型数据是用来表示具有小数点的实数的.在C语言中,实数是以指数形式存放在存储单元中的.一个实数表示为指数可以有不上一种形式.由于小数点位置可以浮动,所以实数的指数形式称为浮点数.
规范化指数形式:小数点前为0,小数点后第1位不为0.
浮点数类型包括:float(单精度浮点型),double(双精度浮点型),long double(长双精度浮点型).
1)float型.分配4个字节,数值以规范化的二进制数指数形式存放在存储单元中.在存储时,系统将实型数据分成小数部分和指数部分两个部分分别存放.float型数据能得到6位有效数字.
2)double型.分配8个字节.可以得到15位有效数字.
3)long double型.不同编译系统对其分配不同.
3.2.6 怎么确定常量的类型
从常量的表示形式即可以判定其类型.对于字符常量很简单,只要看到由单撇号括起来的单个字符或转义字符就是字符常量.
整型常量.不带小数点的数值是整型常量,但应注意其有效范围.
在一个整数的末尾加大写字母L或小写字母l,表示它是长整型(long int).
浮点型常量.凡以小数形式或指数形式出现的实数,是浮点型常量,在内存中都以指数形式存储.C编译系统把浮点型常量都按双精度处理,分配8个字节.
可以在常量的末尾加专用字符,强制指定常量的类型.
注意:要区分类型和变量.
每个变量都属于一个确定的类型,类型是变量的一个重要的属性.变量是占用存储单元的,是具体存在的实体,在其占用的存储单元中可以存储数据.而类型是变量的共性,是抽象的,不占用存储单元,不能用来存储数据.
3.2.7 运算符和表达式
1.基本的算术运算符:+(正号运算符,单目运算符) –(负号运算符,单目运算符) * / % +(加) -(减)
两个实数相除的结果是双精度实数,两个整数相除的结果是整数.如果除数或被除数有一个值为负值,则舍入方法不固定.
%运算符要求参加运算的运算对象(即操作数)为整数,结果也是整数.
除%以外的运算符的操作数都可以是任何算术类型.
2.自增,自减运算符
注意:自增运算符(++)和自减(--)只能用于变量,而不能用于常量或表达式.常量的值不能改变.
自增(减)运算符常用于循环语句中,使循环变量自动加1;也用于指针变量,使指针指向下一个地址.
3.算术表达式和运算符的优先级与结合性
在表达式求值时,先按运算符的优先级别顺序执行,级别相同按"结合方向"处理,算法运算符的结合方法都是"自左至右".赋值运算符按从右到左的顺序.
4.不同类型数据间的混合运算
如果一个运算符的两侧的数据类型不同,则先自动进行类型转换,使二者具有同一种类型,然后进行运算.
1)+,-,*,/运算中有一个数为float或double型,系统会将所有float型数据都先转换成double型,结果是double.
2)如果int型与float型或double型数据进行运算,先把int型和float型数据转换成double型,然后进行运算,结果是double型.
3)字符(char)型数据与整型数据进行运行,就是把字符的ASCII代码与整型数据进行运算.字符数据可以直接与整型数据进行运算.如果字符型数据与实型数据进行运算,则将字符的ASCII代码转换为double型数据,然后进行运算.
以上转换为系统自动完成.
例3.3 给定一个大写字母,用小写字母输出.下面是把大写A用小写输出
#include#include int main() { char c1,c2; c1='A'; c2=c1+32; printf("%c\n",c2); printf("%d\n",c2); return 0; }
一个字符数据既可以以字符形式输出,也可以以整数形式输出.
5.强制类型转换运算符
可以利用强制类型转换运算符将一个表达式转换成所需的类型
(double)a
(int)(x+y)
(float)(5%3)
其一般形式为: (类型名)(表达式)
在强制类型转换时,得到一个所需类型的中间数据,而原来变量的类型未发生变化.
6.C运算符
1)算术运算符( + – * / % ++ -- )
2)关系运算符( > < == >= <= != )
3)逻辑运算符( ! && || )
4)位运算符( << >> ~ | ∧ &)
5)赋值运算符(=及其扩展的赋值运算符)
6)条件运算符(?:)
7)逗号运算符(,)
8)指针运算符(*和&)
9)求字节数运算符(sizeof)
10)强制类型转换运算符((类型))
11)成员运算符(. - >)
12)下标运算符([ ])
13)其他(如函数调用运算符())
3.3 C语句
一个函数包含声明部分和执行部分,执行部分是由语句组成的,执行相应的操作.一个C语句经过编译后产生若干条机器指令,声明部分不是语句,它不产生机器指令,只是对有关数据的声明.
C语句分为以下5类:
1)控制语句.C中9种控制语句:if()…else…,for()…,while()…,do…while(),continue(结束本次循环语句),break(中止执行switch或循环语句),switch(多分支选择语句),return(从函数返回语句),goto(转向语句,在结构化程序中基本不用goto语句)
2)函数调用语句.函数调用语句由一个函数调用加一个分号构成.
3)表达式语句.表达式语句由一个表达式加一个分号构成.
一个表达式的最后加一个分号就成了一个语句.一个语句必须在最后加一个分号,分号是语句中不可缺少的组成部分,而不是两个语句间的分隔符号.
4)空语句.只有一个分号,什么也不做.可以用来作为流程的转向点(流程从程序其他地方转到此语句处),也可用来作为循环语句中的循环体(循环体是空语句,表示循环体什么也不做).
5)复合语句.可以用{}把一些语句和声明括起来成为复合语句(又称语句块).可以在复合语句是包含声明部分,习惯放在语句块开关位置.复合语句中最后一个语句中最后的分号不能忽略不写.
3.3.2 最基本的语句-赋值语句
例3.4 给出三角形的三边长,求三角形面积
下面给三边赋值,求面积
#include#include #include int main() { double a,b,c,s,area; a=3.68; b=5.4; c=6.21; s=(a+b+c)/2; area=sqrt(s*(s-a)*(s-b)*(s-c)); printf("a=%f\tb=%f\tc=%f\n",a,b,c); printf("area=%f\n",area); return 0; }
sqrt函数是求平方根的函数,由于要调用数学函数库中的函数,有程序开头加上一条#include指令,把头文件"math.h"包含到程序中来.
'\t’是转义字符,使输出位置跳到下一个tab位置.
凡在程序中要用到数学函数库中的函数,都应当"包含"math.h头文件.
1.赋值运算符.2.复合的赋值运算符.3.赋值表达式.
由赋值运算符将一个变量和一个表达式连接起来的式子称为"赋值表达式".它的一般形式为 变量 赋值运算符 表达式
对赋值表达式求解的过程是:先求赋值运算符右侧的"表达式"的值,然后赋给运算符左侧的变量.赋值运算符左侧应该是一个可修改的值.变量可以作为左值,而算术表达式就不能作为左值,常量也不能作为左值,因为常量不能被赋值.
赋值表达式中的"表达式”又可以是一个赋值表达式.
赋值表达式不能作为左值.
赋值表达式也可以出现在输出语句,循环语句等中.
4.赋值过程中的类型转换
如果赋值运算符两侧的类型一致,则直接进行赋值,如果不一致,但都是算术类型时,在赋值时要进行类型转换.类型转换由系统自动进行,转换规则为:
1)将浮点型数据赋给整形变量时,先对浮点数取整,然后赋值给整形变量.
2)将整型数据赋给单,双精度变量时,数值不变,但以浮点数形式存储到变量中.
3)将一个double型数据赋给float变量时,先将双精度数转换为单精度,即只取6~7位有效数字,存储到float变量的4个字节中.就注意双精度数值的大小不能超出float型变量的数值范围.
将一个float型数据赋给double变量时,数值不变,在内存中以8个字节存储,有效位数扩展到15位.
4)字符型数据赋给整形变量时,将字符的ASCII代码赋给整形变量.
5)将一个占字节多的整形数据赋给一个占字节少的整形变量或字符变量时,只将其低字节原封不动地送到被赋值的变量(即发生"截断").
要避免把占字节多的整型数据向占字节少的整型变量赋值,因为赋值后数值可能发生失真.
实型数据之间以及整型与实型之间的赋值,是先转换(类型)后赋值.
5.赋值表达式和赋值语句
赋值表达式的末尾没有分号,而赋值语句的末尾必须有分号.在一个表达式中可以包含一个或多个赋值表达式,但绝不能包含赋值语句.
6.变量赋初值
可以用赋值语句对变量赋值,也可以在定义变量进对变量赋以初值.
可以用赋值语句对变量赋值,也可以在定义变量时对变量赋以初值.也可以使被定义的变量的一部分赋初值.
如果对几个变量赋予同一个初值,应写成 int a=3,b=3,c=3;而不能写成int a=b=c=3;
一般变量初始化不是在编译阶段完成的(只有在静态存储变量和外部变量的初始化是在编译阶段完成的),而是在程序运行时执行本函数时赋予初值的,相当于执行一个赋值语句.
3.4 数据的输入输出
#include#include #include int main() { double a,b,c,disc,x1,x2,p,q; scanf("%lf%lf%lf",&a,&b,&c); disc=b*b-4*a*c; p=-b/(2.0*a); q=sqrt(disc)/(2.0*a); x1=p+q;x2=p-q; printf("x1=%7.2f\nx2=%7.2f\n",x1,x2); return 0; }
&a表示变量a在内存中的地址.该scanf函数表示从终端输入的3个数据分别送到地址为&a,&b,&c的存储单元,也就是赋给变量a,b,c.双撇号内用%lf格式声明,表示输入的是双精度型实数.
输入数据时两个数之间用空格分开,如果用其他符号(如逗号)会出错.
在printf函数中,在格式符f的前面加了"7.2",表示在输出x1,x2时,指定数据占7列,其中小数占2列.
3.4.2 有关数据输入输出的概念
没有输出的程序是没有意义的.
所谓输入输出是以计算机主机为主体而言 的.C语言本身不提供输入输出语句,输入和输出操作是由C标准函数库中的函数来实现的.
在使用系统库函数时,要在程序文件的开头用预处理指令#include把有关头文件放在本程序中,如#include
stdio是standard input & output(标准输入输出)的缩写,文件后缀中"h"是header的缩写.
#include指令都放在程序文件的开头,因此这类文件称为头文件.
#include
用尖括号形式时,编译系统从存放C编译系统的子目录中去找所包含的文件,这称为标准方式.如果用双撇号形式,在编译时,编译系统先在用户的当前目录(一般是用户存放源程序文件的子目录)中要包含的文件,若找不到,再按标准方式查找.
注意:应养成这样的习惯:只要在本程序文件中使用标准输入输出库函数时,一律加上#include
3.4.3 用printf函数输出数据
1.printf函数的一般格式
printf(格式控制,输出表列)
1)"格式控制"是用双撇号括起来的一个字符串,"格式字符串",它包括:格式声明(由"%"和格式字符组成(如%d,%f),格式声明问题由"%"开始)和普通字符(需要原样输出的字符).
2)"输出表列"是程序需要输出的一些数据,可以是常量,变量或表达式.
printf(参数1,参数2,参数3,...,参数n)
参数1是格式控制字符串,参数2~参数n是需要输出的数据.执行printf函数时,将参数2~参数n按参数1所指定的格式进行输出.参数1是必须有的,参数2~n是可选的.
2.格式字符
1)d格式符.用来输出一个有符号的十进制整数.可以在格式声明中指定输出数据的域宽(所占的列数),如用"%5d",指定输出数据占5列,输出的数据显示在此5列区域的右侧.
2)C格式符.用来输出一个字符.也可以指定域宽.
3)s格式符.用来输出一个字符串.
4)f格式符.用来输出实数(包括单,双精度,长双精度),以小数形式输出.基本型, 用%f. 指定数据宽度和小数位数,用%m.nf, 输出的数据向左对齐,用%-m.nf
注意:在用%f输出时要注意数据本身能提供的有效数字,如float型数据的存储单元只能保证6位有效数字.double型数据能保证15位有效数字.不要以为计算机输出的所有数字都是绝对精确有效的.
5)e格式符.用格式声明%e指定以指数形式输出实数.
还有i格式符,o格式符(以八进制整数形式输出),x格式符(以十六进制数形式输出整数),u格式符,g格式符.
格式声明的一般形式可以表示为:
% 附加字符 格式字符
除X,E,G外,其他格式字符必须用小写字母.
如果想输出字符"%",应该在"格式控制字符串"中用连接两个"%"表示.
3.4.4 用scanf函数输入数据
一般格式: scanf(格式控制,地址表列)
格式声明也是以%开始,以一个格式字符结束,中间可以插入附加的字符.
应注意的问题:"格式控制"后面应当是变量地址,而不是变量名.
如果在"格式控制字符串"中除了格式声明以外还有其他字符,则在输入数据时在对应的位置上应输入与这些字符字符.
3.4.5 字符数据的输入输出
1.用putchar函数输出一个字符
格式:putchar(c)
例3.8 先后输出BOY三个字符
#include#include int main() { char a='B',b='O',c='Y'; putchar(a); putchar(b); putchar(c); putchar('\n'); return 0; }
下面结果与上面一样
#include#include int main() { int a=66,b=79,c=89; putchar(a); putchar(b); putchar(c); putchar('\n'); return 0; }
putchar函数是输出字符的函数,它输出的是字符而不能输出整数.
putchar(c)中的c可以是字符常量,整型常量,字符变量或整型变量.
2.用getchar函数输入一个字符
格式:getchar()
getchar函数没有参数,它的作用是从计算机终端输入一个字符,即计算机获得一个字符.getchar函数只能接收一个字符,如果想输入多个字符就要用多个getchar函数.
例3.9 从键盘输入BOY3个字符,然后把它们输出到屏幕.
#include#include int main() { char a,b,c; a=getchar(); b=getchar(); c=getchar(); putchar(a); putchar(b); putchar(c); putchar('\n'); return 0; }
1.假如我国国民生产总值的年增长率为10%,计算10年我国国民生产总值与现在相比增长多少百分比.
计算机公式为: ,r为年增长率,n为年数,p为与现在相比的倍数.
#include#include #include int main() { float p,r,n; r=0.1; n=10; p=pow(1+r,n); printf("p=%f\n",p); return 0; }
6.请编程序将"China"译成密码,密码规则是:用原来的字母后面第4个字母代替原来的字母.
#include#include int main() { char c1='C',c2='h',c3='i',c4='n',c5='a'; c1=c1+4; c2=c2+4; c3=c3+4; c4=c4+4; c5=c5+4; printf("password is %c%c%c%c%c\n",c1,c2,c3,c4,c5); return 0; }