作者构造了Picture类,汇总需求细节,见招拆招,尤其在“接口设计”这一节里,把自己当成客户,跟自己一问一答(“我希望有些什么操作,如何表述这些操作?”),逐步分析不断复杂的需求,然后抽象出接口,其中不乏作者的经验之谈:要想决定具体操作的形式,有一个好办法,就是试着使用这些操作,从使用的例子推导出操作的定义形式要比从头苦思冥想地发明这些操作容易得多。
1、最初需求是打印如下文字:
Paris
in the
Spring
2、构造的Picture类,只需要一个构造函数和一个输出即可完成,如果打印如下文字:
+-------+
|Paris |
|in the |
|Spring|
+-------+
3、如果使用C式的过程代码,需要做些打印内容的改变可以完成,作者为Picture类添加了一个frame(Picture&)来完成,如果打印内容改变了,我想C式代码作者就会抓头皮了:
Paris +-------+
in the |Paris |
Spring|in the |
|Spring|
+-------+
4、Picture类便有了 Picture operator |(const Picture&, const Picture&) 接口,用字符‘|’做两个Picture对象的横向合并,用Picture operator &(const Picture&,const Picture&)接口,用字符‘&’做纵向合并,当我们需要打印如下文字的时候:
+--------------+
|+------+ |
||Paris | |
||in the| |
||Spring| |
|+------+ |
|Paris +------+|
|in the|Paris ||
|Spring|in the||
| |Spring||
| +------+|
+--------------+
我们只需要一句 cout << frame(frame(p) & (p | frame(p))) << endl即可完成。
下面是Picture类的源码(原书代码中有些许错误,均做过修改和测试):
1 #include <iostream>
2
3
4 using namespace std;
5
6 class Picture
7 {
8 friend Picture frame(const Picture&); //加框
9 friend Picture operator&(const Picture&, const Picture&); //纵向合并
10 friend Picture operator|(const Picture&, const Picture&); //横向合并
11 friend ostream& operator << (ostream& o, const Picture& p);
12 private:
13 int height, width;
14 char* data;
15 char& position(int row, int col){
16 return data[row * width + col];
17 };
18 char position(int row, int col) const{
19 return data[row * width + col];
20 };
21 void copyblock(int,int,const Picture&);
22 public:
23 Picture() : height(0),width(0),data(0){};
24 Picture(const char* const*, int);
25 Picture(const Picture& );
26 ~Picture();
27 Picture& operator=(const Picture&);
28 static int max(int m, int n)
29 {
30 return m > n ? m : n;
31 };
32 void init(int h, int w);
33 void clear(int , int ,int ,int );
34 };
35
36 ostream&
37 operator << (ostream& o, const Picture& p)
38 {
39 for(int i = 0; i < p.height; ++i)
40 {
41 for(int j =0; j < p.width; ++j)
42 o << p.position(i,j);
43 o << endl;
44 }
45 return o;
46 };
47
48
49 void Picture::init(int h, int w)
50 {
51 height = h;
52 width = w;
53 data = new char[height * width];
54 };
55
56 Picture:icture(const char* const* array, int n)
57 {
58 int w = 0;
59 int i ;
60 for(i = 0; i < n; i++)
61 w = Picture::max(w, strlen(array));
62 init(n,w);
63 for(i = 0; i < n; i++)
64 {
65 const char* src = array;
66 int len = strlen(src);
67 int j = 0;
68 while(j < len)
69 {
70 position(i,j) = src[j];
71 ++j;
72 }
73 while(j < width)
74 {
75 position(i, j) = ' ';
76 ++j;
77 }
78 }
79 }
80
81 Picture:icture(const Picture& p):
82 height(p.height), width(p.width),
83 data(new char[p.height * p.width])
84 {
85 copyblock(0,0,p);
86 }
87
88 Picture::~Picture()
89 {
90 delete []data;
91 }
92
93 Picture& Picture:perator=(const Picture& p)
94 {
95 if(this != &p)
96 {
97 delete []data;
98 init(p.height,p.width);
99 copyblock(0,0,p);
100 }
101 return *this;
102 }
103
104 void Picture::copyblock(int row,int col,const Picture& p)
105 {
106 for(int i =0; i < p.height; ++i)
107 {
108 for(int j =0; j < p.width; ++j)
109 position(i+row, j+col) = p.position(i,j);
110 }
111 }
112
113 void Picture::clear(int h1,int w1,int h2,int w2)
114 {
115 for(int r = h1; r < h2; ++r)
116 for(int c = w1; c < w2; ++c)
117 position(r,c) = ' ';
118 }
119
120 Picture frame(const Picture& p)
121 {
122 Picture r;
123 r.init(p.height + 2, p.width + 2);
124 for(int i = 1; i < r.height -1; ++i)
125 {
126 r.position(i,0) = '|';
127 r.position(i, r.width - 1) = '|';
128 }
129 for(int j = 1; j < r.width - 1; ++j)
130 {
131 r.position(0, j) = '-';
132 r.position(r.height - 1, j) = '-';
133 }
134 r.position(0, 0) = '+';
135 r.position(0, r.width-1) = '+';
136 r.position(r.height-1, 0)= '+';
137 r.position(r.height-1,r.width-1)='+';
138 r.copyblock(1,1,p);
139 return r;
140 }
141
142 Picture operator&(const Picture& p, const Picture& q)
143 {
144 Picture r;
145 r.init(p.height + q.height, Picture::max(p.width ,q.width));
146 r.clear(0,p.width,p.height,r.width);
147 r.clear(p.height,q.width,r.height,r.width);
148 r.copyblock(0,0,p);
149 r.copyblock(p.height,0,q);
150 return r;
151 }
152
153 Picture operator|(const Picture& p, const Picture& q)
154 {
155 Picture r;
156 r.init(Picture::max(p.height,q.height),p.width + q.width);
157 r.clear(p.height,0,r.height,q.width);
158 r.clear(q.height,p.width,r.height,r.width);
159 r.copyblock(0,0,p);
160 r.copyblock(0,p.width,q);
161 return r;
162 }
测试代码:
1 char *init[]= {"aris","in the","Spring"};
2 Picture p(init,3);
3 cout << frame(frame(p) & (p | frame(p))) << endl;
设计一个编写仅包含C++程序基本构成元素的程序
/* //注释行开始
This is the first C++ program.
Designed by zrf
*/ //注释行结束
#include <iostream> //包含头文件
using namespace std; //打开命名空间std
// This is the main function //单行注释语句
int main(void) //主函数,程序入口
{ //块作用域开始
int age; //声明一个变量
age= 20; //赋值语句
cout<<"The age is:\n"; //输出一个字符串
cout<<age<<endl; //输出变量中的值
return 0; //主函数返回0
} //块作用域结束
【案例2-2】计算圆的周长和面积——C++语言中常量、变量
#include <iostream>
using namespace std;
int main()
{ const float PI=3.1415926; //float 型常量
float r=2.0; //用float 型常量初始化变量
cout<<"r="<<r<<endl; //输出圆的半径
float length; //float型变量声明
length=2*PI*r; //计算圆的周长
cout<<"Length="<<length<<endl; //输出圆的周长
float area=PI*r*r; //计算圆的面积
cout<<"Area="<<area<<endl; //输出圆的面积
return 0;
}
【案例2-3】整数的简单运算——除法、求余运算法和增量减量运算符
#include <iostream>
using namespace std;
int main()
{ int x, y;
x = 10; y = 3;
cout << x << " / " << y << " is " << x / y //整数的除法操作
<<" with x % y is " << x % y << endl; //整数的取余操作
x ++; --y ; //使用增量减量运算符
cout << x << " / " << y << " is " << x / y << "\n" //整数的除法操作
<< x << " % " << y << " is " << x % y<<endl; //整数的取余操作
return 0;
}
【案例2-4】多重计数器——前置和后置自增运算符
#include<iostream>
using namespace std;
int main()
{ int iCount=1; iCount=(iCount++)+(iCount++)+(iCount++); //后置++
cout<<"The first iCount="<<iCount<<endl;
iCount=1; iCount=(++iCount)+(++iCount)+(++iCount); //前置++
cout<<"The second iCount="<<iCount<<endl;
iCount=1; iCount=-iCount++; //后置++
cout<<"The third iCount="<<iCount<<endl;
iCount=1; iCount=-++iCount; //前置++
cout<<"The fourth iCount="<<iCount<<endl;
return 0;
}
【案例2-5】对整数“10”和“20”进行位运算——位运算的应用
#include <iostream>
using namespace std;
int main()
{ cout << "20&10=" << (20&10) << endl; //按位与运算
cout << "20^10=" << (20^10) << endl; //按位异或运算
cout << "20|10=" << (20|10) << endl; //按位或运算
cout << "~20=" <<(~20) << endl; //按位取反运算
cout << "20<<3=" << (20<<3) << endl; //左移位运算
cout << "-20<<3=" << (-20<<3) << endl; //左移位运算
cout << "20>>3=" << (20>>3) << endl; //右移位运算
cout << "-20>>3=" << (-20>>3) << endl; //右移位运算
return 0;
}
【案例2-6】实现逻辑“异或”运算——逻辑运算应用
#include <iostream>
using namespace std;
int main()
{ bool p, q;
p = true; q = true;
cout <<p <<" XOR "<<q<<" is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
p = false; q = true;
cout <<p<<" XOR "<<q<< " is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
p = true; q = false;
cout <<p<<" XOR "<<q<<" is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
p = false; q = false;
cout <<p<<" XOR "<<q<<" is "<<( (p || q) && !(p && q) )<< "\n"; //输出异或结果
return 0;
}
【案例2-7】高效筛选器——用条件运算符“?”构建条件表达式
#include<iostream>
using namespace std;
int main()
{ int iNum1=1,iNum2,iMax;
cout<<"lease input two integers:\n";
cin>>iNum1>>iNum2;
iMax = iNum1>iNum2 ? iNum1 : iNum2; //使用条件运算符构建条件表达式
cout<<"The max integer is: "<<iMax<<endl;
return 0;
}
【案例2-8】“多计算与单提取”功能的实现——逗号表达式
#include<iostream>
using namespace std;
int main()
{ int Val1, Val2, Val3, Left, Midd, Righ;
Left = 10; Midd = 20; Righ = 30;
Val1 = (Left++, --Midd, Righ++); //使用逗号表达式
Val2 = (Righ++, Left++, --Midd); //使用逗号表达式
Val3 = ( --Midd, Righ++,Left++); //使用逗号表达式
cout <<"Val1=\t"<<Val1 <<"\nVal2=\t"<<Val2 <<"\nVal3=\t"<<Val3<<endl;
return 0;
}
【案例2-9】高效的算术运算符——复合赋值运算符
#include <iostream>
using namespace std;
int main()
{ int n=20; cout << "n = " << n << endl;
n += 8; cout << "After n += 8, n = " << n << endl; //使用复合的赋值运算符+=
n -= 6; cout << "After n -= 6, n = " << n << endl; //使用复合的赋值运算符-=
n *= 1; cout << "After n *= 1, n = " << n << endl; //使用复合的赋值运算符*=
n /= 4; cout << "After n /= 4, n = " << n << endl; //使用复合的赋值运算符/=
n %= 3; cout << "After n %= 3, n = " << n << endl; //使用复合的赋值运算符%=
return 0;
}
【案例2-10】计算不同数据类型的存储容量——sizeof运算符
#include <iostream>
using namespace std ;
int main()
{ cout << "The size of an int is:\t\t" << sizeof(int) << " bytes.\n";
cout << "The size of a short int is:\t" << sizeof(short) << " bytes.\n";
cout << "The size of a long int is:\t" << sizeof(long) << " bytes.\n";
cout << "The size of a char is:\t\t" << sizeof(char) << " bytes.\n";
cout << "The size of a wchar_t is:\t" << sizeof(wchar_t) << " bytes.\n";
cout << "The size of a float is:\t\t" << sizeof(float) << " bytes.\n";
cout << "The size of a double is:\t" << sizeof(double) << " bytes.\n";
return 0;
}
【案例2-11】巧妙获取整数部分——double和int数据类型的转换
#include <iostream>
using namespace std;
int main()
{ int nn=10,mm;
double xx=4.741,yy;
cout<<"nn*xx="<<nn*xx<<endl; //表达式类型转换
mm=xx; yy=nn; //赋值类型转换
cout<<"mm="<<mm<<endl <<"yy="<<yy<<endl;
cout<<"int(xx)="<<int(xx)<<endl <<"(int)xx="<<(int)xx<<endl; //强制类型转换
cout<<"int(1.412+xx)="<<int(1.412+xx)<<endl; //强制类型转换
cout<<"(int)1.412+xx="<<(int)1.412+xx<<endl; //强制类型转换
return 0;
}
【案例2-12】将分数转换为小数——强制类型转换
#include <iostream>
using namespace std;
int main()
{ for( int i=1; i <= 5; ++i )
cout << i << "/ 3 is: " << (float) i / 3 << endl; //强制类型转换
return 0;
}
【案例2-13】安全的除法计算器
#include <iostream>
using namespace std;
int main()
{ int a, b;
cout << "Enter numerator: "; cin >> a;
cout << "Enter denominator: "; cin >> b;
if(b) cout << "Divide Result is: " << a / b << '\n'; //排除除数为零的情况
else cout << "Divide by zero!\n";
return 0;
}
【案例2-14】猜数游戏——嵌套的if条件语句
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{ int MagNum, GueNum;
MagNum = rand(); //产生随机数
cout << "Enter the Guess number: "; cin >> GueNum;
if (GueNum == MagNum)
{ //if语句块起始位置
cout << "* It is Right *\n"<< MagNum << " is the Magess number.\n";
} //if语句块结束位置
else
{ // else语句块起始位置
cout << "Sorry, you're wrong."<<endl;
if(GueNum > MagNum)
cout <<"Guessed number is too high.\n";
else
cout << "Guessed number is too low.\n";
} //else语句块结束位置
return 0;
}
【案例2-15】根据输入月份输出从年初到本月底的天数——不带break的switch
#include <iostream>
using namespace std;
int main()
{ int year,month,days=0;
cout<<"Input year and month:"; cin>>year>>month;
switch (month) //每个case分支均没有break语句
{ case 12: days +=31;
case 11: days +=30;
case 10: days +=31;
case 9: days +=30;
case 8: days +=31;
case 7: days +=31;
case 6: days +=30;
case 5: days +=31;
case 4: days +=30;
case 3: days +=31;
case 2: //判断是否为闰年
if (year % 4==0 && year % 100!=0 || year %400==0)
days +=29;
else
days +=28;
case 1: days +=31;
}
if (days==0) cout<< "Wrong month"<<endl;
else cout << "Total days is:" <<days<< endl;
return 0;
}
【案例2-16】计算数的阶乘——do-while循环语句
#include <iostream>
using namespace std;
int main()
{ long limits;
cout << "Enter a positive integer: "; cin >> limits;
cout << "Factorial numbers of "<<0<<" is " << 1<<endl;
cout << "Factorial numbers of "<<1<<" is " << 1<<endl;
long fac=1, i=1;
do //使用do-while循环
{ fac *= ++i;
cout << "Factorial numbers of "<<i<<" is " << fac<<endl;
} while (fac < limits);
return 0;
}
【案例2-17】计算数的阶乘——for循环
#include <iostream>
using namespace std;
int main()
{ long limits;
cout << "Enter a positive integer: "; cin >> limits;
cout << "Factorial numbers of "<<0<<" is " << 1<<endl;
cout << "Factorial numbers of "<<1<<" is " << 1<<endl;
long fac=1;
for(int i=2;fac<=limits;i++) //使用for 循环
{ fac *= i;
cout << "Factorial numbers of "<<i<<" is " << fac<<endl;
}
return 0;
}
【案例2-18】筛选素数——步长为2的for循环
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{ long n;
cout << "Enter a positive integer: "; cin >> n;
if (n < 2)
cout << n << " is not prime." << endl;
else if (n < 4)
cout << n << " is prime." << endl;
else if (n%2 == 0)
cout << n << " = 2*" << n/2 << endl;
else
{ for (int i=3; i <= n/2; i += 2) //步长为2
if (n%i == 0)
{cout << n << " = " << i << "*" << n/i << endl; exit(0);}
cout << n << " is prime." << endl;
}
return 0;
}
【案例2-19】输出1~20之间的偶数——continue语句
#include <iostream>
using namespace std;
int main()
{ cout<<"The even numbers are as follows:"<<endl;
for(int i=0; i<=20; i++)
{ if(i%2) continue; //根据条件使用continue结束本次循环
cout << i << ' ';
}
return 0;
}
【案例2-20】统计输入整数的个数并求和——exit()函数
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{ int sum=0,num=0,m;
cout<<"lease input integers (0:end):"<<endl;
do { cin>>m; num++; sum+=m;
if(m==0)
{ cout<<"Entered numbers:"<<num<<" integers.\n";
cout<<"The sum is:"<<sum<<endl;
exit(0); // 使用exit()函数终止程序
}
}while(1);
return 0;
}
【案例2-21】“剪刀、石头、布”游戏——枚举类型
#include <iostream>
using namespace std;
enum Choice {ROCK, CLOTH, SCISS}; //声明枚举类型Choice
enum Winner {Play1, Play2, Tie}; //声明枚举类型Winner
int main()
{ int n;
Choice cho1, cho2;
Winner winner;
cout << "Choose rock (0), cloth (1), or Sciss (2):" << endl;
cout << "layer No. 1: "; cin >> n; cho1 = Choice(n);
cout << "layer No. 2: "; cin >> n; cho2 = Choice(n);
if (cho1 == cho2) winner = Tie;
else if (cho1 == ROCK)
if (cho2 == CLOTH) winner = Play2;
else winner = Play1;
else if (cho1 == CLOTH)
if (cho2 == SCISS) winner = Play2;
else winner = Play1;
else
if (cho2 == ROCK) winner = Play2;
else winner = Play1;
if (winner == Tie) cout << "\tTied!\n";
else if (winner == Play1) cout << "\tPlayer No. 1 wins." <<endl;
else cout << "\tPlayer No. 2 wins." << endl;
return 0;
}
【案例2-22】简单的学生信息类型——结构体
#include <iostream>
#include <iomanip>
using namespace std;
struct student //学生信息结构体
{ int num;
char name[20];
char gender;
int age;
}stu1={1001,"Zhang San",'M',19};
int main()
{ student stu2={1002,"Li Si",'M',20}; //声明结构体变量并初始化
student stu3={1003,"Wang Hong",'F',22}; //声明结构体变量并初始化
cout<<setw(7)<<stu1.num<<setw(20)<<stu1.name<<setw(3)<<stu1.gender<<setw(3)<<stu1.age<<endl;
cout<<setw(7)<<stu2.num<<setw(20)<<stu2.name<<setw(3)<<stu2.gender<<setw(3)<<stu2.age<<endl;
cout<<setw(7)<<stu3.num<<setw(20)<<stu3.name<<setw(3)<<stu3.gender<<setw(3)<<stu3.age<<endl;
return 0;
}
【案例2-23】综合案例——百钱买百鸡问题
#include<iostream>
using namespace std;
int main()
{
int n=100;
cout<<"鸡公 鸡母 鸡雏"<<endl; //i表示鸡公,j表示鸡母,k表示鸡雏
for ( int i = 1; i <= n; i++ )
for ( int j = 1; j <= n; j++ )
for( int k = 1; k <= n; k++ )
if(( n == 5 * i + 3 * j + k / 3 ) && ( k % 3 == 0 ) && ( n == i + j + k ))
cout << i << " " << j << " " << k << endl;
return 0;
}
#include<stdio.h>
int main()
{
int x,y,z,j=0;
printf("Folleing are possible plans to buy 100 fowls with 100 Yuan.\n");
for(x=0;x<=20;x++) //外层循环控制鸡翁数
for(y=0;y<=33;y++) //内层循环控制鸡母数y在0~33变化
{
z=100-x-y; //内外层循环控制下,鸡雏数z的值受x,y的值的制约
if(z%3==0&&5*x+3*y+z/3==100) //验证取z值的合理性及得到一组解的合理性
printf("%2d:cock=%2d hen=%2d chicken=%2d\n",++j,x,y,z);
}
}
【案例3-1】编写输出专用函数——无参函数
#include<iostream>
using namespace std;
void DispMessage(void) //定义无参函数
{
cout<<"This is a Message!"<<endl;
}
int main()
{
DispMessage(); //调用无参函数DispMessage
return 0;
}
【案例3-2】编写求和函数——有参函数
#include<iostream>
using namespace std;
double add(double x,double y) //定义有参函数
{
double z; z=x+y; return(z);
}
int main()
{
double a=0.5, b=1.0;
cout<<"add(a,b)="<<add(a,b)<<endl; //调用有参函数add()
return 0;
}
【案例3-3】编写求和函数——函数的不同调用形式
#include<iostream>
using namespace std;
double add(double x,double y) //函数的定义,其有返回值
{
double z; z=x+y;
cout<<x<<"+"<<y<<"="<<z<<endl;
return(z);
}
int main()
{
double a=0.5,b=1.0;
//以不同参数形式调用函数add()
cout<<"add(1.5,2.5)="<<add(1.5,2.5)<<endl;
cout<<"add(a,b)="<<add(a,b)<<endl;
cout<<"add(2*a,a+b)="<<add(2*a,a+b)<<endl;
double c=2*add(a,b); //以表达式方式调用函数add()
cout<<"c="<<c<<endl;
add(2*a,b); //以语句方式调用函数add()
cout<<" add(a, add(a,b))="<<add(a, add(a,b))<<endl; //以函数参数形式调用函数add()
return 0;
}
【案例3-4】编写符号函数——函数的返回值
#include<iostream>
using namespace std;
int sgn(double x) //定义符号函数sgn(),其返回值为int类型
{
if (x>0) return(1); //返回出口1
if (x<0) return(-1); //返回出口2
return(0); //返回出口3
}
int main()
{
double x;
for (int i=0;i<=2;i++)
{
cout<<"Input x="; cin>>x;
cout<<"sgn("<<x<<")="<<sgn(x)<<endl;
}
return 0;
}
【案例3-5】编写最值函数——函数原型声明
#include<iostream>
using namespace std;
//…函数原型声明语句也可以在这里
int main()
{
float max(float,float); //max()函数原型声明语句
float a,b,Max; //变量声明语句
cout<<" Input a="; cin>>a; //输入参数a
cout<<" Input b="; cin>>b; //输入参数b
Max=max(a,b); //调用max()函数
cout<<"max("<<a<<","<<b<<")="<<Max<<endl;
return 0;
}
float max(float x,float y) {
float z; z=(x>y)?x:y;
return(z); //返回值类型为浮点型
}
【案例3-6】值传递和引用传递的区别
#include <iostream>
using namespace std;
void fun(int,int&); //函数参数一个为值传递,一个引用传递
int main()
{
int a = 22, b = 44;
cout << "Initial a = " << a << ", b = " << b << endl;
fun(a,b); cout << "After fun(a,b), a = " << a << ", b = " << b << endl;
fun(2*a-3,b); cout << "After fun(2*a-3,b), a = " << a << ", b = " << b << endl;
return 0;
}
void fun(int x, int& y)
{
x = 88; y = 99;
}
【案例3-7】编写最值函数——内联函数
#include<iostream>
using namespace std;
inline int max(int x,int y) //使用inline关键字声明max()为内联函数
{
return x>y?x:y;
}
int main()
{
int a=3,b=5,c;
c=max(a,b); cout<<"max("<<a<<","<<b<<")="<<c<<endl;
cout<<"max("<<15<<","<<11<<")="<<max(15,11)<<endl;
return 0;
}
【案例3-8】计算圆的面积和周长函数——通过引用返回多于1个的数值
#include <iostream>
using namespace std;
void ComCircle(double&, double&, double); //函数的原型声明
int main()
{
double r, a, c;
cout << "Enter radius: "; cin >> r;
ComCircle(a, c, r);
cout << "The area = " << a << ", and the circumference = " << c << endl;
return 0;
}
void ComCircle(double& area, double& circum, double r) //通过引用变量返回面积和周长
{
const double PI = 3.141592653589793;
area = PI*r*r; circum = 2*PI*r; //计算面积和周长
}
【案例3-9】最小公倍数函数——函数的嵌套调用
#include <iostream>
using namespace std;
long int gcd(long int m,long int n) //求最大公约数
{
if (m < n) swap(m,n);
while (n>0)
{
int r = m%n; m = n; n = r;
}
return m;
}
long int lcm(long int m,long int n) //求最小公倍数
{
return m*n/gcd(m,n);
}
int main()
{
int m, n;
cout << "lease input two integers: "; cin >> m >> n;
cout << "lcm(" << m << "," << n << ") = " << lcm(m,n) << endl;
return 0;
} 【案例3-10】显示函数的参数——带默认参数的函数
#include <iostream>
using namespace std;
void disp(int x=1,int y=1,int z=1) //带有默认参数值的函数
{
cout<<"arameter 1 is: "<<x<<endl;
cout<<"arameter 2 is: "<<y<<endl;
cout<<"arameter 3 is: "<<z<<endl;
}
int main() //main()函数中测试参数带有默认值的函数disp()
{
cout<<"No actual parameter"<<endl; disp();
cout<<"One actual parameter"<<endl; disp(1);
cout<<"Two actual parameter"<<endl; disp(1,2);
cout<<"Three actual parameter"<<endl; disp(1,2,3);
return 0;
} 【案例3-11】通用最值函数——参数数目可变的函数
#include <iostream>
#include <cstdarg>
using namespace std;
int max(int,int...); //原型声明
int main()
{
int a,b,c,d,e;
cout<<"Enter five integers, seperate with space:"; cin>>a>>b>>c>>d>>e;
cout<<"The maxmum in a and b is:"<<max(2,a,b)<<endl;
cout<<"The maxmum in five integers is:"<<max(5,a,b,c,d,e)<<endl;
return 0;
}
int max(int num,int integer...) //定义参数数目可变的函数
{
va_list ap;
int n=integer;
va_start(ap,integer);
for(int i=1;i<num;i++)
{
int t=va_arg(ap,int);
if(t>n)
n=t;
}
va_end(ap);
return n;
}
【案例3-12】多变的最值函数——参数数目不同的重载函数
#include <iostream>
using namespace std;
int main()
{
int min (int a, int b, int c); //函数声明
int min (int a, int b); //函数声明
int i1 ,i2,i3,i;
cout<<"Enter three integers:"; cin >>i1 >>i2 >>i3; //输入3个整数
i = min(i1 ,i2) ; cout <<"The min in two intergers=" <<i <<endl; // 2个整数中最小者
i = min(i1 ,i2 ,i3) ; // 3个整数中最小者
cout <<"The min in three intergers=" <<i <<endl;
return 0;
}
int min(int a,int b,int c) //定义求3个整数中的最小者的函数
{
int k;
k=(a<b)?a:b;
k=(k<c)?k:c;
return k;
}
int min(int a,int b) //定义求2个整数中的最小者的函数
{
int k;
k=(a<b)?a:b;
return k;
}
【案例3-13】求绝对值——使用系统函数
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
void main( void )
{
int ix = -4, iy;
long lx = -41567L, ly;
double dx = -3.141593, dy;
iy = abs( ix ); cout<<"The absolute value of"<<ix <<" is "<<iy<<endl;
ly = labs( lx ); cout<<"The absolute value of"<<lx <<" is "<<ly<<endl;
dy = fabs( dx ); cout<<"The absolute value of"<<dx <<" is "<<dy<<endl;
}
【案例3-14】将整数和小数分离——使用系统函数
#include<iostream>
#include<cmath>
using namespace std;
void main(void)
{
double fraction, integer,number = 103.567;
fraction = modf(number, &integer);
cout<<number<<"整数部分为:"<<integer<<" 小数部分为:"<<fraction;
}
【案例3-15】求平方根——使用系统函数
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
void main( void )
{
double question = 45.35, answer;
answer = sqrt( question );
if( question < 0 )
cout<<"Error: sqrt returns "<<answer<<endl;
else
cout<<"The square root of "<<question<<" is "<<answer<<endl;
}
【案例3-16】求随机数——使用系统函数
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void main(void)
{
cout << "RAND_MAX=" << RAND_MAX << endl;
cout<<"产生10个 0 到 99的随机数如下:\n";
for(int i=0; i<10; i++)
cout<<(rand() % 100)<<' '; //求除以100的余数
cout << "\n使用srand:\n";
srand( (unsigned)time( NULL ) );
for( i = 0; i < 10;i++ )
cout<<rand() <<' ';
}
【案例3-17】计算时间差——使用系统函数
#include <iostream >
#include <ctime >
#include <conio.h>
using namespace std;
void main(void)
{
time_t start,end;
start = time(NULL);
cout << "请按Enter键!\n";
for (;;)
{
if (getch()=='\r')
break;
}
end = time(NULL);
cout << "按键前后相差:"<<difftime(end,start)<<" 秒";
}
【案例4-1】编写设计全部成员为public模式的类
#include<iostream>
using namespace std;
class PubClass
{public: //以下成员均为公有成员
int value; //公有数据成员
void set(int n) //公有函数成员
{
value=n;
}
int get(void) //公有函数成员
{
return value;
}
};
int main()
{
PubClass a; //创建对象
a.set(10); cout<<"a.get()="<<a.get()<<endl; //直接访问对象的公有成员函数
a.value=20; cout<<"a.value="<<a.value<<endl; //直接访问对象的公有数据成员
return 0;
}
【案例4-2】编写设计private数据访问模式的类
#include <iostream>
using namespace std;
class PriClass
{
int iv; double dv; //私有数据成员
public:
void set_PriClass(int n,double x); //公有函数成员为接口函数
void show_PriClass(char*); //公有函数成员为接口函数
};
//定义PriClass类的接口成员函数
void PriClass::set_PriClass(int n,double x) { iv=n; dv=x;}
void PriClass::show_PriClass(char *name)
{
cout<<name<<": "<<"iv=" <<iv<< ", dv=" <<dv<< endl;
}
int main()
{
PriClass obj;
obj.show_PriClass("obj"); //通过接口函数来访问数据成员
obj.set_PriClass(5,5.5); obj.show_PriClass("obj"); //通过接口函数来访问数据成员
return 0;
}
【案例4-3】编写结构体类——以结构体形式定义类
说明:结构体和类唯一区别是:结构体成员的访问权限默认为公有的,而类成员的访问权限默认为私有的
#include<iostream>
using namespace std;
struct StructClass //用struct关键字定义StructClass类
{
void set_value(int n) //公有属性
{
value=n;
}
void show_value(char *name) //公有属性
{
cout<<name<<": "<<value<<endl;
}
private: //为了保持私有属性,不能省略private
int value;
};
int main()
{
StructClass a;
a.show_value ("a"); //通过对象访问公有属性函数
a.set_value(100);
a.show_value ("a"); //通过对象访问公有属性函数
return 0;
}
【案例4-4】完善有理数类——拷贝构造函数的调用时机
#include <iostream>
using namespace std;
int gcd(int m, int n) //返回m 和n最大公约数
{
if (m<n) swap(m,n);
while (n>0) { int r=m%n; m = n; n = r; }
return m;
}
class Ratio
{
public:
Ratio(int n=0, int d=1) : num(n), den(d)
{
cout << "Common constructor called\n"; reduce();
}
Ratio(const Ratio& r):num(r.num), den(r.den) //拷贝构造函数
{
cout << "Copy constructor called\n";
}
void disp()
{
cout <<num<<"/"<<den<<endl;
}
private:
int num, den;
void reduce()
{
if (num == 0 || den == 0)
{
num = 0; den = 1; return; }
if (den < 0) {den *= -1; num *= -1; }
if (den == 1) return;
int sgn = (num<0?-1:1); int g = gcd(sgn*num,den);
num /= g; den /= g;
}
};
Ratio func(Ratio r) //初始化形参时调用拷贝构造函数
{
Ratio s = r;
return s; //返回时调用拷贝构造函数
}
int main()
{
Ratio x(20,7);
cout<<"Ratio x is:"; x.disp();
Ratio y(x); //调用拷贝构造函数,用x初始化y
cout<<"Ratio y is:"; y.disp();
cout<<"Func() Start:"<<endl;
func(y); //调用拷贝构造函数3次
cout<<"Func() End"<<endl;
return 0;
}
【案例4-5】完善的有理数类——析构函数
#include <iostream>
using namespace std;
class Ratio
{
int num, den;
public:
Ratio() {cout << "Constructor called.\n";}
Ratio(Ratio &r) { cout << "Copy constructor called.\n"; }
~Ratio() { cout << "Destructor called.\n"; }
};
int main()
{
Ratio x;
{ //x的作用域开始
Ratio y; //y的作用域开始
cout << "Now y is alive.\n";
} //y的作用域结束,调用析构函数1次
cout << "Now between blocks.\n";
{
Ratio z(x); //z的作用域开始
cout << "Now z is alive.\n";
} //z的作用域结束,调用析构函数1次
return 0;
}
//x的作用域结束,调用析构函数1次
【案例4-6】综合案例——电子日历
#include <iostream >
#include <cstdlib >
using namespace std;
class CDate //定义电子日历类
{
int m_nDay; int m_nMonth; int m_nYear; //日月年
public:
CDate(){}; //默认构造函数
CDate(int year, int month,int day ) //带参构造函数
{
SetDate(year, month, day); //调用成员函数来初始化
};
void Display(); //显示日期
void AddDay(); //返回加1后的日期
void SetDate(int year, int month, int day) //设置日期
{
m_nDay=day; m_nMonth=month; m_nYear=year;
}
~CDate() {};
private:
bool IsLeapYear() ; //判断是否为闰年
};
void CDate:isplay() //显示日期
{
char day[5] ,month[5], year[5] ;
_itoa (m_nDay, day, 10) ;
_itoa (m_nMonth, month, 10) ;
_itoa(m_nYear,year, 10) ;
cout << day << "/" << month << "/" << year << endl;
}
void CDate::AddDay () //返回加1后的日期
{
m_nDay++;
if (IsLeapYear())
{
if ((m_nMonth==2) && (m_nDay==30))
{
m_nMonth++;
m_nDay=1;
return;
}
}
else
{
if((m_nMonth==2)&& (m_nDay==29))
{
m_nMonth++;
m_nDay=1;
return;
}
}
if (m_nDay>31 )
{
if(m_nMonth==12) { m_nYear++; m_nMonth=1 ; m_nDay=1 ; }
else { m_nMonth++; m_nDay=1 ; }
}
}
bool CDate::IsLeapYear() //判断是否为闰年
{
bool bLeap;
if(m_nYear%4!=0) bLeap=false;
else if(m_nYear%100!=0) bLeap=true;
else if(m_nYear%400!=0) bLeap=false;
else bLeap=true;
return bLeap;
}
void main ()
{
CDate d (2010,4,6); //调用构造函数初始化日期
cout << "Current date:";
d.Display();
d.AddDay();
cout << "Add 1 to Current date:";
d.Display();
d. SetDate(2010,4,8); //调用成员函数重新设置日期
cout << "After reset Date,the date:";
d.Display();
} 【案例5-1】局部作用域的效果
#include <iostream>
using namespace std;
void fun() //变量num将在每次进入函数fun()时进行初始化
{
int num = 10;
cout << num << "\n";
num++; // 这个语句没有持续效果
}
int main()
{
for(int i=0; i < 3; i++)
fun();
return 0;
}
【案例5-2】屏蔽效应——作用域效果导致的名称隐藏
#include <iostream>
using namespace std;
int main()
{
int i = 10, j = 30;
if(j > 0)
{
int i; // 内部的i 将隐藏或屏蔽外层的i
i = j / 2;
cout << "inner variable i: " << i << '\n';
}
cout << "outer variable i: " << i << '\n';
return 0;
}
【案例5-3】筛选偶数——文件作用域变量
#include <iostream>
using namespace std;
int count; //这是一个全局变量
void func1()
{
void func2();
cout << "count: " << count<< '\n'; //可以访问全局变量count
func2();
}
void func2()
{
int count; //这是一个局部变量
for(count=0; count<2; count++)
cout << '*';
}
int main()
{
void func1();
void func2();
int i; //这是一个局部变量
for(i=0; i<10; i++)
{
count = i++;
func1();
}
return 0;
}
【案例5-4】求数据序列的平均值——static局部变量的持续效果
#include <iostream>
using namespace std;
int Average(int i)
{
static int sum = 0, count = 0; //声明静态局部变量,具有全局寿命,局部可见
sum = sum + i; count++;
return sum/count;
}
int main()
{
int num; //局部变量,具有动态生存期
do
{
cout << "Enter numbers (-1 to quit): "; cin >> num;
if(num != -1)
cout << "Running average is: " << Average(num);
cout <<endl;
} while(num > -1);
return 0;
}
【案例5-5】求数据序列的平均值——static全局变量的应用
#include <iostream>
using namespace std;
int Average(int i);
void reset();
int main()
{
int num; //局部变量,具有动态生存期
do
{
cout << "Enter numbers (-1 to quit, -2 to reset): ";
cin >> num;
if(num == -2)
{
reset();
continue;
}
if(num != -1)
cout << "Running average is: " << Average(num);
cout << endl;
} while(num != -1);
return 0;
}
static int sum = 0, count = 0; //静态全局变量,具有静态生存期,全局可见
int Average(int i)
{
sum = sum + i; count++; return sum/count;
}
void reset()
{
sum = 0; count = 0;
}
【案例5-6】时钟类——具有静态生存期的全局变量和全局对象
#include<iostream>
using namespace std;
int h=0,m=0,s=0; //声明全局变量,具有静态生存期
class Clock
{
public:
Clock();
void SetTime(int NewH, int NewM, int NewS); //三个形参均具有函数原型作用域
void ShowTime();
~Clock(){}
private:
int Hour,Minute,Second;
};
Clock::Clock()
{
Hour=h; Minute=m; Second=s; //使用全局变量初始化
}
void Clock::SetTime(int NewH, int NewM, int NewS)
{
Hour=NewH; Minute=NewM; Second=NewS;
}
void Clock::ShowTime()
{
cout<<Hour<<":"<<Minute<<":"<<Second<<endl;
}
Clock globClock; //声明对象globClock,具有静态生存期,文件作用域
int main()
{
cout<<"Initial time output:"<<endl;
//引用具有文件作用域的对象globClock:
globClock.ShowTime(); //对象的成员函数具有类作用域
globClock.SetTime(10,20,30); //将时间设置为10:20:30
//调用拷贝构造函数,以globClock为初始值
Clock myClock(globClock); //声明具有块作用域的对象myClock
cout<<"Setted time output:"<<endl;
myClock.ShowTime(); //引用具有块作用域的对象myClock
return 0;
}
【案例5-7】实现数据共享——公有静态数据成员
#include <iostream>
using namespace std;
class PubClass
{
public:
static int num; //公有静态数据成员的声明
void shownum() { cout << "The num is:"<<num << endl; }
};
int PubClass::num; //在类外定义num
int main()
{
PubClass a, b;
PubClass::num = 1000; //通过类名访问静态成员num
a.shownum();
b.shownum();
a.num = 2000; //通过对象访问静态成员num
a.shownum();
b.shownum();
return 0;
}
【案例5-8】实现数据共享——私有型静态数据成员
#include <iostream>
using namespace std;
class PriClass
{
static int num; //私有型静态成员
public:
void setnum(int i) { num = i; };
void shownum() { cout << "The num is:"<<num << "\n"; }
};
int PriClass::num; //在类外定义 num
int main()
{
PriClass a, b;
a.shownum(); b.shownum();
a.setnum(1000); //设置静态成员num为1000
a.shownum(); b.shownum();
return 0;
}
【案例5-9】实现函数共享——静态函数成员
#include <iostream>
using namespace std;
class FunClass
{
static int count; //静态数据成员声明
public:
FunClass() { count++; cout << "Constructing object " <<count << endl; }
~FunClass() { cout << "Destroying object " << count << endl; count--; }
static int GetCount() { return count; } //静态函数成员
};
int FunClass::count; //静态数据成员定义
int main()
{
FunClass a, b, c;
cout << "From Class, there are now " << FunClass::GetCount() << " in existence.\n";
cout << "From Object, there are now " << a.GetCount() <<" in existence.\n";
return 0;
}
【案例5-10】求最小公因子——友元函数的访问类的私有成员
#include <iostream>
using namespace std;
class FriFunClass
{
int a, b;
public:
FriFunClass(int i, int j) { a=i; b=j; }
friend int FriFun(FriFunClass x); //友元成员函数
};
int FriFun(FriFunClass x) //注意:FriFun() 不是任何类的成员函数
{
//由于函数FriFun() 是类FriFunClass的友元函数,所以它不能直接访问a和b
int max = x.a < x.b ? x.a : x.b;
for(int i=2; i <= max; i++)
if((x.a%i)==0 && (x.b%i)==0)
return i;
return 0;
}
int main()
{
FriFunClass n(10, 20); //声明类对象
if(FriFun(n))
cout << "Common denominator is " <<FriFun(n) << "\n";
else cout << "No common denominator.\n";
return 0;
}
【案例5-11】判断圆柱体和立方体的颜色是否相同——多个类共享友元函数
#include <iostream>
using namespace std;
class Cylinder; // 前向引用声明
enum Colors { red, green, yellow }; //定义颜色枚举类型
class Cube
{
Colors color;
public:
Cube(Colors c) { color = c; }
friend bool TestSame(Cube x, Cylinder y); //声明为Cube的友元函数
};
class Cylinder
{
Colors color;
public:
Cylinder(Colors c) { color= c; }
friend bool TestSame(Cube x, Cylinder y); //声明为Cylinder的友元函数
};
bool TestSame(Cube x, Cylinder y)
{
if(x.color == y.color)
return true;
else return false;
}
int main()
{
Cube cube1(red), cube2(yellow);
Cylinder cyl(yellow); //声明对象并初始化
if(TestSame(cube1, cyl))
cout << "The color of cube1 and cyl are the same.\n";
else
cout << "The color of cube1 and cyl are different.\n";
if(TestSame(cube2, cyl))
cout << "The color of cube2 and cyl are the same.\n";
else
cout << "The color of cube2 and cyl are different.\n";
return 0;
}
【案例5-12】计算2个三角形之和——友元函数的应用一看就能懂的c++打印案例只属数学课堂范例了
#include <iostream>
#include <cmath>
using namespace std;
class Trig
{
double x,y,z;
double area() {double d=(x+y+z)/2; return sqrt(d* (d-x)* (d-y)* (d-z)) ; }
public :
Trig (int i,int j,int k) { x=i;y=j;z=k; }
int isTriangle() //判断是否构成三角形
{
if (x+y>z && x+z>y && y+z>x)
return 1 ;
else
return 0;
}
friend double twoarea(Trig tl,Trig t2) //声明友元函数
{
return tl.area()+t2.area() ;
}
};
int main()
{
Trig tl (3,5,7) ,t2 (8, 7, 12) ;
if (tl.isTriangle() && t2.isTriangle())
cout << "Total area of two Triangles:" << twoarea(tl,t2) << endl;
else
cout << "Cannot form a Triangle"<< endl;
return 0;
}
【案例5-13】数据的单向传递——常引用作函数形参
#include <iostream>
using namespace std;
//常引用作形参,在函数中不能更新z所引用的对象,因此对应的实参不会被破坏。
void fun(int x, int& y, const int& z)
{
x += z;
y += z;
cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}
int main()
{
int a = 20, b = 30, c = 40;
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
fun(a,b,c);
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
fun(2*a-3,b,c);
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
return 0;
}
【案例5-14】成员函数的选择调用——常成员函数
#include<iostream>
using namespace std;
class ZRF
{
public:
ZRF(int Z1, int Z2){ZRF1=Z1;ZRF2=Z2;}
void disp();
void disp() const; //常成员函数声明
private:
int ZRF1,ZRF2;
};
void ZRF::disp()
{
cout<<ZRF1<<":"<<ZRF2<<endl;
}
void ZRF::disp() const //常成员函数定义
{
cout<<ZRF1<<":"<<ZRF2<<endl;
}
int main()
{
ZRF a(2,3);
a.disp(); //调用void disp()
const ZRF b(10,20);
b.disp(); //调用void disp() const
return 0;
}
【案例5-15】计算圆周长——不带参数的宏定义
#include<iostream>
using namespace std;
#define PI 3.14159 //宏名PI为符号常量
#define n a //宏名n将用a来替换
#define LENGTH 2*PI*n // 宏名LENGTH将用2*PI*n来替换
int main()
{
int n=1; //int n=1;替换为int a=1;
cout<<"LENGTH="<<LENGTH<<endl; //替换为cout<<"LENGTH="<<2*3.14159*a<<endl;