第1章 用最简单的案例讲述C++
(本资料qq讨论群112133686)
若要学会一门程序设计语言,必须得多动手、多实践。本书就是一本用案例的方式帮助读者理解C++技术的入门书。说它入门,是因为本书的案例都是从最基本的C++语法入手,这样会让读者学得更轻松、理解更深刻。
在编写C++程序之前,读者必须了解C++的一些基本特征,如定义变量、实现输入和输出、定义数据结构来保存要处理的数据。不同的对象定义不同的变量,如整数变量、浮点数变量或字符串变量。定义变量后才能对变量进行处理,处理过程中可能涉及变量之间的转换。
本章从最简单的数学计算开始,讲解C++语言支持的5种数学运算符:加(+)、减(-)、乘(*)、除(/)和取模(%)。
1.1 C++程序的结构
C++程序编排按照“缩进”方式,程序的注释以符合“//”引出 。一个C++程序中必须有一个主程序。标识函数“()”.,函数体语句大致由变量定义、执行语句和返回语句三部分组成。C++程序基本元素有:字符集、标识符、基本数据类型和变量定义。C++有丰富的运算符,运行表达式用来说明一个计算过程,由操作符和操作数组成,其中操作数包含常量、变量或函数调用。
案例1-1显示“Hello World!”
【案例描述】
下面介绍第一个程序,其功能是在屏幕上显示“Hello World!”。虽然这个程序非常简单,但它展示了每个C++程序的基本组成结构。本例效果如图1-1所示。
图1-1 在屏幕上显示欢迎界面(cout)
【实现过程】
(1)包含本例代码需要用到的两个头文件;
(2)显示提示性字符串;
(3)暂停,等待用户的输入;
(4)用户输入任意键退出程序。
详细代码如下:
#include<iostream.h> //包含头文件
#include<iostream>
int main() //主函数
{
cout << "Hello World!" << endl; //标准输出流
cout << "Welcome to C++ Programming" << endl;
system("pause");
return 0; //返回语句
}
【案例分析】
(1)每个C++程序都包含一个或多个函数,而且必须有一个命名为main的函数,main()是所有程序运行的起始点,不管它是在代码的开头、结尾还是中间。程序由执行函数功能的语句组成。以两个斜线符号(//)开始的程序行都被认为是注释行。以#标志开始的句子是预处理器的指示语句,如#include<iostream.h>告诉编译器的预处理器将输入/输出流的标准头文件包含在本程序中。
(2)cout <<把一串字符串插入到输出流(控制台输出)中,cout的声明在头文件iostream.h中。return 0;是返回语句,表示main()函数执行完毕。
提示:在C++中,语句的分隔是以分号(;)为分隔符隔开的。并不是程序中所有的行都会被执行,如程序中的注释行(以//开头)、编译器预处理器的指示行(以#开头)、函数的声明(本例中的main函数)等,这些行都不会被执行。
1.2 常量
所谓的常量是指其值在程序的运行中不允许改变的量,分为字面常量和符号常量。包括整形常量、实型常量、字符常量、字符串常量和布尔常量。
案例1-2 各类常量的使用例子
【案例描述】
一个常量(constant)是一个有固定值的表达式。C++语言中的字用来在程序源码中表达特定的值,即用来给变量赋予特定的值。本例详细介绍了各种常量的定义,效果如图1-2所示。
图1-2 各类常量的使用例子
【实现过程】
该程序用预处理器指令#define定义常量和用const前缀定义指定类型的常量,然后分别定义整数、浮点数、字符、字符串和布尔型数据类型的常量。其代码如下:
#include <iostream>
#include <iostream.h>
#define PI 3.14159265
#define NEWLINE '\n' //换行符newline
#define WIDTH 100
double circle;
void main()
{
int r=2.2;
circle = 2 * PI * r;
std::cout <<"预处理器指令#define输出演示:"<<circle<<NEWLINE;
system("pause");
const int width = 100;
const char tab = '\t'; //跳跃符tabulation
const zip = 12440; //整数
std::cout <<"const前缀定义常量输出演示:"<< width<<tab<<zip<<NEWLINE;
system("pause");
int i1=75; //十进制 decimal
int i2=0113; //八进制 octal
int i3=0x4b; //十六进制 hexadecimal
std::cout<<"进制输出演示:"<<i1<<i2<<i3<<NEWLINE;
system("pause");
int j1=75; //整型
unsigned int j2=75u ; //无符号整型
long j3=75l; //长整型
unsigned long j4=75ul ; //无符号长整型
std::cout<<"常数数据类型输出演示:"<<j1<<j2<<j3<<j4<<NEWLINE;
system("pause");
float f1=3.14159; // 3.14159
float f2=6.02e23; // 6.02 x 10^1023
float f3=1.6e-19; // 1.6 x 10^-19
float f4=3.0 ; // 3.0
std::cout<<"浮点数输出演示:"<<f1<<f2<<f3<<f4<<NEWLINE;
system("pause");
//字符和字符串
char a1='\n';
char a2='\t'; //回车
char *a3="Left \t Right" ;
char *a4="one\ntwo\nthree" ; //定义字符串
std::cout<<"字符和字符串常量输出演示:"<<a1<<a2<<a3<<a4<<NEWLINE;
system("pause");
//布尔型常量
bool b1=true;
bool b2=false;
std::cout<<"布尔型常量输出演示:"<<b1<<b2<<NEWLINE;
system("pause");
return;
}
【案例分析】
(1)C++常量有:整数(Integer Numbers)、浮点数(Floating-Point Numbers)、字符(Characters)、字符串(Strings)和布尔型常量(Boolean Literals)。整型常数表示十进制整数值。除十进制整数外,C++还允许使用八进制(octal numbers)和十六进制(hexadecimal numbers)的字常量(literal constants)。浮点数以小数(decimals)和指数幂( exponents)的形式表示。C++程序中还有表示特殊的字符,例如,换行符newline (\n)或跳跃符tab (\t),所有这些符号的前面要加一个反斜杠(\)。布尔型只有两个有效的值:true和false,其数据类型为bool。
(2)使用预处理器指令#define,可以将那些经常使用的常量定义为自己取的名字,而不需要借助于变量。格式是:#define identifier token-stringopt,如代码中的#define PI 3.14159265。通过使用const前缀,可以定义指定类型的常量,就像定义一个变量一样,如代码中的const int width = 100。
提示:字用来在程序源码中表达特定的值,在代码中已经用了很多字来给变量赋予特定的值。例如:j1=75,其中的75就是一个字常量。
1.3 变量与基本类型
与常量相反,变量是程序的执行过程中其值可以变化的量。它的标识是用名字,是程序中最活跃的基本元素。变量的声明形式:数据类型 变量名1,变量名2,…,变量名n,如:int num,;等。变量必须先定义,定义的同时可以给它赋以初值。
案例1-3取之不尽的箱子
【案例描述】
变量代表了一个值,这个值是不固定的。使用变量可以处理各种数据,并通过一定的控制程序来完成指定的功能。在编程中怎么定义变量,怎么给变量赋值,怎么使用控制程序来操作变量,都是初学者需要掌握的基础知识。下面演示一个用变量进行加法、减法的案例,效果如图1-2所示。
图1-3 取之不尽的箱子
【实现过程】
(1)首先会提示用户输入自己的选择;
(2)根据用户的选择获取输入的值;
(3)开始做相应的加法或减法运算,当while条件满足时程序会重复执行,其中switch语句会根据输入的值来执行相应的代码。
详细代码如下:
#include <iostream>
#include <iostream.h>
int main()
{
int inputnum, outputnum,sum=0;
int sel;
do
{
cout<<"选择(1:输入箱子数据 2:取出箱子数据 3:查询库存箱子数量 其他退出):";
cin>>sel; //取得输入选择
switch(sel)
{
case 1:{
std::cout << "输入箱子数据:" << std::endl;
std::cin >>inputnum;
sum=sum+inputnum; //累加输入箱子数据
};
break;
case 2:{
std::cout << "取出箱子数据:" << std::endl;
std::cin >>outputnum;
sum=sum-outputnum; //减去输入箱子数据
};
break;
case 3:{
std::cout << "箱子数量为:" <<sum<< std::endl;
};
break;
}
}while(sel==1||sel==2||sel==3); //条件为真时重复执行
return 0;
}
【代码解析】
(1)变量占用一定的内存空间,用来存储一个不确定的值。每一个变量都需要一个名字,以便与其他变量相区别,如inputnum、outputnum和sum。变量是可以进行各种运算的,如sum=sum-outputnum;。程序中int是数据类型,C++的基本数据类型有很多,如char、short int (short)、long int (long)等。程序中的sum=0;是变量初始化语句。
(2)C++提供了一些控制结构语句来实现程序的执行顺序:
q 选择结构:格式为if (condition) statement,其中,condition是一个将被计算的表达式;
q 循环结构:while的格式为while(表达式expression){ 语句statement},它的功能是当expression的值为真时,重复执行statement;
q 多项选择结构:格式为switch (expression) {case constant1:block 1 break; default: default block of instructions},其中,default表示其他选择,也就是上面的条件都不符合时将执行此选择。
提示:编写程序时,首先要定义变量并将其初始化,然后对变量进行处理,有时在程序最后需要释放为变量申请的内存。
案例1-4物品存放
【案例描述】
实际编程中,经常将几个变量混合在一起进行计算,以实现for循环功能,下面的代码会帮助读者理解这种混合使用。本例演示的是如何打印一个正三角形符号,其中会涉及两种特殊的数据类型的前缀:本例有符号和无符号。本例效果如图1-3所示。
图1-4 物品存放
【实现过程】
(1)子函数用来打印正三角图形,它定义了一个循环从第1行到输入行数n。循环中再嵌套两个循环,用来打印空白字符' '和打印'*'字符。代码如下:
void trgl(unsigned int n) //打印正三角形的函数
{
unsigned i,j;
for (i=1;i<=n;i++) //根据输入行数执行1到n的循环
{
for (j=1;j<(n-i+1);j++) //打印空白字符
cout<<' ';
for (j=1;j<=(2*i-1);j++) //打印*字符
cout<<'*';
cout<<endl;
}
}
(2)主程序提示用户输入要打印的行数,然后调用正三角函数进行输出。代码如下:
void main()
{
unsigned int k; //定义整数
cout<<"请输入要打印的行数:";
cin>>k;
trgl(k); //调用打印正三角的函数
system("pause");
}
【代码解析】
(1)unsigned int n和unsigned i,j;这两个变量定义有什么区别呢?整型数据类型(char、short、long和int)可以是有符号的(signed)或无符号的(unsigned),这取决于需要表示的数据范围。有符号类型(signed)可以表示正数和负数,而无符号类型(unsigned)只能表示正数和0;程序中的变量默认都是signed。signed和unsigned 也可以被单独用来表示简单类型,意思分别与signed int和unsigned int相同。int数据类型的有符号范围为:-2147483648到2147483647,无符号范围为:0到4294967295。
(2)控制结构for,可以循环执行里面的代码。如for (i=1;i<=n;i++)表示执行n次循环,n代表用户输入的行数。上面代码中的3个for循环用来实现打印正三角的功能。
提示:本例的光盘代码中有一个打印反三角形的函数re_trgl,读者可以编程调试一下,以了解它与打印正三角形函数的区别,重点是理解它们在算法上的差别。
案例1-5交换物品
【案例描述】
变量定义为内存的一部分,用以存储一个确定的值。每一个变量需要一个名字,以便将它与其他变量相区别,变量的值是可以改变的。本例将演示如何赋值给变量,如何改变变量的值,效果如图1-4所示。
图1-5 交换物品
【实现过程】
(1)提示用户输入任意两个数;
(2)程序使用if语句判断哪个数小,哪个数大;
(3)执行while循环,累加从小数到大数所有的值,最后输出结果。
详细代码如下:
#include <iostream>
int main()
{
//提示输入数的范围
int v1, v2, lower, upper;
std::cout << "输入两个数: " << std::endl;
std::cin >> v1 >> v2;
//小数存储在lower变量中,大数存储在upper变量中
if (v1 <= v2) {
lower = v1;
upper = v2;
} else {
lower = v2;
upper = v1;
}
//求从小数到大数的累计和,包括小数和大数本身的值
int sum = 0;
int val = lower;
while (val <= upper) //直到upper大于val
{
sum += val; // sum = sum + val
++val; // 累加 val (等同于val = val + 1)
}
std::cout << "累加从 " << lower << " 到 " << upper
<< " 得到的值为: " << sum << std::endl;
system("pause");
return 0; //返回语句
}
【代码解析】
(1)if (v1 <= v2)是判断语句,如果输入的v2是大数,那么将v2的值赋给变量upper,小数赋给变量lower,否则相反。
(2)赋值运算符(=)的功能是将一个值赋给一个变量,如lower = v1;,表示变量lower的值为v1。cin用于输入,cout用于输出。cout(标准输出流)通常被定向到屏幕,而cin(标准输入流)通常被定向到键盘。
提示:std::cin、std:: cout和cin、cout的意义相同,不同的是cin和cout在使用时需要在程序开始处包含#include<iostrsam>,而如果没有这条语句,就要在程序中写明std::cin和std:: cout。
1.4 运算符与表达式
案例1-6 单片机应用(位操作)
【案例描述】
在与硬件操作相关的编码过程中,经常需要通过改变内存中某单元的某一位(bit)来改变位值,这就是位运算。位运算是针对二进制的操作。本例讲解单片机开发中常见的位运算的使用情况,效果如图1-8所示。
图1-6 单片机应用
【实现过程】
程序定义了4个short型变量,然后进行各种位运算,最后输出结果。代码如下:
#include <iostream>
using namespace std;
int main()
{
using namespace std;
short X=521,Y=123,C,D,E; //声明4个short型变量
C=X & Y; //位与
D=X | Y; //位或
E=~X ; //取反
cout<<"C is "<<C<<endl; //输出
cout<<"D is "<<D<<endl; //输出
cout<<"E is "<<E<<endl; //输出
system("pause");
return 0;
}
【代码解析】
C++有6种位运算符:按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)、右移(>>)。其中,按位与运算符(&)是双目运算符,其功能是将参与运算的两个数对应的二进位进行相与操作。只有对应的两个二进位均为1时,结果位才为1,否则为0。参与运算的数以补码方式出现。
提示:单片机的操作涉及硬件时,需要程序员熟悉二进制知识。
案例1-7 房间面积(*)
【案例描述】
实际编程中经常要用到数学运算,所以后面的几个【案例会介绍在程序中如何正确使用算术运算符。本例计算房间面积和比较房间面积的大小,效果如图1-9所示。
图1-7 房间面积(*)
【实现过程】
(1)编写一个子函数,提示用户输入房间的长度和宽度,然后计算面积。如果用户输入的长度和宽度之和小于或等于0,给出错误提示,返回面积为0。其代码如下:
double calcu_area(void)
{
double Length,Width,area; //定义房间的长度、宽度、面积
cout<<"请输入房间的长度、宽度:";
cin>>Length>>Width; //取得长度、宽度
if(Length+Width>0)
{
area=Length*Width; //房间的面积
}
else
{
cout<<"错误!输入的房间的长度、宽度不能构成房间!"<<endl;
area=0;
}
return area;
}
(2)主程序首先要定义用来存储房间面积的变量,再调用两次上面的子函数来计算房间1和房间2的面积,然后输出这两个面积;接着用判断语句比较两个面积的大小,显示面积的差值;最后计算两个房间面积的和。代码如下:
void main()
{
double area1,area2; //定义存储两个房间面积的变量
area1=calcu_area(); //调用计算函数
area2=calcu_area();
cout<<"房间1面积:"<<area1<<endl;
cout<<"房间2面积:"<<area2<<endl;
if(area1>area1)
cout<<"房间1面积比房间2大:"<<area1-area2<<endl;
else
cout<<"房间2面积比房间1大:"<<area2-area1<<endl;
cout<<"总面积:"<<area1+area2<<endl;
system("pause");
return ;
}
【代码解析】
(1)这个【案例介绍了算术运算符号在实际中的运用。C++语言支持的5种数学运算符为:加(+)、减(-)、乘(*)、除(/)、取模(%);计算房间的面积area=Length*Width;,输入的是double数据类型,返回的也是该类型。area1-area2表示两个double型变量相减。
(2)calcu_area()是子函数,即用户可以自定义的函数;相同功能的代码写在一起,使代码的可读性更强、更精练。
提示:加(+)、减(-)、乘(*)、除(/)运算对读者来说已经很熟悉了,它们和一般的数学运算符没有区别。读者不太熟悉的是【案例011用百分号(%)表示的取模运算(module)。
案例1-8 平分物品(/)
【案例描述】
本例还是数学计算的话题,是除运算符(/)在编程中的应用。本例还会提到怎样使用数组存储数据,这里利用循环控制结构,重复数学计算问题,另外,还介绍了怎样按格式输出对齐数据。本例效果如图1-10所示。
【实现过程】
程序首先初始化各自所分到的量A[]为0.0,然后循环10次,按比例分物品,最后输出分得的结果。其代码如下:
#include <iostream.h>
#include <iostream>
#include <iomanip.h>
int main()
{
float S,A[]={0.0,0.0,0.0}; //用数组存放各自所分到的量
char *name[]={"老大分得","老二分得","老三分得"};
for(int i=1;i<=10;i++)
{
S=19-A[0]-A[1]-A[2]; //进行计算
// cout<<S<<endl;
A[0]=S/2+A[0];
A[1]=S/4+A[1];
A[2]=S/5+A[2];
// cout<<A[0]+A[1]+A[2]<<endl;
}
for(int j=0;j<3;j++)
cout<<setiosflags(ios::left)
<<setw(4)<<name[j] //设置输出方式
<<resetiosflags(ios::left)
<<setw(10)<<setiosflags(ios::fixed)<<setprecision(10)<<A[j]<<endl;
system("pause");
return 0; //返回语句
}
【代码解析】
(1)A[0]=S/2+A[0];是一个算术表达式,计算顺序是先S/2,再+A[0],/符号为除运算符。
(2)setiosflags是命名空间iomanip里面的C++操作符,作用是执行(ios::left)指定的动作。resetiosflags(ios::left)表示输出左对齐,setiosflags(ios::fixed)<<setprecision(10)表示输出小数点后10位的浮点数。setw(4)表示输出的域宽度是4。
提示:实际编程中应灵活使用setw()和setprecision()对齐输出结果。
案例1-9 取余数(%)
【案例描述】
百分号(%)表示取模运算(module),即取两个整数相除的余数。如果a = 11 % 2;,变量a的值将会为1,因为1是11除以2的余数。本例判断用户输入整数能否被3、5和7整除,效果如图1-11所示。
图1-9 取余数(%)
【实现过程】
程序判断用户输入的一个整数能否被3、5和7整除,最多只能输入3次。代码如下:
#include <iostream.h>
#include <iostream>
int main()
{
int x,j=0;
do
{
cout<<"Input a number:"; //提示输入一个整数
cin>>x;
if ((x%3==0) && (x%5==0) && (x%7==0)) //不能被3、5和7整除
cout<<x<<" can be devided by 3,5 and 7."<<endl;
else
if (x%3==0)
if (x%5==0)
cout<<x<<" can be devided by 3 and 5."<<endl; //能被3和5整除
else
if (x%7==0)
cout<<x<<" can be devided by 3 and 7."<<endl; //能被3和7整除
else
cout<<x<<" can be devided by 3."<<endl;
else
if (x%5==0)
if (x%7==0)
cout<<x<<" can be devided by 5 and 7."<<endl; //能被5和7整除
else
cout<<x<<" can be devided by 5."<<endl; //能被5整除
else
if (x%7==0)
cout<<x<<" can be devided by 7."<<endl; //能被7整除
else
cout<<x<<" cann't be devided by 3,5 or 7."<<endl;
//不能被3、5和7整除
j++;
}while (j<=2);
system("pause");
return 0; //返回语句
}
【代码解析】
(1)注意代码j=0;和if (x%3==0),运算符=(赋值号)不同于运算符==(逻辑等)。第一个(=)是赋值运算符(将等号右边的表达式值赋给左边的变量);第二个(==)是一个判断相等关系的运算符,用来判断运算符两边的表达式是否相等。
(2)do{ ...}while (j<=2);是重复循环结构,先执行{...}中的代码,然后才检查条件(j<=2),条件不满足时结束循环。
提示:编程时双等号(==)和单等号(=)不能混淆;do-while循环和while循环的区别是前者多执行其中的代码一次,然后判断是否结束循环。
案例1-10 反转整数(%)
【案例描述】
本章开始举算法的是例。算法是指解题方案准确而完整的描述,是一系列解决问题清晰的指令。算法代表用系统的方法描述解决问题的策略机制。也就是能够对一定规范的输入,在有限时间内获得所要求的输出。本【案例举取得输入整数中每个整数位数的值,通过反向组合输出整数。本例效果如图13-1所示。
【实现过程】
取得一个输入的整数,通过取模运算取得每个整数位数的值,通过反向组合输出整数。代码如下:
int main()
{
int i,num,subscript; //定义变量
int digit[5]; //暂存整数各位数的值
cout<<"输入一个整数:"<<endl;
cin>>num;
cout<<"原来整数为:"<<num<<endl; //取得输入整数
subscript=0; //数组下标初值
do{
digit[subscript]=num%10; //取模运算
num=num/10;
subscript++; //修改下标
}
while (num>0);
for(i=0;i<subscript;i++) //整数的反向组合
num=num*10+digit[i]; //原来的值乘10再加各位数的值
cout<<"反向后整数为:"<<num<<endl;
system("pause");
return 0;
}
【代码解析】
代码中%表示取模运算,取模运算是取两个整数相除的余数。int digit[5];,声明digit数组是由5个int型元素组成。
提示:不同的算法可用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
案例1-11求余下的物品数(%)
【案例描述】
“%”表示取模运算,案例011也提到过,取模运算是取两个整数相除的余数,例如,代码a = 17 % 3;,变量a的值将会为2,因为2是17除以3的余数。有了这个运算符,在编程中方便多了,下面举一个分配物品的【案例,效果如图2-8所示。
图1-11 求余下的物品数(%)
【实现过程】
(1)定义两个子程序surp和aver,函数surp()输入物品数量,计算物品数量和参加物品分配人数取模运算a%num,如有余数,则输出每人分得的物品int(a/num)和余下的物品a-num* (int(a/num)),否则调用函数aver()输出物品,平均分配每人分得的物品a/num。其代码如下:
void surp (int a);
void aver (int a);
int num=6;
void surp (int a) {
if ((a%num)!=0) //不能平均分配,那有余下的物品
cout << "物品每人分得:"<<int(a/num)<<"余下的物品:"<<a-num*(int(a/num))<<endl;
else
aver (a);
}
void aver (int a) { //刚好平分
if ((a%num)==0) //取模运算
cout <<" 物品平均分配,每人分得物品:"<<a/num<<endl;
else surp (a);
}
(2)主程序显示参加物品分配人数,一个while循环,提示输入物品数量,取得物品数量,调用上面的子程序surp,看能否平均分,如不能平均分,还余下多少件。代码如下:
int main () {
int i;
cout <<"参加物品分配人数:"<<num<<endl;
do {
cout << "输入物品数量: (0 to exit)";
cin >> i;
surp (i);
} while (i!=0); //如果输入为0,则退出主程序
return 0;
}
【代码解析】
(1)这个【案例演示算术运算符在实际中的运用。代码中的a%num是物品数量和参加物品分配人数的取模运算;(a%num)!=0时为有余数,否则(a%num)==0为没有余数,平均分配完。
(2)代码if ((a%num)!=0)使用了if控制结构,格式是:if (condition) statement1 else statement2,对表达式(a%num)!=0进行判断,为真则执行statement1,否则执行statement2。
提示:学习过Visual Basic语言的读者应该知道,其中有个mod运算符,或者说求余运算,与C++的%取模运算是一样的。
案例1-12 班级人数(综合)
【案例描述】
前面的案例较详细地介绍了变量和算术运算符。在编程中,综合利用它们可以实现一些具体功能。本例是一个统计班级成绩的程序,通过计算和判断,得到优秀、及格或不及格的各成绩段的人数。本例效果如图1-12所示。
【实现过程】
(1)该子函数输入3门课程的成绩,然后计算平均分,判断是优秀、及格或不及格,返回对应优秀、及格或不及格的人数。其代码如下:
int& level(int grade[],int size,int& tA,int& tB,int& tC)
{
int temp=0;
for(int i=0;i<size;i++) //循环取得成绩总分
temp+=grade[i]; //累加
temp/=size; //取得成绩平均分
if (temp>=85) return tA; //优秀
else if (temp>=60) return tB; //及格
else return tC; //不及格
}
(2)主函数中,首先定义数组int a[5][3]用来存储成绩,然后初始化优秀、及格或不及格人数,初始化学生人数和3门课程,再循环输入每个学生的成绩,调用上述子函数进行计算,最后显示循环输入每个学生的成绩。代码如下:
int main()
{
int a[5][3]={{65,60,78},{60,80,90},{89,92,78},{75,65,82},{65,50,58}};//学生成绩
int typeA=0,typeB=0,typeC=0;
int stdSize=5; //假设统计5个学生的成绩
int gradeSize=3; //有3门课程
for(int i=0;i<stdSize;i++) //循环输入每个学生的成绩
level(&a[i][0],gradeSize,typeA,typeB,typeC)++;//返回的引用作为左值,直接增量
cout<<"优秀人数为:"<<typeA<<endl;
cout<<"及格人数为:"<<typeB<<endl;
cout<<"不及格人数为:"<<typeC<<endl;
system("pause");
return 0; //返回语句
}
【代码解析】
(1)a[5][3]是二维数组,大小为5´3。函数level()的声明中,有几个变量的类型后面跟了一个地址符&,它的作用是指明变量是按地址传递的,而不是像通常一样按数值传递。
(2)组合运算符(+=、-=、*=、/=及其他),这些组合运算符让代码看起来更简洁。本例应用了组合运算符+=和/=,temp+=grade[i];等同于temp=temp+grade[i];。同样,temp/=size;等同于tempt=temp/size。
提示:实际编程中应灵活应用组合运算符,使编写的程序更简洁。
案例1-13 称水果(比较)
【案例描述】
在编程的时候经常会用到判断语句if和多选项判断语句switch。本例通过判断输入水果的品种得到不同的水果价格,然后计算价钱。通过本例的介绍,读者应学会如何正确使用if和switch。本例效果如图1-13所示。
图1-13 称水果(比较)
【实现过程】
程序首先提示用户输入水果的重量、水果的品种编号,然后取得品种编号对应的价格,做后计算应付的钱数并输出这个价钱。其代码如下:
#include <iostream>
#include <iostream.h>
#include <math.h>
int main()
{
int type,sum=0;
double sale,weigt=0,price;
std::cout << "输入水果重量:" << std::endl;
std::cin >>weigt;
std::cout << "1.西瓜1.80 2.木瓜1.70 3.哈密瓜2.60 4.山竹1.60" << std::endl;
std::cout << "输入水果品种编号:" << std::endl;
std::cin >>type;
switch (type) //输出数字
{
case 1: //西瓜
std::cout << "输入水果品种---西瓜,每公斤1.80" << std::endl;
price=1.80;
break;
case 2:
std::cout << "输入水果品种---木瓜,每公斤1.70" << std::endl;
price=1.70;
break;
case 3:
std::cout << "输入水果品种---哈密瓜,每公斤2.60" << std::endl;
price=2.60;
break;
case 4:
std::cout << "输入水果品种---山竹,每公斤1.60" << std::endl;
price=1.60;
break;
default:
break;
}
if (weigt<=0)
sale=0.00;
else
sale=floor(weigt*price*100 +0.5)/100; //小数点后2位四舍五入
cout<<"应付人民币: "<<sale<<"元"<<endl;
system("pause");
return 0;
}
【代码解析】
(1)代码中的if为条件结构,形式是if (condition) statement,条件结构表示仅在某种条件满足的情况下才执行一条语句或一个语句块。代码中,switch语句的语法形式为switch(expression) {[case constant1:]. [statement]. . . [default:statement] },它的作用是检查表达式expression是否有多个可能的常量值,如值为constant1时,执行statement,作用类似于多个if语句的嵌套。
(2)数学函数floor返回小于或者等于指定表达式的最大整数,使用它需要包含头文件math.h。
提示:从实现结果来看,switch是可以用if替换的,不过程序的可读性会变差,不如使用switch简洁。
案例1-14 信号灯(++ --)
【案例描述】
为了书写简练,使用算术运算符通常会改变写法,如递增运算符(++)和递减运算符(--)。本例以模拟常见的信号灯为例,介绍这两个符号的应用,效果如图1-14所示。
图1-14 信号灯(++ --)
【实现过程】
程序先输入一个计算时间的整数,然后从0到num循环,红灯变量递增,绿灯变量递减,时间间隔是1秒。代码如下:
#include <iostream.h>
#include <iostream>
void main()
{
int red,green,num;
cout<<"请输入一个数!"<<endl;
cin>>num;
if ((num>0)&&(num<60))
{
green=num;
red=0;
for(int i=0;i<num;i++) //从0到num循环
{
system("cls"); //清除屏幕
red++; //red递增
cout<<"红灯 "<<red<<endl;
green--; //green递减
cout<<"绿灯 "<<green<<endl;
_sleep(1*1000); //延时1秒
}
}
else cout<<"输入的数不合规定!"<<endl;
system("pause");
}
【代码解析】
(1)递增运算符(++)和递减运算符(--)使得变量中存储的值加1或减1,分别等同于+=1和-=1。因此,red++、red+=1、red= red +1在功能上全部等同,即全部使变量red的值加1。它的存在是因为最早的C编译器的原因,现在编译器已基本自动实行代码优化,所以,以上三种不同的表达方式编译成的机器代码在实际运行上已基本相同。同理,green--、green-=1、green= green -1在功能上全部等同,即使变量green的值减1。
(2)表达式green =3;red=++green;,这时red的值为 4,green的值为4,但表达式green =3;red=green++;,这时red的值为3,green的值为4。虽然在简单表达式如a++或++a中,这两种代码的写法代表同样的意思,但当递增或递减的运算结果被直接用在其他的运算式中时,它们就代表不同的意思:当递增运算符被用作前缀prefix (++green)时,变量a的值先增加,然后再计算整个表达式的值,因此增加后的值被用在表达式的计算中;当它被用作后缀suffix (green ++)时,变量a的值在表达式计算后才增加,因此,a在增加前所存储的值被用在表达式的计算中。
提示:初学者不一定都要求做到代码书写简练,要多实践。
案例1-15 篮球反弹
【案例描述】
现实生活中小的数学计算问题要用编程实现,往往会涉及到循环和四则运行。虽然简单,但是编写程序要计算正确编程也要仔细。本【案例演示一个球从100m高处*落下,每次着地后又跳回到原高度的一半再落下,再反弹,求它在第十次落地高度和经过的距离。本例效果如图1-15所示。
【实现过程】
第十次落地时,经过的距离为多少米,第十次反弹多高。其代码如下:
#include <iostream.h>
void main()
{
double height=100,sum=0; //定义高度和经过的距离
int count = 10;
int i;
for(i=1;i<=10;i++) //10次反弹
{
sum +=height+height/2; //总的距离
height /=2;
}
cout<<"第十次落地时,经过"<<(sum-height)<<"米"<<endl;
cout<<"第十次反弹高度 :"<<height<<endl;
system("pause"); //暂停
}
【代码解析】
第一次落地走了100米,之后弹上去,有上有下,是一个2倍的进程。第一次是100,第二次是100*0.5^1*2,第十次是100*0.5^9*2,然后求和100+100(0.5^1+0.5^2+...+0.5^9)*2。
提示:C++以书写简练著称的一大特色就是运用了组合运算符(+=、-=、*= 和/=及其他),这些运算符使得只用一个基本运算符就可改写变量的值。
案例1-16 求被3整除的数(%+算法)
【案例描述】
在第1章学过数学计算符(*)、(/)和(%),本例涉及(%)运行。本例举个编程中经常用到的数学计算的【案例,效果如图1-16所示。
图1-16 求被3整除的数(%+算法)
【实现过程】
通过一个for循环,和3取模运行,逐个输出整数的值。其代码如下:
#include <iostream>
using std::endl;
using std::cout;
int main()
{
long i;
int n=0;
cout<<"个位数是6且能被3整除的数如下:"<<endl;
for(i=10006;i<99996;i+10) //for循环
{
if(i%3==0) //取模运算
{
cout<<i<<"\t"; //输出整数
n++;
}
}
cout<<"个位数是6且能被3整除的总个数如下:"<<n<<endl;
return 0;
}
【代码解析】
%表示的是取模运算,也就是取两个整数相除的余数。例如编写a = 11 % 3;,变量a的值将会为结果2,因为2是11除于3的余数。
案例1-17 鸡兔同笼
【案例描述】
这个案例是个古老数学问题,实际上是一个算术运算求解问题。涉及到算术运算符号,编程的时候经常会遇到这样简单的数学问题,本例根据笼中鸡兔头和脚数,求鸡兔头数,效果如图1-17所示。
【实现过程】
主函数输入测试次数,for循环取得头和脚的数量,判断是否有解,根据算法输出兔子和鸡的数量。代码实现如下:
#include <iostream>
using namespace std;
int main()
{
int n;
cout<<"输入测试数:"<<endl;
cin>>n; //输入测试次数
for(int i=1;i<=n;i++)
{
int m,n;
cout<<"输入头和脚的数量:"<<endl;
cin>>n>>m;
if((m%2!=0)||((m/2-n)<0)||((2*n-m/2)<0)) //判断是否有解
cout<<"No answer"<<endl; //不能得出结果
else
cout<<"兔子数"<<2*n-m/2<<" "<<"鸡数"<<m/2-n<<endl; //根据算法
}
system("pause");
return 0;
}
【代码解析】
(1)鸡兔同笼是中国古代著名趣题之一。有若干只鸡兔同在一个笼子里,从上面数有35个头,从下面数有94只脚,问笼中各有几只鸡和兔?这个问题有个最简单的算法:(总脚数-总头数*鸡的脚数)÷(兔的脚数-鸡的脚数)=兔的只数,按这个算法答案就是(94-35×2)÷2=12(兔子数),总头数(35)-兔子数(12)=鸡数(23)。
(2)代码基本上用的是简单数学运算符,涉及到C++基本的加、减、乘、除和取模算术运算。
1.5 本章练习