问题求解与程序设计(第2版)——鲍春波、林芳
第一章 计算机与程序设计
1.4 典型程序演示
程序清单1.1
猜数游戏
/*
Guess number game,guessnNumber.c
*/
#include<stdio.h>
#include<stdlib.h> //for rand()
#include<time.h> //for time()
#include<conio.h> //for getch() 本行课本少写了,会报错,缺少getch函数的声明
// function prototype
int makeMagic(); //think a magic number
void guessNumber(int magic); //guess
//application entrance
int main(void)
{
char a;
int magic;
srand(time(NULL)); //seed random number generator
printf("Welcome to GuessNumber Game\n");
do
{
magic=makeMagic(); //call makeMagic
printf("I have a magic number between 1 to 1000,please guess:");
guessNumber(magic); //call guessNumber
printf("Continue or no? Y/N\n");
a=getch(); //input a character for continue or no
}while(a=='Y'||a=='y');
return 0;
}
// define makeMagic function
int makeMagic()
{
int magicNumber;
magicNumber=rand()%1000+1;
return magicNumber;
}
// define guessNumber function
void guessNumber(int magic)
{
int guess;
do
{
scanf("%d",&guess);
if(guess>magic)
printf("Wrong,too high!try again!\n");
else if(guess<magic)
printf("Wrong,too low!try again!\n");
}while(guess<magic||guess>magic);
printf("Congratulation!you are right!\n");
}
第二章 数据类型与变量——程序设计入门
2.1 在屏幕上输出文字信息
程序清单2.1
/*
* hello.c 在屏幕上显示信息
*/
#include<stdio.h> //printf需要的头文件
int main(void) //应用程序的入口
{
printf("Hello,Welcome to C/C++!\n"); //调用printf,显示给定的信息
return 0;// 程序正常结束时返回0
}
程序清单2.2
/*
* hello.c:display Messages
*/
#include<stdio.h>
int main(void)
{
printf("Hi,How are you!\n");
printf("Hello\nWelcome to C/C++!\n");
return 0;
}
表2.1 常用的转义序列
| 转义序列 | 含义 | 转义序列 | 含义 |
|---|---|---|---|
\n |
换行(Newline) | \' |
输出序列号(Single Quotation Mark) |
\\ |
水平制表(Horizontal Tabulation) | \? |
输出问号(Question Mark) |
\a |
输出反斜杠(Backslash) | \r |
输出回车符(Carriage Return)(不换行,光标定位当前行的开始位置) |
\* |
响铃符(Alert or Bell) | \b |
退格(Backspace) |
\" |
输出双引号(Double Quotation Mark) | \t |
水平制表(Tab=4个空格) |
2.2计算两个固定整数的和与积
程序清单2.3
两个固定整数的和与积
/*
* add2int1.c :两个固定整数的和与积
*/
#include<stdio.h>
int main(void)
{
printf("2+3=%d\n2*3=%d",2+3,2*3); //2+3和2*3的结果填入到格式说明中%d对应的位置
return 0;
}
程序清单2.4
/*
* add2int2.c 两个固定整数的和与积改进版
*/
#include<stdio.h>
int main(void)
{
int number1,number2; //为存储整数声明几个整型变量
int sum,product;
number1=2; //为变量赋值
number2=3;
sum=number1+number2; //两个整型变量中的值求和,结果放在整型变量sum中
product=number1*number2; //两个整型变量的值求积,结果放在变量product中
printf("%d+%d=%d\n",number1,number2,sum); //按照格式输出各个变量中的值
printf("%d*%d=%d\n",number1,number2,product);
return 0;
}
程序清单2.5
/*
* intalign:整数输出的宽度和对齐方式
*/
#include<stdio.h>
int main(void)
{
printf("%d %d %d\n",2,33,556); //整数的实际宽度输出
printf("%d %d %d\n",232,2233,245);
printf("%5d %5d %5d\n",2,33333,556); //规定了整数的宽度是5,不足五位的右对齐
printf("%d %d %d\n",232,33333,245);
printf("%-5d %-5d %-5d\n",2,33333,556); //规定了整数的宽度是5,不足五位的左对齐
printf("%-5d %-5d %-5d\n",232,33333,245);
return 0;
}
程序清单2.6
/*
* sizeoftype.c: 各种常用数据类型的变量
*/
#include<stdio.h>
int main(void)
{
printf("Data type Number of Bytes\n");
printf("--------- ---------------\n");
printf("char %d\n",sizeof(char));
printf("int %d\n",sizeof(int));
printf("unsigned %d\n",sizeof(unsigned));
printf("short %d\n",sizeof(short));
printf("long long %d\n",sizeof(long long));
printf("float %d\n",sizeof(float));
printf("double %d\n",sizeof(double));
return 0;
}
2.3计算任意两个整数的和与积
程序清单2.7
/*
* add2int3.c :求两个任意整数的和与积
*/
#include<stdio.h>
int main(void)
{
int number1,number2; //为存储整数声明几个整型变量
int sum,product;
scanf("%d%d",&number1,&number2); //从标准输入读取数据
sum = number1 + number2; //两个整型变量中的值求和,结果放在整型变量sum中
product = number1 * number2; //两个变量中的值求积,结果放在product中
printf("%d + %d = %d\n",number1,number2,sum); //按照格式输出各个变量中的值
printf("%d * %d = %d\n",number1,number2,product);
return 0;
}
程序清单2.8
/*
* add2int4.c : 求任意多两个任意整数的和与积
*/
#include<stdio.h>
int main(void)
{
int number1,number2; //为存储整数声明几个整形变量
int sum,product;
while(1)
{
scanf("%d%d",&number1,&number2); //按照规定的格式从标准输入读数据
sum = number1 + number2; //两个变量中的值求和,结果放在整型变量sum中
product = number1 * number2; //变量中的值求积,结果放在整型变量product中
printf("%d+%d=%d\n",number1,number2,sum);//按照格式输出变量中的值
printf("%d*%d=%d\n",number1,number2,product);
} //无限循环,在运行时要结束这个无限循环必须通过CTRL-C强行中断
return 0;
}
2.4温度转换
程序清单2.9
/*
* fahr2celsius1.c : 华氏温度转化为摄氏温度
* 在程序中给定一个华氏温度,用变量初始化确定一个华氏温度值
* 使用计算公式:celsius=5*(fahr-32)/9计算摄氏温度
*/
#include<stdio.h>
int main(void)
{
int fahr=100; //初始化
int celsius; //未初始化
celsius = 5 * (fahr-32)/9; //计算结果赋给celsius
printf("%d\n",celsius); //输出结果
return 0;
}
程序清单2.10
/*
* fahr2celsius2.c: 华氏温度转换为摄氏温度
* 键盘输入华氏温度,使用计算公式celsius = 5 *(fahr-32)/9计算摄氏温度
*/
#include<stdio.h>
int main(void)
{
int fahr; //变量声明
int celsius;
scanf("%d",&fahr); //输入一个华氏温度
celsius = 5 * (fahr-32)/9; //计算对应的摄氏温度
printf("%d\n",celsius); //输出
return 0;
}
程序清单2.11
/*
* fahr2celsius3.c:
* 对fahr=0、20...300使用公式celsius = 5*(fahr-32)/9
* 分别计算对应的摄氏温度值,打印出华氏温度与摄氏温度对照表
*/
#include<stdio.h>
int main()
{
int fahr,celsius;
int lower,upper,step;
//初始化
lower=0; //温度表的下限
upper=300; //温度表的上限
step=20; //步长
fahr=lower; //华氏温度从0开始
while(fahr<=upper){ //这里fahr<=upper是一个重复的条件
celsius = 5*(fahr-32)/9; //对不同的fahr进行计算celsius的值
printf("%d\t%d\n",fahr,celsius); //按照格式打印华氏与摄氏的温度值
fahr=fahr+step; //fahr增加一个步长
} //对增加的步长进一步回到while,判断重复的条件是否真实
return 0;
}
2.4.2运算的优先级和结合性
如果在一个表达式中有两个以上同一级别的双目算术运算,则从左向右依次进行,在C/C++语言中称这种特性为结合性
因此可以说双目算术运算是左结合的,而单目的取正和取负运算以及赋值运算则是右结合的
表2.2运算的优先级和结合性(优先级从高到低)
| 运算符 | 含义 | 结合性 |
|---|---|---|
| () | 括号 | - |
| +,- | 单目运算,取正、负 | 从右向左 |
| *,/,% | 双目运算,乘、除、求余 | 从左向右 |
| +,- | 双目运算,加、减 | 从左向右 |
| = | 双目运算,赋值 | 从右向左 |
2.5求两个整数的平均值
程序清单2.12
/*
* intAverage.c: 求两个整数的平均值,结果仍为整数
*/
#include<stdio.h>
int main(void)
{
int number1; //声明存放第一个加数的变量
int number2; //声明存放第二个加数的变量
int average; //声明存放整数平均值的变量
scanf("%d%d",&number1,&number2); //从标准输入读取数据
average=(number1+number2)/2; //计算平均值
printf("%d\n",average); //输出结果
return 0;
}
程序清单2.13
/*
* floatAverage.c:求两个整数的平均值,结果为实数
* 默认的精度,精确到6位小数
*/
#include <stdio.h>
int main(void)
{
int number1; //存放第一个加数的变量
int number2; //存放第二个加数的变量
float average; //存放整数平均值
scanf("%d%d",&number1, &number2);//从标准输入读数据
average =(float) (number1 + number2)/2; //把整型数显示转换为浮点型计算平均值
printf("%f\n",average);//按默认的精度输出,精确到6位小数
//average =(number1 + number2)/2.0; //把整型数2显示转换为浮点型2.0, 计算平均值
//printf("%f\n",average);//按默认的精度输出,精确到6位小数
return 0;
}
程序清单2.14
/*
* floatAverage2.c:求两个整数的平均值,结果为实数,精确到1位小数
*/
#include <stdio.h>
int main(void)
{
int number1; //定义整型加数1
int number2; //定义整型加数2
float average; //定义实数平均值,浮点型/单精度
scanf("%d%d",&number1, &number2); //从标准输入读数据
average = (float)(number1 + number2)/2;//把整型数显示转换为浮点型,再计算平均值
printf("%.1f\n",average);//输出浮点型平均值,精确到1位小数
return 0;
}
表2.3浮点型数据的IEEE标准
IEEE 754是IEEE二进制浮点数算术标准(ANSI/IEEE Std.754-1985),又称IEC 60559:1989,它是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点预算器所采用,该标准的主要贡献者是美国伯克利大学的Kahan教授,1989年的ACM图灵奖得主
IEEE : Institute of Electrical and Electronics Engineers
| 类型 | 内存字节数 | 最小正值 | 最大正值 | 精度 |
|---|---|---|---|---|
| float | 4 | 1.17×10^-38^ | 3.40×10^38^ | 6~8位有效数字 |
| double | 8 | 2.22×10^-308^ | 1.79×10^308^ | 6~17位有效数字 |
程序清单2.15
/*
* floatPrecision.c: 浮点数的精度
*/
#include<stdio.h>
int main(void)
{
float x;
double y;
printf("the default precision:\n");
x = 0.1234567292012; //小数位数大于6位
y = 0.1234567890123456939; //小数位数大于16位
printf(" %f %f\n",x, y); //单精度到小数6位,双精度小数也是6位
x = 1234.1234567292012; //整数若干位,小数若干位
y = 1234.1234567890123456939; //整数若干位,小数若干位
printf(" %f %f\n",x, y); //单精度:整数加小数有效数字8位,双精度最多16位,小数最多6位
x = 12345678.7234567292012; //
y = 1234567890123456789.233674755435;
//scanf("%f%lf",&x, &y); //也可以键盘输入
printf(" %f %f\n",x, y); //默认最高输出精度:float8位,double17位
printf("the customized width and precision:\n ");
x = 0.1234567292012; //小数位数大于6位
y = 0.123456789012345678939; //小数位数大于17位
printf("%11.9f %20.18f\n",x, y); //指定输出精度,但单精度的最多8位有效,双精度最多17位有效
x = 12345678.7234567292012; //
y = 1234567890123.233674755435;
printf("%11.9f %20.18f\n",x, y); //指定输出精度,但单精度的最多8位有效,双精度最多17位有效
return 0;
}
程序清单2.16
/*
* floaterr1.c: 舍入误差
*/
#include<stdio.h>
int main(void)
{
float a, b;
a = 12345678900;
b = a + 200;
printf("a=%f\n +200\nb=%f\n", a, b);
b = a + 1000;
printf("\na=%f\n +1000\nb=%f\n", a, b);
b = a + 2000;
printf("\na=%f\n +2000\nb=%f\n", a, b);
b = a + 4000;
printf("\na=%f\n +4000\nb=%f\n", a, b);
b = a + 40000;
printf("\na=%f\n +40000\nb=%f\n", a, b);
a = 1234567.125;
b = a + 234.796;
printf("\na=%f\n +234.796\nb=%f\n", a, b);
return 0;
}
程序清单2.17
/*
* floaterr2.c: 浮点数的溢出
*/
#include<stdio.h>
int main(void)
{
float toobig=3.4E38*100.0f;//3.4E38是最大的单精度数
printf("%f\n", toobig); //扩大100倍后向上溢出
float x=0.123456; //6位有效数字
printf("%f\n",x/100); //再缩小100倍向下溢出
return 0;
}
程序清单2.18
/*
* typeconvers.c : 算术运算类型转换和赋值运算类型转换
* 输出时不能转换
*/
#include<stdio.h>
int main(void)
{
int k=10;
double x=100.0;
printf("%f %d\n", k+x, k+x); //k提升为double型与x相加,但x不能降低为int
printf("%d %f\n", k, x); //k依然是整型变量,它仅仅是在k+x时临时提升
float y = 5.6;
k = y/2;
x = y/2;
printf("%d %f\n", k, x);
return 0;
}
2.6计算圆的周长和面积
程序清单2.19
define宏定义用法
/*
* areacircle.c: 计算圆的周长和面积
*/
#include<stdio.h>
#define PI 3.141593
int main(void)
{
int r;
double circ,area;
scanf("%d",&r);
circ = 2*PI*r;
area = PI*r*r;
printf("PI:%f\n", PI );
printf("circumference = %f\n", circ );
printf("area = %f\n", area );
return 0;
}
带参数的宏
- 除了一个常量可以定义一个宏代替外,一个表达式也可以定义一个带参数的宏替代。带有参数的宏定义形式如下
#define 宏名字(宏参数列表) 含有参数的宏替换表达式
/*
* macro.c : 带参数的宏
*/
#include<stdio.h>
#define SQUARE(x) ((x) * (x))
int main(void)
{
int a = 99;
printf("%d\n", SQUARE(a+1));
return 0;
}
注意,在宏定义中,必须把参数括起来,还要把整个替换表达式括起来,不然宏替换的结果就会出错。
第三章 判断与决策——选择程序设计
3.1让成绩合格的学生通过
程序清单3.1
/*
* stupassed.c:判断学生成绩是否通过
*/
#include<stdio.h>
int main(void)
{
int grade;
while( 1 )
{
scanf("%d",&grade);
if (grade >= 60)
printf("Good! You passed!\n");
}
return 0;
}
表3.1运算的优先级和结合性(优先级从高到低)
| 运算符 | 含义 | 结合性 |
|---|---|---|
| () | 括号 | 最近的括号配对 |
| +,- | 单目运算,取正、负 | 从右向左 |
| *,/,% | 双目运算,乘、除、求余 | 从左向右 |
| +,- | 双目运算,加、减 | 从左向右 |
| >,<,>=,<= | 双目运算,比较大小 | 从左向右 |
| ==,!= | 双目运算,判断是否相等 | 从左向右 |
| = | 双目运算,赋值 | 从右向左 |
程序清单3.2
/*
* compare2numbers.c:比较两个数
*/
#include<stdio.h>
int main(void)
{
int a=10, b=20;
printf("%d ",a>b);
printf("%d ",a>=b);
printf("%d ",a<b);
printf("%d ",a<=b);
printf("%d ",a==b);
printf("%d\n",a!=b);
return 0;
}
程序清单3.3
/*
* logicAssign.c:两个数的比较结果暂存到一个逻辑变量中或者整型变量中
*/
#include<stdio.h>
//#include<stdbool.h>
int main(void)
{
int a=10, b=20;
//int status;
//_Bool status;
bool status;
status=a>b;
printf("%d ",status);
status=a>=b;
printf("%d ",status);
status=a<b;
printf("%d ",status);
status=a<=b;
printf("%d ",status);
status=a==b;
printf("%d ",status);
status=a!=b;
printf("%d\n",status);
return 0;
}
程序清单3.4
/*
* compare2numbers2.c:比较两个数
*/
#include<stdio.h>
int main(void)
{
int a, b;
scanf("%d%d",&a,&b);
if(a>b)
printf("%d>%d\n",a,b);
if(a>=b)
printf("%d>=%d\n",a,b);
if(a<b)
printf("%d<%d\n",a,b);
if(a<=b)
printf("%d<=%d\n",a,b);
if(a==b)
printf("%d==%d\n",a,b);
if(a!=b)
printf("%d!=%d\n",a,b);
return 0;
}
程序清单3.5
/*
* realCompare.c: 实数比较大小
*/
#include<stdio.h>
int main(void)
{
float a,b;
a=3.1;
b=3.099999991397669;
printf("%11.9f %11.9f\n",a,b);
printf("%f %f\n",a,b);
if(a>b)
printf("a>b\n");
if(a<b)
printf("a<b\n");
if(a==b)
printf("a==b\n");
double x,y;
x=3.1;
y=3.099999991397669;
printf("%20.18f %20.18f\n",x,y);
printf("%f %f\n",x,y);
if(x>y)
printf("x>y\n");
if(x<y)
printf("x<y\n");
if(x==y)
printf("x==y\n");
return 0;
}
程序清单3.6
/*
* realCompare2.c: 判断给定的PI值是否符合精度
*/
#include<stdio.h>
#include<math.h>
int main(void)
{
double eps=0.001,yourPi;
double pi=3.1415926;
printf("I have a precision now,pls input your PI value:\n");
scanf("%lf",&yourPi); //输入一个pi值
double err=fabs(pi-yourPi); //计算误差
printf("fabs(pi-yourPi)=%10.8f\n",err); //打印误差
if(err<=eps) //符合精度
{
printf("%10.8f = %10.8f according to the precision %10.8f\n",pi,yourPi,eps);
printf("yourPi %10.8f is met the precision %10.8f\n",yourPi,eps);
}
if(fabs(pi-yourPi)>eps) //没有达到精度
printf("yourPi %10.8f is not met the precision eps %10.8f\n",yourPi,eps);
return 0;
}
3.2按成绩把学生分成两组
P70