360 likes | 487 Views
第二章 C 语言语法元素概览. 本章对 C 语言的 基本语法元素 做简要概览,包括 变量与常量 、 算术运算 、 控制流 、 函数 、 数组 、 基本输入输出 等,让读者对 C 语言有一个整体的感性认识,能模仿编写简单的小程序。但是,本章我们并不想完整地或很精确地对 C 语言进行介绍。. 函数 的离散值表. 2.1 变量与表达式. [ 例 2-1] #include <stdio.h> #include <math.h> /* 打印一个周期内,三角函数的离散值表* / int main() { int x; double y;
E N D
第二章 C语言语法元素概览 本章对C语言的基本语法元素做简要概览,包括变量与常量、算术运算、控制流、函数、数组、基本输入输出等,让读者对C语言有一个整体的感性认识,能模仿编写简单的小程序。但是,本章我们并不想完整地或很精确地对C语言进行介绍。
函数 的离散值表 2.1 变量与表达式 [例2-1] #include <stdio.h> #include <math.h> /* 打印一个周期内,三角函数的离散值表*/ int main() { int x; double y; int start, end, step; start = 0; /* 角度下限*/ end = 360 ; /* 角度上限*/ step = 30; /* 步长*/ x = start; while (x <= end) { y = sin(x*3.1415926/180); printf("%d\t\t%f\n", x, y); printf("\n"); x = x + step; } return 0; }
[例2-1]的功能是打印出常见三角函数 在一个周期(0˚- 360 ˚)内变化,其对应的函数离散值表,如图2-1所示。我们可以根据该表拟合出三角函数的三角曲线。 分析:上述程序的第一、二行: #include <stdio.h> #include <math.h> 叫做编译预处理命令,用于告诉编译程序在本程序中包含标准输入输出库以及其他库函数的有关信息。许多C源程序的开始处都包含相似的行。
注释行的下面是main函数,在所有C语言的程序中,必须有且仅有一个main函数,所有程序的运行都是从main函数开始,到main结束,其中“main”是函数的名称,称为主函数。注释行的下面是main函数,在所有C语言的程序中,必须有且仅有一个main函数,所有程序的运行都是从main函数开始,到main结束,其中“main”是函数的名称,称为主函数。 • 为了实现程序的功能,我们必须定义一些变量来存储数据,在C语言中,所有变量都必须先定义后使用,定义用于声明变量的性质,它由一个类型名与若干所要定义的变量名组成,例如: int x; double y; 其中,“int”,“double”是系统已经定义好的关键字。所谓关键字是指系统事先定义好的代表一些特殊含义的名称。 “int”代表整数的类型,“double”代表浮点数类型。
接下来要赋予这些变量具体的数据,在程序[2-1]中,以 4个赋值语句(也可称为赋值表达式)开始,为变量设置初值。 start = 0; end = 360 ; step = 30; x = start; 总体来看,C语言中的表达式事实上就是常量和变量通过各种C语言允许的运算符号进行连接。由例子程序可见,C语言的语句必须以“;”结束。
2.2 分支语句 2.2.1 if语句 [例2-2](程序见于课本P9)程序的功能是统计C语言 程序设计课程期末考试各成绩段的人数,统计分成 下述几档: 0~59 不及格 60~69 及格 70~79 中等 80-89 良好 90-99 优秀 100 满分 要求输出各成绩段的具体人数 。
在C语言程序中经常会采用如下模式来表示多路判定:在C语言程序中经常会采用如下模式来表示多路判定: if (条件1) 语句1; else if (条件2) 语句2; ⋯ ⋯ else 语句n;
这就是C语言中的if语句。在if语句中,各个条件从前往后依次求值,直到满足某个条件,这时执行对应的语句部分,语句执行完成后,整个if构结束。注意,其中语句1~n中的任何语句都可以是括在花括号中的若干个语句。如果其中没有一个条件满足,那么就执行位于最后一个else之后的语句。如果没有最后一个else及对应的语句,那么这个if构造就不执行任何动作。在第一个if与最后一个else之间可以有0个或多个这就是C语言中的if语句。在if语句中,各个条件从前往后依次求值,直到满足某个条件,这时执行对应的语句部分,语句执行完成后,整个if构结束。注意,其中语句1~n中的任何语句都可以是括在花括号中的若干个语句。如果其中没有一个条件满足,那么就执行位于最后一个else之后的语句。如果没有最后一个else及对应的语句,那么这个if构造就不执行任何动作。在第一个if与最后一个else之间可以有0个或多个 else if (条件) 语句;
2.2.1 switch语句 C语言中的多路分支,也可以用switch语句完成。 switch语句的通用用法如下: switch(表达式) { case 表达式1:语句1; case 表达式2:语句2; …. case 表达式n:语句n; default: 语句n+1; }
2.3 循环语句 2.3.1 while循环语句 以[例2-1]中的以下语句为例: while (x <= end) { . . . } while循环语句的执行步骤如下:首先测试圆括号中的条件。如果条件为真(x小于等于end),则执行循环体(括在花括号中的三个语句)。然后再重新测试该条件,如果为真(条件仍然成立),则再次执行该循环体。当该条件测试为假(x大于end)时,循环结束,继续执行跟在该循环语句之后的下一个语句。
while语句的循环体可以是用花括号括住的一个或多个语句,也可以是不用花括号括住的单个语句,例如:while语句的循环体可以是用花括号括住的一个或多个语句,也可以是不用花括号括住的单个语句,例如: 在这两种情况下,我们总是把由while控制的语句向里缩入一个制表位(在书中以四个空格表示),这样就可以很容易地看出循环语句中包含哪些语句。 while (i < j) i = 2 * i;
2.3.2 for循环语句 C语言提供了多种循环控制语句,除了上一小节提到的while循环外,用得比较多的还有for循环。我们将[例2-1](打印一个周期内三角函数离散值表)中的循环控制用for语句来实现,改写为[例2-4],描述如下:
[例2-4] #include <stdio.h> #include <math.h> /* 打印一个周期内,三角函数的离散值表*/ int main() { int x; double y; for (x = 0; x <= 360; x=x+30) { y = sin(x*3.1415926/180); printf("%d\t\t%f\n", x, y); printf("\n"); } return 0; }
例子程序中的for语句也是一种循环语句,是while语句的推广。如果将其与前面介绍的while语句比较,就会发现其操作要更清楚一些。for循环的通用语法如下:例子程序中的for语句也是一种循环语句,是while语句的推广。如果将其与前面介绍的while语句比较,就会发现其操作要更清楚一些。for循环的通用语法如下: 在圆括号内共包含三个部分,它们之间用分号隔开。 for(表达式1; 表达式2; 表达式3) 循环体语句;
示例程序中的表达式1为x = 0是初始化部分,仅在进入循环前执行一次。然后计算表示式2,这里表达式2为x <= 360,用于控制循环的条件测试部分:这个条件要进行求值,如果所求得的值为真,那么就执行循环体。循环体执行完,再执行表达式3:x = x + 30加步长,并再次对条件表达式2求值。如果求得的表达式为真,继续执行循环体,一旦求得的条件值为假,那么就终止循环的执行。像while语句一样,for循环语句的循环体可以是单个语句,也可以是用花括号括住的一组语句。初始化部分(表达式1)、条件部分(表达式2)与加步长部分(表达式3)均可以是任何表达式。
2.4 符号常量 [例2-4]中的程序把3.1415925、360、30等常数直接写在了程序中,这并不是一种好的习惯,原因有: 1)这些纯粹的数没有任何的表征意义,几乎不能给以后可能要阅读该程序的人提供什么信息; 2)使程序的修改变得困难,因为如果要将终止温度和步长修改的话,必须修改程序中的所有的360和30。
解决上述问题的一种方法是赋予它们有意义的名字。#define指令就用于把符号名字(或称为符号常量)定义为一特定的字符串:解决上述问题的一种方法是赋予它们有意义的名字。#define指令就用于把符号名字(或称为符号常量)定义为一特定的字符串: 此后,所有在程序中出现的在# define中定义的名字,如果该名字既没有用引号括起来,也不是其他名字的一部分,都用所对应的替换文本替换。这里的名字与普通变量名有相同的形式:它们都是以字母打头的字母或数字序列。替换文本可以是任何字符序列,而不仅限于数字。 #define 名字 替换文本
[例2-5] #include <stdio.h> #include <math.h> /* 打印一个周期内,三角函数的离散值表*/ #define PI 3.1415926 #define START 0 #define END 360 #define STEP 30 int main() { int x; double y; for (x = START; x <= END; x=x+STEP) { y = sin(x*PI/180); printf("%d\t\t%f\n", x, y); printf("\n"); } return 0; }
上例是用符号常量打印三角函数的离散值表。 这里,START、END、PI与STEP称为符号常量,而不是变量,故不需要出现在定义中这样如果需要提高函数曲线的拟合精度就只需要缩小STEP并给定更精确的PI值即可。。符号常量名通常用大写字母拼写,这样就可以很容易与用小写字母拼写的变量名相区别。注意:# define也是一条编译预处理的命令,因此该行的末尾是没有分号的。
2.5 输入输出 例[2-6]用scanf函数实现的三角函数离散值表 #include <stdio.h> #include <math.h> /* 打印一个周期内,三角函数的离散值表*/ #define PI 3.1415926 int main() { int x; double y; int start,end,step; printf("请输入周期起始点、终止点和步长\n"); scanf("%d%d%d", &start, &end, &step); for (x = start; x <= end; x=x+step) { y = sin(x*PI/180); printf("%d\t\t%f\n", x, y); printf("\n"); } return 0; }
其中行 就是负责从键盘输入数据的函数,其使用方法与printf函数基本相同,不同点主要体现在第二个参数以后的参数,其前面都有符号“&”,表示取这些变量的地址。 scanf("%d%d%d", &start, &end, &step);
2.6 数组 在C语言中,当我们要定义一组类型相同的数据的时候,可以通过定义数组的方式来定义这些元素,通过数组名和下标来引用某一个元素,数组的下标总是从0开始,在[例2-2]中,这个数组的6个元素分别是grade [0]、grade[1]、⋯、grade[5]。这一点在分别用于初始化和打印数组的两个for循环语句中得到了反映。 C语言中数组不能当作一个整体来访问,必须通过下标依次访问,每个元素基本等价于一个同类型的普通变量。下标可以是任何整数表达式,包括整数变量(如i)与整数常量。
2.7 函数 C语言的程序是由一个个的函数构成的,除了有且必须有的main主函数以外,用户也可以自己定义函数。此外,C语言的编译系统还提供了一些库函数。 在上述的例子中,我们所使用的函数(如printf、getchar与putchar等)都是函数库为我们提供的。接下来,我们看看怎样编写自己的函数。
我们通过编写一个求阶乘的函数factorial ( n) 来说明定义函数的方法。 函数定义的一般形式为: 返回值类型 函数名(可能有的参数定义) { 申明和定义序列 语句序列 }
例[2-8] #include <stdio.h> int factorial (int n); /* 测试factorial 函数*/ main ( ) { int i; for ( i =0; i < 10; ++i ) printf("%d的阶乘是:%d\n", i, factorial(i) ); return 0; } /* factorial : n的阶乘, n >=0 */ int factorial (int n) { int i, p; p = 1; for (i = 1; i <= n; ++i ) p = p * i; return p; }
在我们的例子中,factorial函数定义的第一行:int factorial(int n),申明参数的类型与名字以及该函数返回的结果的类型。factorial的参数名只能在factorial内部使用,在其他函数中不可见:在其他函数中可以使用与之相同的参数名而不会发生冲突。一般而言,把在函数定义中用圆括号括住的表中命名的变量叫做形式化参数。 factorial函数计算得到的值由return语句返回给main函数。关键词return可以后跟任何表达式: 函数不一定都返回一个值。 return 表达式;
printf("%d的阶乘是:%d\n", i, factorial(i) ); 对函数的使用,叫函数调用。main主程序在如下命令行中对factorial函数进行了调用: 调用factorial函数时,传送了一个变量i给它,一般把函数调用中与参数对应的值或变量叫做实际参数,如变量i,由实际参数传递值给形式参数。而factorial函数则在调用执行完时返回一个要按一定格式打印的整数。在表达式中, factorial(i)就像i一样是一个整数。 注意: 这个函数不是一个实用的阶乘函数,它只能用于处理比较小的整数的阶乘,因为如果要求阶乘的整数比较大,使用该方法很容易越界,导致程序没办法获得正确的结果。希望读者读完整本书以后能为该问题找到正确的解决方法。
2.8 算法 2.8.1 算法概念 程序设计的关键之一,是解题的方法与步骤,是算法。学习高级语言的重点和难点之一就是掌握分析问题、解决问题的方法,锻炼分析、分解,最终归纳整理出算法的能力。与之相对应,具体语言,如C语言的语法是工具,是算法的一个具体实现。所以在高级语言的学习中,一方面应熟练掌握该语言的语法,因为它是算法实现的基础,另一方面必须认识到算法的重要性,加强思维训练,寻找问题的最优解决方法,以写出高质量的程序。
[例2-8]设有一物体从高空坠下,每次落地后都反弹到原高度2/3差一米的地方,现在测得第9次反弹后的高度为2米,请编程求出该物体从多高的地方开始下坠。[例2-8]设有一物体从高空坠下,每次落地后都反弹到原高度2/3差一米的地方,现在测得第9次反弹后的高度为2米,请编程求出该物体从多高的地方开始下坠。 问题分析: 此题粗看起来有些无从着手的感觉,但我们仔细分析物体的运动规律后,能找到一些蛛丝马迹。假设物体坠落时的高度为:,设第一次到第九次反弹的高度依次为:,现在只有是已知的,但我们从物体的反弹规律能找出各反弹高度之间的关系: 可进一步转换为: 这就是此题的数学模型。
算法设计: 1) ; {第9次物体反弹的高度} 。{反弹次数初值为9} 2) 。{计算上次的反弹高度} 3) 。{将上次的反弹高度作为下一次计算的初值} 4)i=i-1。 5)若i > = 0,转2 )。 6)输出 的值。 其中2)~5)步为循环,递推计算各次反弹的高度。
算法设计的具体方法: 1)弄清如果由人来做,解决问题的基本步骤。 2)对这些步骤进行归纳整理,抽象出数学模型。 3)对其中的重复步骤,通过使用相同变量等方式求得形式的统一,然后简练地用循环解决。
算法设计思考题 • Hanoi问题 • Bubble Sort
2.8.2 流程图与算法描述 描述算法的工具有多种,其中使用最广泛的是流程图,流程图又称程序框图。流程图是一种传统的算法表示法,它利用几何图形的框来代表各种不同性质的操作,用流程线来指示算法的执行方向。由于它简单直观,所以应用广泛,它部分消除了不同国籍程序员之间的交流障碍。