C语言程序设计-第1章 程序设计和C语言
所谓程序,就是一组计算机能识别和执行的指令.
每一条指令使计算机执行特定的操作.一个特定的指令序列,用来完成一定的功能.
计算机的本质是程序的机器,程序和指令是计算机系统中最基本的概念.
计算机能直接识别和接受的二进制代码称为机器指令(machine instruction),机器指令的集合就是该计算机的机器语言(machine language).为了克服机器语言的难学难写难记难检查难修改难推广使用的缺点,人们创造出了符号语言(symbolic language),它用一些英文字母和数字表示一个指令.符号语言又称为符号汇编语言(symbolic assembler language)或汇编语言(assembeler language).
汇编语言也称为低级语言(low level language),现在使用高级语言(high level language).
计算机不能直接识别高级语言程序,需要用一种称为编译程序的软件把用高级语言写的程序(称为源程序,source program)转换为机器指令的程序(称为目标程序,object program),然后让计算机执行机器指令程序,最后得到结果.高级语言的一个语句往往对应金条机器指令.
C:系统描述语言,C++:支持面向对象程序设计的大型语言,Visual Basic:支持面向对象程序设计的语言,Java:适于网络的语言
C语言的特点主要表现在具有多种数据类型(如字符,数值,数组,结构体和指针等).
C语言是一种用途广泛,功能强大,使用灵活的过程性(procedural)编程语言,既可用于编写应用软件,又能用于编写系统软件.
C语言有以下一些主要特点:
(1)语言简洁,紧凑,使用方便,灵活.C语言一共有37个关键字,9种控制语句,程序书写形式自由,主要用小写字母表示,压缩了一切不必要的成分.实际上,C是一个很小的内核语言,只包括极少的与硬件有关的成分,C语言不直接提供输入和输出语句和有关文件操作的语句和动态内存管理的语句等(这些操作是由编译系统所提供的库函数来实现的),C的编译系统 相当简洁.
(2)运算符丰富.包括34种运算符,C语言把括号,赋值和强制类型转换等都作为运算符处理,从而使C语言的运算类型极其丰富,表达式类型多样化.
(3)数据类型丰富.C语言提供的数据类型包括:整形,浮点型,字符型,数据类型,指针类型,结构体类型和共用体类型等,C 99又扩充了复数浮点类型,超微乎其微整型(long long)和布尔类型(bool)等.尤其是指针类型数据,使用十分灵活和多样化,能用来实现各种复杂的数据结构(如链表,树,栈等)的运算.
(4)具有结构化的控制语句(如if…else语句,while语句,do…while语言句,switch语句和for语句).用函数作为程序的模块单位,便于实现程序的模块化.C语言是完全模块化和结构化的语言.
(5)语法限制不太严格,程序设计自由度大.例如,对数组下标越界不进行检查,由程序编写者自己保证程序的正确.对变量的类型使用比较灵活,例如,整形量与字符型数据以及逻辑型数据可以通用.一般的高级语言语法检查比较严,能检查出几乎所有的语法错误,而C语言允许编写者有较大的自由度,因此放宽了语法检查.
(6)C语言允许直接访问物理地址,能进行位(bit)操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作.因此C语言既具有高级语言的功能,又具有低级语言的许多功能,可用来编写系统软件.C语言的这种双重性,使它既是成功的系统描述语言,又是通用程序设计语言.
(7)用C语言编写的程序可移植性好.由于C的编译系统相当简洁,因此很容易移植到新的系统.而且C编译系统在新的系统上运行时,可以直接编译"标准链接库"中的大部分功能,不需要修改源代码,因为标准链接库是用可移植的C语言写的.因此,几乎在所有的计算机系统中都可以使用C语言.
(8)生成目标代码质量高,程序执行效率高.
目前C的主要用途之一是编写"嵌入式系统程序".
例1.1要求在屏幕上输出以下一行信息.
This is a C program.
解题思路:在主函数中用printf函数原样输出以上文字.
#include <stdio.h> //这是编译预处理指令 int main() //定义主函数 { //函数开始的标志 printf("This is a C program.\n"); //输出所指定的一行信息 return 0; //函数执行完毕时返回函数值0 } //函数结束的标志
程序第5行"return 0;"的作用是:当main函数执行结束前将整数0作为函数值,返回到调用函数处.
C 99建议把main函数指定为int型(整型),它要求函数带回一个整数值.在main函数中,在执行的最后设置一个”return 0;”语句,当主函数正常结束时,得到的函数值为0,当执行main函数过程中出现异常或错误时,函数值为一个非0的整数.这个函数值是返回给调用main函数的操作系统的.程序员可以利用操作指令检查main函数的返回值,从而判断main函数是否已正常执行,并据此决定以后的操作.如果在程序中不写"return 0;"语句,有的C编译系统会在目标程序中自动加上这一语句,因此,主函数正常结束时,也能使函数值为0.为使程序规范和可移植性,希望写的程序一律将main函数指定为int型,并在main函数的最后加一个"return 0;"语句.
每一个C语言程序都必须有一个main函数.函数体由花括号{}括起来.本例中printf是C编译系统提供的函数库中的输出函数.\n是换行符,即在输出后,显示屏上的光标位置移到下一行的开头.这个光标位置称为输出的当前位置,即下一个输出的字符出现在此位置上.每个语句最后都有一个分号,表示语句结束.
在使用函数库中的输入输出函数时,编译系统要求程序提供有关此函数的信息(例如对这些输入输出函数的声明和宏的定义,全局量的定义等).stdio.h是系统提供的一个文件名,stdio是"standard input & output"的缩写,文件后缀.h的意思是头文件(header file),因为这些文件都是放在程序各文件模块的开头的.输入输出函数的相关信息已事先放在stdio.h文件中.现在,用#include指令把这些信息调入供使用.
在程序中如要用到标准函数库中的输入输出函数,应该在本文件模块的开头写上下面一行:
#include <stdio.h>
在程序进行预编译处理时将每个注释替换为一个空格,因此在编译时注释部分不产生目标代码,注释对运行不起作用.
(1)以//开始的单行注释.(2)以/*开始,以*/结束的块式注释.
在字符串中的//和/*都不作为注释的开始,而是作为字符串的一部分.
例1.2 求两个整数之和
解题思路:设置3个变量,a和b用来存放两个整数,sum用来存放和数.用赋值运算符"="把相加的结果传送给sum.
#include<stdio.h> int main() { int a,b,sum; a=123; b=456; sum=a+b; printf("sum is %d\n",sum); return 0; }
第8行输出结果,这个printf函数圆括号内有两个参数,一个是双撇号中的内容sum is %d\n,它是输出格式字符串,作用是输出用户希望输出的字符和输出的格式.其中%d是指定的输出格式,d表示用"十进制整数"形式输出.圆括号内第2个参数sum,表示要输出变量sum的值.在执行printf函数时,将sum变量的值(以十进制整数表示)取代双撇号中的%d.现在sum的值是579,所以在输出时,十进制整数579取代了%d.
由于本程序正常运行和结束,因此main函数的返回值为0.
例1.3 求两个整数中的较大者.
#include <stdio.h> #include <stdlib.h> //主函数 int main()//定义主函数 {//主函数体开始 int max(int x,int y);//对被调用函数max的声明 int a,b,c;//定义变量a,b,c scanf("%d,%d",&a,&b);//输入变量a和b的值 c=max(a,b);//调用max函数,将得到的值赋给c printf("max=%d\n",c);//输出c的值 return 0;//返回函数值为0 }//主函数体结束 //求两个整数中的较大者的max函数 int max(int x,int y)//定义max函数,函数值为整形,形式参数x和y为整形 { int z;//max函数中的声明部分,定义本函数中用到的变量z为整形 if(x>y)z=x;//若x>y成立,将x的值赋给变量z else z=y;//否则(即y>x),将y的值赋给变量z. return (z);//将z的值作为max函数值,返回到调用max函数的位置 }
程序中需要对被调用函数max进行声明,在主函数中要调用max函数,而max的定义却在main函数之后,程序的编译是自上而下执行的,在上面调用max时,编译系统无法知道max是什么,因而无法把它作为函数调用处理.为了使编译系统能识别max函数,就要在调用max函数之前用"int max(int x,int y);"对max函数进行"声明",所谓声明,就是告诉编译系统max是什么,以及它的有关信息.
scanf后面括号里包括两个部分内容:一是双撇号中的内容,它指定输入的数据是按什么格式输入."%d"的含义是十进制整数形式.二是输入的数据准备放到那里,即赋给那个变量.
在C语言中"&"是地址符,&a的含义是"变量a的地址",&b是"变量b的地址".执行scanf函数,从键盘读入两个整数,送到变量a和b的地址处,然后把这两个整数分别赋给变量a和b.
c=max(a,b);在调用max时将a和b作为max函数的实际参数,分别传给max函数中的形式参数x和y,然后执行max函数的函数体,使max函数中的z得到一个值,return(z)的作用是把z的值作为max函数值带回到主函数调用max函数的位置,取代max(a,b),然后所这个值赋给变量c.
注意:本例程序中两个函数都有return语句.两个函数都定义为整型,都有函数值,都需要用return语句作为函数指定返回值.但是main函数中的return语句指定的返回值一般为0,而max函数的返回值是求出的最大值,只有通过return语句才能把求出的z值作为函数的值并返回调用它的位置上.在函数中执行的语句并不会自动将值返回调用处,必须用reture语句指定半那个值作为函数值.也不能不加分析地在所有函数的最后都写上"return 0".
1.4.2 C语言程序的结构
(1)一个程序由一个或多个源程序文件组成.
在一个源程序文件中可以包括3个部分: 1.预处理指定.如#include<stdio.h>指令,就是将stdio.h头文件的内容读进来,放在#include指令行,取代#include<stdio.h>. 2.全局声明.即在函数之外进行数据声明.如把”int a,b,sum”放到main函数的前面就是全局声明,在函数外面声明的变量称为全局变量.如果是在程序开头(定义函数之前)声明的变量,则在整个源程序文件范围内有效.在函数中声明的变量是局部变量,只在函数范围内有效. 3.函数定义.每个函数用来实现一定的功能,在调用这些函数时,会完成函数定义中指定的功能.
(2)函数是C程序的主要组成部分.程序的几乎全部工作都是由各个函数分别完成的,函数是C程序的基本单位,每个函数都用来实现一个或几个特定的功能.编写C程序的工作就是编写一个个函数.
一个C语言程序是由一个或多个函数组成的,其中必须包含一个main函数(且只能有一个main函数).
一个程序包含若干个源程序文件,每个源程序文件又包含若干个函数.一个源程序文件就是一个程序模块,即将一个程序分成若干个程序模块.
在进行编译时是以源程序文件为对象进行的.
在程序中被调用的函数,可以是系统提供的库函数(例如printf和scanf函数),也可以是用户根据自己编制设计的函数.不同编译系统所提供的库函数个数和功能是不完全相同的.
(3)一个函数包括两个部分. 1.函数首部.即函数的第一行,包括函数名,函数类型,函数属性(形式参数)名,参数类型.
一个函数名后面必须跟一对圆括号,括号内写函数的参数名及其类型.如果函数没有参数,可以在括号中写void,也可以是空括号.
如 int main(void) 或 int main()
2.函数体.即函数首部下面的花括号内的部分.如果在一个函数中包括有多层花括号,则最外层的一对花括号是函数体的范围.
函数体一般包括以下两个部分:
声明部分.声明部分包括:定义在本函数中所用到的变量,对本函数所调用函数进行声明.
执行部分:由若干个语句组成,指定在函数中所进行的操作.
(4)程序总是从main函数开始执行的,而不论main函数在整个程序中的位置如何.
(5)程序中对计算机的操作是由函数中的C语句完成的.如赋值,输入输出数据的操作都是由相应的C语句实现的.
(6)在每个数据声明和语句的最后必须有一个分号.
(7)C语言本身不提供输入输出语句.输入和输出的操作是由库函数scanf和printf等函数来完成的.C对输入输出实行"函数化".由于输入输出操作涉及具体的计算机设备,把输入输出操作用库函数实现,就可以使C语言本身的规模较小,编译程序简单,很容易在各种机器上实现,程序具有可移植性.
(8)程序应当包含注释.
1.5 运行C程序的步骤与方法
计算机不能直接识别和执行用高级语言写的指令,必须编译程序(也称为编译器)把C源程序翻译成二进制形式的目标程序,然后再将该目标程序与系统的函数库以及其他目标程序连接起来,形成可执行的目标程序 .
(1)上机输入和编辑源程序.
(2)对源程序中进行编译,先用C编译系统提供的"预处理器"对程序中的预处理指令进行编译预处理.
编译的作用首先是对源程序进行检查,判定它有无语法错误,若有,发出"出错信息",修改再重新编译,直到无语法错误时才把源程序软的为二进制形式的目标程序(在C++中后缀为.obj).
(3)进行连接处理.编译是以源程序文件为对象的,一次编译只能得到与一个源程序文件 相对应的目标文件 (也称为目标模块),它只是整个程序的一部分.
必须把所有的编译后得到的目标模块连接装配起来,再与函数库连接成一个整体,生成一个可供计算机执行的目标程序,称为可执行程序(executive program).在C++中后缀为.exe.
(4)运行可执行程序,得到运行结果.
如图,其中实线表示操作流程,虚线表示文件的输入输出.
例如,编辑后得到一个源程序文件f.c,然后在进行编译时再将源程序文件f.c输入,经过编译得到目标程序文件f.obj,再将所有目标模块输入计算机,与系统提供的库函数等进行连接,得到可执行的目标程序f.exe,最后把f.exe输入计算机,并使之运行,得到结果.
1.6 程序设计的任务
从确定问题到最后完成任务,一般经历以下几个工作阶段:
1)问题分析.2)设计算法.3)编写程序.4)对源程序进行编辑,编译和连接.5)运行程序,分析结果.6)编写程序文档.
试题:
1.编写一个C程序,输入a,b,c三个值,输出其中最大者.
#include <stdio.h> #include <stdlib.h> int main() { int a,b,c,max; printf("please input a,b,c:\n"); scanf("%d,%d,%d,",&a,&b,&c); max=a; if(max<b) max=b; if(max<c) max=c; printf("the largest number is %d\n",max); return 0; }