资源简介 (共42张PPT)编程语言基础-C语言(第5版)主编 陈琳高等教育出版社第1章 C 语 言 概 述1.1 C语言的产生和发展1.2 C语言的特点1.3 简单的C程序介绍1.4 C 程序上机步骤1.5 Dev-c++ 介绍1.1 C语言的产生和发展机器语言:机器指令实际上是由二进制数1和0组成的有限序列。汇编语言:用符号来替代二进制序列,易于理解。高级语言:高级语言是一种接近自然语言的编程语言。C语言是1972年由美国的Dennis Ritchie设计发明的, 并首次在UNIX操作系统的DEC PDP-11计算机上使用。1.2 C语言的特点简洁紧凑、灵活方便。运算符丰富。数据类型丰富。C语言是结构化语言。语法限制不太严格、程序设计自由度大。C语言允许直接访问物理地址,可以直接对硬件进行操作。C语言程序生成代码质量高,程序执行效率高。C语言适用范围大,可移植性好。1.3 简单的C程序介绍例1-1: 在屏幕上输出一行信息:Hello, World!程序如下:#include main( ) // 主函数main{printf("Hello, World!"); // 输出Hello, World!getch(); // 按任意键结束}例1-2:求出两个整数的和并输出。int sum( int x, int y ) // 子函数sum{int z;z = x + y;return z;}main( ) // 主函数main{int a,b,c;scanf("%d,%d", &a, &b ); // 输入2个整数c = sum( a, b ); // 计算2个整数之和printf("sum = %d \n", c); // 输出结果getch();}输出结果:5,6sum = 11C程序特点一个C程序是由若干函数构成的。一个C程序总是从main函数开始执行。每条语句均以分号结束。注释行从”//” 开始到本行结束, 连续若干注释行可以以”/*”开始,并以”*/”结束。每行可以有多条语句,一条语句也可以分写在多行上。1.4 C 程序上机步骤开始编辑编译有错?连接执行结果正确?结束源 程序a.c程序a.obj库函数和其他目标程序可执行目标程序a.exe有无正确不正确图 1-1目标常见错误解决语句末尾遗漏了分号:修改错误时不要过分依赖错误行号,应根据错误原因来分析修改。“非法字符”错误中文显示成乱码1.5 Dev-c++ 介绍Dev-c++是一个Windows环境下C&C++开发工具,它是一款自由软件,遵守GPL协议。Dev-c++是一个非常实用的编程软件,多款著名软件均由它编写而成,它在C的基础上,增强了逻辑性。它即可以运行C源程序,也可运行C++源程序,区别在于源程序的扩展名不同,若要运行C源程序,需将文件保存为.c文件。1.5.1 Dev-c++ 5.10 界面1.5.2 Dev-c++ 5.10英文主菜单和中文主菜单1.5.3 Dev-c++部分按钮中文说明1.5.4 在Dev-c++ 上运行一个C程序的基本步骤1. 新建 或打开 一个文件2. 在编辑窗输入或修改C程序#include < stdio.h >#include < process.h >main( ){system ( "cls" );printf ( "Hello \n" );// getch ( );}3. 保存C源程序若本文件是首次执行保存命令,其“保存类型”应选择“.c”4. 编译、链接、执行C程序1.6 Microsoft Visual C++ 2010 学习版介绍Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)微软公司的C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI等编程语言。学习版,是对Visual C++ 2010 Express版本的中文习惯称呼,express版表示这是精简版,里面有些功能没有,我们暂时也用不到,但体积更小,启动速度更快。因为是免费的,它主要用于教学等非商业用途。安装Express需要2G左右的容量。1.进入Microsoft Visual C++ 2010 学习版界面在开始菜单中单击打开后出现以下界面,左边是解决方案资源管理器,右边是起始页2.创建或打开一个项目方法1:单击起始页上的方法2:单击主菜单[文件]下的工具方法3:选择主菜单项[文件]->[新建]->[项目]接着出现以下对话框:左边选择[Win32],右边选择[Win32控制台应用程序]。 在下方 <输入名称> 处输入项目名称,比如”pj1”;再单击 [浏览] ,选择项目所在的文件夹,比如 ”E:\cxiangmu”,当然该文件夹应该事先建好确定后进入”Win32应用程序向导”对话框,单击”下一步”,进入”应用程序设置”在”附加选项”中对”空项目”打勾,单击”完成”3.在项目中添加一个C源程序在左边[解决方案资源管理器]中,右键单击[源文件],选择[添加],再选择[新建项]然后出现以下对话框,在右边选择 ”C++ 文件(.cpp)”在 <输入名称>处输入C源文件名,如 ”welcom.c”,注意: 文件名一定要加后缀 ”.c”, 否则将创建的是c++源文件,单击添加按钮,返回主界面。在主界面右边输入C源文件内容#include #include main( ){printf(" 欢迎使用[Microsoft Visual C++ 2010 学习版]\n");getch( );}单击 ”自动调试” 按钮或 选择菜单”调试” -> “自动调试” 或 按F5,出现运行结果对话框如果程序末尾中没有 ”getch();” 语句,调试时可以按 ctrl + F5 ,否则运行结果会一闪而过;使用”getch();”,最好在文件开头增加一条说明 ” #include ” 。4.在项目中移除或删除一个源文件由于一个项目只能有一个main函数,因此如果还想调试其他C程序,可以另外建立新的项目,如果觉得麻烦,可以在本项目中将源文件 ”移除” 或 ”删除”。如果选择”移除”, 以后可以再 ”添加”,而 ”删除” 是永久删除。1.7 宏定义和文件包含宏定义和文件包含都属于编译预处理命令,以‘#’开头,结尾部分不要加分号(除非有特别需要)。编译预处理命令的作用不是实现程序的功能,而是给C语言编译系统提供信息,通知C编译器在对源程序进行编译之前应该做哪些预处理工作。1.宏定义不带参数的宏定义命令的一般形式:#define 标识符 字符串定义中的“标识符”为用户定义标识符,称为宏名,宏名一般用大写字母书写。在预编译时,将程序中出现的宏名均替换成“字符串”的内容,这一过程称为宏展开。 例如:#define PI 3.1415926则程序中凡遇PI均用3.1415926替代如: 2* PI*r 宏展开为:2*3.1415926*r。例1-3 求梯形的面积。说明:梯形的面积为上底加下底乘高除2。设梯形的上底、下底和高分别用a、b和h表示,则梯形的面积等于 (a+b)*h/2.0。程序和运行结果如下:#include #include #define S(a,b,h) (a+b)*h/2.0main( ){double y;y=S( 2, 3, 5 );printf ("梯形面积=%f \n", y );getch( );}2.文件包含文件包含的作用是将一个源程序文件包含到另一个源程序文件中,它以 ”#include” 开头例如,例1-3的开头两行就是两个文件包含命令。格式一: #include <文件名>C编译系统将在系统指定的路径下搜索尖括号中的文件,一般适用于包含库函数的头文件格式二: #include “文件名”系统首先会在用户当前的目录中搜索双引号中的文件,如果找不到,再按系统指定的路径下搜索,一般适用于包含用户文件的头文件。例1-4 创建一个头文件prt.h,用来输出一个整数;main函数所在文件ex1-4.c包含该头文件操作步骤:在解决方案资源管理器中,右键单击“头文件”,选择“添加”,”新建项”,选择“头文件(.h)”,输入名称prt,单击 [添加] 返回主菜单,输入prt.h内容。#define INT(a) printf("%d ", a)在“源文件”处添加主函数文件ex1-4.c#include #include #include "prt.h"main( ){INT(2);INT(3);INT(5);getch( );}按F5运行程序,运行结果如下:本章小结本章介绍了C语言的主要特点、C程序结构、C程序编写方法以及在Dev-C++平台上和Microsoft Visual C++ 2010平台上C程序的运行步骤。读者可以根据自己的喜好和条件选择合适的软件编写和调试程序。本章介绍了C语言的主要特点、结构、编写规则和开发过程。要注意以下几个问题:1.编写程序应该规范,建立良好的程序设计风格。2.一个C语言程序由一个至多个函数组成,其中有且仅有一个main( ) 函数。。3.一个函数由若干语句组成,每条语句末尾必有分号,由”{}”括起来的多条语句,构成一条复合语句。。4.熟练掌握源程序的编辑、保存、编译、连接及运行的操作方法,了解程序调试的基本概念。(共61张PPT)第2章 基本数据类型与简单程序设计2.1 C语言的基本数据类型2.1.1 常用标准数据类型说明:在Dev-C++或visual c中,int 同long,在winTC中,int 等同short。int之前可加上类型修饰符long(长型),即long int,在Dev C和VC2010中int等同于long int 或long;char和int之前还可加上类型修饰符signed(有符号型)和unsigned(无符号型);double之前可加上long。这些数据类型的准确长度取决于具体的编译器,故程序员在编程时最好不要假设它们具有固定的长度。若想了解某个类型所占字节数,可使用运算符sizeof格式为:sizeof(类型标识符)2.2 常量和变量2.2.1 常量和符号常量在程序的运行过程中,其值保持不变的量称为常量。#define PI 3.1415926此后,凡在文件中出现的PI均可用3.1415926来代替。2.2.2 整型常量除了我们比较熟悉的整型常量如: 100、0、-256之外, C语言中还有其他形式的整型常量。例 子 说 明-1234 十进制整型常量 (包含数字0~9)01234 八进制整型常量(以0开头,包含数字0~7)0x1234 十六进制整型常量(以0x或0X开头,包含数字0~9、字母A~F或a~f)0L long型十进制整型常量(以l或L结尾)例如:0235等于十进制数157,即2×82 +3×81 +5×80 =157。-0X23等于十进制数 -35。任何类型的数据在计算机中都是以二进制补码形式存储的。正数的补码等于其原码,而负数的补码等于其原码的反码+1。例如:0000 0000 0101 0011 表示 831111 1111 1010 1101 表示 -830000 0000 0000 0000 0000 0000 0101 0011 表示 83L1111 1111 1111 1111 1111 1111 1010 1101 表示 -83L2.2.3 浮点型常量C语言中的浮点类型主要分为单精度和双精度浮点型两种。以下是合法的十进制浮点数表示:1234.56、-1.2、0.0、.5、6.、1000000000.0。浮点数还可采用科学表示法,以下是合法的科学浮点数表示:1.23456e2、 0.345E-3、-765e12、-.5E-8、6.e-7、1.0e10。出现在字母e(或E)之前的小数点,其左边和右边应有一位数字在字母e(或E)之后必须是整数。1.34E1.2、.e2 均是非法的浮点数。2.2.4 字符型数据C的字符常量是用单引号(即撇号)括起来的一个字符。如 '*'、'a'、'A'、'&'、'!' 等都是字符常量。注意,'a' 和 'A' 是不同的字符常量。字符数据存放在内存时,并不是字符本身,而是字符的代码,称之为ASCII码。部分字符对应的ASCII码字符 回车 空格 * + 0 1 2 3 …… 9ASCII码 13 32 42 43 48 49 50 51 …… 57字符 A B C …… Z a b c …… zASCII码 65 66 67 …… 90 97 98 99 …… 122常用的转义字符有:‘\n’ 换行符 (将当前位置移到下一行开头)‘\t’ 水平制表符 (跳到下一个位置)‘\b’ 退格‘\r’ 回车 (将当前位置移到本行开头)‘\f’ 走纸‘\\’ 反斜杠’\’‘\’’ 单引号’‘\”’ 双引号转义字符看起来是两个字符,实际上只能算一个字符。也可以使用 "\" 加上一个1~3位的8进制数或 "\x" 加上一个1~2位的16进制数表示的ASCII码值来表示转义字符,例如:‘\0’ 表示 空字符'\33' 或 '\033' 表示ESC(27)'\07' 表示响铃'\x0A' 表示换行(10)。2.2.5 变量在程序的运行过程中,值可以改变的量称为变量。每个变量都有一个名字,称为变量名。每个变量均必须进行变量说明,指明变量的类型如: int k=50;变量名和符号常量名的命名方法相同,都是用标识符表示。标识符就是一个名字,其命名必须按照一定的规则进行,只能由字母、数字和下划线组成,且第一个字符必须为字母或下划线,不允许使用数字。如下面是合法的标识符。Class_1, _abc1, id, a1b2, sum, total下面是不合法的标识符:a b //标识符不能含空格符1a //标识符不能以数字打头#abc //标识符不能使用#xyz-1//标识符不要把减号“-”和下划线“_”混淆注意:大写字符和小写字符被认为是两个不同的字符。如: a1和A1是两个不同的变量。变量和符号常量的不同之处在于:变量的值可以改变,而符号常量则不行。例2-1int i, j, k;char c1, c2;上面两行语句定义了3个int型变量i, j, k和2个字符型变量c1、c2例2-2float x1, x2; //定义2个单精度浮点型变量double z1, z2; //定义2个双精度变量float x;double y;x = 123456.789; //给变量赋初值y = 1.23456789E5;2.3 赋值语句所谓赋值,就是将一个数据存入一个连续的具有若干存储单元的存储空间中,该存储空间有一个名字,就是前面介绍的变量名。对一个变量进行定义后,这个变量如果没有进行赋值,它的值是不确定的。2.3.1 赋值语句的格式与功能一般形式:变量 = 表达式;功能:首先计算赋值号“=”右边表达式的值,然后将结果值送给赋值号“=”左边的变量。例如:g = 9.8;g = 10 + 20 - 9;“=”不是等号,而是赋值号。例2-1char c1, c2;c1 = 'a';c2 = 'b';上面定义了2个字符型变量 c1, c2,一个字符型变量可存放一个字符。将一个字符常量存放到一个字符变量中,实际上并不是把该字符本身放到内存中,而是将该字符的相应的ASCII码存放内存单元中。C语言字符型数据与整型数据之间可以通用。例2-2#include main( ){char c1 = 'a', c2;int k;k = c1; //将字符型变量c1赋给整型变量kc2 = 97; //将整数97赋给字符型变量c2printf("%c, %c, %d", c1, c2, c1);//字符变量既可按字符形式输出,亦可按整型输出printf("\n %d, %c", k, k );//整型变量既可按整型形式输出,亦可按字符型输出getch();}运行结果:a, a, 9797, a例2-3 将小写字母转换成大写字母。#include main( ){ char c1,c2;int i, j;c1 = 'a';c2 = c1-32; // c2 = 'A'printf("%c, %c", c1, c2 );getch();}运行结果:a, A2.3.2 赋值语句中的类型转换“=”左边变量与右边表达式的数据类型不一致时,C编译系统会自动实现数据类型的转换。转换的原则是,将赋值号右边的表达式值的类型转换成与左边变量相同的类型后再赋值。例如:int a; long b; char c;a = b;// long型变量b的值变换成int型后再赋给ab = a;// int型变量a的值变换成long型后再赋给bb = a + c;// int型a + c的值变换成 long型后再赋给 b当右边表达式值的类型比左边变量的类型要长时,会对右边的数据进行截取,仅取出与左边变量类型相同的长度,这意味着,会丢失高位字节或高位字。例2-4main( ){ int a =350, b;char c ;c = a;b = c;printf("%d, %d, %d ", a, c, b );getch( );}运行结果为:350, 94, 942.4 数据的输出2.4.1 字符输出函数 putchar( )函数putchar( ) 的功能是把一字节的代码值所代表的字符输出到显示器上。常用格式如下:putchar( c );其中参数C可以是字符常量、变量或字符表达式。例2-5 字符输出函数putchar( )的功能#include main( ){ char c ='A';putchar( c ); //输出字符Aputchar('\n'); //输出换行符putchar('#'); //输出字符#putchar('\n'); //输出换行符getch( );}2.4.2 格式化输出函数printf( )格式化输出函数是按指定的格式完成输出过程。一般使用形式如下:printf("输出格式串", 表达式表 );其中,输出格式串包含“格式符”或非格式符。“格式符”以%开头后面跟一个字母。格式符见表2-4。格式符 功能说明%c 按字符形式输出%d 按十进制整数形式输出%o 按八进制整数形式输出%x 按十六进制整数形式输出%f 按浮点形式输出,默认6位小数%m.nf 按浮点形式输出,显示宽度不小于m,n位小数printf( ) 函数的功能是凡遇格式符,就将对应的表达式的值按指定格式输出到显示器上,凡遇非格式符,则原样输出。输出格式串中的转换说明符与表达式的个数必须相同,它们按各自的先后顺序—一对应,如图2-2所示。例如:a =100;b =200;printf("%d + %d = %d \n", a, b, a + b );输出结果为:100 +200 =300(换行)例2-8#include main( ){float x1 = 123.5678, x2 = -4567.789;printf("x1 = %f, x2 = %f \n", x1, x2 );printf("x1 = %8.2f \t x2 = %8.2f \n", x1, x2 );getch( ); //按任意键printf("%c%3c \n", '*', '*' );printf("%d%3d \n", 11, 22 );}运行结果为x1 = 123.567802, x2 = -4567.789062x1= 123.57 x2 = -4567.79 (按任意键后显示)* *11 222.5 数据的输入数据的输入,一般是以键盘为处理对象的,从键盘接受字符和数据。字符输入函数getchar( ) 和输出函数putchar( ),是以一个字节的字符代码为单位来完成输入输出过程的。在程序中使用这两个函数时,要求在程序开头包含头文件stdio.h。即#include 2.5.1 字符输入函数 getchar( )功能是接收从键盘上输入的字符。在程序中使用这个函数输入字符时,可以用另一个变量接收读取的字符,例如:c = getchar( );例2-9 字符输入函数getchar( )的功能#include main( ){ char ch;ch = getchar( );printf("ch = %c, ch = %d \n", ch, ch ); getch( );}当执行到语句:ch = getchar( ); 时,计算机就会等待用户击键(等待输入)。2.5.2 格式化输入函数 scanf( )scanf( ) 函数的功能是按指定的格式从键盘接受输入信息。一般使用格式如下:scanf(“格式串”,地址表 );“格式串”中既可以含格式符,也可以含非格式符。输入时,凡遇非格式符,要求原样输入,凡遇格式符,按指定格式输入数据。输入格式符表格式符 功能说明%c 接收一个字符型数据%d 接收一个整数型数据,直到遇到空格、或回车符%f 接收一个浮点型数据例2-10 从键盘上输入直径d的值,然后计算圆的面积area和周长len。# define PI 3.1415926main( ){float d, area, len, r;printf("请输入直径的值:");scanf("%f ", &d );r = d / 2;area = PI * r * r;len =2 * PI * r;printf("半径r = %f, 面积S = %f, 周长L = %f \n", r, area, len );}2.6 运算符和表达式将运算符和运算对象按一定规则连接起来就成为表达式.2.6.1 算术运算符运算符 运 算 优先级 例 子( ) 圆括号 1 5 /(1 – 3 )* 乘法 3 7 * 3 = 21/ 除法 3 7 / 3 .0 = 2.3333337 / 3 = 2% 模除 3 7 % 3 = 1+ 加法 4 7 + 3 = 10- 减法 4 7 - 3 = 4说明:1. 模除运算是两个整数相除后取余数;要求 % 两边必须是整型数据。2. 若算术运算符两边均为整数,则结果仍为整数。例: 7 / 3 = 2 1 / 2 = 03. 若参加运算的两个数中有一个数为实数,则结果为double型。4. 每个运算符都有一个优先级。如乘除的优先级高于加减。在表达式求值时,按运算符的优先级高低次序进行。如先乘除,后加减。( )可改变运算次序。若在一个运算符对象两侧的运算符的优先级相同,则按规定的“结合方向”处理。有些运算符的结合方向为“从右到左”,即“右结合性”。2.6.2 自增、自减运算符——“右结合性”,优先级为2。“++”为自增运算符,“--”为自减运算符。自增、自减运算表达式的结合方向都是自右至左。但 ++k与k++ 的不同之处在于:前者先执行k = k + 1,然后再使用k的值;而后者则先使用k的值,再执行k = k +1。例2-11#include main( ){ int i, j, k;k = 30;i = k++;//先将k值30赋给i,再使k值增1,此时k =31, i = 30printf("i = %d, k = %d", i, k );j = ++k;// k值先增1,再将k值赋于i,此时k =32, i = 32printf("\n j = %d, k = %d", j, k );}运行结果:i = 30, k = 31j = 32, k = 322.6.3 赋值运算符——“右结合性”,优先级为14。赋值运算符为“=”例2-12main( ){ float k, x, y;x = ( k = 9.8 ) +7;printf("k = %5.1f, x = %5.1f \n ", k, x );y = k = 9.8 + 7;printf("k = %5.1f, y = %5.1f \n", k, y );}运行结果:k= 9.8, x= 16.8k= 16.8, y= 16.82.6.4 逗号运算符逗号运算符将两个表达式连接起来。其优先级15,最低。格式:表达式1,表达式2功能:先求解表达式1,再求解表达式2。整个逗号表达式的值为表达式2的值。在很多情况下,使用逗号表达式只是想求出各个表达式的值。例2-13main( ){ int i, j = 0123;//012是八进制数,其等价的十进制数是83i = 0x3a;//0x3a是十六进制数,其等价的十进制数是58printf("%d, %d \n ", i, j );}运行结果:58, 832.6.5 位运算所谓位运算是指对操作数以二进制位 (bit) 为单位进行的数据处理。每一个二进制位只能存放一位二进制数 ”0” 或 ”1”,因此位运算的运算对象是一个二进制数位的集合。表2-7 位运算符取反运算是单目运算,其余为双目运算。运算的操作数只能是整数或字符型数据,不能为实型数据。运算符 含义 优先级 格式~ 取反 2 ~ a<< 左移n位 5 a << n>> 右移n位 5 b >> n& 按位与 8 a & b^ 按位异或 9 a ^ b| 按位或 10 a | b各种逻辑位运算符的求值规律a b ~ a a & b a ^ b a | b1 1 0 1 0 11 0 0 1 10 1 1 0 1 10 0 0 0 0运算规律:~ 运算, 0变1,1变0;& 运算,当两个对应位均为1时,结果为1,否则为0;^ 运算,当两个对应位相同时,结果为1,否则为0;| 运算,当两个对应位均为0时,结果为0,否则为1;2.7 常用的数学函数在使用数学函数之前,要求在程序开头包含头文件"math.h",即: #include 以下函数的参数类型和函数值类型均为实型。sqrt( x ) 求x的开平方,x≥0。pow( x,y ) 求xyexp(x ) 求exabs(x) 求x的绝对值,n为int整型数。fabs(x) 求x的绝对值,n为double型浮点小数。log( x ) 求x的对数,以e为底,x>0。log10( x ) 求x的对数,以10为底,x>0。sin( x ) 求x的正弦,x的单位为弧度。cos(x ) 求x的余弦,x的单位为弧度。tan(x ) 求x的正切,x的单位为弧度。rand() 产生0~32767范围内的整数随机数。例2-14:输入一个正数x,求x的开平方。#include main( ){ float x,y;printf("input x:");scanf("%f", &x );y = sqrt( x );printf("sqrt (%7.2f ) = %7.2f \n", x, y );}运行程序的结果是:input x: 81↙sqrt ( 81.00) = 9.00例2-15: 使用pow函数求幂 ab。#include main( ){ float a, b;scanf("%f %f", &a, &b );printf("a = %.1f,b = %.1f,a ^ b = %.1f \n",a, b, pow(a,b) );}输入:5 3 回车,输出:a = 5.0, b = 3.0, a ^ b = 125.02.8 顺序结构程序设计应用实例一个结构化程序有三种基本结构,就是顺序结构、选择结构、循环结构。顺序结构是一组按书写顺序执行的语句。顺序结构程序是按语句的书写顺序执行的.例2-19:已知三角形的两边A、B及其夹角a,求第三边C及面积S。题目分析:根据三角形公式可知;C=S= ABsinα程序如下:#define PI 3.1415926#include main( ){float a, b, c, s, alfa;scanf("%f %f %f", &a, &b, &alfa );alfa = alfa * PI / 180;c = sqrt( a * a + b * b -2 * a * b * cos ( alfa ) );s = a * b * sin( alfa ) / 2;printf("a=%.1f, b=%.1f,alfa =%.1f\n",a,b,alfa);printf(" c = %.1f, s = %.1f \n", c, s );getch( );}若输入:5 8 30 ↙,则输出:a = 5.0, b = 8.0, alfa = 0.5c = 4.4, s = 10.0本章小结C语言的基本数据类型有:char、int、long、float、double等几种。计算机中没有无限大或无穷大的数。与整型不同的是,浮点运算无法表示百分之百的精确,它受到精度的限制。使用运算符时,应特别注意运算符的优先级、结合方向和运算对象的类型。末尾有分号的是表达式语句。末尾没有分号的是表达式。注意基本输入、输出函数getchar、putchar、scanf、printf等的使用,特别是输入输出格式要求。(共29张PPT)第3章 分支程序设计3.1 关系表达式和逻辑表达式3.1.1 关系运算关系运算就是对两个数据按它们值的大小进行比较的运算。判断它们是否符合给定条件:若符合,则结果为1(即“真”);否则结果为0(即“假”)。C语言提供了6种关系运算符,如表6-1所示。运算符 含义 优先级< 小于 6<= 小于或等于> 大于>= 大于或等于== 等于 7!= 不等于C语言关系运算符的优先级如下:关系运算符被分为两组不同的优先级==、!= 优先级低于 <、<=、>、>=关系运算符的优先级低于算术运算符。关系运算符的优先级高于赋值运算符。例如:a > b + 3 等价于 a > ( b +3 ) a = b > 3 等价于 a = ( b >3 ) a != b > 3 等价于 a != ( b > 3 )当相同优先级的关系运算符同时出现时,从左向右进行运算。例如:a != b == c 等价于 ( a != b ) == c3.1.2 逻辑运算C语言有三种逻辑运算符,如表3-2所示。运算符 含义 优先级 结合方向! 逻辑非 2 右&& 逻辑与 11 左|| 逻辑或 12 左说明:① 逻辑运算符中,“&&”和“||”是双目运算符,要求有两个运算量;“!”是单目运算符。② 下面是C语言逻辑运算符的优先级说明。1) “!”高于 “&&” ,“&&” 高于 “||” 。2) “!”高于算术运算符,而 “&&” 和 “||” 低于关系运算符。③ 假设A和B是两个表达式,下面对逻辑运算进行说明。1) A && B 若A、B均为真,则“A && B”值为真,否则为假。2) A || B 若A、B均为假,则“A || B值”为假,否则为真。3)! A 若A为真,则 “!A”为假;否则为真。看下面的例子:( 3 < 2 ) && ( 7 > 5 ) 值:0 只有 && 右面的子表达式为真( 3 < 2 ) || ( 7 > 5 ) 值:1 只要求有一个子表达式为真! ( 3 < 2 ) 值:1 子表达式为假。④ 用逻辑运算符连接若干个表达式组成的式子,称逻辑表达式。因为任何类型表达式都有真假,所以逻辑运算符可以连接任何类型的数据。例如:x > 7 && x + y != 20等价于( x > 7 ) && ( ( x + y ) != 20 )3.2 条件语句(if语句)if语句通常被称为选择语句或分支语句。它不再局限于顺序结构单一流程,而是用来对给定条件进行判定,根据其判定结果,从两种操作中选择其一。if语句用于实现分支结构,C语言提供了二种形式的if语句。3.2.1 if语句一般形式:if(表达式) 语句执行过程如图3-1所示。说明:1.执行if语句时,先对“表达式”进行求值,如果计算结果非0(为“真”),则执行其后的“语句”,否则跳过其后的“语句”。2.“表达式”的类型可以为任何类型的表达式。表达式语 句真(非0)假(0)例3-1 输入一个成绩score,如果成绩大于60,则显示“pass”,否则不显示。main( ){int score;scanf("%d", &score );if ( score >= 60 ) printf("pass \n");getch( );}运行结果:1. 输入:65↙输出: pass2. 若输入:56↙,则无输出3.2.2 if__else语句格式: if ( 表达式 ) 语句1;else 语句2;执行过程如图3-2所示。表达式语 句 1语 句 2真(非0)假(0)例3-2:从键盘输入一个正整数,如果该数为6的倍数,就输出一个“Yes!”,否则输出一个“No!”。main( ){ int x;printf("请输入一个正整数:");scanf("%d", &x );if ( x%6 ==0 )printf("Yes! \n ");elseprintf( "No! \n ");getch( );}运行结果:1. 请输入一个正整数:36↙Yes!2. 请输入一个正整数:15↙No!3.2.3 if语句的嵌套一般形式是:if(表达式1) 语句1;else if(表达式2) 语句2;else if (表达式3) 语句3;else 语句4;执行过程如图3-4所示。假表达式1语 句 1表达式2语 句 2表达式3语 句 3语 句 4假假真真真例3-3 有一函数,写一程序,输入x,输出y值。x ( x < 1 ) y= 2 x -1 ( 1 ≤ x < 10 )3 x -10 ( x ≥10 )main( ){float x, y;printf("请输入x的值:");scanf("%f", &x );if ( x < 1 ) y = x;else if ( x < 10 ) y = 2 * x -1;else y = 3 * x -10;printf("y值为:%.2f \n", y );getch( );}3.2.4 条件表达式条件运算符是三目运算符,由“ ”和“:”组成,要求有三个运算对象。条件表达式的一般形式:表达式1 表达式2 : 表达式3执行过程如图3-6所示。计算表达式3的值表达式1计算表达式2的值真(非0) 假(0)例3-5:编写一个程序,判断一个字符是否为大写英文字母,若是,则转换为小写字母。main( ){ char ch;scanf("%c", &ch );ch = ( ch >= 'A' && ch <= 'Z' ch +32 : ch );printf("%c \n", ch );}3.3多分支语句(switch语句)一般形式如下:switch ( 表达式 ){case 常量表达式1:语句部分1; [ break;]case 常量表达式2:语句部分2; [ break;]┇case 常量表达式n:语句部分n; [ break;][ default:语句部分n+1;]}switch语句的工作过程是:首先对switch语句括号中的表达式进行计算,然后依次与各case中的常量表达式的值比较,一旦匹配成功,则马上执行相应的语句部分,若遇break,结束switch语句;若均不匹配,则执行 default(若有的话)后的语句部分。当程序执行break语句后,它就使程序流程跳出switch结构,并转而执行switch结构后面的第一条语句。例3-5:根据考试成绩的等级(A、B、C、D),输出“优秀”,“良好”等评语。#include main( ){ char grade;printf("请输入成绩等级(A、B、C、D):");grade = getchar( );switch ( grade ){ case 'A': printf("优秀 \n"); break;case 'B': printf("良好 \n"); break;case 'C': printf("及格 \n"); break;default: printf("不及格 \n"); break;}getch( );}运行结果:请输入成绩等级(A、B、C、D):C↙及格执行过程grade优秀良好及格不及格‘A’ ‘B’ C’ default例3-6:在switch结构中多个case标号共用一组执行语句#include main( ){char grade;printf("请输入成绩等级(A、B、C、D):");grade = getchar( );switch ( grade ){ case 'A':case 'B':case 'C': printf("及格 \n"); break;case 'D': printf ("不及格 \n"); break;default: printf("输入数据错误 \n");}getch( );}3.4 分支程序设计应用实例例3-7: 从键盘输入二个整数,输出其中最大者。main( ){int a, b, max;printf("请输入二个整数:");scanf("%d %d", &a, &b );if ( a > b ) max = a;else max = b;printf("二者中最大值为:%d", max );getch( );}运行结果:17 31↙二者中最大值为:31例3-8:从键盘输入二个整数,从小到大输出。方法:若第一个数较大,两者值互换。main( ){ int a, b, tmp;printf("输入二个整数:");scanf("%d %d", &a, &b ); // a = 20, b =15if ( a > b ){tmp = a; // ① tmp = 20a = b; // ② a = 15b = tmp; // ③ b = 20}printf("%d, %d", a, b );}例3-9:编写一个程序,判断一个字符是否为英文字母。例3-10:由半径为 1的圆和半径为 2的圆所围成的圆环如图3-3所示。编写程序,输入x,y,若点 (x, y) 在圆环内,则输出TRUE;否则输出FALSE。本章小结if语句和switch语句用于实现分支结构。分支结构的特点是语句由多条分支构成,在程序的一次运行过程中,通常只有其中一条分支的语句被执行,而其它分支上的语句被跳过。switch语句通常用于多重选择。switch语句根据表达式的值来选择执行哪个分支的语句。break语句则控制程序跳出switch结构。if结构和switch结构都有测试表达式,通常情况下,是关系表达式或逻辑表达式,但也允许为其它任何类型的表达式。任何类型的表达式,"非0"为真; "0"为假。C语言用 1表示“真”,用0表示“假”。(共20张PPT)第4章 循环程序设计4.1 while循环while语句是一种称为“当型”的循环。它的一般形式是:while(表达式){语句序列;}while语句它的执行过程表达式语句序列假(0)真(非0)注意:循环必须在有限的次数内结束,否则会出现“死循环”,在程序中应避免出现死循环。while循环执行的特点是先判断条件,后执行循环体,因此,循环次数可能为0。例4-1: 编程求1+2+3+4+5之和。#include main( ){ int sum, i;sum = 0; // 累加器sum置0i = 1; // 循环变量i赋初值1while ( i <= 5 ){ sum = sum + i; // 将i值累加到sum中i = i +1; // 改变循环变量i的值}printf("1+2+3+4+5 = %d", sum );getch( );}运行结果:1+2+3+4+5 =15执行过程如表4-1所示。变量名 sum i 循环条件 ( i<=5 )初始状态 0 1 真第1轮循环后 0+1=1 2 真第2轮循环后 0+1+2=3 3 真第3轮循环后 0+1+2+3=6 4 真第4轮循环后 0+1+2+3+4=10 5 真第5轮循环后 0+1+2+3+4 +5 = 15 6 假(结束循环)4.2 do_ while循环do_while语句是称为“直到”型的循环结构,是另一种形式的循环。它的一般形式是:do{语句序列} while ( 表达式 );do_while语句的执行过程真(非0)表达式语句序列假(0)例4-2:比较do while语句和while语句:#include < stdio . h>main( ){ char ch ;ch=getchar() ;do{ putchar(ch) ;ch=getchar( ) ;} while(ch!='*');getch( );}运行结果*AB* ↙*AB #include < stdio . h >main( ){ char ch ;ch=getchar() ;while(ch!='*'){ putchar(ch);ch=getchar( );}getch( );}运行结果:*AB*↙无输出例4-3输入一个整数,按相反次序输出。例如,输入54321,输出12345。4.3 for循环for语句的一般形式是:for(表达式1;表达式2;表达式3){语句序列}for语句的执行过程表达式1表达式2语句序列表达式3假(0)真(非0)例4-4:从键盘上输入10个整数,求其和。main( ){int i, num, sum;sum = 0;for(i=1; i<=10; i++){ scanf("%d", &num );sum = sum + num;}printf("这10个整数的和为:%d", sum );getch( );}说明:当求累加值时,存放累加值的变量sum的初值应该为0。for括号中用两个分号分隔的三个表达式:“表达式1”只在循环开始时执行一次;“表达式2”是循环条件,在每一轮循环开始前进行计算,如果结果为真则执行循环体,否则退出for循环;“表达式3”用于循环变量的更新。可以省略for语句括号中的一个或几个表达式,但不能省略分号。例4-5:从键盘上输入若干个整数,直到输入0为止,求它们的乘积。for语句一般用于循环次数比较明确的情形,而while或do_while语句则用于循环次数难以判定的情形。main( ){int n;long t = 1; // 累乘初值为1scanf("%d", &n ); // 输入第一个整数while ( n != 0 ){ t= t * n;scanf("%d", &n ); // 输入下一个整数}printf("%ld \n", t ); // 输出长整型数据getch( );}运行时,输入:5 4 7 0 ↙则输出:1404.4 多重循环一个循环的循环体中又包含另一个循环,称为循环嵌套。这个嵌套重复下去,就是多重循环,也称为嵌套循环。while、do_while、for可以相互嵌套,自由组合。例4-6:打印九九乘法表。main( ){ int i, j;for(i=1; i<10; i++)printf ( "%8d", i );printf (" \n---------------------------------" );printf ("-----------------------------------\n" );for ( i = 1; i < 10; i++ ){ for ( j = 1; j <= i; j++ )printf ( " %2d * %d = % -3d ", i, j , i*j );printf ( " \n " ); // 换行}getch ( );}格式符“%8d”的作用是使输出的 每个数据占8个字符位置,右对齐;“%-3d”表示占3列,左对齐。4.5 break语句和continue语句breakbreak语句也可以用于循环结构中,使程序提前跳出循环,结束循环,转移到循环后面的语句。例4-7:求不同半径的圆柱体的体积,只计算体积在100以下的圆柱体。continue语句continue语句的作用是:流程跳过循环体中该语句后的所有语句,提前结束本轮循环,直接进入下一轮循环。continue语句与break语句的区别是:前者只是结束本次循环,而不是结束整个循环;后者则是结束整个循环。例4-8:输出50到100之间所有不能被7整除的数。4.6 循环结构应用实例例4-9:判断一个数是否为素数。例4-10:找出100到200之间所有的素数。例4-11:输入两个整数,求它们的最大公约数。方法是,采用“碾转相除法”,即反复模除取余,直到余数为0。本章小结用于实现循环结构的语句有:while语句、do_while语句、for语句。循环结构的特点是:循环体内的代码可能被反复执行多次。while语句和for语句都是先判断循环条件再决定是否执行循环体,可能一次循环也不执行。do_ while语句则是先执行循环体再判断循环条件,至少执行循环体一次。break和continue是循环的辅助语句, continue只能用于循环语句。(共33张PPT)第五章 数 组在C语言中,数组是一种构造类型,即它是由基本类型数据按照一定规则组成的新类型.数组中每个值的类型必须与数组的类型相同,使用数组名和下标来唯一确定数组中的元素。5.1 一维数组的定义和使用5.1.1 一维数组的定义类型说明符 数组名[ 常量表达式 ];例如:int a[10];//数组名为a,有10个int类型元素*/double scores[ 50 * 2 ];// 数组名为scores,有100个double元素*/定义数组时需要注意以下几个问题:数组名命名规则和变量名相同,应遵循标识符命名规则;常量表达式表示数组元素的个数(即数组的长度),在定义数组时必须指定该值。引用元素时下标从0开始。常量表达式中可以包括常量和符号常量,但不能包含变量。数组元素在内存中是连续存放的,数组名本身表示内存的首地址。5.1.2 一维数组元素的引用C语言规定只能逐个引用数组元素而不能一次引用整个数组。数组元素的表示形式为:数组名[ 下标 ];例如:int a [10 ]; a数组的10个元素分别是:a[0]、a[1]、a[2]、a[3]、a[4]、a[5]、a[6]、a[7]、a[8]、a[9]。例6-1 输入10个学生的成绩并求总分。main( ){int i;float scores[10], sum = 0;for ( i = 0; i < 10; i++ ){scanf("%f", &scores[ i ] );sum += scores[ i ];}printf("sum = %.2f", sum ) ;getch( );}运行结果如下:56 67 84 46 81 90 32 55 63 92sum = 66.605.1.3 一维数组的初始化1.对全部元素赋值。例如:int a[10] = { 1,2,3,4,5,6,7,8,9,10 };2.只对部分元素赋值。例如:int a[10] = { 1,2,3,4,5 };3.如果在 { } 中指定了所有元素的值,则数组的长度可省略不写。例如:int a[ 10 ] = { 1,2,3,4,5,6,7,8,9,10 };可改写为:int a[ ] = { 1,2,3,4,5,6,7,8,9,10 };例6-2 输出Fibonacci序列的前10个数。main( ){int i;int a[10] = { 1,1 }; //序列的第1,2个数值为1for( i = 2; i < 10; i++ ) //从第3个数开始,按规律求值a[ i ] = a[ i -1] + a[ i-2 ];for( i = 0; i <10; i++ )printf("%4d", a[ i ] );getch( );}运行结果如下:1 1 2 3 5 8 13 21 34 555.2.1 二维数组的定义及引用二维数组的定义方式为:数组名[ 行标 ] [ 列标 ]注意:数组下标从0开始,因此行标范围是0 ~ M - 1,列标范围是0 ~ N - 1。例如:#define M 3#define N 5int c[M][N];定义了二维数组c,它是一个具有M行N列的二维数组,共有M×N个元素。C采用行优先的方式来存储二维数组,即先在内存中顺序存储第一行(行标为0)的元素,再存放第二行的元素,依此类推。5.2.2 二维数组的定义及引用1.分行全部赋值。例如:int a[3][4] = { { 1,2,3,4 },{ 5,6,7,8 },{ 9,10,11,12 } };2.分行部分赋值。例如:int a[3][4] = { { 1,2 },{ 5 },{ 9,10,11 } };3.按一维数组形式赋值。例如:int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12 };4。如果对全部元素赋值(无论是一维形式还是分行形式),则定义数组时可省略第一维长度,但第二维长度不能省略。例如:int a[ ][4] = { { 1,2,3,4 },{ 5,6,7,8 },{ 9,10,11,12 } };例6-3 输入一个3 * 4矩阵,找出矩阵中负数的个数并输出。main( ){int a[3][4];int i, j , count = 0;printf( "input matrix:\n");for( i = 0; i < 3; i++ )for( j = 0; j < 4; j++ ){ scanf( "%d",&a[ i ] [ j ] );if ( a[ i ] [ j ] < 0 ) count++;}printf( "the number of negative is %d",count );getch( );}5.3 字符数组的定义和使用5.3.1 字符数组的定义及元素引用字符数组的定义类似于前面所介绍的数组定义,例如: char s[10];5.3.2 字符数组的初始化char s1[10] = {'f', 'a', 's', 'h', 'i', 'o', 'n' };该定义只对前8个元素赋值,后2个元素为零值(即ASCII码为0的字符)。它在内存中的表示如图5-4所示。f a s h i o n \0 \0由于采用字符串常量的方式对字符数组初始化时,系统会系统增加一个 ‘\0’,因此对于语句:char s2[ ]= "fashion";系统将认为数组s的长度是7,占8个字节。该数组在内存中的表示如:上述语句等价于:char s2[8] = {'f', 'a', 's', 'h', 'i', 'o', 'n' };f a s h i o n \05.3.3 字符数组的输入输出同其他类型的数组一样,字符输出的输入与输出可以逐个元素进行处理。例如:char s[10];for( i = 0; i <10; i++ )scanf( “%c”, &s[ i ] );for( i = 0; i < 10; i++ )printf( “%c”,s[ i ] );由于字符数组可以按照字符串形式处理,因此在输入输出时可以使用格式符 “%s” 整体进行。例如:char s[10] = “hello!”;printf( “%s”, s );输出时,系统检测到结束标志 ‘\0’ 即停止输出,因此输出结果为:hello!以 “%s” 输出时需要注意,该格式表示输出字符串,因此在输出项中应该写数组名,而不能使用数组元素的形式,即语句:printf( “%s”, s[0] );这种形式是不对的。输入时,系统遇到第一个 ‘\0’ 即停止输出,即使该字符后仍有其他字符。例如:char s[10] = “hello!\0ab”;printf( “%s”, s );输出结果为:hello!使用scanf进行字符串输入时,系统以空格或回车作为一个字符串的输入结束标志。使用gets函数或puts函数对字符数组进行整体输入与输出。在使用gets函数或puts函数之前,应包含头文件“stdio.h”。使用gets函数对字符数组进行整体输入格式:gets ( 字符数组名 )作用:从键盘上输入一个字符串赋给该数组。例如:char s[20]; gets(s);若从键盘上输入:thank you此时字符数组s的值为字符串 “thank you”。使用puts函数对字符数组进行整体输出格式:puts( 字符数组名 )或:puts( 字符串常量 )作用:将一个字符数组或字符串输出。例如:char str[20]={"One Two \0 Three"};printf("%s",str);puts(str);puts("thank you! \0 abc ");5.3.4 字符串处理函数C语言的函数库中提供了许多字符串的处理函数(头文件为string.h),使用户能够方便地处理字符串。这里介绍一些常用的函数如下:求串长函数strlen(s)、串复制函数strcpy(s1,s2)、串连接函数strcat(s1,s2)、串比较函数strcpy(s1,s2)。说明:其中的参数是符合指定要求的字符串数据。1.strlen(字符数组)作用:计算字符串s的长度,即首次出现 '\0' 之前的字符个数。参数要求:字符串s既可以是字符串常量,也可以是字符数组。例如:char s1[ ]={"perfect"};// strlen(s1) 等于7char s2[20]={"One\0 Two \0 Three"};// strlen(s2) 等于3char s3[ ]="thank& you! \0 abc";// strlen(s3) 等于10strlen( "abc \t 1234 \n" ) 等于9;strlen( "abc \t 1234 \123 \n" ) 等于10。其中,’\t’、’\n’和’\123’均为转义字符,按一个字符计算。2.串复制函数strcpy(s1,s2)作用:将字符串s2的内容复制到字符串s1中。参数要求:s1必须是容量足够大的字符数组;s2既可以是字符串常量,也可以是字符数组。不允许象其他变量一样对字符数组整体赋值,例如下面语句是错误的:char s1[10], s2[ ] = “hello!”;s1 = s2;因为数组名s1是地址常量,不能进行赋值运算,必须采用strcpy函数进行复制。例如:char s1[10]="thank you! ",char s2[ ] = “hello!”;strcpy (s1, s2 );执行后,s1的状态如图5-8所示。h e l l o ! \04.串比较函数strcpy(s1,s2)作用:比较字符串s1和字符串s2内容的大小。参数要求:s1和s2既可以是字符串常量,也可以是字符数组。字符串比较并不是比较它们的长度,而是依据这样的规则:对两个字符串从左至右依次比较对应的字符(按照字符的ASCII码值进行比较),直到遇到不同字符为止。若全部字符相同,则认为两字符串相等,否则以遇到的第一个不同字符的大小来决定两个字符串的大小。例如:“abc” 大于 “ABC” (因为 'a' > 'A')“abCdef” 小于 “abcd” (因为 'C'< 'c')“ABC” 等于 “ABC”“COM” 小于 “COMPUTER”调用函数strcmp ( s1, s2 )的结果:若s1 小于s2,则函数值 < 0;若s1 等于s2,则函数值 == 0;若s1 大于s2,则函数值 > 0。该函数的返回值返回比较的结果:字符数组1 = 字符数组2,函数值 = 0;字符数组1 > 字符数组2,函数值 > 0;字符数组1 < 字符数组2,函数值 < 0;例如:char s1[ ] = “thank”, s2[ ] = “you”;if ( strcmp ( s1, s2 ) > 0 )printf ( “bigger \n” );5.4数组的应用举例例6-4:找出10个学生中成绩低于其平均成绩的人数并输出。分析:可以定义一个长度为10的实型数组scores存储10个学生成绩。先计算出平均成绩,然后统计成绩低于平均成绩的人数。程序如下:main( ){int i, count = 0; //count存储人数,初始化为0float scores[10], ave; //ave存储平均成绩for( i = 0; i <10; i++ ){scanf( "%f", &scores[ i ] );ave += scores[ i ]; //累加成绩求总分}ave /= 10; //求出平均成绩for( i =0; i <10; i++ )if ( scores[ i ] < ave ) count++; //若低于平均成绩,计数器加1printf( "%2d", count );getch( );}例5-5:输入5个学生的3门课程成绩,求得每个学生的平均成绩和每门课程的平均成绩。例5-6 已有一个排好序的序列,输入一个数插入到该序列中,使之仍然保持有序。例如:将15插入到有序序列 { 3,7,10,12,18,20 } 中。例5-7 编写一个程序,将字符串转置后并输出。例如 “abcde” → “edcba”。本章小结C语言中定义数组时,方括号中必须是常量表达式,表明该数组元素的个数。数组元素的下标从0开始,最大下标 = 元素个数 - 1。字符串是以 ‘\0’为结尾的一维字符数组。可以在scanf和printf函数中使用 “%s” 格式对字符串输入输出。字符串变量间不能相互赋值,应使用字符串复制函数strcpy实现,字符串数据间不能进行比较运算,应该使用字符串比较函数strcmp实现。字符串处理函数的头文件名为“string.h”。(共32张PPT)第六章 函 数从用户角度看,C语句中的函数可以分为两种:(1) 标准函数,即库函数。(2) 用户自定义函数。6.1 函数的定义6.1.1 函数的定义函数定义的形式为:类型说明符 函数名(形式参数表列){声明部分;语句部分;}例如:int sum ( int a, int b ){ int c; // 声明部分c = a + b; // 语句部分return c;}这是一个求两个整数和的函数。6.1.2 函数的参数如果函数调用时需要传递数据,则在定义函数时在函数名后的括号内指明所需要的参数,包括参数类型和参数名。在函数定义时指定的参数称为形式参数(简称 “形参” ),在函数调用中传递的数据称为实际参数(简称 “实参” )。例6-1 输出两个整数的最大值。int max ( int x, int y ){int z;z = x > y x : y;return z;}main( ){int a,b,c;scanf( “%a %b” , &a, &b );c = max ( a, b );printf( “max is: %d” , c );}运行结果为:5 6↙max is: 6说明:1.函数的形参可以有多个,可以是相同类型也可以不同类型。int max ( int x, int y )2.形参必须是变量,但实参可以是常量、变量和表达式。3.实参类型必须与形参类型兼容。4.在C语言中,函数进行的是 “值传递” ,将实参的值传递给形参。这种传递是单向的.6.1.3 函数的返回值使用return语句将结果返回给调用程序。格式为:return (表达式);或者 return 表达式;一个函数可以有多个return语句.当遇到第一个return语句时,C立即终止函数的执行.如果函数不需要返回计算结果,即不需要返回值时,最好定义为void类型.6.2 函数的调用6.2.1 函数的调用函数调用的一般形式为:函数名(实参表列);如果函数没有参数,括号内为空,但不能省略括弧。如果有多个参数,参数之间使用逗号分隔。调用时,应保证实参的个数与形参相同,类型一致。例6-2 计算1到n的整数和。int calcu( int x ){int i, total = 0;for( i = 1; i <= x; i++ )total = total + i;return total;}main( ){int n;scanf( “%d” , &n );printf( “sum = %d” , calcu( n) );}按照函数调用时出现的位置,可以分为以下三种调用方式:1.函数语句2.函数表达式3.作为函数参数6.2.2 函数原型函数声明的格式和函数定义的首部相同,并在其后添加分号表示语句结束。例如:int max ( int x, int y );int calcu ( int x );这种函数声明称为 “函数原型” 。一般地,为了提供程序的可读性,把函数原型写在main函数之前,函数的定义写在main函数之后。但如果函数的定义出现在main函数之前,则可省略相应的函数原型。6.2.3 函数的嵌套调用和递归函数定义内部不能定义其他函数,即不能出现函数定义的嵌套。但函数的调用是可以嵌套的。函数可以嵌套调用。若函数调用自身,称为函数的递归调用。递归必须有条件地进行。例6-3 求n!分析:根据阶乘的性质可以有如下递归公式:例如5!,等于5 * 4!,而4!= 4 * 3!,…… ,1!=1。float fac( int n ) // 求n的阶乘函数{ float f;if ( n <= 1 ) f = 1; // 条件满足,终止递归else f = n * fac ( n –1 ); // 否则继续递归return f; // 返回阶乘值}例6-4 求Fibonacci序列的第n项的值分析:Fibonacci序列的规律是:每个数等于前面两个数之和。由此可得如下公式:int fib ( int n ){if ( n <= 2 ) return 1; // 递归终止else return fib( n –1 ) + fib( n –2 );}6.3 数组作为函数参数6.3.1 数组元素作为函数参数例6-5 找出数组的最大值。6.3.2 数组名作为函数参数例6-6 编写一个函数显示数组的值。6.3.3 多维数组作为函数参数例6-7 将一个4 * 4的矩阵转置。6.4 变量的作用域变量的作用域又称作用范围,指的是一个变量在何处可以使用。根据变量的作用域可将变量分为局部变量和全局变量。6.4.1 局部变量局部变量是在函数内部声明的变量,这包括函数的形参。它们仅在包含该变量声明的函数中才起作用,在该函数外不能使用这些变量。例6-8 局部变量示例void local_value( ){int a = 1, b = 2;printf( “%d%d” , a, b);}main( ){int a = 5;float b = 2.5;printf( “%d%f” , a, b );}由于局部变量只在本函数内有效,因此可以在程序的各个部分使用同名变量,同样,在参数传递时,实参也允许和形参同名。使用局部变量时要注意:(1) main函数中的变量也是局部变量。(2) 可以在复合语句中定义变量,这样的变量只在复合语句内有效,这种复合语句也称为 “分程序” 或 “程序块” 。6.4.2 全局变量在函数外定义的变量称为全局变量,又称外部变量或全程变量。全局变量的有效范围从定义位置到文件结束,在这个范围内的任何地方都可使用(包括函数)。例6-9 全局变量示例int a = 5, b =10; // 全局变量void modify ( ){ a++;b--;printf( “%d,%d \n” , a, b );}main( ){ modify( );printf( “%d,%d\n” , a, b );}运行结果为:6,96,9例6-10 全局变量与局部变量同名示例。int a = 5, b = 10;void modify( ){ int a = 5, b = 10;a++; // 修改的是局部变量a和bb--;printf( “%d,%d \n” , a, b ); // 输出局部变量a和b}main( ){modify();printf( “%d,%d\ n” , a, b ); // 输出全局变量a和b}运行结果为:6,95,106.5变量的存储类别6.5.1 存储方式静态存储方式动态存储方式。6.5.2 自动变量函数中的局部变量如果未加static声明就属于自动变量。这包括函数内的局部变量、函数形参和复合语句中定义的变量。自动变量是动态分配内存的,其值存储在动态存储区中。调用函数时为自动变量分配内存,调用结束释放内存。也可为自动变量添加auto关键字声明。6.5.3 静态局部变量如果局部变量使用static关键字声明,就属于 “静态局部变量” 。这种变量属于静态存储类型,在静态存储区分配内存。程序运行开始(而不是函数被调用时)就给静态局部变量分配内存,运行结束释放。而自动变量是调用函数时才分配内存,调用结束释放内存。这是静态局部变量和自动变量的一个本质区别。例6-11 静态局部变量示例void sub( ){ int a = 0;static int b = 0;a++; b++;printf( “%d,%d \n” , a, b );}main( ){ int i;for( i = 1; i <= 3; i++)sub( );}运行结果为:0,10,20,3使用静态局部变量时须注意以下几点:1.静态局部变量如果没有显式初始化,则系统自动为其初始化为零值。2.尽管静态局部变量在程序运行期间都存在,但它的作用域是函数内部。6.5.4 寄存器变量当需要频繁使用某一个变量时,从内存中读写该变量都需要耗费一定的时间。为了提高程序的性能,C语言允许将变量存储在CPU的寄存器中。这种存储类别的变量称为 “寄存器变量” ,可以使用register关键字声明。只有局部变量和形式参数才允许声明为寄存器变量。register变量的使用与否意义不大。6.5.5 外部变量外部变量(全局变量)是在函数外部定义的,其作用域是从定义处开始到文件结束。系统对外部变量采用静态存储方式,即编译时分配内存,程序运行结束释放。同静态变量类似,未显式初始化的外部变量初值是0。如果在外部变量定义处之前需要使用该变量,则需要在使用之前使用extern关键字声明该变量,以表示该变量是一个已定义过的外部变量。例6-13 extern关键字示例main( ){extern int a,b; // 外部变量声明++a;b += a;printf( “%d,%d” , a, b );}int a = 5, b = 10; // 定义外部变量运行结果为:6,166.6 函数应用实例例6-14 将序列的最大值和第一个数交换,最小值和最后一个数交换,并输出新序列。例6-15 编写一个函数,在一个整数序列中查找某个整数,若存在,返回该整数序列中的位置;否则返回 -1。要求在主函数中调用,输出结果。本章小结所有C函数的定义都是并列的,不能在一个函数内再说明或定义另一个函数。函数不能嵌套定义,但可嵌套调用,也可以递归调用。函数通过调用被执行,调用时给出函数名和实参。实参的类型、个数、顺序要与形参一致。调用时,实参的值传递给实参。如果数组名作为参数传递,那么实际传递的是数组的首地址。如果函数定义在后、调用在前,则必须在调用语句前声明。声明时,最好使用函数原形进行声明,以确定被函数返值的类型和形式参数。有了函数,可以实现模块化程序设计。定义一个函数后,可以进行多次函数调用。通过函数调用,将相互独立的函数间建立某种关联。(共16张PPT)第7章 结构体7.1 概述数组中的各元素具有相同的数据类型。在实际应用时,有时需要将不同类型的数据组合成一个有机的整体,便于进行程序设计。结构体属于构造类型,其各元素的数据类型既可相同,亦可不同。结构体中的各元素亦称为数据项或域。7.2 定义结构体变量的方法所有的自定义类型变量的定义均有三种方法:先定义类型,后定义变量;类型和变量同时定义;直接定义变量7.2.1 先定义类型,后定义变量;格式:(1)先定义类型struct 结构体名{ 类型标识符1:域标识符1;类型标识符2:域标识符2;……类型标识符n:域标识符n;};(2)在使用结构体变量之前的适当位置,定义变量struct 结构体名 变量名表 ;注意:1. 此处struct不能省,只有 “结构体名 变量名表;”是错误的。2. 紧接在定义的右花括号后的分号是不能省略的,因为一个结构体定义就是一条语句。例7-1main ( ){ struct date{ int year, month, day;} ; // 右括号后不能缺少分号struct date today;scanf (" %d %d %d" , &today.year, &today.month, &today.day );printf (" %d 年%d月%d日 \n" , today.year, today.month, today.day );}7.2.2 类型和变量同时定义格式:struct 结构体名{ 类型标识符1:域标识符1;类型标识符2:域标识符2;……类型标识符n:域标识符n;}变量名表;例如,可以用下面的方法定义一个日期变量 workday。struct date{ int year, month, day; } workday;7.2.3 直接定义变量格式:struct{ 类型标识符1:域标识符1;类型标识符2:域标识符2;…类型标识符n:域标识符n;}变量名表;说明:直接定义变量只适合于该结构体类型只出现一次。7.3 结构体变量的引用7.3.1 结构体变量的引用结构体变量名.域名例7-2:定义一个结构体变量t,从键盘上输入3 个域的值,并在屏幕上输出。main( ){ static struct{ int m, d, y;}t;scanf("%d, %d, %d", &t.m, &t.d, &t.y );printf("%d, %d, %d \n", t.m, t.d, t.y );}7.3.2 结构体变量的初始化可以在定义结构体变量的同时,对结构体变量进行初始化。例如:struct xyz{ int a;char c;}d1={1, 'a'};struct date d2={2, ' b'};例7-3:main( ){ int i;static struct{ char no[ 9 ] ; // 学号char kc[16 ] ; // 课程int cj ; // 成绩} cjb1 ={"20051508", "ENGLISH", 85};printf ("\n学号 :%s\n", cjb1.no);printf (" 课程 : %s\n" , cjb1.kc);printf (" 成绩 : %d\n" , cjb1.cj);}7.3.3 同类型结构体变量间的赋值格式是:结构体变量1 = 结构体变量2 ;例7-4:定义两个同属于类型struct date 的变量 d1和d2,先对变量d1赋值,再将d1赋给变量d2。struct date{ int mm , dd , yy ; };main( ){ struct date d1, d2;d1.mm=9;d1.dd=1;d1.yy=2004;d2=d1;printf ("%d-%d-%d \n", d2.mm, d2.dd, d2.yy );}语句d2=d1;等价于执行下列3条语句:d2.mm=d1.mm;d2.dd=d1.dd;d2.yy=d1.yy;7.4 结构体数组在实际应用中,可以把结构体定义为数组,数组的元素类型是结构体类型。例如:typedef struct student{ char no [ 10 ] ;char name [ 8 ] ;char sex [ 2 ] ;struct date birthday;int score ;} STUD;STUD s[50];这样可以存放50 个学生的课情况。7.5 结构体应用实例例7-5:用结构描述学生成绩,并处理一个学生和数据。例7-6:输入某个日期,输出第二天的日期。例7-7:建立学生选课表。本章小结① 结构体是一种自定义类型,它不像char, int等是系统定义的标准类型。用户在使用自定义类型前必须先定义,后使用。② 结构体类型是把不同类型的数据项放在一个变量中作为整体来处理,其中的数据项称为域。域也可以是一个结构体类型。③ 一个结构体数据所占用的字节数是它所有域所占字节数之和。④ 结构体类型可以嵌套定义,即结构体中的域可以是结构体类型。域的引用形式如:结构体变量名。域名。子域名(共24张PPT)第8章 指针8.1 指针的概念指针,也就是内存地址。指针变量是用来存放这些内存地址的变量。不同类型指针变量所占用的存储单元长度是相同的.直接访问方式:根据变量名实现对存储空间的访问。间接访问方式:通过存放地址的指针变量实现对存储空间的访问。如果将变量x的地址2060存放到另一个变量p中,即p的值为2060,这样通过变量p可以找到变量x的地址,从而找到 x 的值。存放地址的变量p就是指针变量。可以形象地说,p指向x。"*" 是指针运算符,或称为“间接访问”运算符。*p表示指针变量p所指向的变量。若要改变x变量的值,也可通过改变 *p的值来实现。如执行 *p = 47;则此时x=47。"&" 也是一个指针运算符,称为取地址运算符。如为了让指针p指向变量x,可执行p = &x,此时变量x的地址即存入了指针p中。注意,指针变量只能存放地址值,不要将一个整型数据赋给一个指针变量。8.2 指向简单变量的指针指针变量也必须先定义后使用。格式如下:类型标识符 * 指针变量名;例如:int *p1, p2;则p1是指针变量,而p2是整型变量。例8-1:通过指针变量访问变量。main( ){int a, b, *p1, *p2;float x, y, *q1, *q2;a=123; b=45;x=1.25; y=-0.98;p1=&a;p2=&b;q1=&x;q2=q1;printf("\na=%d, b=%d\n", a, b );printf("*p1=%d, *p2=%d\n", *p1, *p2 );printf("x=%f, y=%f\n", x, y );printf("*q1=%f, *q2=%f\n", *q1, *q2 );}例8-1运行结果8.3 指向数组的指针变量任何可通过数组下标完成的操作也可通过指针完成。然而它们之间也存在细微但很重要的区别。一般来讲,使用指针速度更快,程序更紧凑。8.3.1 指向一维数组的指针变量指针变量可以指向数组或数组元素,即把数组的起始地址或某一元素的地址存放到一个指针变量中。例如:定义指针p指向一维整型数组a[5]。可进行如下说明:int a [5];int *p;注意,不能定义成int *p[5];如果这样定义,就表示定义了一个指针数组。它有5个元素,p[0]、p[1]、p[2]、p[3]、p[4],每个元素都指向整型变量。如果数组为int型,则指针变量亦应指向int型。执行语句: p = a ; 或 p = &a[0];均可以使指针p 指向数组a的第1个元素a[0]。C语言规定,数组名代表数组的首地址,也就是第一个元素的地址。此外,p+1指向下一个元素,p+i 指向p后的第i个元素 a[i]。无论某个数组的元素占据多少内存字节( 即元素长度,设为len ),当指针p指向其中一个元素时,p+1均是指向它的下一个元素,而不是p+len。可见,a[i], *(a+i), *(p+i) 都是等价的。例8-2:用三种方法输出数组元素。main ( ){ static int a[5]={5, 4, 3, 2, 1 };int i, *p = a;for ( i = 0; i < 5; i++ )printf (" %d, %d, %d \n ", a[i], *(a+i), *(p+i ) );}运行结果:5, 5, 54, 4, 43, 3, 32, 2, 21, 1, 1例8-3:输出数组的所有元素。main ( ){ int a[5], *p, i ;for ( i = 0; i < 5; i++ )scanf ("%d", a + i );for ( p = a; p < a+5; p++ )printf ("%4d ", *p );}运行结果:1 3 5 7 9↙1 3 5 7 9说明:指针变量和数组名有区别,指针变量是一个变量,可以改变其值,而数组名是数组首地址,是一个地址常量,不能对它赋值。8.3.2 指向多维数组的指针变量C 语言将二维数组定义时的行数和列数分别用两个方括号分开,如 int a[4][3];,目的是把二维数组看作是一种特殊的一维数组,它的元素又是一个一维数组。如,把a看作是由四个元素a[0]、a[1]、a[2]、a[3] 组成的一维数组,而每个元素a[i]( i=0,1,2,3 ),又都是具有3个元素的一维数组。例8-5:输出数组int a[4][3] 中的第3行的所有元素。main ( ){ static int a[4 ][3]= {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};int *p;for ( p = a[2 ]; p < a[2]+3; p++)printf ("%4d", *p );}运行结果:7 8 9例8-8:用指针输出二维数组的各元素。#include #define M 4#define N 3#define L M*Nmain ( ){ int a[M][N], *p=a[0], i;for ( ; p < a[0]+L; p++ ) // 从键盘上输入L个数据scanf ( "%d", p );for ( i = 0; i < M; i++ ){ p = a[i]; // 取第i行的首地址for( ; p < a[i] + N; p++ ) // 输出第i行的n个元素printf ("%5d", *p ) ;printf ( "\n" ); // 换行}}8.4 指向字符串的指针变量在C语言中,字符串可以用字符数组实现。其实,字符串还可以用字符指针实现,而且字符指针更方便、简洁。例如:char string[ ] = "this is a string!";char *pstr = "that is a book!";例8-10:编写字符串复制函数strcpy (s1, s2 )。用数组方法void strcpy ( char s1[ ],char s2[ ] ){ int i = 0;while ( s2[i] != '\0' ){ s1[i] = s2[i];i++;}s1[i]=0; // 补上串结尾符}用指针方法void strcpy ( char *p,char *q ){ while ( *q != '\0' ){ *p = *q;p++;q++;}*p=0; // 补上串结尾符}例8-12:分别用字符指针和字符数组表示字符串。#include main( ){ char s1[5], s2[8], *p;p=s2;scanf("%s %s", s1, p );puts(s1); puts(p);}运行上述程序:qwe iop↙qweiop例8-13:改变数组指针的程序。#include main( ){ char *p = "money order";p = p+6;printf("%s \n", p);}运行结果:order8.5 指针作为函数参数例8-15:输入两个整数a, b,从大到小输出。main( ){ int a, b;scanf("%d %d", &a, &b );if ( a < b ) swap (&a, &b );printf("%d %d \n", a, b );}swap( int *q1, int *q2 ){ int tmp = *q1;*q1 = *q2;*q2 = tmp;}8.6 指向结构体的指针变量#include struct student{ char xh[3], xm[7];int cj;};main( ){ struct student *p, s;p = &s; // 将结构体变量s 的起始地址存入指针p中scanf("%s%s%d", (*p).xh, (*p).xm, &s.cj );// 可通过指针p对s的域赋值printf("%s,%s,%d", p->xh, p->xm, p->cj );// 通过指针p输出s的内容}运行:30 wang 79↙30, wang,79以下3 种形式等价:① s.xh② (*p).xh③ p -> xh8.7 应用实例例8-20:将数组b 中n个整数按相反顺序存放。invert1 ( int b[ ], int n ) //用数组实现{ int tmp, i, j, m = n / 2;i = 0; j = n -1;for ( ; i < m; i++, j-- ){ tmp = b[i];b[i] = b[j];b[j] = tmp;}}invert2 ( int *p, int n ){int tmp, *i, *j;i = p;j = p + n - 1;for ( ; i < j; i++, j-- ){ tmp =*i;*i =*j;*j =tmp;}} //用指针实现本章小结1.指针( pointer )是用于存放内存地址的特殊变量( 这里地址一般是指内存中另一个变量的位置 )。称指针指向某个变量,也就是说,指针存放的是该变量的地址值。指针变量的命名规则同普通变量。2.通常所说的指针类型是指它所指向的变量的数据类型。3.求地址运算符&,返回操作数变量在内存中的地址,而与变量的内容无关。4.运算符*,返回操作数所指变量的值。5.下面三个表达式等价:dd.year(*p).yearp->year(共14张PPT)第9章 文件9.1 文件概述文件是程序设计中一个重要的概念。所谓文件是存贮在外存介质(如磁盘) 上数据的集合。通过对数据集命名(文件名) ,而达到对这部分数据存取的目的,即所谓“按名存取”。C语言把文件看作是一个字符(字节) 的序列,即由一个个字符(字节) 的数据顺序组成,称为流式文件。根据数据的组织方式,可分为ASCII文件和二进制文件。在C语言中,没有提供输入输出语句,对文件的读写都是通过库函数来实现的。ANSI文件系统的I/O函数在stdio.h中说明。9.2 文件的打开和关闭9.2.1文件的打开缓冲文件系统中,关键的概念是“文件指针”。每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息(如文件的名字、文件的状态及文件当前位置等) 。这些信息是保存在一个结构体类型变量FILE中。ANSI C规定了标准输入输出函数库,用fopen( )函数来实现打开文件。fopen函数的调用方式通常为:FILE *fp;fp = fopen(文件名,文件使用方式)例如fp = fopen("fn1.dat", "r" ); 表示以读方式打开一个磁盘文件fn1.dat。fp指向了fn1.dat文件。使用文件方式文件使用方式 含义"r" (读) 为输入打开一个已存在的文本文件"w" (写) 为输出打开一个新的文本文件"a" (追加) 向文本文件尾追加数据"rb" (只读) 为输入打开一个二进制文件"wb" (写) 为输出打开一个新二进制文件"ab" (追加) 向二进制文件尾追加数据"r+" ( 读写) 为读写打开一个文本文件"rb+" ( 读写) 为输出打开一个二进制文件9.2.2 文件的关闭用fclose函数关闭文件。格式:fclose ( 文件指针变量 );例如:fclose(fp) ;此函数解除文件指针和文件的联系,并在解除这种联系之前进行善后处理(如把缓冲区剩余数据写入文件)。忽略对文件的关闭操作将会造成数据丢矢,因此关闭文件的操作是必不可少的。9.3文件的读写函数文件的读操作,实际上是将一个已打开的文件的内容读出(亦称输入或取出) 。文件的写操作,实际上是将某些数据写入(亦称输出或存入) 某文件,该文件可以是新建的,也可以是一个已存在的文件。部分读写函数格 式 功 能fputc ( 字符,文件指针 ) 把一个字符写到指定文本文件上。fgetc ( 文件指针 ) 从指定文本文件读入一个字符,fgets ( 串始地址,字符数+1,文件指针 ) 从文件流中读取一个字符串。fputs ( 串始地址,文件指针 ) 向文件流的当前位置写入一字符串。fwrite ( 始地址,字节数,个数,文件指针 ) 一般用于二进制文件输出。fread ( 始地址,字节数,个数,文件指针 ) 一般用于二进制文件输入。fprintf ( 文件指针,格式字符串,输出表列 ) 同 printf ,但向指定文件输出。fscanf ( 文件指针,格式字符串,输入表列 ) 同 scanf ,但从指定文件读入。说明:函数fputc和fgetc用于单个字符写和读。若文件以二进制形式打开,用fread和fwrite函数可以读写任何类型的信息。若fread和fwrite调用成功,则返回值为“个数”值,读写数据块的长度=字节数×个数。例9-1:fputs函数将字符串写入磁盘文件“fa.txt”中,测试该函数的返回值。再用fgets函数读取若干字符串。例9-2:fprintf函数将2个浮点型数据写入磁盘文件“fb.dat”中,并测试该函数的返回值,再将这2个浮点型数据从磁盘文件“fb.dat”中读出,并在屏幕上输出。9.4 文件的定位函数和文件结尾标志函数打开一个文件时,文件的位置指针指向文件开头,随着文件读写的不断进行,文件的位置指针也作相应变化,用户可以通过使用文件的定位函数将文件的位置指针指向指定位置。文件的定位函数和文件结尾标志函数函数名 格式 功能rewind rewind ( fp ) 将位置指针 返回文件开头处fseek fseek ( fp , w, 0 ) 将位置指针移到距离文件开头 w 字节处fseek ( fp , w, 1 ) 将位置指针移到距离当前位置 w 字节处fseek ( fp , -w, 2 ) 将位置指针移到距离文件末尾 w 字节处ftell ftell ( fp ) 返回 位置指针距离文件开头的字节数feof feof ( fp ) 若 位置指针指向文件末尾,则返回真,否则返回假。说明:函数fseek中“w值”可以是正数,也可以是负数。例如:fseek ( fp , 50L, 0 ) ; 将位置指针移到距离文件开头50字节处。fseek ( fp , 100L, 1 ) ; 将位置指针移到距离当前位置100字节处。fseek ( fp , -10L, 2 ) ; 将位置指针移到距离文件末尾10个字节。例9-3 文件的定位函数和文件结尾标志函数测试。9.5 文件应用实例例9-4 把一个浮点数组以二进制方式写入文件fc.dat中,再从文件fc.dat中读出并显示。例9-5 将3个学生记录存入一个磁盘文件fd.dat中。本章小结C文件根据数据的组织方式可分为ASCII(文本) 文件和二进制文件。缓冲文件系统是靠文件指针与相应文件建立起联系的。一般使用几个文件,就至少有几个文件指针与之一一对应。文件对文件的操作都是由库函数来实现的,因此,在调用这些函数时,应在程序开头包含头文件 stdio.h。在使用文件之前应先打开文件,将磁盘文件名与某个文件指针变量联系起来。而且,在使用文件结束之后,应即时关闭该文件,以免丢失文件数据。 展开更多...... 收起↑ 资源列表 第1章 C语言概述.ppt 第2章 基本数据类型与简单程序设计.ppt 第3章 分支程序设计.ppt 第4章 循环程序设计.ppt 第5章 数组.ppt 第6章 函数.ppt 第7章 结构体.ppt 第8章 指针.ppt 第9章 文件.ppt