问题求解与程序设计(第2版)——鲍春波、林芳


问题求解与程序设计(第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


  目录