1--该章节新知识点
① 在 UNIX 和 Windows 系统中,执行完一个程序后,可以通过 echo 命令获得其返回值;
# UNIX系统中,通过如下命令获得状态
echo $?
② 在标准库中,定义了两个输出流 ostream 对象:cerr 和 clog;
cerr 通常用于输出警告和错误信息,称为标准错误;
clog 通常用于输出程序时的一般性信息;
③ std::endl 的作用:用于结束当前行,并将与设备关联的缓冲区(buffer)中的内容刷到设备中;
缓冲刷新操作可以保证程序所产生的所有输出都写入输入流中,而不是仅停留在内存中等待写入流;
④ 当遇到文件结束符或遇到一个无效输入时,istream对象的状态会变为无效;处于无效状态的istream对象会使条件(while循环)变为假;
在 UNIX 系统中,输入文件结束符的命令为:Ctrl + D;
⑤ 编程习惯问题:
标准库头文件通常不带后缀;
包含来自标准库的头文件时,应该用尖括号(< >)包含头文件名;
对于不属于标准库的头文件,习惯用双引号(" ")包围;
2--书包程序完整代码
① Sales_item.h
#ifndef SALESITEM_H
// we're here only if SALESITEM_H has not yet been defined
#define SALESITEM_H
// Definition of Sales_item class and related functions goes here
#include <iostream>
#include <string>
class Sales_item {
// these declarations are explained section 7.2.1, p. 270
// and in chapter 14, pages 557, 558, 561
friend std::istream& operator>>(std::istream&, Sales_item&);
friend std::ostream& operator<<(std::ostream&, const Sales_item&);
friend bool operator<(const Sales_item&, const Sales_item&);
friend bool
operator==(const Sales_item&, const Sales_item&);
public:
// constructors are explained in section 7.1.4, pages 262 - 265
// default constructor needed to initialize members of built-in type
Sales_item() = default;
Sales_item(const std::string &book): bookNo(book) { }
Sales_item(std::istream &is) { is >> *this; }
public:
// operations on Sales_item objects
// member binary operator: left-hand operand bound to implicit this pointer
Sales_item& operator+=(const Sales_item&);
// operations on Sales_item objects
std::string isbn() const { return bookNo; }
double avg_price() const;
// private members as before
private:
std::string bookNo; // implicitly initialized to the empty string
unsigned units_sold = 0; // explicitly initialized
double revenue = 0.0;
};
// used in chapter 10
inline
bool compareIsbn(const Sales_item &lhs, const Sales_item &rhs)
{ return lhs.isbn() == rhs.isbn(); }
// nonmember binary operator: must declare a parameter for each operand
Sales_item operator+(const Sales_item&, const Sales_item&);
inline bool
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
// must be made a friend of Sales_item
return lhs.units_sold == rhs.units_sold &&
lhs.revenue == rhs.revenue &&
lhs.isbn() == rhs.isbn();
}
inline bool
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
return !(lhs == rhs); // != defined in terms of operator==
}
// assumes that both objects refer to the same ISBN
Sales_item& Sales_item::operator+=(const Sales_item& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
// assumes that both objects refer to the same ISBN
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)
{
Sales_item ret(lhs); // copy (|lhs|) into a local object that we'll return
ret += rhs; // add in the contents of (|rhs|)
return ret; // return (|ret|) by value
}
std::istream&
operator>>(std::istream& in, Sales_item& s)
{
double price;
in >> s.bookNo >> s.units_sold >> price;
// check that the inputs succeeded
if (in)
s.revenue = s.units_sold * price;
else
s = Sales_item(); // input failed: reset object to default state
return in;
}
std::ostream&
operator<<(std::ostream& out, const Sales_item& s)
{
out << s.isbn() << " " << s.units_sold << " "
<< s.revenue << " " << s.avg_price();
return out;
}
double Sales_item::avg_price() const
{
if (units_sold)
return revenue/units_sold;
else
return 0;
}
#endif
② 测试程序
#include <iostream>
#include "Sales_item.h"
int main(){
Sales_item total;
if(std::cin >> total){
Sales_item trans;
while(std::cin >> trans){
if(total.isbn() == trans.isbn()){
total += trans;
}
else{
std::cout << total << std::endl;
total = trans;
}
}
std::cout << total << std::endl;
}
else{
std::cerr << "No data?!" << std::endl;
return -1;
}
return 0;
}