@C++prime plus 第十章编程练习(用两种数据形式描述数据成员)
为复习题5描述的类提供方法定义,并编写一个小程序来演示所有特性。
复习题5:定义一个类来表示银行账户。数据成员包括储户姓名、账号(使用字符串)和存款。成员函数执行如下操作
~创建一个对象并将其初始化;
~显示储户姓名、账号和存款;
~存入参数指定的存款;
~取出参数指定的存款。
~使用字符串和字符数组两种数据形式描述数据成员部分,并使用不同的show()方法进行数据输出。
***/**************bank.h************/***
#pragma once
#ifndef BANK_H_
#define BANK_H_
#include<string>
using std::string;
class Bank
{
private:
string name;
string acctnum;
double ballance;
char Name[40];
char AcctNum[25];
public:
Bank();
Bank(const string &nm,const string &acct,double bal=0.0);
Bank(const char* client, const char* num, double bal = 0.0);
void deposit(double cash);
void withdraw(double cash);
void show()const;
friend void show(const Bank &bk);
};
#endif
***/**************bank.cpp********/***
#ifndef BANK_H_
#define BANK_H_
#include<string>
using std::string;
class Bank
{
private:
string name;
string acctnum;
double ballance;
char Name[40];
char AcctNum[25];
public:
Bank();
Bank(const string& nm, const string& acct, double bal = 0.0);
Bank(const char* client, const char* num, double bal = 0.0);
void deposit(double cash);
void withdraw(double cash);
void show()const;
friend void show(const Bank& bk);
};
#endif
#include<string>
#include<iostream>
#include"bank.h"
using std::cout;
using std::string;
using namespace std;
Bank::Bank()
{
name = 'Null';
acctnum = '\0';
ballance =0;
}
Bank::Bank(const string &client, const string &num, double bal)
{
name = client;
acctnum = num;
ballance = bal;
}
Bank::Bank(const char* client, const char* num, double bal)
{
strncpy(Name, client, 39);
Name[39] = '\0';
strncpy(AcctNum, num, 24);
AcctNum[24] = '\0';
ballance = bal;
}
void show(const Bank &bk)
{
cout << "bankname: " << bk.name << endl
<< "bankaccount:" << bk.acctnum << endl
<< "bank ballance:" << bk.ballance << endl;
}
void Bank::show()const
{
cout << "bankname: " << Name << endl
<< "bankaccount:" << AcctNum << endl
<< "bank ballance:" << ballance << endl;
}
void Bank::deposit(double cash)
{
ballance += cash;
}
void Bank::withdraw(double cash)
{
ballance-= cash;
}
/**************usebank.cpp********/
#include<string>
#include<iostream>
#include"bank.h"
using namespace std;
int main()
{
const string& str1 = "mhy";
const string& Acctnum = "65230102";
Bank bank1("mxy","65230101",100000);
Bank bank2 = Bank(str1, Acctnum, 2000);
bank1.show();
bank1.withdraw(50000);
bank1.show();
bank1.deposit(50001);
bank1.show();
bank1.withdraw(500000);
bank1.show();
show(bank2);
bank2.withdraw(2000);
show(bank2);
bank2.deposit(2);
show(bank2);
return 0;
}
2、下面是一个非常简单的类定义,它使用了一个string对象和一个字符数组,让您能够比较它们的用法。请提供为定义的方法的代码,以完成这个类的实现。再编写一个使用这个类的程序。它使用了三种可能的构造函数调用(没有参数、一个参数和两个参数)以及两种显示方法。
/*****************person.h***********************/
#pragma once
#ifndef PERSON_H_
#define PERSON_H_
#include<string>
using std::string;
class Person {
private:
static const int LIMIT = 25;
string lname;
char fname[LIMIT];
public:
Person() { lname = ""; fname[0] = '\0'; }
Person(const string& ln, const char* fn = "Heyyou");
void Show()const;
void FormalShow()const;
};
#endif
/*****************person.cpp***********************/
#include<string>
#include<iostream>
#include"person.h"
using std::string;
using std::cout;
using std::endl;
Person::Person(const string& ln, const char* fn)
{
lname = ln;
strncpy(fname, fn, 24);
fname[24] = '\0';
}
void Person::Show()const
{
cout << lname << endl;
}
void Person::FormalShow()const
{
cout << fname << endl;
}
/*****************UsePerson.cpp***********************/
#include"person.h"
#include<string>
#include<iostream>
using std::string;
using std::endl;
using std::cout;
int main()
{
Person one;
Person two("Smythecraft");
Person three("Dimwiddy", "Sam");
one.Show();
one.FormalShow();
three.Show();
three.FormalShow();
return 0;
}
3、完成第九章的编程练习1,但要用正确的golf类声明替换那里的代码。用合适参数的构造函数替换setgolf(golf &, const char *, int),以提供初始值。保留setgolf()的交互版本,但要用构造函数来实现它(例如,setgolf()的代码应该获得数据,将数据传递给构造来创建一个临时对象,并将其赋给调用对象,即 *this)。
/****************golf.h*********************/
#pragma once
#ifndef GOLF_H_
#define GOLF_H_
//const int Len = 40;
class golf
{
private:
static const int Len = 40;
char fullname[Len];
int handicap;
public:
golf();
golf(const char* fn, int hd=0);
const golf& setgolf(golf& g);
void showgolf()const;
void sethandicap(int hc);
};
#endif
/****************golf.cpp*********************/
#include<iostream>
#include"golf.h"
using std::cout;
using std::cin;
using std::endl;
golf::golf()
{
strcpy_s(fullname, "no name");
handicap = 0;
}
golf::golf(const char* fn, int hd)
{
strncpy(fullname,fn,39);
handicap = hd;
}
const golf& golf::setgolf(golf& g)
{
cout << "Please enter a name;\n";
cin.getline(g.fullname, Len);
cout << "Please enter a hndicap;\n";
cin >> g.handicap;
cin.get();
return *this=g;
}
void golf::showgolf()const
{
cout << "fullname:" << fullname << endl;
cout << "handicap:" << handicap << endl;
}
void golf::sethandicap(int hc)
{
handicap = hc;
}
/****************main.cpp*********************/
#include<iostream>
#include"golf/golf.h"
int main()
{
golf a;
golf b("Ann Birdfree",24);
a.showgolf();
b.showgolf();
a.setgolf(b);
a.showgolf();
return 0;
}
4、完成第9章的的编程练习4,但将Sales结构及相关的函数转换为一个类及其方法。用构造函数替换setSales(sales&,double[],int)函数。用构造函数实现setSales(Sales &)方法的交互版本。将类保留在名称空间SALES中。
#pragma once
#ifndef SALES_H_
#define SALES_H_
#include<iostream>
namespace SALES {
class Sales
{
private:
const static int QUARTERS = 4;
double sales[QUARTERS];
double average;
double max;
double min;
public:
Sales();
Sales(const double* ar, int n);
Sales(const Sales& s);
void setSales();
void showsales()const;
double maxval (const Sales& s);
double minval(const Sales& s);
double avr(const Sales& s);
double maxval(const double* ar);
double minval(const double* ar);
double avr(const double* ar);
};
}
#endif
Sales.cpp接口函数实现细节,加入了与C语言的printf语法,实现两种语言输出函数。的比较。
/***************sales.cpp*****************/
#include<iostream>
#include<cstdio>
#include"sales.h"
#include<string>
using std::string;
using std::cout;
using std::cin;
using std::endl;
namespace SALES
{
Sales::Sales()
{
int i;
for (i = 0; i < QUARTERS; i++)
sales[i] = 0.0;
average = max = min = 0;
}
Sales::Sales(const double* ar, int n)
{
int i;
for (i = 0; i < n&&i<4; i++)
sales[i] =ar[i];
max = maxval(ar);
min = minval(ar);
average = avr(ar);
}
Sales::Sales(const Sales& s)
{
int i;
for (i = 0; s.sales[i]&&i<4; i++)
sales[i] = s.sales[i];
max = maxval(s);
min = minval(s);
average = avr(s);
}
void Sales::setSales()
{
cout << "Enter 4 sales:\n";
for (int i = 0; i < QUARTERS; i++)
{
cout << "sales " << i + 1 << " :";
cin >> sales[i];
}
average = avr(sales);
max = maxval(sales);
min = minval(sales);
*this = Sales(sales, QUARTERS);
}
double Sales::avr(const Sales& s)
{
double sum = 0, aver;
int i;
for (i = 0; s.sales[i] && i < 4; i++)
sum += sales[i];
aver = sum / i;
return aver;
}
double Sales::maxval(const Sales& s)
{
int i;
double max = s.sales[0];
for (i = 1; s.sales[i] && i < 4; i++)
{
if (max < sales[i])
max = sales[i];
}
return max;
}
double Sales::minval(const Sales& s)
{
int i;
double min = s.sales[0];
for (i = 1; s.sales[i] && i < 4; i++)
{
if (min > sales[i])
min = sales[i];
}
return min;
}
double Sales::maxval(const double *ar)
{
int i;
double max = ar[0];
for (i = 1; ar[i] && i < 4; i++)
{
if (max < ar[i])
max = ar[i];
}
return max;
}
double Sales::minval(const double* ar)
{
int i;
double min = ar[0];
for (i = 1; ar[i]&&i<4; i++)
{
if (min > ar[i])
min = ar[i];
}
return min;
}
double Sales::avr(const double* ar)
{
double sum = 0, aver;
int i;
for (i = 0; ar[i]&&i<4; i++)
sum += ar[i];
aver = sum / i;
return aver;
}
void Sales::showsales()const
{
using std::ios_base;
ios_base::fmtflags orig =
cout.setf(ios_base::fixed, ios_base::floatfield);
std::streamsize prec = cout.precision(2);
for (int i = 0; i < 4; i++)
cout << sales[i] << " ";
cout<< endl;
cout << "MAX value: " << max << endl
<< "Min value: " << min << endl;
printf("average is %3.2f\n", average);
cout<< "average valur: " << average << endl;
//restore original format
cout.setf(orig, ios_base::floatfield);
cout.precision(prec);
}
}
main.cpp简单的一个主程序界面。
/***************main.cpp*****************/
#include<iostream>
#include"sales.h"
using namespace SALES;
int main()
{
Sales saler;
saler.setSales();
saler.showsales();
double dou[4] = { 1.0,2.0,3.0,4.0 };
Sales saler1(dou, 4);
saler1.showsales();
}
5、考虑下面的结构声明:
struct customer{
char fullname[35];
double payment;
};
编写一个程序,它从栈中添加和删除customer结构(栈用Stack类声明表示)。每次customer结构被修改删除时,其payment的值都被加入到总数中,并报告总数。注意:应该可以直接使用Stack类而不做修改。
本题的重点在于对于结构体赋值的问题,结构体变量之间可以用 “=”赋值,但是结构体成员中的字符串则不行。
//stack.h -- class defintion for the stack ADT
#pragma once
#ifndef STACK_H_
#define STACL_H_
struct customer {
char fullname[35];
double payment;
};
typedef customer Item;
class Stack {
private:
enum{MAX=10};
Item items[MAX];
int top;
public:
Stack();
bool isempty()const;
bool isfull()const;
//push()returns false if stack already is full, true otherwise
bool push(const Item& item);
//pop() returns false if stack already is empty,true otherwise
bool pop(Item& item);
};
#endif
//stack.cpp
#include"Stack.h"
Stack::Stack()
{
top = 0;
}
bool Stack::isempty()const
{
return top == 0;
}
bool Stack::isfull()const
{
return top == MAX;
}
bool Stack::push(const Item& item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
bool Stack::pop( Item& item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
//stacker.cpp
#include<iostream>
#include<cctype>
#include"Stack.h"
#include<string>
int main()
{
using namespace std;
Stack st;
char ch;
Item po;
double payment=0;
cout << "Plese enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
while (cin >> ch && toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << '\a';
continue;
}
switch (ch)
{
case 'A':
case 'a':cout << "Enter a PO fullname:";
cin.get(po.fullname, 35);
cout << "Enter a PO number to add: ";
cin >> po.payment;
cin.get();
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'p':
case 'P':if (st.isempty())
cout << "stack already empty\n";
else
{
st.pop(po);
cout << "PO: " << po.fullname << " payment: " << po.payment << " popped\n";
payment += po.payment;
cout << "The total of payment: " << payment << endl;
}
break;
}
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO,or Q to quit.\n";
}
cout << "Bye\n";
return 0;
}
6.下面是一个类声明:
class Move
{
private:
double x;
double y;
public:
//Move(); //default conostructor;
Move(double a=0, double b=0); //set x,y to a,b,it's a defaulet contructor,but it's also a constructor
void showmove()const; //shows current x,y values
Move add(const Move &m)const;
//this functong adds x of m to x of invoking object to get new x,
//adds y of m to y of invoking obhect to get new y ,creats a new
//move object initialized to new x,y values and returns it
void reset(double a = 0, double b = 0);//resets x,y to a,b
};
请提供成员函数的定义和测试这个类的程序。
/******************move.h*************************/
#pragma once
#ifndef MOVE_H_
#define MOVE_H_
class Move
{
private:
double x;
double y;
public:
//Move(); //default conostructor;
Move(double a=0, double b=0); //set x,y to a,b,it's a defaulet contructor,but it's also a constructor
void showmove()const; //shows current x,y values
Move add(const Move &m)const;
//this functong adds x of m to x of invoking object to get new x,
//adds y of m to y of invoking obhect to get new y ,creats a new
//move object initialized to new x,y values and returns it
void reset(double a = 0, double b = 0);//resets x,y to a,b
};
#endif
/******************Move.cpp*************************/
#include<iostream>
#include"move.h"
using namespace std;
/*Move::Move()
{
x = y = 0;
}*/
Move::Move(double a, double b)
{
x = a;
y = b;
}
void Move::showmove()const
{
cout << "x: " << x
<< " y: " << y << endl;
}
Move Move::add(const Move &m)const
{
Move adder;
adder.x = x + m.x;
adder.y = y + m.y;
return adder;
}
void Move::reset(double a, double b)
{
x = a;
y = b;
}
/******************mover.cpp*************************/
#include<iostream>
#include"move.h"
using namespace std;
int main()
{
Move p1(10, 5);
Move p2(20, 10);
Move p3;
p1.showmove();
p3 = p1.add(p2);
p3.showmove();
p2.reset(0, 0);
p2.showmove();
system("pause");
}
##注意构造函数和默认构造函数(default constructor)的定义,
Move(double a=0, double b=0);
既能做构造函数,又能做默认构造函数。##
*7.Betelgeusean plorg 有这些特征。
数据:
plorg的名称不超过19个字符;
pllorg有满意指数(CI),这是一个整数。
操作:
新的plorg将有名称,其CI值为50;
plorg的CI可以修改;
plorg可以报告其名称和CI;
plorg的默认名称为“Plorga”。
请编写一个PLorg类声明(包括数据成员和成员函数原型)来表示plorg,病变西成员函数的函数定义。然后编写一个小程序,以演示Plorg类的所有特性。
/****************Plorg.h******************/
#pragma once
#ifndef PLORG_H_
#define PLORG_H_
#include<string>
class Plorg
{
private:
char name[20];
int CI;
public:
Plorg(const char name[20] = "Plorga", int n = 50);
void show()const;
void setPlorg(int n);
};
#endif
/****************Plorg.cpp******************/
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Plorg.h"
using std::cout;
using std::endl;
using std::cin;
Plorg::Plorg(const char *str,int n)
{
strcpy(name, str);
CI = n;
}
void Plorg::setPlorg(int n)
{
CI = n;
}
void Plorg::show()const
{
cout << name << endl;
cout << CI << endl;
}
/****************UsePlorg.cpp******************/
#include"Plorg.h"
#include<iostream>
using std::endl;
int main()
{
Plorg p1;
Plorg P2("Plogra", 12);
P2.show();
P2.setPlorg(30);
P2.show();
p1.show();
}
7.可以将简单列表描述成下面这样:
~可存储0个或多个某种类型的列表;
~可创建空列表;
~可在列表中添加数据项;
~可确定列表是否为空;
~可确定列表是否为满;
~可访问列表中每一个数据项,并对它执行某种操作。
可以看到,这个列表确实很简单,例如,它不允许插入或删除数据项。请设计一个List类来表示这种抽象类型。
#pragma once
#ifndef STACK_H_
#define STACK_H_
typedef int Item;
class Stack {
private:
enum{MAX=10};
Item items[MAX];
int top;
public:
Stack();
bool isfull()const;
bool isempty()const;
bool push(const Item &item);
bool pop(Item & item);
void visit(void(*pf)(Item &));
};
#endif
#include"stack.h"
Stack::Stack()
{
top = 0;
}
bool Stack::isfull()const
{
return top == MAX;
}
bool Stack::isempty()const
{
return top == 0;
}
bool Stack::push(const Item &item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}
bool Stack::pop(Item &item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}
void Stack::visit(void(*pf)(Item &))
{
for (int i = 0; i < MAX; i++)
{
(pf)(items[i]);//or *pf(items[i])
}
}
#include"stack.h"
#include<iostream>
void show(Item &it);
int main()
{
Stack is;
for (int i = 2; i <= 11; i++)
{
if (is.isfull() != 1)
is.push(i);
else
continue;
}
is.visit(show);
std::cout << "pop the value of stack\n";
Item po;
while (!is.isempty())
{
is.pop(po);
std::cout << po << std::endl;
}
//is.visit(show);
return 0;
}
void show(Item &it)
{
std::cout << it << "\n";
}
#关于将函数的地址作为参数传递给另一个函数调用
1.在讲这个问题之前,我们要明白一个问题。就是我们为什么要把一个函数的地址作为参数传递给另一个参数。要知道在C语言中,一个函数内部是可以直接调用其他函数的,既然可以直接调用,为什么还要用这么麻烦的办法去把函数当做参数来传递呢。下面我举个例子。
例如我们设计一个estimate() 的函数计算一个程序运行的时间,但不同的人估算时间的时候可能算法有所不同,算出的时间也应该不同。但我们都调用同一个estimate() 函数,现在该怎么办呢,重写estimate() 函数固然是一个办法,但是我们还有另外的办法,比如我们把estimate()函数中计算时间的算法作为一个公共变量让其作为参数传入,我们只需要把 各自的计算时间的算法写成一个函数,再通过参数传递给estimate() ,而estimate()中的内容还是原来的不变,这样就可以实现不同的人计算出来的时间不同了。
2.既然知道了函数参数传递的用处,那么我们现在就来说一下它的用法。
首先参数传递分为两种,一种是值传递,一种是地址传递。 一般我们传递时用的是地址传递。因为,若是采用值传递的话,比如我们传递一个数组 double a[100],则在调用函数的时候。编译器会把这整个数组复制到函数中,这样使用的空间是 100*sizeof(double)=800.若是我们只传递数组名 a 这个地址的话,那么复制进去的空间只有 64/8=8 这么多(假设计算机是64位的)。这样比较下来,就有了100倍的差距,是不是很吓人。 所以,不管是函数作为参数,还是数组,结构体什么的,我们一般都用地址传递,而不用值传递,记好了。
3.下面,来看一下函数地址是怎么传递的。
先说一次传递一个函数的: 我们先定义一个函数
double add(double x, double y)
{
return x + y;
}
然后接着建立一个函数指针 double (*pf)(double,double)=add; //这里(*pf)的括号不能省,不然就不是函数指针了。
我们现在有一个函数
double calculate(double x1, double y1, double(*f)(double, double)) //函数调用里面传递 函数指针数组 的方法
{
cout << “add:” << (*f)(x1, y1) << endl;
return 1;
}
然后我们来进行值传递
int x = 2; y = 1;
calculate(x, y, pf);
最后可以得到输出的结果是 2+1=3。
这是最基本的,下面讲我要说的重点,就是一次传递多个函数进去。
想传递多个函数进去,我们要建立一个函数数组 。先定义两个函数
double add(double x, double y)
{
return x + y;
}
double add2(double x, double y)
{
return x - y;
}
然后建立函数数组并赋值 double (*pf[2])(double,double) = { add, add2 };
接着传递给上面定义的calculate函数。调用方式为:calculate(x, y, pf);
calculate函数的接收方式应为:double calculate(double x1, double y1, double(**f)(double, double)) //传递的pf是一个数组的数组名且本身也是一个指针,即为二重指针 或者double calculate(double x1, double y1, double(*f[])(double, double))
最后给出完整的代码
#include “iostream”
using namespace std;
double add(double, double);
double add2(double x, double y);
double calculate(double x1, double y1, double(**f)(double, double)) //函数调用里面传递 函数指针数组 的方法
{
cout << “add:” << (*f[0])(x1, y1) << endl;
cout << “add2:” << (*f[1])(x1, y1) << endl;
return 1;
}
int main()
{
int x, y;
double (*pf[2])(double,double) = { add, add2 };
x = 2; y = 1;
calculate(x, y, pf);
system("pause()");
return 0;
}
double add(double x, double y)
{
return x + y;
}
double add2(double x, double y)
{
return x - y;
}
————————————————
版权声明:本文为CSDN博主「c_flybird」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/c_flybird/article/details/49431009