??采取以下方法来保证得到结构化的程序:
实型常量??注意:e或E之前必须有数字,且e或E后面必须为整数。
字符常量??从其字面形式上即可识别的常量称为“字面常量”或“直接常量”。字面常量是没有名字的不变量。
符号常量??用#define指令,指定用一个符号名称代表一个常量。
??使用符号常量的好处:
??注意:要区分符号常量和变量,不要把符号常量误认为变量。符号常量不占内存,只是一个临时符号,代表一个值,在预编译后这个符号就不存在了,故不能对符号常量赋新值。为与变量名相区别,习惯上符号常量用大写表示,如PI,PRICE等。
常变量??可以说,常变量是有名字的不变量,而常量是没有名字的不变量。
??从使用的角度看,常变量具有符号常量的优点,而且使用更方便。有了常变量以后,可以不必多用符号常量。
标识符??C语言规定标识符只能由字母、数字和下画线3种字符组成,且第1个字符必须为字母或下画线。
??注意:编译系统认为大写字母和小写字母是两个不同的字符。
基本整形(int型)??TurboC2.0为每一个整型数据分配2个字节(16个二进位),而VisualC++为每一个整型数据分配4个字节(32位)。在存储单元中的存储方式是:用整数的补码(complement)形式存放。??求负数的补码的方法是:先将此数的绝对值写成二进制形式,然后对其所有二进位按位取反,再加1。(正数的补码是它自已。)
??如果给整型变量分配4个字节(VisualC++),其能容纳的数值范围为$-2^{31}\sim(2^{31}-1)$,即$-2\;147\;483\;648\sim2\;147\;483\;647$。
短整型(shortint)VisualC++编译系统分配给短整型2个字节。范围是$-32\;768\sim32\;767$。
长整型(longint)??类型名为longint或long。VisualC++对一个long型数据分配4个字节(即32位),因此longint型变量的值的范围是$-2^{31}\sim(2^{31}-1)$,即$-2\;147\;483\;648\sim2\;147\;483\;647$。
双长整型(longlongint)??类型名为longlongint或longlong,一般分配8个字节。这是C99新增的类型,但许多C编译系统尚未实现。
??C标准没有具体规定各种类型数据所占用存储单元的长度,这是由各编译系统自行决定的。C标准只要求long型数据长度不短于int型,short型不长于int型。即
整型变量的符号属性
??可以在类型符号前面加上修饰符unsigned,表示指定该变量是“无符号整数”类型。如果加上修饰符signed,则是“有符号类型”。如果既未指定为signed也未指定为unsigned的,默认为“有符号类型”。
??对无符号整型数据用“%u“格式输出。%u表示用无符号十进制数的格式输出。
字符与字符代码
??ASCII代码最多用7个二进位就可以表示。所以在C语言中,指定用一个字节(8位)存储一个字符(所有系统都不例外)。此时,字节中的第1位置为0。
??在使用有符号字符型变量时,允许存储的值为一$128\sim127$,但字符的代码不可能为负值,所以在存储字符时实际上只用到$0\sim127$这一部分,其第1位都是0。
??由于小数点位置可以浮动,所以实数的指数形式称为浮点数。
float型
??小数部分占的位(bit)数愈多,数的有效数字愈多,精度也就愈高。指数部分占的位数愈多,则能表示的数值范围愈大。float型数据能得到6位有效数字,数值范围为$-3.4\times10^{-38}\sim3.4\times10^{38}$。
double型
??在C语言中进行浮点数的算术运算时,将float型数据都自动转换为double型,然后进行运算。
longdouble型
??而VisualC++则对longdouble型和double型一样处理,分配8个字节。请读者在使用不同的编译系统时注意其差别。
整型常量
??在一个整数的末尾加大写字母L或小写字母l,表示它是长整型(longint)。但在VisualC++中由于对int和longint型数据都分配4个字节,因此没有必要用longint型。
浮点型常量
??加字母F或f,就表示是float型常量,分配4个字节。如果在实型常量后面加大写或小写的L,则指定此常量为longdouble型。
注意:要区分类型与变量。??有些读者容易弄不清类型和变量的关系,往往把它们混为一谈。应当看到它们是既有联系又有区别的两个概念。每一个变量都属于一个确定的类型,类型是变量的一个重要的属性。变量是占用存储单元的,是具体存在的实体,在其占用的存储单元中可以存放数据。而类型是变量的共性,是抽象的,不占用存储单元,不能用来存放数据。
??但是,如果除数或被除数中有一个为负值,则舍入的方向是不固定的。多数C编译系统(如VisualC++)采取“向零取整”的方法,取整后向零靠拢。
??%运算符要求参加运算的运算对象(即操作数)为整数,结果也是整数。
??建议谨慎使用++和--运算符,只用最简单的形式,即i++,i--。而且把它们作为单独的表达式,而不要在一个复杂的表达式中使用++或--运算符。
??关于“结合性”的概念在其他一些高级语言中是没有的,是C语言的特点之,希望能弄清楚。
??(类型名)(表达式)
??注意,表达式应该用括号括起来。??需要说明的是,在强制类型转换时,得到一个所需类型的中间数据,而原来变量的类型未发生变化。
控制语句??C语言只有9种控制语句:
复合语句??注意:复合语句中最后一个语句末尾的分号不能忽略不写。
复合的赋值运算符
??凡是二元(二目)运算符,都可以与赋值符一起组合成复合赋值符。有关算术运算的复合赋值运算符有+=,-=,*=,/=,%=。
赋值表达式
??左值的意思是它可以出现在赋值运算符的左侧,它的值是可以改变的。
赋值过程中的类型转换
??将浮点型数据(包括单、双精度)赋给整型变量时,先对浮点数取整,即舍弃小数部分,然后赋予整型变量。
??将一个double型数据赋给float变量时,先将双精度数转换为单精度,即只取$6\sim7$位.有效数字,存储到float型变量的4个字节中。应注意双精度数值的大小不能超出float型变量的数值范围。
??将一个占字节多的整型数据赋给一个占字节少的整型变量或字符变量时,只将其低字节原封不动地送到被赋值的变量(即发生“截断”)。
赋值表达式和赋值语句
??在if的条件中可以包含赋值表达式,但不能包含赋值语句。
注意:要区分赋值表达式和赋值语句。??赋值表达式的末尾没有分号,而赋值语句的末尾必须有分号。在一个表达式中可以包含一个或多个赋值表达式,但绝不能包含赋值语句。
变量赋初值
??不能写成inta=b=c=3;
??C语言本身不提供输入输出语句,没有输人输出语句就可以避免在编译阶段处理与硬件有关的问题,可以使编译系统简化,而且通用性强,可移植性好,在各种型号的计算机和不同的编译环境下都能适用,便于在各种计算机上实现。
??这两种#include指令形式的区别是:用尖括号形式(如
??c格式符用来输出一个字符。如果整数比较大,则把它的最后一个字节的信息以字符形式输出。
??f格式符用来输出实数(包括单、双精度、长双精度),以小数形式输出不指定输出数据的长度,由系统根据数据的实际情况决定数据所占的列数。系统处理的方法一般是:实数中的整数部分全部输出,小数部分输出6位。
??指定数据宽度和小数位数,用%m.nf。对其后一位采取四舍五人方法处理。如果把小数部分指定为0,则不仅不输出小数,而且小数点也不输出。
??输出的数据向左对齐,用%-m.nf。在m.n的前面加一个负号,其作用与%m.nf形式作用基本相同,但当数据长度不超过m时,数据向左靠,右端补空格。如:
??i格式符。作用与d格式符相同,按十进制整型数据的实际长度输出。
??o格式符。以八进制整数形式输出。将内存单元中的各位的值(0或1)按八进制形式输出,因此输出的数值不带符号,即将符号位也一起作为八进制数的一部分输出。按内存单元中实际的二进制数按3位一组构成八进制数形式,
??x格式符。以十六进制数形式输出整数。
??u格式符。用来输出无符号(unsigned)型数据,以十进制整数形式输出。
??g格式符。用来输出浮点数,系统自动选f格式或e格式输出,选择其中长度较短的格式,不输出无意义的0。
??除了X,E,G外,其他格式字符必须用小写字母,如%d不能写成%D。如果想输出字符“%”,应该在“格式控制字符串”中用连续两个“%”表示
??*,本输人项在读人后不赋给相应的变量
??输入数值时,在两个数值之间需要插入空格(或其他分隔符),以使系统能区分两个数值。在连续输入字符时,在两个字符之间不要插入空格或其他分隔符。
??在输人数值数据时,如输人空格、回车、Tab键或遇非法字符(不属于数值的字符),认为该数据结束。
??用putchar函数既可以输出能在显示器屏幕上显示的字符,也可以输出屏幕控制字符。
??getchar函数没有参数。按Enter键后,字符才送到计算机中。
??执行getchar函数不仅可以从输入设备获得一个可显示的字符,而且可以获得在屏幕上无法显示的字符,如控制字符。
??if语句无论写在几行上,都是一个整体,属于同一个语句。
??“!“为三者中最高的。
??else总是与它上面的最近的未配对的if配对。
??在执行完一个case标号后面的语句后,就从此标号开始执行下去,不再进行判断。
??在case子句中虽然包含了一个以上执行语句,但可以不必用花括号括起来,会自动顺序执行本case标号后面所有的语句。当然加上花括号也可以。
??C99允许在for语句的“表达式1”中定义变量并赋初值。显然,这可以使程序简练,灵活方便。但应注意:所定义的变量的有效范围只限于for循环中,在循环外不能使用此变量。
??break语句只能用于循环语句和switch语句之中,而不能单独使用
??常量表达式中可以包括常量和符号常量,如“inta[3+5];“是合法的。不能包含变量,如“inta[n];“是不合法的。也就是说,C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。
??在定义数组时对全部数组元素赋予初值。
??可以只给数组中的一部分元素赋值。
??如果想使一个数组中全部元素值为0,可以写成inta[10]={0};,未赋值的部分元素自动设定为0。
??在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组长度。
??如果在定义数值型数组时,指定了数组的长度并对之初始化,凡未被“初始化列表”指定初始化的数组元素,系统会自动把它们初始化为0如果是字符型数组,则初始化为’\0‘,如果是指针型数组,则初始化为NULL,即空指针。
??分行给二维数组赋初值。
??可以将所有数据写在一个花括号内,按数组元素在内存中的排列顺序对各元素赋初值。
??可以对部分元素赋初值。
??如果对全部元素都赋初值(即提供全部初始数据),则定义数组时对第1维的长度可以不指定,但第2维的长度不能省。
??在定义时也可以只对部分元素赋初值而省略第1维的长度,但应分行赋初值。
??如果花括号中提供的初值个数(即字符个数)大于数组长度,则出现语法错误。如果初值个数小于数组长度,则只将这些字符赋给数组中前面那些元素,其余的元素自动定为空字符(即’\0‘)。
??C系统在用字符数组存储字符串常量时会自动加一个’\0‘作为结束符。在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度。
1charc[]="Iamhappy";??注意字符串的两端是用双撇号而不是单撇号括起来的。字符串常量的最后由系统加上一个’\0‘。
??字符数组并不要求它的最后一个字符为’\0‘,甚至可以不包含’\0‘。为了使处理方法一致,便于测定字符串的实际长度,以及在程序中作相应的处理,在字符数组中也常常人为地加上一个’\0‘。
??如果一个字符数组中包含一个以上’\0‘,则遇第一个’\0‘时输出就结束。
??scanf函数中系统会自动在字符串后面加一个’\0‘结束符。数组中未被赋值的元素的值自动置’\0‘。
??函数间可以互相调用,但不能调用main函数。main函数是被操作系统调用的。
??可以省略第一维的大小说明。但是不能把第2维以及其他高维的大小说明省略。
??有效范围为从定义变量的位置开始到本源文件结束。
??在编译时遇到extern时,先在本文件中找外部变量的定义,如果找到,就在本文件中扩展作用域;如果找不到,就在连接时从其他文件中找外部变量的定义。如果从其他文件中找到了,就将作用域扩展到本文件;如果再找不到,就按出错处理。
??如果一个函数只能被本文件中其他函数所调用,它称为内部函数。在定义内部函数时,在函数名和函数类型的前面加static,即:
??如果在定义函数时,在函数首部的最左端加关键字extern,则此函数是外部函数,可供其他文件调用。
1externintfun(inta,intb)??C语言规定,如果在定义函数时省略extern,则默认为外部函数。
??一个变量的指针的含义包括两个方面,一是以存储单元编号表示的纯地址(如编号为2000的字节),一是它指向的存储单元的数据类型(如int,char,float等)。
??使用指针法能使目标程序质量高(占内存少,运行速度快)。
??两个地址不能相加,如p1+p2是无实际意义的。
??指向数组元素的指针变量也可以带下标。
??由于++和*同优先级,结合方向为自右而左,因此它等价于*(p++)。先引用p的值,实现*p的运算,然后再使p自增1。
??”int(*p)[4]“表示定义p为一个指针变量,它指向包含4个整型元素的一维数组。注意,*p两侧的括号不可缺少。
??数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值。
??字符数组中各元素的值是可以改变的(可以对它们再赋值),但字符指针变量指向的字符串常量中的内容是不可以被取代的(不能对它们再赋值)。
??定义指向函数的指针变量的一般形式为
1类型名(*指针变量名)(函数参数表列);??由于优先级的关系,“*指针变量名”要用圆括号括起来。
??定义指向函数的指针变量,并不意味着这个指针变量可以指向任何函数,它只能指向在定义时指定的类型的函数。??对指向函数的指针变量不能进行算术运算。
??其实,main函数中的形参不一定命名为arge和argv,可以是任意的名字,只是人们习惯用argc和argv而已。
??不要把“指向void类型”理解为能指向”任何的类型”的数据,而应理解为“指向空类型”或“不指向确定的类型”的数据。
??如果写成123.0,则认为是单精度实数,按单精度实型的存储形式存放。
??虽然在VisualC++中也为指针变量分配4个字节,但不同于整型数据的存储形式。
??一个地址型的数据实际上包含3个信息:
??有关指针变量的归纳比较:
??在stdio.h头文件中对NULL进行了定义:
1#defineNULL0??系统保证使该单元不作它用(不存放有效数据)。
??C99标准允许对某一成员初始化,如:
??“.”是成员运算符,它在所有的运算符中优先级最高。
??同类的结构体变量可以互相赋值。
??共用体变量所占的内存长度等于最长的成员的长度。
??不能引用共用体变量,而只能引用共用体变量中的成员。
??同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一个成员,而不是同时存放几个。
??可以对共用体变量初始化。但初始化表中只能有一个常量,
??共用体变量中起作用的成员是最后一次被赋值的成员,在对共用体变量中的一个成员赋值后,原有变量存储单元中的值就取代。
??不能对共用体变量名赋值,也不能企图引用变量名来得到一个值。
??C99允许同类型的共用体变量互相赋值。
??以前的C规定不能把共用体变量作为函数参数,但可以便用指向共用体变量的指针作函数参数。C99允许用共用体变量作为函数参数。
??C编译对枚举类型的枚举元素按常量处理,故称枚举常量。不要因为它们是标识符(有名字)而把它们看作变量,不能对它们赋值。也可以人为地指定枚举元素的数值,在定义枚举类型时显式地指定。
??枚举元素的比较规则是按其在初始化时指定的整数来进行比较的。
??命名一个新的类型名代表数组类型
??指向文件的指针变量并不是指向外部介质上的数据文件的开头,而是指向内存中的文件信息区的开头。
??所谓“打开”是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输入输出的数据)。
??如果不能实现“打开”的任务此时fopen函数将带回一个空指针值NULL。
??其实,带b和不带b只有一个区别,即对换行的处理。
??输出的数据形式是由程序中采用什么读写语句决定的。例如,用fscanf和fprintf函数是按ASCII方式进行输入输出,而fread和fwrite函数是按二进制进行输入输出。
??程序中可以使用3个标准的流文件——标准输入流、标准输出流和标准出错输出流。系统定义了3个文件指针变量stdin、stdout和stderr。
??如果不关闭文件就结束程序运行将会丢失数据。
??fclose函数也带回一个值,当成功地执行了关闭操作,则返回值为0;否则返回EOF(-1)。
??在文件的所有有效字符后有一个文件尾标志。当读完全部字符后,文件读写位置标记就指向最后一个字符的后面,即指向了文件尾标志。如果再执行读取操作,则会读出-1(不要理解为最后有一个结束字节,在其中存放了数值-1。它只是一种处理方法)。文件尾标志用标识符EOF(endoffile)表示,EOF在stdio.h头文件中被定义为-1。
1char*fgets(char*str,intn,FILE*fp);??其中,n是要求得到的字符个数,但实际上只从fp所指向的文件中读入n-1个字符,然后在最后加一个“\0”字符,这样得到的字符串共有n个字符,把它们放到字符数组str中。如果在读完n-1个字符之前遇到换行符“\n”或文件结束符EOF,读入即结束,但将所遇到的换行符“\n”也作为一个字符读入。
??在内存与磁盘频繁交换数据的情况下,最好不用fprintf和fscanf函数,而用下面介绍的fread和fwrite函数进行二进制的读写。
??文本读写函数:用来向文本文件读写字符数据的函数(如fgetc,fgets,fputc,fputs,fscanf,fprintf等)。??二进制读写函数:用来向二进制文件读写二进制数据的函数(如getw,putw,fread,fwrite等)。
??用rewind函数使文件位置标记指向文件开头。??用fseek函数改变文件位置标记。
??用ftell函数测定文件位置标记的当前位置
??应该注意,对同一个文件每一-次调用输人输出丽数,都会产生一个新的ferror函数值,因此,应当在调用一个输入输出函数后立即检查ferror函数的值,否则信息会丢失。在执行fopen函数时,ferror函数的初始值自动置为0。??clearerr的作用是使文件出错标志和文件结束标志置为0。
《C语言程序设计(第五版)谭浩强》及《C语言程序设计:学习辅导(第五版)谭浩强》