练习7.2
曾在 2.6.2 节的练习(第 76 页)中编写了一个 Sales_data类,请向这个类添加 combine 和 isbn 成员。
创建头文件sales.h
#ifndef SALES_H
#define SALES_H
#include <string>
#include <stdlib.h>
using namespace std;
struct Sales_data
{
string isbn() const //返回书的编号
{
return bookNo;
}
Sales_data& combine(const Sales_data& rhs);
string bookNo; //书编号
unsigned units_sold = 0; //售出的册数
double revenue = 0.0; //总销售额
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.units_sold;
return *this;
}
#endif;
练习7.3
修改 7.1.1 节(第 229 页)的交易处理程序,令其使用这些成员。
#include <iostream>
using namespace std;
#include "sales.h"
#include <string>
//读取销售记录,生成每本书的销售报告,显示售出册数、总销售额和平均售价
int main()
{
Sales_data total; //保存当前求和结果的变量
if (cin >> total.bookNo >> total.units_sold >> total.revenue)
{
Sales_data trans;
while (cin >> trans.bookNo >> trans.units_sold >> trans.revenue)
{
if (total.isbn() == trans.isbn())
total.combine(trans);
else
{
cout << total.bookNo << " 的总销售记录是:共售出 " << total.units_sold << " 本,总收入是 " << total.revenue;
total = trans;
}
}
cout << total.bookNo << " 的总销售记录是:共售出 " << total.units_sold << " 本,总收入是 " << total.revenue << " 平均每本价格是 "<<total.revenue/total.units_sold;
}
}
练习7.4
编写一个名为 Person 的类,使其表示人员的姓名和住址。使用 string 对象存放这些元素,接下来的练习将不断充实这个类的其他特征。
创建头文件person.h
#pragma once
#include<string>
using namespace std;
struct Person {
string Name;
string Address;
};
练习7.6
对于函数 add、read、和 print,定义你自己的版本。
创建头文件sales.h
#ifndef SALES_H
#define SALES_H
#include <string>
#include <stdlib.h>
using namespace std;
struct Sales_data
{
string isbn() const
{
return bookNo;
}
Sales_data& combine(const Sales_data& rhs);
istream& read(istream& is, Sales_data& item);
ostream& print(ostream& os, Sales_data& item);
Sales_data add(const Sales_data& lhs, const Sales_data& rhs);
string bookNo; //书编号
unsigned units_sold = 0; //售出的册数
double revenue = 0.0; //总销售额
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.units_sold;
return *this;
}
istream& Sales_data::read(istream& is, Sales_data& item) //is用来代替cin,istream类和ostream类见后续的IO类型
{
double price;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream& Sales_data::print(ostream& os, Sales_data& item)
{
os << item.isbn() << " 的总销售记录是:共售出 " << item.units_sold << " 本,总收入是 "
<< item.revenue << " " << " 平均每本价格是 "<<item.revenue/item.units_sold;
return os;
}
Sales_data Sales_data::add(const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data sum = lhs; //把lhs的数据成员拷贝给sum
sum.combine(rhs); //把rhs的数据成员加到sum中
return sum;
}
#endif;
练习7.7
使用这些新函数重写 7.1.2 节(第 233 页)练习中的交易处理程序。
#include <iostream>
using namespace std;
#include "sales.h"
#include <string>
//读取销售记录,生成每本书的销售报告,显示售出册数、总销售额和平均售价
int main()
{
Sales_data total;
if (total.read(cin,total))
{
Sales_data trans;
while (total.read(cin,trans))
{
if (total.isbn() == trans.isbn())
total.combine(trans);
else
{
total.print(cout,total);
cout << endl;
total = trans;
}
}
total.print(cout, total);
cout << endl;
}
}
练习7.9
对于 7.1.2节(第 233 页)练习中的代码,添加读取和打印 Person 对象的操作。
#pragma once
#include <string>
#include <iostream>
using namespace std;
struct Person {
string Name;
string Address;
istream& read(istream& is, Person& per);
ostream& print(ostream& os, const Person& per);
};
istream& Person::read(istream& is, Person& per)
{
is >> per.Name >> per.Address;
return is;
}
ostream& Person::print(ostream& os, const Person& per)
{
os << "名字为:" << per.Name << " 地址为:" << per.Address;
return os;
}
练习7.14、7.15、7.22
7.14.编写一个构造函数,令其用我们提供的类内初始值显式地初始化成员。
7.15.为你的 Person 类添加正确的构造函数。
7.22.修改你的 Person 类使其隐藏实现的细节。
头文件
#pragma once
#include <string>
#include <iostream>
using namespace std;
'''构造函数可以有多个,发生了重载,实例化的时候只能调用一个'''
class Person
{
public:
//1、无参构造函数,可以直接Person p创建实例
Person() = default;
//2、无参显示构造,可以直接Person p创建实例,和默认无参构造无法发生重载
Person():Name("megumi"),Address("japan"){}
//3、有参构造函数,需要Person p("sanae","erci")创建实例
Person(string N, string A) :Name(N), Address(A) {}
//4、类外构造函数的声明
Person(istream& is);
istream& read(istream& is, Person& per); //读取函数
ostream& print(ostream& os, const Person& per); //输出函数
private:
string Name;
string Address;
};
//类外构造函数的定义
Person::Person(istream &is)
{
read(is,*this);
}
istream& Person::read(istream& is, Person& per)
{
is >> per.Name >> per.Address;
return is;
}
ostream& Person::print(ostream& os, const Person& per)
{
os << "名字为:" << per.Name << " 地址为:" << per.Address;
return os;
}
主程序
#include <iostream>
using namespace std;
#include "person.h"
int main()
{
//1和2采用这种实例化
Person per;
per.print(cout, per);
cout<<endl;
//3采用这种实例化
Person per1("sanae","beijing");
per1.print(cout,per1);
cout<<endl;
//4类外构造函数的使用
Person per2(cin);
per2.print(cout,per2);
}
练习7.23、7.24、7.26
头文件screen.h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Screen
{
public:
typedef string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd) :height(ht), width(wd) { }
Screen(pos ht,pos wd,char c):height(ht),width(wd),contents(ht*wd,c) { }
char get() const //读取光标处的字符
{
return contents[cursor]; //隐式内联
}
inline char get(pos ht, pos wd) const; //显示内联
Screen& move(pos r, pos c); //能在之后被设为内联
private:
pos cursor = 0;
pos height = 0, width = 0;
string contents;
};
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
inline Screen& Screen::move(pos r, pos c) //内联,最好用这种方法,容易理解
{
pos row = r * width;
cursor = row + c;
return *this;
}
练习7.27
头文件screen.h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Screen
{
public:
typedef string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd) :height(ht), width(wd) { }
Screen(pos ht,pos wd,char c):height(ht),width(wd),contents(ht*wd,c) { }
char get() const //读取光标处的字符
{
return contents[cursor]; //隐式内联
}
inline char get(pos ht, pos wd) const; //显示内联
Screen& move(pos r, pos c); //负责移动光标,能在之后被设为内联
Screen& set(char);
Screen& set(pos r, pos col, char ch);
Screen& display(ostream& os)
{
do_display(os);
return *this;
}
const Screen& display(ostream& os) const
{
do_display(os);
return *this;
}
private:
pos cursor = 0; //光标的位置
pos height = 0, width = 0; //屏幕的宽高
string contents; //存放数据
//该函数负责显示Screen的内容
void do_display(ostream& os) const
{
os << contents;
}
};
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
inline Screen& Screen::move(pos r, pos c) //内联,最好用这种方法,容易理解
{
pos row = r * width;
cursor = row + c;
return *this;
}
inline Screen& Screen::set(char c)
{
contents[cursor] = c; //设置当前光标所在位置的新值
return *this; //将this对象作为左值返回
}
inline Screen& Screen::set(pos r, pos col, char ch)
{
contents[r * width + col] = ch; //设置给定位置的新值
return *this; //将this对象作为左值返回
}
主程序
#include "screen.h"
int main()
{
Screen myScreen(5, 5, 'x'); //创建一个有5*5个x的对象
myScreen.move(4, 0).set('#').display(cout);//移动光标4*5+0下,把那个位置的x替换成#,并且显示出来
cout << '\n';
myScreen.display(cout);
cout << '\n';
}
结果为:
xxxxxxxxxxxxxxxxxxxx#xxxx
xxxxxxxxxxxxxxxxxxxx#xxxx