新概念C语言案例教程_第1页
新概念C语言案例教程_第2页
新概念C语言案例教程_第3页
新概念C语言案例教程_第4页
新概念C语言案例教程_第5页
已阅读5页,还剩195页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

新概念C程序设计教程

上册

第一章C语言的基本概念

1.1c语言程序的构成成分:

例题1.1

1)ftinclude<stdio.h>/*编译预处理命令,将标准输入输出函数

2)作为头文件包扩到用户源程序文件中*/

3)8include<math.h>/*编译预处理命令,将系统提供的数学函数

4)作为头文件包扩到用户源文件中*/

5)intmain()//函数名为main的主函数的函数首部

6){〃函数体开始

7)floatx,y;〃定义部分.定义变量及其类型

8)x=45.2;〃语句部分.赋值语句

9)y=sqrt(3*x+5.6);〃语句部分.赋值语句

10)printf(“斌\n”,y);〃语句部分.输出语句

11)return0;〃/语句部分.返回语句

12)}〃函数体结束

注意:最左边的行号是为了说明方便而加上的,实际C语言程序中是不能有的。

1.C语言的源程序的主要构成成分是函数定义(从第5到第12行)。一个C语言源程序文

件一般由多个函数定义顺序组成(直到第5章才讨论由两个以上函数构成的C语言源程

序),但是其中必须有一个main函数。程序的运行都是从系统调用main函数开始的。

2.函数定义由函数首部(第5行)和函数体(第6到第12行)组成。函数体必须用大括号

“{”和“}”括住。

3.C语言源程序的次要构成成分是:编译预处理命令(第1、3两行的左边部分)、注释(每

一行右半部以//开始的内容,或以/*开始,以*/结束的内容)和声明(见第5章)。编译预

处理命令和注释是不以分号结束的。

4.C语言程序中,(任何函数的)函数体的主要构成成分是:定义序列(第7行的左半部)

和语句序列(第8行到第11行的左半部)。这两种成分都要以分号结束(复合语句除外)。

C语言函数体中,所有定义必须位于语句序列之前(*注)。

*注:这是C89标准,其它高级编程语言不一定有此先后顺序要求。C99标准放宽了要求,

可以在复合语句的前半部定义仅在复合语句中有效的局部变量,但目前不少编译器并不支持

C99标准。所以,为了获得较好的程序可移植性,本书的论述以较老的C89标准为主。

深入一步:

定义序列被编译程序翻译成了内存中的数据序列(包括对存放数据的内存空间的事先

安排),而语句序列则被翻译成了指示如何加工这些数据序列的机器语言的指令序列。将

要运行的程序的指令序列也是位于内存中的。所以在运行某个程序前,程序用户必须借助

于操作系统将位于外存文件中的这两部分内容加载到内存中。

*5.在正式进行编译之前,编译预处理程序将根据源程序中的编译预处理命令对源程序文件

进行一些辅助性的文本插入(include命令)、替换(#define命令)和编辑工作。编译预处

理命令都是以“#”开始,不以分号结束。每条编译预处理命令必须书写在同一行上。

6.注释以“/*”开始,以“*/”结束。注释会被编译程序首先删除掉。但良好的注释使程

序更易被人们读懂。不要忘记书写注释的结束符号“*/”o注释有两种常用方式:一种是

注释内容独自占据多行,对注释以下的一段程序或整个源程序文件进行说明;另一种是出现

在一行的右边,对该行左边的内容进行说明。(注释部分在VC++6.0中是以绿色字体显示出

来的。)

单行注释以“〃”开始,它用起来比较方便,但它不是C语言标准规定的。

1.2C语言程序的语法要素

1.1X即争除了格式控制串(见1.4节printfO和scanf()函数)和注释部分以外的C语

言源程序的其它部分,称为C语言的源程序的正文部分。(正文部分在VC—6.0中是以黑色

字体显示出来的。)

2.C语言的字符集,

26个大小写英文字母:A----Z,a---z;

阿拉伯数字字符:0——9;

特殊字符:!#%,&*+=

()[]{)?:空格字符(对应键盘上的最长键Space)换行符(对应

Enter键)制表符(对应Tab键)

以上所有这些字符构成了C语言的字符集。书写C语言的源程序的正文部分,只能使

用C语言字符集中的字符,其它任何字符不得使用。字符集中的任何字符,只能用英文半

角方式来进行输入。

3.标识符是以26个大小写英文字母、阿拉伯数字0到9和下划线构成的字符序列;其中从

左边开始的第一个字符不能是数字。在C语言中,只能使用符合标识符规定的名字,来对

变量、符号常量、函数、语句标号命名。C语言对标识符的大小写敏感,也就是说main与

Main,printf与Printf都是不同的标识符(main和printf都是C语言中的已经规定的函数名,

所以,我们不能用来作为自定义的标识符)。

4.关键字是被编译程序保留下来的特殊标识符;主要分为两大类:用于定义(或声明)的

关键字和用于构成语句的关键字。(C89标准中的)关键字都是由小写英文字母组成的。关

键字(还包括预处理明令)在VC++6.0中是以蓝色字体显示出来的。

所有关键字列表如下:

在ANSIC89标准中共有32个关键字

autobreakcasecharconstcontinuedefaultdodoubleelseenum

extxrnfloatforgotoifintlongregisterreturnshortsigned

sizeofstaticstructswitchtypedefunionunsignedvoidvolatilewhile

在ANSIC99标准中增加了5个关键字

BoolComplexImaginaryinlinerestrict

5.C语言源程序中可使用的分隔符有三个:空格、回车/换行、逗号。同类项之间要用逗号

分隔,关键字和标识符之间要用空格或回车/换行来分隔,不能用逗号(比如int

在C语言中,合理地使用多余的空格和空行,可以使得程序更清晰、易懂、优美。

6.C语言中常量分为数值常量(又称为字面常量)和符号常量两种。应当多使用符号常量,

尽量少用数值常量。

・最常用的数值常量有以下儿种:

1).整型常量567,-425,0等,是没有小数分量的数值。

2).实型(浮点型)常量:

由正负号、数字、小数点构成。0.543、543.、543.0、0.0都是十进制的小数形式。在

数的左边还可以加上正负号。比如-543.0。

3).字符型常量'K',*,,,8,,,\n,等,是用单引号括起来的ASCH码表中的字

符,包括键盘上的可显示(或可打印)的字符和不可显示的一些控制字符(字符'\n'就是表

示一个控制字符——Enter键,详见附录ASCH码表)。

深入一步:字符型量的本质

字符常量在编写程序时,要用两个单引号括住它。它属于一种从表面上看来是非数值型

的量。但其实在计算机的内存中,它就是以ASCII码的形式存储的,占用一个字节内存空间

的一个二进制正整数(取值在0一—127之间)。字符型量是用计算机进行文字处理的基础。

・符号常量一般由大写英文字母组成的标识符构成,用#define来进行定义,比如:

#defincPI3.1416。源程序中所有出现的记号PI都会被编译预处理程序用3.1416

替代。修改常量的值变得非常方便,程序的可读性也更好。

7.变量

定义变量的作用:要求系统为存放(其数值可以变化的)数据事先分配内存单元,变量

名作为内存单元的行号地址。

定义变量的形式是:〈类型名〉〈变量列表》:

定义变量只能使用标识符。多个变量之间用逗号隔开,构成变量列表。

C语言中各种常用的变量类型是int(整型)、float(单精度浮点型)、char(字符型)、

double(双精度浮点型)、long(长整型)。

通过变量名score,可以找到(即映射为)相应的内存单元地址。假设地址为2000,

语句:score=38.0;

的含义和作用是:将数值38.0存放在地址为2000的内存单元中。

变量的值是可以变化的。而变量名所对应的内存地址是不变的。

8.变量一定要先进行定义,定义后一定要进行初始化(即存入一个初始值在变量对应的内

存单元中,参见P页),然后才能在表达式中使用或进行输出。否则,变量所对应的内

存单元中的垃圾掣般就会在程序中(的表达式或输出语句)被误用。

9.运算符是用来告诉编译程序对运算量要做何种运算的抽象形式。由编译程序转化成具体

的运算类指令。最常用的运算符分为三大类:算术运算符、关系运算符(见下一章)、逻辑

运算符(见下一章)。各种算术运算符见下表

表2.x各种算术运算符

运算符运算举例结果

+正号+88

-负号-a(a的值为3)-3

+加11+516

-减11-56

*乘法11*555

/除法11/52(这是整数除法)

/除法11.0/52.2(这是实数除法)

%取模(取整除的余数)11%51(11除以5的余数)

乘法运算符最容易漏写(比如:将2*x*y,误写为2xy),不要把实数除法运算符误用

为整数除法(比如:错把1.0/3写成1/3o1/3的值是0)。

10.所谓表达式,是用运算符将运算量(常量、变量、函数调用)连接起来的有意义的式子。

其中还可使用圆括号来改变运算符固有的先后运算顺序——圆括号内的部分优先进行运

算。单个常量、变量和函数调用是最简单的表达式。在初学编程时,表达式极易出现多种

书写错误。在命令型高级语言中,实际上只能用表达式和语句这种抽象的、形式化的方式,

来命令计算机为你进行数据处理工作(由编译程序转化为一系列的取数指令和运算指令)。

单个常量、单个变量和单个函数调用是最简单的表达式(比如x,可以看成是表达式

x+0)»

深入一步:普通的(指没有副作用的,见本章提高部分)表达式中出现变量的含义

表达式x+y中,出现变量的含义是:根据变量名(这对应着一个内存单元的地址)到

内存中去取该变量的值(取到CPU的某个寄存器中去),然后(在运算器中)进行指定的运

算。该变量的值依然不变。

11.赋值语句的形式是:<变量>=<&达式>;。赋值语句先计算出赋值号“=”右边表达

式的值,然后将此值存放在赋值号左边的变量(所对应的内存单元)之中。

注意:赋值号的左边不能是表达式,只能是单个变量。

赋值语句中变量值的变与不变:“左边改变,右边不变”

赋值号右边表达式中的变量(如果有的话)仅仅是取出它的值来参与表达式规定的运算,

变量的值仍然未变。而赋值号左边变量(所对应的内存单元中)的原来值,将被表达式算出

的新值存入而“覆盖”掉。

12.形式如x=包含方堡/x的乂滋X、;(x可以是任何简单类型的变量)

的赋值语句,大量的出现在程序中。它表示的是一种琴代天春即指明了如何由变量x的一

个老值(取出来参与表达式所规定的运算),最终得到了变量x的一个新值(最终存入到赋

值号右边的变量X中)。

专题讨论:库函数和库函数调用

•库函数:编译程序(又称为编译器)附带的,一批可以被任何别的C语言程序“调用”的,

通用的、命名了的子程序。

所有这些库函数组成了一个标准函数库,与编译程序一道打包发行。安装了C编译程序

后,我们就能在编写程序时,咽为这些库函数。

・函数调用(functioncal1):在我们编写的C语言源程序中,可以调用库函数为我们的程

序做一些复杂的(通常是辅助性的)运算和处理工作,函数的调用方式为:

库函数名(参数列表)

其中参数列表中的参数如果多于一个,参数之间就要用逗号隔开.比如要求出5.6的4

次方是多少,就要调用库函数pow(5.6,4);将2开平方,就要调用库函数:sqrt(2)。

调用库函数时千万不要忘记包含相应的头文件。参数可以是常量、变量、表达式。参数

必须要用圆括号括住。比如pow(x,3.7),sin(alfa*3.1416/180);C语言中的各种常用

库函数的调用方法说明,请见附录。

编程时调用了库函数,这些事先编译好的、命名了的子程序,就可以通过“编译”步骤

之后的“链接”这一步骤,“键入”到你所编写的程序之中,共同组成一个可执行的机器语

言程序(可执行程序文件的扩展名是.exe)。这样就可以大大减少编写程序的工作量.

以下仅列出常用的数学库函数(要包含头文件math,h):

sin(x)x为弧度,正铉函数

cos(x)X为弧度,余铉函数

X

exp(x)e以e为底的指数函数

log(x)logcx以e为底的对数函数

loglO(x)logioX以10为底的对数函数

fabs(x)X求X的绝对值函数

fmod(x,y)整除):/y的余数

floor(x)求不大于X的最大整数

pow(x,y)xy赛函数,

sqrt(x)x1/2开平方函数

1.3数据输出与输入:

1.3.1数据(变量或表达式的值)输出

可调用格式化输出库函数:printf()函数。调用的一般形式为

printf(参数1,参数2,参数3,……,参数n)

其中参数1是格式控制串。参数2,参数3,……,参数n是输出项列表

例题1.2

#nclude<stdio.h>

main()

intnum;

floatx;

num=123;

x=34.678

printf(/z%d%f”,num,x);

}

程序运行结果为:

12334.678000

格式控制串是用双引号括起来的字符串。

%d是第一个输出项num的格式说明,以有符号的卜进制形式输出整数(正数不输出符号)

%f是第二个输出项x的格式说明,以小数形式输出单、双精度实数,默认输出6位小数

显然,%d是控制整数num的,%f是控制实数x的。

为了清晰起见,格式控制串中除了格式说明之外,还可以有按照原样输出的普通字符

例如:printf("num=%dx=%f”,num,x);

输出结果为:

num=123x=34.678000

如果num是车牌号,而x是车速的话,则以下的语句更为优秀:

printf("车牌为%d号,车速是%f千米/小时\n”,num,x);

输出结果为:

车牌为123号,车速是34.678000千米/小时

在格式控制串中,还可以有换行符号'\n'(这是一种转义字符)

例:printf(<<num=%d\nx=%fw,num,x);

输出结果为:

num-123

x=34.678000

域宽和精度%m.nf:对于实数,要想改变默认的小数点后面显示6位。可改为%,nf

例如:printf例x=%.2fw,x);

输出结果为:

x=34.68〃4舍5入

printf("x=%7.2f",x);

输出结果为:

产34.68

说明:34.68左边多出两个空格,整个变量x的输出域宽(包括小数点)占了7位。

如果指定域宽小于输出项的实际宽度,则指定的域宽不起作用。

1.4.2数据(变量)输入,可调用格式化输出库函数:scanf。函数

格式化输入库函数scanf的调用,可以使得程序运行暂停下来,等待用户的输入,程序

用户可以通过键盘输入一个数值到变量(所对应的内存单元)中。不过在函数调用时,第一

个参数是相应的占位符%d,%f或%c,它们与要输入的变量类型的对应关系如下表:

占位符输入变量的类型

%dint

%ffloat

%cchar

库函数scanf()的调用通过键盘输入一个变量值的最简单形式是:

scanf("占位符、&变量名);

变量左边的符号是一个取地址符号。这个取地址符号,在scanf()函数调用时,初

学者最容易漏写。

注意:占位符中的转携申明一定要与后面存储输入数据的变曩等犁相匹配。

深入一步:格式化库输入函数scanf()的工作原理简述

等待程序用户从键盘上输入字符串,在用户按下回车键后,按照占位符中的转换说明,

对输入字符串进行数值数制转换,变成二进制的整数、实数或ASCII码,然后将此二进制的

整数、实数或ASCH码,存入到由后一个参数(即“&变量”)指定了地址的变量所对应的内

存单元中。

不必感到吃惊,你在PC机或笔记本电脑的键盘上的任何多次(或一次)击键产生的输

入,系统其实都是当作一串(或一个)字符来对待的。

功能强大、复杂而又容易用错的格式化输入库函数scanf()的比较详细的讲解请参见

本章提高部分。

1.5用计算机求解问题的一般步骤:

到目前为止,我们学了不少有关c语言的基础语法知识。但是在进行编程工作时,其实

只有变量、表达式、赋值语句、输入数据到变量和输出变量或表达式的结果,这些要素才是

我们需要重点考虑的。其中的变量,成为我们编程解决实际问题时的核心和主线。

要考虑的关键问题是:需要定义哪些变量;需要输入哪些L1知的变量;如何根据己知的

变量构造出合适的表达式,从而用赋值语句来求出未知变量的值;最后将求出的变量(或表

达式)的值输出。

用计算机求解问题,解决问题的一般过程是:

1.用普通语言简要并尽可能精确地叙述问题;

2.问题中已知的量有几个,其中有几个量随求解的具体应用场合会发生变化?(这些量应当

定义为变量)有哪几个不会发生变化(这些量可用数值常量或符号常量来表示)?其中会变

化的已知量一般应当在程序中用到此数据前,用输入函数调用(有的高级语言用输入语句)

进行数据输入。

3.问题中要求出的有几个量?

4.从已知的量如何得到要求出的量?有何公式可以利用?有何方程式可以利用?如果是公式,

就可以直接将其转换为赋值语句,只需把公式右边的数学表达式转换为高级语言的算术

表达式即可。如果是方程式,则需你自己亲自将方程式求解得到最后的公式,然后将其

转换为赋值语句,只有到了这一步,才可以将工作交给计算机做。

5.如果从已知的到要求的最终结果需要一些中间变量,则需要在程序中说明这些中间变

量,并且得到怎么从已知的量到中间变量的值的公式,最终山已知量,中间变量得到所

要求的结果的公式,将所有这些公式转换为赋值语句。

6.将结果输出。

其中最为困难的往往是第4步和第5步。这两步通常又被称为寻找求解问题的算法。

1.6逐步求精的伪代码表示算法:

表示问题求解的算法有多种方法,其中最为常用的是伪代码和流程图。但由于流程图只

适合解决规模较小的、比较简单的问题。虽然初学者易于理解和掌握,但在程序员和编程高

手中并不流行——因为它不利于对算法的构思、修改和调整(仅适用于比较清晰地表达算

法)。所以本书不作介绍(养成了用流程图来表示算法的习惯后,人们很难再转变成用其它

更好的方式去构造算法,所以还不如一步到位,采用伪代码)。本书使用的是用逐步求精的

伪代码来表示算法。所谓伪代码没有严格的规范(所以也比较灵活),但其中有一些结构要

素,可以用一些比较规范的方式来表述对问题的计算和处理流程。

一级算法只是解决问题的一个轮廓。有些复杂问题,只根据一级算法还难以直接写出c

语言的源程序。这时可对一级算法进一步求精(称为二级求精),将它其中的某些步骤,扩

展成更详细的步骤,...直到可以很容易写出C语言程序的语句时为止。

对于某些人是很显然的算法描述,对于其他人可能并不显而易见。因此,算法求精的

过程和步骤是因人而异的。你的编程经验越丰富,算法求精的步骤就可能越少。不过,算法

求精的步骤太少也不一定是好事。因为程序员的•个良好习惯,就是把伪代码表示的•级算

法(最多到二级求精),转变为源程序中的注释。注释太过简洁,会加大别人和自己阅读程

序的困难。

学习体会:

学习用伪代码来表达自己的编程思路和算法,笔者的体会是没有什么捷径让你能够迅速

掌握它,开始只能是去模仿,去领悟。时间长了,看的、模仿的、写的算法多了,慢慢就会

了。类似于学游泳和学骑自行车。在大量地模仿和大量地实践过程中,你就会不知不觉地掌

握它。

第1讲大小写字符之间的转换

编写一个程序,运行时接受用户输入的小写英文字母,程序将其转换为大写英文字母

并显示在屏幕上。

类型必修题

趣味性*

难度*

分析:此程序主要是要考虑如何由输入的任意一个小写的英文字母,得到所对应的大写英文

字母。查看ASCII码表,发现所有小写英文字母的ASCII码值都比相应的大写字母ASCII

码值大32。即存在以下等式关系:

大写英文字母的ASCII码=小写英文字母的ASCH码-32

于是编写C语言程序如下:

1#include<stdio.h>

2main()

3{

4charchi,ch2;

5printf("请键入一个小写英文字母并按回车键\n”);

6scanf&chl);

7ch2=chl-32;

8printf(“相对应的大写英文字母为%c\n",ch2);

9)

程序说明:在C语言中,字符变量其实就是占有一个字节内存的一种小整型变量,它的取值

一般就是在0——127之间的整数值,对应着标准ASCH表上的128个字符。细节问题请参

考本章提高部分:对字符变量的进一步说明。

问题1:

是否可以将第4行与第6行互相调换?

答:不可以。在C语言中,定义(序列)必须放在语句(序列)的前面。

问题2:

是否可以漏掉第4行到第8行中的任意一行最后面的分号?

答:不可以。在C语言中,任何定义或语句,都必须以分号作为结束符。只有一个例外一

—那就是复合语句,参见下一章。

问题3:如果将第8行改写为:

printf("相对应的大写英文字母为%d\n”,ch2);

程序将会出现什么问题?

答:这时输HI的是该字符所对应的ASCH码(其实也是字符变量在内存中的真正值转换成

的十进制数)。

第2讲求三个数的和及平均值

类型必修题

趣味性*

难度*

变量安排:3个已知的数要用3个变量al,a2,a3;

三个数的和用1个变量sum,

平均值用1个变量ave,

所有变量都为实型变量。

一级算法:

1.输入这三个数al,a2,a3;

2.求这三个数的的和sum及平均值ave:

3.输出sum,ave;

其中第二步由于不能直接转化成语句而需要进一步求精

根据求和及求平均值的公式

sum=a1+a2+a3

ave=sum-?3

只需将其转化为赋值语句即可

第2步的二级求精:

2.1sum=al+a2+a3;/*求这三个数的和

2.2ave=sum/3;/*求这三个数的平均值

转化成C语言程序:

/*求三个数的和及平均值*/

1#include<stdio.h>

2intmain()

3(

4floatal,a2,a3;/*三个已知数,说明为实型变量*/

5floatsum,ave;/*两个未知数,说明为实型变量*/

6/*输入这三个数al,a2,a3*/

7print/请输入3个数,3个数之间用空格隔开\n");

8scanfT%f%f%F',&al,&a2,&a3);

9

10/*求这三个数的的和sum及平均值ave*/

11sum=al+a2+a3;

12ave=sum/3;

13

14/*输出sum,ave*/

15printf("sum=%f,ave=%f,,sum,ave);

16return0;

17}

注意:运行此程序时,要用键盘输入三个数值给变量al,a2,a3,三个数之间要用空

格隔开。输完后,按下回车键,程序才会继续运行下去(其中的道理参见9.5节)。

、点评将算法的伪代码,转化为程序中的注释:

注意,伪代码形式的一级算法,在程序中转变为注释,使得程序的可读性比较好。这

是一种良好的编程习惯。

问题:如果将第8行改为scanf(t4%f,%f,%f9,&al,&a2,&a3);数据应当如何输入?

答:输入的数据之间现在不能用逗号隔开,而要用逗号隔开了。

练习:请将程序第7行删掉再编译运行,感受一下程序是否不友好了?

第3讲已知三角形的两边夹角,求对边长度及面积

类型必修题

趣味性*

难度*

一级算法

1.输入三角形的两边x,y及夹角alfa

2.求三角形对边长度一length

3.求三角形面积farea

4.输出三角形的对边长度及面积

其中第2、第3步需要进一步求精

C语言的库函数中,有一批数学库函数,其中包含正弦函数sin()及余弦函数cos()(注意,

库函数名都是小写的)。不过对这些库函数的调用,首先要包含头文件:#include<math.h>。

其次,这两个三角函数所要用到的角度是以弧度作为单位的,而不是度,因此,如果输入的

角度是以度为单位的,还必须转化位弧度为单位的角度。然后,才能利用公式来求三角形的

对边长度和面积。

sqrt函数,是用来求一个数的平方根的数学库函数。

length=sqrt(x*x+y*y-2*x*y*cos(alfa*PI/180))

area=x*y*sin(alfa*180/3.1416)*1/2

转化成C语言的程序

1#include<stdio.h>

2#include<math.h>

3#definePI3.1416

4intmain()

5{

6floatx,y,alfa;

7floatlength,area;

8

9/*输入三角形的两边x,y及夹角alfa*/

10printf(“请输入三角形的两边及夹角\n");

11scanfC%f%f%F',&x,&y,&alfa);

12

13/*求三角形对边长度*/

14length=sqrt(x*x+y*y-2*x*y*cos(alfa*PI/l80));

15

16/*求三角形面积*/

17area=x*y*sin(alfa*PI/l80)/2;

18

19/*输出三角形的对边长度及面积*/

20

21printf("三角形的对边长为%f,面积为%f\n?,,length,area);

22

23return0;

24}

问题1:第2行是否可以不要?

答:不行,只要调用库函数中的数学函数,必须包含此头文件。

小结:对变量进行初始化的三种方式

1.在变量定义时,立即给它一个初值(比如inti=0;);

2.用赋值语句,将表达式计算出来的值,赋给变量;i=0;

3.采用输入函数,将数据由外部(键盘或文件等输入设备)存入变量所代表的内存中(比

如scanf("%d",&i););。

任何变量,在定义后,你都必须采用上述三种方式之一,对其进行初始化。没有进行初

始化的变量,是决对不能出现在表达式中的。

第4讲将一个三位整数反向后输出

类型必修题

趣味性*

难度**

一级算法

1.输入一个三位整数一n

2.通过利用学过的算术运算符整除\和取余数%进行分解,分别求出此

三位整数n的百位数n3,十位数n2和个位数nl

3.反向后的三位整数为num=n1*100+n2*10+n3

4.输出此三位数

其中第2步由于不能立即写出C语言的语句,需要进一步求精:

2.1求出n的百位数:n3=n/100

2.2求出n的十位数n2=(n-n3*100)/10

2.3求出n的个位数nl=n%10

算法验证:假设将一个任意指定的三位整数比如315-n(即存入变量n中),用于验证

上述算法过程的正确性:由2.1可得到百位数n3的值为:315/100即等于3;由2.2可得到

十位数n2的取值为:(315-3X100)/10等于1;山2.3可得到个位数nl的取值为:315%10

等于5。再通过算法的第3步,反向后的值num为:nl*100+n2*10+n3=5*100+l*100+3=513。

最终值num确实等于513。

算法验证是正确的(验证算法的其他重要方法请看第讲洗扑克牌算法P页)。

转化为C语言程序:

1#include<stdio.h>

2intmain()

3(

4intn;/*输入变量*/

5intn3>n2,nl;/*中间变量*/

6intnum;/*结果变量*/

7/*输入一个三位整数n*/

8printff请输入一个三位整数\n");

9scanf("%d",&n);

10

11/*分别求出它的百位数n3,卜位数n2,个位数nl*/

12n3=n/100;

13n2=(n-n3*l00)/10;

14nl=n%10;

15

16/*反向后的三位整数为*/

17num=n1*100+n2*10+n3;

18

19/*输出此三位数*/

20printf("num=%d”,num);

21return0;

22}

问题1:第8行起什么作用?是否可以删掉这句?

答,这一句起到提示的作用。可以删掉,但程序对使用者不友好(不好用),使得用户要面

对黑屏进行数据输入,很容易出现输入错误。

问题2:是否可以将第17行和第20句合并为下面这一句并删掉第6行?

printf("num=%d”,nl*100+n2*10+n3);

答:可以。printf()函数调用时,格式串后的输出项参数,既可以是常量或变量,也可以

是一个表达式。直接输出值时可以不定义变量,直接将表达式(的计算结果)作为输出参数。

问题3:是否可以用赋值语句n=315,取代输入变量n的第9句scanf("%d”,&n);?

答:可以,赋值语句n=315,和输入函数调用语句scanf("%d”,&n);都可以使变量n能够

得到初始化(即得到有用的初值)。但用前者,程序失去了灵活性,它只能将一个固定的三位

整数315反向输出。如果想要将别的三位整数反向输出,则需要编程者重新修改程序。输

入函数调用语句scanf("%d“,&n),则可以使得程序用户输入任何的三位整数。只需将程序

重新运行一遍即可,不需要修改程序。

问题4:将第12行和第13行颠倒次序是否可以?

答:不可以,变量n3会出现初始化错误。因为颠倒次序以后,赋值语句

n2=(n-n3*100)/10;中,的表达式:(n-n3*100)/10中的变量n和n3,是要到相应

变量的内存空间中去取出数值来,参与表达式所给定的运算的。变量n的值没有问题,但变

量n3因为没有得到初始化,其内存中是垃圾数据。也就是说,13行的赋值语句:n2=(n-

n3*100)/10;的执行,依赖于12行的赋值语句:n3=n/100;的执行,变量n3的值才得以

初始化。

问题5:将13行与14行互换是否可以?

答:可以,因为两条赋值语句之间的变量并没有依赖关系。

问题6:第10条语句是否可改为printf("num=%d'',&num);

答:不可以,这样打印出来的一般是变量num的内存地址,而不是在这个地址的存储单

元中存放的(变量的)数据。也就是说,如果变量num的内存地址是123456,而变量num

的值是546,那么,此句运行后,得到的是:

num=123456

这显然是错的。

问题7:是否可以将所有变量n,n3,n2,nl都用实型float来定义?

答:不可以;程序12行、13行的赋值语句的表达式,都要求是整除运算。14行的n%10,

运算符%也要求变量n是整型,而不是实型。

问题8:是否可以将4,5,6行,用一行来表示?

答:可以。但不好,最好是将已知变量(要初始化的)、结果变量(求出的结果)和中间(临

时)变量分开写,这样有利于检查程序:已知变量是否初始化了,结果变量是否输出了。

习题1.将一个两位整数反向输出;

习题2.将一个4位整数反向输出;

第5讲鸡兔同笼问题

类型必修题

趣味性**

难度*

题目,已知鸡和兔的总头数和总脚数,求鸡有多少只,兔有多少只?

一级算法

1.输入总头数heads,总脚数feet

2.求鸡的只数chicken和兔的只数rabbit

3.输出变量chicken和rabbit的值

其中只有第二步需要求精

根据二元一次方程组可知四个变量heads,feet,chicken,rabbit之间的关系为

heads=chicken+rabbit

feet=2Xchicken+4Xrabbit

解此方程组可得到如下两个公式:

chicken=(4Xheads-feet)/2

rabbit=(feet-2Xheads)/2

将此公式转化为赋值语句,考虑到输入的总头数和总脚数不一定能得到整数解,因此将变

量chicken(表示鸡的只数),rabbit(表示兔的只数),定义为实型变量。

二级求精

2.1chicken=(4*heads-feet)/2.0

2.2rabbit=(feet-2*heads)/2.0

转化为C语言程序

1#include<stdio.h>

2intmain()

3(

4intheads,feet;

5doublechicken,rabbit;

6/*输入总头数heads,总脚数feet*/

7

8printf(“请输入总头数和总脚数,两数间用空格隔开\n”);

9scanf("%d%d",&heads,&feet);

10

11/*求鸡的只数chicken和兔的只数rabbit*/

12

13chicken=(4.0*heads-feet)/2.0;

14rabbit=(feet-2.0*heads)/2.0;

15/*输出变量chicken和rabbit的值

16

17printf(“鸡的只数%f只,兔的只数%f只",chicken,rabbit);

18return0;

19}

问题1:如果不解方程组,而直接将其转变为赋值语句,也就是用

heads=chicken+rabbit;

feet=2*chicken+4*rabbit;

取代第5和第6句,结果会如何?

答:赋值语句右边的表达式中出现的变量,必须是已经是经过初始化的变量(参见P

页)。赋值语句是用赋值号右边的表达式求出的值,存放到赋值号左边的变量表示的存储单

元中。所以,这两句是不正确的,但大多编译程序不会报错。程序运行时会用内存存储单元

中不确定的变量chicken,和rabbit的值(垃圾数据),经过运算得到两个错误数值,去改

变变量heads和feet的原来值。换言之,方程式不能直接转变为赋值语句,只有公式才可

以直接转变为赋值语句(公式是等号左边为一个要求值的变量,等号右边是一个数学代数式,

数学代数式中出现的变量的值都是已知的)。

、点评:所谓计算机的智能

此题程序一旦编好,由另一个用户来使用计算机运行这个程序,他会觉得计算机很聪明,

竟然会求解鸡兔同笼的方程式,得到正确答案。“深蓝”计算机为什么能够战胜人类的国际

象棋世界冠军卡斯帕罗夫,其道理是类似的。人类的智能转变成了程序存存放在了计算机中,

与计算机的强大计算能力(普通PC机目前每秒可运算几亿次)、“记忆能力”(存储容量巨大)

结合起来,使得运行着程序的计算机让外行看起来非常聪明能干。

1.3一个小型C程序的开发过程

一个小型c程序的整个开发过程包括如下几个步骤:

1.分析问题并进行构思,安排所需变量和符号常量;

2.用逐步求精的伪代码或流程图构造算法(并验证算法,参见第讲);

3.(用编辑软件)编辑输入源程序,并保存在扩展名为.c的文件中;(参见附录A)

4.进行编译预处理;(参见8.2节)

5.用编译器进行编译;(在集成开发环境下,第4和第5步是一次性完成的)

6.根据编译错误和警告回到第3步修改语法错误;

7,编译无错后,生程目标文件(扩展名为.obj);

8.将用户程序与库函数的程序进行连接,并生成可执行的程序(扩展名为.exe);

9.运行程序,发现链接或运行时错误则回到第3步修改;

10.结束编程过程,保存并保管好无错误的源程序文件(II后进行软件维护这是必须的);

11.将可执行程序交给用户使用。

2.13用C语言编写科学计算类小型程序的•般常用格式(在只有个main函数的情况下):

#include<stdio.h>/*头文件包含部分*/

#definePI3.1416/*符号常量宏定义部分*/

intmain()/*主函数首部*/

/*定义序列部分*/

int整型变量列表;

float单精度浮点型变量列表;

char字符型变量列表;

/*变量初始化部分,主要是输入库函数的调用语句,在程序运行时从键盘上得到由用

户输入的变量的初值,或者由赋值语句给变量赋初值*/

printfC'");〃输入的提示信息

scanfC1”,地址列表);

/*计算、处理流程部分,用来得到中间变量和最终结果的值,由计算型的赋值语句和

流程控制型语句(选择结构语句和循环结构语句)构成*/

/*程序结果输出部分,主要是输出函数的调用,将变量的值输出在显示屏匕*/

printf(.….);

return0;/*返回到操作系统*/

说明:程序输出部分,完全可以与其他语句混合在一起,变量的值的输入也可以出现在

程序的说明序列后的任何部分,这里只是列出一个一般的科学计算类程序的编程格式,读者

在后面的编程题中可以看到,不少非科学计算类的程序(比如游戏程序,管理程序),与此

格式有不小区别。此处列出来仅仅是给初学者提供一个基本编程格式的框架。只有定义序列

部分是必须放在函数体的最前面的。

提高部分:(建议初学者快速浏览遍即可,编程需要用到时再来查阅。)

二、变量类型

本书的第二章中,简单变量类型只使用了

•整型int,

・单精度浮点型float,

•字符型char

这3种类型。

这是最基本的最常用的(不过单精度浮点型使用的频度并不如双精度浮点型double)。

但还有很多由基本类型派生出的类型。在使用变量和常量的类型时有一个原则,那就是:只

要基本类型够用,就不用其它的派生类型。

其实在C89标准(ANSIC即美国在1989年颁布的C语言标准,在1999年还出了一个新

版的标准,称为C99标准)中,C语言中基本数据类型不止上述3种,还有双精度浮点型

即double型和无值型void。这些类型构成了其它几种派生类型的基础。

双精度浮点型变量,在VC++6.0中,占用8个字节的内存空间。

注意:对于双精度浮点型变量,在调用格式化输入函数scanf()输入该类型变量的值

时,必须使用的占位(格式)符是%Lf或%lf(在%与£之间的字符是英文字符L的小写,

而不是数字1。所以,最好不要用小写英文字母1,而用大写的L),不能用%f格式。但

是,在调用格式化输出函数prints)输出双精度变量的值时,却可以使用%f格式。

问题:如果变量x的类型是double型的,请问

1、输入此变量时是否可用占位符%f?

2、输入此变量时是否可用占位符%Lf?

3、输出此变量时是否可用占位符%f?

4、输出此变量时是否可用占位符%Lf?

除了字符型在任何情况下都是占用一个字节的内存空间外,对其它类型的变量,ANSI

C89标准只规定了每种数据类型的最小取值范围。在应用中如有必要,则应当查找相关手册,

确定变量的真正取值范围。在不同编译环境下,变量的取值范围会有不同。

void类型既可以用来表示无返回值的函数,又可生成适于各种元素的指针。

基本类型的修饰符:

除void类型外,基本类型之前都可以加各种修饰符。修饰符改变基本类型的含义,以

更加精确的适合特定需要。修饰符有如下几种:

signed(有符号)

unsigned(无符号)

long(长型)

short(短型)

有符号和无符号整数间的区别在于,计算机怎样解释二进制位串形式的整数的最高位

(即最左边的一位)。如果定义一个有符号整数,则C编译程序生成的代码(即机器指令)

认为该数最高位是符号标志:最高位是0,表示正数,最高位是1,则表示的是负数。(参见

后面)

如果用这些修饰符来修饰整型int,int本身可以省略不写。

例如signed等价于signedint

long等价于longint

unsigned等价于unsignedint

short等价于shortint

不过定义signedint这种类型是多余的,因为int型本身就是默认为有符号的。

对大多数程序而言,常常使用有符号数,但有符号整数的最大值,只有无符号数的一半。

例如如果系统用两个字节来存放整数,那么int型的最大值是32767。

而unsigned型的整数最大值是65535。

至于什么时候要用修饰符,还是那个简单原则:可不用时就不用。

问题:十进制32767用2进制来表示是多少?十进制65535用2进制来表示是多少?

•浮点型变量的有效位:

由程序运行得到的结果,有多少位是有效的?单精度浮点型变量的取值有效位•般是7

位。超出7位的值是无效的。

问题:一个很大的实型数,如果加上1个数值比较小的数,结果会如何?

答:比较小的那个数,有可能被忽略不计了。如果哪个比较大的单精度浮点数,其值超出了

7位的话。比如12345678.9+7.8,这个加法对于使用单精度变量来编程计算,就变得毫无

意义(因为前一个数的最后一位很可能是无效的)。

如果你想要得到精度比较高的实数运算结果,可以采用双精度实型double来说明变量。

在C语言中,双精度变量取值的有效位一般可确保卜进制的13位(如果两个双精度的浮点

数相加,此结论仍然有效,但对于乘法运算后的结果,有效位将大大减少)。

正因如此,所以在银行等金融行业,我们一般不能用浮点型变量去进行利息等的计

算,哪怕是双精度浮点型。因为帐目最终可能不平衡。解决的办法是使用长整型变量。

长整型变量的取值范围如果还不够大,则采用纯数字构成的字符串来解决问题(参见本

书后面相关的讨论)。

2.常量类型

本书的基本语法要素中,常量只使用了

•整型常量567,-425

・实型常量567.17,

・字符型常量‘a"\(T,⑻等

•字符串常量"567","hello!”等.

这些类型。

这是最基本的最常用的。在使用变量和常量的类型时也有一个原则,那就是:只要基本类型

够用,就不用其它的类型。

・除基本整型外,整型常量还包括:长整型,要以字母L或1结尾如:123456789L;无符号

整型常量,以u或U结尾如12345U,无符号长整型123456789UL。此外,除了十进制常

量外,在C语言中还可以使用八进制、十六进制形式的整型常量。八进制数以0开始,比

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论