资源描述
1. 语言变量声明和变量赋值
1)基本数据类型
在C语言中,仅有4种基本数据类型—整型、浮点型、指针和聚合类型(如数组和结构等),所有其他的类型都是从这4种基本类型的某种组合派生而来。
整型:整型家族包括字符、短整型、整型和长整型,它们都分为有符号(signed)和无符号(unsigned)两种版本。规定整数值相互之间大小的规则很简单:长整型至少应该和整型一样长,而整型至少应该和短整型一样长。
浮点类型:诸如3.14159和2.3×1023这样的数值无法按照整数存储。第一个数为非整数,而第二个数远远超出了计算机整数所表达范围,这样的数就可以用浮点数的形式存储。浮点数家族包括float、double和long double类型。通常,这些类型分别提供单精度、双精度以及在某种扩展精度的机器上提供扩展精度。ANSI标准仅仅规定long double至少和double一样长,而double至少和float一样长。标准同时规定了一个最小范围:所有浮点类型至少能够容纳从10-37到1037之间的任何值。
指针:变量的值存储于计算机内存中,每个变量都占据一个特定的位置。每个内存的位置都由地址唯一确定并应用,就像一条街上的房子由他们的门牌号码标识一样,指针知识地址的另一个名字。
2)变量声明形式
只知道基本的数据类型是远远不够的,你还应该知道怎样声明变量。变量的基本形式是:
说明符(一个或多个) 声明表达式列表
对于简单的类型,声明表达式列表就是被声明的标识符的基本类型。对于相对比较复杂的类型,声明表达式列表的每个条目实际上是一个表达式,显示被声明的名字的可能用途。
例如:int a, double b;
该语句就是一条声明语句,其中a,b就是变量名,该语句指明了变量a,b是int数据类型。所有变量在使用前都必须写在执行语句之前,也就是变量声明要与执行语句相分离,否则就是出现编译错误。
3)变量命名
C语言中任何的变量名都是合法的标示符。所谓标识符就是由字母、数字和下划线组成的但不以数字开头的一系列字符。虽然C语言对标示符的长度没有限制,但是根据ANSI标准,C编译器必须要识别前31个字符。C语言是对大小写敏感的,即C语言认为大写字母和小写字母的含义是不同的,因此a1和A1是不同的标识符。
到目前为止,没有一种命名规则可以让所有的程序员赞同,程序设计教科书一般都不指定命名规则。常用的命名规则有匈牙利命名法和驼峰命名法等,在实际操作中,我们会采取相对简单方便的命名规则,即“类型首字母”+“_”+“变量用途英文缩写”,其中英文缩写首字母为大写,例如 int i_Num,char c_Name[5]。
4)变量赋值
在一个变量声明中,你可以给一个标量变量指定一个初始值,方法是在变量名后面跟一个等号(赋值号),后面就是你想要给变量的值。例如:
int i_Num=10;
char c_Name[]=”student”;
上述语句声明i_Num为一个整数变量,其初始值为10,声明c_Name为一个字符数组,其初始值为“student”。
在C语言中,全局变量和静态变量,如果没有赋初值,则默认初始值int,float,char分别为0,0.0,’\0’,除了全局变量和静态变量以外,其他变量如果没有赋初值,则默认初始值为内存中的垃圾内容,对于垃圾内容不能有任何假设。注意:定义指针后,默认初始值不是0,而是随机的一个值,故定义指针后,一定要初始化。
在实际操作中,变量的赋值都是以赋值语句的形式出现,赋值语句是由赋值表达式再加上分号构成的表达式语句。其一般形式为:
变量=表达式;
在赋值语句的使用中需要注意以下几点:
a) 由于在赋值符“=”右边的表达式也可以又是一个赋值表达式。
下述形式:
变量=(变量=表达式);
该语句是成立的,从而形成了嵌套的情形。其展开后的一般形式为:
变量=变量=…=表达式;
例如:a=b=c=d=e=5;
按照赋值运算符的右结合性,因此实际上等效于:e=5;d=e;c=d;b=c;a=b;
b) 注意在变量声明中给变量赋初值和赋值语句的区别
给变量赋初值是变量说明的一部分,赋初值后的变量与其后的其他同类变量之间仍必须用逗号隔开,而赋值语句则必须用分号隔开。
例如:int a=5,b,c;
c) 在变量声明中,不允许连续给多个变量赋初值。
如下述说明就是错误的:
int a=b=c=5;
正确写法为:int a=5,b=5,c=5;
但是,赋值语句允许连续赋值。
d) 注意赋值表达式和赋值语句的区别。
赋值表达式是一种表达式,它可以出现在任何允许表达式出现的地方,而赋值语句则不能。下述语句是合法的:
If((x=y+7)>0) z=x;
语句功能为若表达式x=y+5大于0则z=x。
但是,下述语句是错误的:
If((x=y+7;)>0) z=x;
因为x=y+7;是语句,不能出现在表达式中。
实例:
#include “stdafx.h”
void main()
{
int i_Tmp,i_Type=8;
float f_Tmp;
double d_Tmp;
char c_Tmp;
d_Tmp=d_Tmp=f_Tmp=12;
f_Tmp=i_Type;
i_Tmp=i_Type+3;
printf("a=%d,b=%d,c=%.3f,d=%.6lf",i_Tmp,i_Type,f_Tmp,d_Tmp);
}
参考书目:
1. (美)Kebbeth A.reek.《C与指针》29-40
2. H.M.Deitel P.J.Deitel等《how to program Second Edition》19-23
2. 算术运算符及使用方式
C语言提供了最基本的算术运算符,如下表:
运算符
含义
举例
结果
+
加法运算符
a+b
a和b的和
-
减法运算符
a-b
a和b的差
*
乘法运算符
a*b
a和b的乘积
/
除法运算符
a/b
a除b的商
%
求余运算符
a%b
a除b的余数
++
自加运算符
a++,++a
a自加1
--
自减运算符
a--,--a
a自减1
1、+、-、*、/都适用于浮点类型和整数类型,当两个操作数都为整数时进行整数运算,其余情况则进行double型运算;当/除法运算符的两个操作数为整数时,结果为整数,舍去小数部分,例如5/3的结果为1;%求余运算符只接受两个整型操作数的运算,结果为余数
2、++、--:作用是使变量自加1或自减1,例如i++、++i,都是使i的值加1,但其执行的步骤是不同的。例如:
int i=3,j;
j=i++;// i的值为4 ,j的值为3
int i=3,j;
j=++i;//i的值为4,j的值为4
可见当变量在左侧时,先进行赋值运算再进行自加1操作,当变量在右侧时,先进行自加1操作再进行赋值运算。
3、在赋值运算符之前加上算术运算符既构成复合运算符,例如:a+=b,等价于a=a+b。-=、*=、/=也是如此。
3. 位运算符及使用方式(<<、>>、~、|、&、^)
位运算符是用来对二进制位进行操作,如下表:
运算符
含义
<<
左移
>>
右移
~
取反
|
按位或
&
按为与
^
按为异或
<<、>>:移位运算符,例如左移运算符:
int i=3;i=i<<4;
3的二进制位为00000011,左移4位的结果为00110000,其操作中高位舍弃、低位补0,既i=48,等同于i乘以2的4次方。
右移运算符则有所不同,操作中是低位舍弃,高位则有两种补位方式。一种为逻辑移位,高位补0;另一种为算术移位,当符号位为1时高位全部补1,当符号位为0时则高位全部补0。具体使用哪种移位方式则取决于当前的编译环境。
~:取反运算符,为单目运算符,其操作是对操作数的二进制位按位求反,既1变0,0变1。例如i=5,二进制位为00000101,取反的结果为11111010。
在计算机系统中,数值一律用补码来表示和存储,其中最高位为符号位,用0表示正,1表示负。补码的规定如下:
a) 对正数来说,最高位为0,其余各位代表数值本身,例如14的补码为00001110;对负数而言,则将该数绝对值的补码按位取反,再加1,得该数的补码,既-i=~i+1。例如-14的补码为14的二进制00001110取反加1得11110010。
b) |、&、^:均为双目运算符,对操作数的二进位进行运行,且操作数以补码的方式出现。
c) |按位或,两个对应的二进位至少有一个为1则为1,否则为0;&按位与,两个对应的二进位都为1则为1,否则为0;^按位异或,两个对应的二进位不同则为1,否则为0。例如:
a=5; (00000101)
b=14; (00001110)
a|b=15; (00001111)
a&b=4; (00000100)
a^b=11; (00001011)
4. 关系运算符及使用方式(>、>=、<、<=、==、!=)
运算符
含义
>
大于
>=
大于或等于
<
小于
<=
小于或等于
==
等于
!=
不等于
关系运算符用于比较两个数值之间的关系,例如:a>3为关系表达式,大于号为关系运算符,当表达式成立时,“a>3”的值为“真”,当“a>3”不成立时,“a>3”的值为“假”。
其中应当注意的是关系表达式的返回值为整型值,而不是布尔型。表达式为真时返回值为1,表达式为假时返回值为0。
5. 逻辑运算符及使用方式(&&、||、!)
运算符
含义
举例
结果
&&
逻辑与
a&&b
a,b都为真则结果为真,否则为假
||
逻辑或
a||b
a,b至少有一个为真则结果为真,否则为假
!
逻辑非
!a
当a为真则结果为假,当a为假则结果为真
其中应当注意逻辑或,例如a||b,当a为真时,C语言中直接跳过对b的判断,其返回值为“真”。
当一个表达式包括几种运算符时,则以运算符的优先级对表达式进行运算,表达式的优先级如下:
优先级
运算符类型
说明
1
初等运算符
()、[]、->、.
2
单目运算符
!、~、++、--、*(指针运算符)、&(取地址运算符)
3
算术运算符
先乘除后加减
4
关系运算符
>、>=、<、<=、==、!=
5
逻辑运算符
&&、||
6
条件运算符
三目运算符,例如?:
7
赋值运算符
=
8
逗号运算符
,
6. 指针的概念与使用
1) 指针的定义
指针就是变量的地址,是一个常量。定义指针的目的就是为了通过指针访问内存单元。在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。
指针变量定义的一般形式为:
存储类型 数据类型 * 指针变量名
2) 指针变量运算符
1、取地址运算符:&
该运算符表示的是对&后面的变量进行取地址运算。
例:int a;
则 &a表示取变量a的地址,该表达式的值为变量a的首地址。
2、指针运算符:*
该运算符也称为“取内容运算符”,后面接一个指针变量。表示的是访问该指针变量所指向的变量,即访问指针所指向的存储空间中的数据。
例:int a=7;
int *p;
p=&a;
则 *p 表示指针变量 p 指向变量 a,即 *p 就是 a,所以 *p=7。
一个指针变量 p 在程序中通常有如下表示形式:
p: 指针变量,它的内容是地址量;
*p:指针所指向的变量,是指针所指向的内存空间中的数据;
&p:指针变量所占存储空间的地址;
【例1】分析程序的运行结果
源程序如下:
#include<stdio.h>
void Locate()
{
int i_a;
int *pst_a;
printf("\n请输入i_a的值:");
scanf("%d",&i_a);
pst_a =&i_a;
printf("i_a的值为:%d\n",i_a);
printf("pst_a的值为:%x\n", pst_a);
printf("&i_a的值为:%x\n",&i_a);
printf("*pst_a的值为:%d\n",* pst_a);
printf("&pst_a的值为:%x\n",& pst_a);
printf("\n");
}
运行结果:
请输入i_a的值:3
i_a的值为:3
pst_a的值为:12fe8c
&i_a的值为:12fe8c
*pst_a的值为:3
&pst_a的值为:12fe80
以上实例中,12fe8c是pst_a的值,也就是i_a的地址;12fe80是pst_a的地址;两者有区别,不能混为一谈。
3) 地址与指针的概念
指针可以有效地表示复杂的数据结构;动态分配内存;方便的使用字符串;有效而方便地使用数组;能直接处理内存地址。
如果在程序中定义了一个变量,在编译时就给这个变量分配内存单元。系统根据程序中定义的变量的类型,分配一定长度的空间。例如,一般微机使用的C系统为整形变量分配两个字节,为实型变量分配4个字节。内存区的每一个字节有一个编号,这就是“地址”,它相当于旅馆中的房间号。在地址所标志的内存单元中存放数据,这相当于旅馆中各个房间中居住旅客一样。
在程序中一般通过变量名对内存单元进行存取操作,这称作“直接访问”,还可以采用 另一种“间接访问”方式,将变量的地址存放在另一个变量中。所谓“指向”就是通过地址来体现的,由于通过地址能找到所需的变量单元,我们可以说,地址“指向”该变量单元,因此在C语言中,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。一个变量的地址成为该变量的“指针”。如果有一个变量专门用来存放另一个变量的地址,则称它为“指针变量”。
4) 变量的指针和指向变量的指针变量
变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。为了表示指针变量和它指向的变量之间的关系,用“*”符号表示“指向”。
定义指针变量的一般形式为:
基类型 *指针变量名;
5) 数组与指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占有存储单元,它们都有相应的地址。指针变量也可以指向数组元素。
6) 空间操作函数malloc、free
C语言提供了两个函数,malloc与free,分别用于执行动态内存分配与释放。这些函数维护一个可用内存池。当一个程序另外需要一些内存时,它就调用malloc函数从内存池中提取一块合适的内存,并返回一个指向这块内存的指针。这块内存此时并没有以任何方式进行初始化,使用时需手动初始化。
这两个函数的原型如下所示,它们都在头文件stdio.h中声明。
void *mallloc(size_t size);
Void *free(viod* pointer);
malloc的参数就是需要分配的内存字节数。如果内存池中的可用内存可以满足这个需要,malloc就返回一个指向被分配的内存块起始位置的指针,如果系统无法向malloc提供更多的内存,malloc就会返回一个NULL指针。
free的参数必须要么是NULL,要么是一个先前从malloc或其他空间申请函数返回的值。
malloc的一般用法
基类型*=(基类型)*Malloc(数量*sizeof(基类型));
7) 动态数组
动态数组是指在声明时没有确定数组大小的数组,即忽略方括号中的下标;当使用时可用malloc语句重新指出数组的大小。使用动态数组的优点是可以根据用户需要,有效利用存储空间。动态数组的内存空间是从堆上分配的。是通过执行代码而为其分配空间。当程序执行到这些语句时,才为其分配空间。程序员自己释放内存。
遵循原则:
申请的时候从外层往里层,逐层申请;
释放的时候从里层往外层,逐层释放。
【例2】:一维数组的动态开辟与释放:
【例3】:二维数组的动态开辟:
7. 数组
数组是构造类型,是一组具有相同类型数据的有序集合。每个数据成为数组的元素,用一个统一的数组名和下标来唯一地确定数组中的元素。
一维数组的声明方式为:
<类型标识符><数组名>[常量表达式]
类型标识符是任一种基本数据类型或构造数据类型;数组名由用户自定义,表示存储空间的地址;常量表达式表示数组元素的个数,也是数组的长度。
例:int a[6];表示一个整型、数组名为a、长度为6的一维数组。
(2)一维数组的引用形式:
下标法:数组名[下标]
例如:a[i];或p[i];a为数组名,p为指向数组的指针变量。
注:C语言中不能依次引用整个数组,只能逐个引用数组中的各个元素。下标就是被访问的数组元素在所定义的数组中的相对位置。下标为0表示的是数组元素在数组的第一个位置上,下标等于1表示的是数组元素在数组的第二个位置上,依次类推。例如:
int a[10];
a[0]=100;//正确
a[10]=100;//不正确,下标越界
例如:
下标法:
int main()
{
int a[10];
for(int i=0;i<10;i++)
a[i]=2*i;
for(int i=0;i<10;i++)
printf(“%d\t”,a[i]);
return 0;
}
指针法:*(a+i)或 *(p+i);a是数组名,p为指向数组的指针变量。
例如:
指针法:
int main()
{
int *p=a;
int i;
for(i=0;i<10;i++)
a[i]=2*i;
for(i=0;i<10;i++)
printf(“%d\t”,*(p+i));
return 0;
}
二维数组的声明方式为:
<类型标识符><数组名>[常量表达式1] [常量表达式2]:
二维数组与一维数组的区别在于多出[常量表达式2]。[常量表达式1] 是第一维,常称为行; [常量表达式2]是第二维,也就是列。
例:int a[3][5];表示一个3行5列的二维数组;数组元素的个数为:3*5=15个。
二维数组的引用形式:
下标法:
数组名[下标] [下标]
注:二维数组在引用时和一维数组一样,只能逐个引用数组中的各个元素。例如:
sz_A[5][6]
下标可以是整数表达式,如sz_A[8-5][2*3-1]。不要写成sz_A[2,3]、
sz_A[8-5,2*3-1]形式。
注意:严格区分定义数组时用的sz_A[5][6]和引用元素时用的sz_A[5][6]的区别。前者sz_A[5][6]用来定义数组的维数,后者sz_A[5][6]的5和6是下标,代表的是数组中的某一个元素。
【例2】分析程序的运行结果
源程序如下:
#include<stdio.h>
void main()
{
int sz_Array[6];//一维数组
int sz_DlArray[3][5];//二维数组
int i_a;
int i_dla;
int i_dlb;
//一维数组
for (i_a=0;i_a<6;i_a++)
{
sz_Array[i_a]=i_a*2+2;
}
printf("\n输出一维数组元素为:\n");
for(i_a=0;i_a<6;i_a++)
{
printf("%d\t",sz_Array[i_a]);
}
//二维数组
for(i_dla=0;i_dla<3;i_dla++)
{
for(i_dlb=0;i_dlb<5;i_dlb++)
{
sz_DlArray[i_dla][i_dlb]=i_dla+i_dlb;}
}
printf("\n输出二维数组元素为:\n");
for(i_dla=0;i_dla<3;i_dla++)
{
for(i_dlb;i_dlb<5;i_dlb++)
{
printf("%d ",sz_DlArray[i_dla][i_dlb]);
}
printf("\n");
}
}
运行结果为:
输出一维数组元素为:
2 4 6 8 10 12
输出二维数组元素为:
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
指针法:
可以通过行指针来引用二维数组元素。
定义行指针变量:int (*p)[3],指针p是指向一个由3个元素所组成的整型数组指针。
例如:
void main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}
int (*p)[4]=a;
for(int i=0;i<3;i++)
{
for(int j=0;i<4;j++)
printf(“%d\t”,p[i][j]);
printf(“\n”);
}
}
参考书目:
1. C++语言程序设计教程与实验(第二版) 温秀梅 丁学钧 李建华主编
2. C/C++程序设计教程 张世民主编
8. 字符数组
1) 字符数组的定义与赋值
字符数组是一串字符的集合,其数组元素为字符型。
字符数组的赋值形式:
char 数组名[常量表达式]=“字符串”;
或 char 数组名[常量表达式]={“字符串”};
例:char sz_A[5]={‘s’, ‘t’, ‘u’, ‘d’, ‘y’, };
定义数组sz_A,包含5个元素,其在内存中的存放情况为:
sz_A[0] sz_A[1] sz_A[2] sz_A[3] sz_A[4]
s
t
u
d
y
则各元素赋值如下:
sz_A[0]=‘s’; sz_A[1]=‘t’; sz_A[2]=‘u’; sz_A[3]=‘d’;sz_A[4] =‘y’
如果花括号中的字符个数大于数组长度,编译系统就会报错,如果花括号中的字符个数小于数组长度,其余元素则由系统自动定义为空字符,即‘\0’。
‘\0’作为字符串的结束标志,因此在定义数组长度时,应在字符串原有的长度上加1,为字符串结束标志预留空间。
例:char sz_A[6]={‘s’, ‘t’, ‘u’, ‘d’, ‘y’, };
定义数组sz_A,包含6个元素,其在内存中的存放情况为:
sz_A[0] sz_A[1] sz_A[2] sz_A[3] sz_A[4] sz_A[5]
s
t
u
d
y
\0
则各元素赋值如下:
sz_A[0]=‘s’; sz_A[1]=‘t’; sz_A[2]=‘u’
sz_A[3]=‘d’; sz_A[4]=‘y’; sz_A[5]=‘\0’
【例3】分析程序的运行结果
源程序如下:
#include<stdio.h>
void main()
{
char sz_A[10]="work hard";
int i;
for(i=0;i<9;i++)
printf("%c",sz_A[i]);
}
运行结果:
work hard
以上实例中,逐个显示字符数组的各个元素,但需注意的是在定义字符数组的下标时,至少比后面的字符串长度大1。其中,字符串长度应包括其中空格的长度。
2) 字符串操作函数:
a) 字符串复制函数strcpy()
格式:strcpy(字符数组1,字符数组2)
功能:是将字符数组2中字符串复制到字符数组1中去。
注:字符数组1的长度必须大于字符数组2,从而能够容纳复制的字符数组2的字符串;字符数组1必须写成数组名形式,字符数组2既可以是字符数组名,也可以是字符串;字符数组之间不能相互赋值。
例如:char sz_str1[10],sz_str2[6]="work hard";
Strcpy(sz_str1,sz_str2);
printf("%s\n",sz_str1);
运行结果:
work hard
b) 字符串连接函数strcat()
strcat(字符数组1,字符数组2)
功能:将字符数组1和字符数组2中的字符串连接起来,字符数组2中的字符串2接到字符数组1中的字符串后面。
注:字符数组1的长度必须足够大,能够同时容纳字符数组1中的字符串和字符数组2中的字符串。
字符数组名2中的字符串连接到字符数组1的字符串时,删除字符数组1中的字符串后面的标志‘\0’,只在新串的最后保留“\0”。
例如:char sz_str1[10]="work",sz_str2[6]="hard";
strcat(sz_str1,sz_str2);
printf("%s\n",sz_str1);
运行结果:
workhard
c) 字符串比较函数strcmp()
strcmp(字符数组1,字符数组2)
功能:比较字符数组1和字符数组2中字符串,通过函数返回值得出比较结果。
若字符数组1中的字符串<若字符数组1中的字符串,函数返回值<0;
若字符数组1中的字符串>若字符数组1中的字符串,函数返回值>0;
若字符数组1中的字符串=若字符数组1中的字符串,函数返回值=0;
注:比较规则:比较过程中,按照从左到右的顺序,逐个比较字符的ASCII码值,直到遇到不相同的字符或“\0”,即结束比较。
例如:char sz_str1[10]="work",sz_str2[10]="hard";
if (strcmp(sz_str1,sz_str2)>0)
{
printf("大于\n");
}
if (strcmp(sz_str1,sz_str2)<0)
{
printf("小于\n");
}
if (strcmp(sz_str1,sz_str2)==0)
printf("相等\n");
运行结果:
大于
d) sprintf()
sprintf(s,”%s%d%c”,”text”,1,’char’);
将输出结果写入数组S中;其函数返回值为字符串长度,相当于strlen;计算长度时不计算“\0”,而sizeof计算时是加上“\0”的。
例如:
char sz_str;
sprintf(sz_str,"%s%d%c","work",6,"hard");
i_Tmp=sprintf(sz_str,"%s%d%c","work",6,"hard");
printf("sprintf结果输出:%s\n",sz_str);
printf("sprintf函数返回值输出:%d\n",i_Tmp);
e) sscanf()
sscanf(s,”%d%f%s”,&a,&b,&c);
从一个字符串中读进与指定格式相同的数据;其返回值为读入有效数据的个数;从数组S中,以固定格式向a,b,c输入,sscanf不识别空格。
char sz_str[11]="work6hard";
char sz_str1[11];
sscanf(sz_str,"%4s",sz_str1);
i_Tmp=sscanf(sz_str,"%4s",sz_str1);
printf("输出结果:%s\n",sz_str1);
printf("sscanf函数返回值:%d\n",i_Tmp);
运行结果:
输出结果:work
sscanf函数返回值:1
9. 全局变量与局部变量的定义和区别
变量的作用域指变量所起的作用范围,变量的定义位置决定了变量的作用域,它可分为全局变量和局部变量。
1) 全局变量
全局变量是指在函数外部定义的变量,它不属于哪一个函数,它属于一个源程序文件,它的作用范围从定义变量定义的位置开始到本源文件的结束。在函数中使用全局变量,一般应做全局变量声明。只有在函数内部经过声明的全局变量才能使用。但在一个函数之前定义全局变量,在该函数内使用可不加以声明。
全局变量的作用是增加函数间数据联系的渠道。同一个文件中的所有函数都能引用全局变量的值,当一个函数改变了全局变量的值,就会影响到其它函数,有利于函数之间信息的传递。
2) 局部变量
在函数中或者复合语句中定义的变量称为局部变量,它的作用范围只限于该函数或者该复合语句中,在其它位置无效。
如果全局变量和局部变量重名,在定义局部变量中的子程序中局部变量起作用,全局变量失效。
程序在编译过程中,系统并不会为局部变量分配存储单元,而在程序的运行过程中,当局部变量所在函数被调用时,系统才会为变量分配临时内存,函数调用结束后,释放空间。
3) 全局变量和局部变量的区别
1 全局变量的有效范围从定义该变量的位置开始到本源文件的结束,局部变量只在定义该变量的函数中有效,在函数外部无效。
2局部变量是程序运行到该函数时给变量分配内存空间,函数运行结束后释放空间,全局变量在程序运行时先分配内存空间,直到本源文件执行完以后释放空间。
4) 程序实例
#include "stdafx.h"
int x=6,y=8;
void plus()
{
printf("x=%d\t,y=%d\n",x,y);
x++;
y++;
}
void main()
{
void plus();
int x=2,y;
x=2,y=3;
printf("x=%d\t,y=%d\n",x,y);
plus();
printf("x=%d\t,y=%d\n",x,y);
plus();
}
参考书目:
1.《C 语言程序设计》作者 张书云 姜淑菊 朱雷 P89-P91
10. 文件操作以处理
1) FILE类型
文件:存储在外部介质上数据的集合。声明FILE结构体类型的信息须声明#inclu<stdio.h>议案不能定义指向FILE类型变量的 指针变量FILE *fp;
2) fopen函数
调用方式:fopen(文件名,使用文件方式),文件打开成功则返回一个FILE类型指针,否则返回NULL。
表 101文件打开方式
文件使用方式
含义
“r”(只读)
为输入打开一个文本文件
“w” (只写)
为输出打开一个文本文件
“a” (追加)
向文本文件尾部增加数据
“rb” (只读)
为输入打开一个二进制文件
“wb” (只写)
为输入打开一个二进制文件
“ab” (追加)
向二进制文件尾增加数据
“r+” (读写)
为读/写打开一个文本文件
“w+” (读写)
为读/写建立一个新的文本文件
“a+” (读写)
为读/写打开一个文本文件
“rb+” (读写)
为读/写打开一个二进制文件
“wb+” (读写)
为读/写建立一个新的二进制文件
“ab+” (读写)
为读/写打开一个二进制文件
fopen("a1","r");
FILE *fp;fp=fopen("a1","r");
将fopen函数的返回值赋给指针变量fp。
常用下面方法打开一个文件:
if((fp=fopen("file1","r"))==NULL)
{
printf("cannot open this file\n");
exit(0);
}
3) fclose函数(文件的关闭)
关闭 fclose(文件指针);当顺利关闭文件,则返回0值,否则返回EOF(-1).
4) fprintf函数与fscanf函数
fprintf函数、fscanf函数与printf函数、scanf函数相仿都是格式化读写函数。只有一点不同:fprintf和fscanf函数的读写对象不是终端而是磁盘文件。它们的一般调用方式为:
fprintf(文件指针,格式化字符串,输出列表);
fscanf(文件指针,格式化字符串,输入列表);
例如:
fprintf(fp,”%d,%6.2f”,I,t);
它的作用是将变量i与t的值按%d与%6.2f的格式输出到fp指向的文件上。
用fprintf函数和fscanf函数对磁盘文件读写,使用方便,容易理解,但由于在输入时要将ASCII码转换为二进制形式,在输出时又要讲二进制形式转换成字符,花费时间较多。因此,在内存与磁盘频繁交换数据的情况下,最好不要使用fprintf和fscanf函数。
5) fread与fwrite函数
ANSI C标准提出设置两个函数(fread与fwrite),用来读写一个数据块,它们的一般调用形式为
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
其中:
buffer:是一个指针。对于fread来说,它是读入数据的存放地址。对fwrite来说,是要输出的数据的地址。
Size:要读写的字节数。
Count:要进行读写多少个size字节的数据项。
fp:文件型指针。
如果fread与fwrite调用成功,则函数返回值为count的值,即输入输出数据项的完整个数。
常用fread与fwrite函数进行文件的读写操作
例:
11. 冒泡排序与折半排序
1) 冒泡排序
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
冒泡排序算法的运作如下:(从后往前)
a) 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
b) 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
c) 针对所有的元素重复以上的步骤,除了最后一个。
d) 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
实例:
#include<stdio.h>
#defineSIZE8
Void Bubble_Sort(int a[],int n);
Void Bubble_Sort(int a[],int n) //n为数组a的元素个数
{
int i,j,temp;
for(j=0;j<n-1;j++)
for(i=0;i<n-1-j;i++)
{
if(a[i]>a[i+1])//数组元素大小按升序排列
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
}
}
int main()
{
int i_Num[SIZE]={
展开阅读全文