#include
#include
using namespace std;
struct Sales_data
{
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
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.bookNo == trans.bookNo)
{
total.units_sold += trans.units_sold;
total.revenue += trans.revenue;
}
else
{
cout << total.bookNo << " " << total.units_sold << " "
<< total.revenue << endl;
total = trans;
}
}
cout << total.bookNo << " " << total.units_sold << " "
<< total.revenue << endl;
}
else
{
cerr << "No data?!" << endl;
return -1;
}
return 0;
}
struct Sales_data
{
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
std::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.revenue;
return *this;
}
#include
#include
using namespace std;
struct Sales_data
{
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
std::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.revenue;
return *this;
}
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 << endl;
total = trans;
}
}
cout << total.bookNo << " " << total.units_sold << " "
<< total.revenue << endl;
}
else
{
cerr << "No data?!" << endl;
return -1;
}
return 0;
}
struct Person
{
std::string name;
std::string address;
};
struct Person
{
std::string isname() const { return name; }
std::string isaddr() const { return address; }
std::string name;
std::string address;
};
应该是const,因为我们只读取,不修改。
/* 书上的就挺好用的,敲一遍也是累积代码量嘛~ */
struct Sales_data
{
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
std::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.revenue;
return *this;
}
double Sales_data::avg_price() const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
istream &read(istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#include
#include
using namespace std;
struct Sales_data
{
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
std::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.revenue;
return *this;
}
double Sales_data::avg_price() const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
istream &read(istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
int main()
{
Sales_data total;
if (read(cin, total))
{
Sales_data trans;
while (read(cin, trans))
{
if (total.isbn() == trans.isbn())
total = add(total, trans);
else
{
print(cout, total) << endl;;
total = trans;
}
}
print(cout, total) << endl;
}
else
{
cout << "No data?!" << endl;
return -1;
}
return 0;
}
因为read函数在读取数据的时候会修改数据;而print函数只读取不修改。
struct Person
{
std::string isname() const { return name; }
std::string isaddr() const { return address; }
std::string name;
std::string address;
};
istream &read(istream &is, Person &item)
{
is >> item.name >> item.address;
return is;
}
ostream &print(ostream &os, Person &item)
{
os << item.isname() << item.isaddr();
return os;
}
if (read(read(cin, data1), data2)
判断data1,data2是否成功写入数据
/* 太懒了,程序就不编了。。。*/
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(n * p) { }
Sales_data(std::istream &);
std::string isbn() const { return bookNo; }`在这里插入代码片`
Sales_data& combine(const Sales_data&);
double avg_price() const;
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(n * p) { }
Sales_data(std::istream &is) { read(is, *this); }
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
#include
#include
using namespace std;
struct Sales_data
{
Sales_data(std::istream &is);
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
std::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.revenue;
return *this;
}
double Sales_data::avg_price() const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
istream &read(istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(std::istream &is)
{
read(is, *this);
}
int main()
{
Sales_data total(cin);
if (!total.isbn().empty())
{
Sales_data trans(cin);
if (total.isbn() == trans.isbn())
total = add(total, trans);
else
{
print(cout, total);
total = trans;
}
print(cout, total);
}
else
{
cerr << "No data?!" << endl;
return -1;
}
return 0;
}
Sales_data(const std::string &s) : bookNo(s), units_sold(0), revenue(0) { }
struct Person
{
Person(const std::string &s1, const std::string &s2) :
name(s1), address(s2) { }
std::string isname() const { return name; }
std::string isaddr() const { return address; }
std::string name;
std::string address;
};
一个类可以包含0个或多个访问说明符,而且对于某个访问说明符能出现多少次也没有严格限定。
定义在public说明符之后的成员在整个程序内可被访问;定义在private说明符之后的成员可以被类的成员函数访问。
当我们希望定义的类的所有成员是public的时,使用struct;反之,如果希望成员是private的,使用class
封装:使用户不能到达对象的内部并且无法控制它的具体实现细节。
优点:1.确保用户代码不会无意间破坏封装对象的状态。2.被封装的类的具体实现可以随时改变,而无须调整用户级别的代码。
class Person
{
public:
Person(const std::string &s1, const std::string &s2) :
name(s1), address(s2) { }
std::string isname() const { return name; }
std::string isaddr() const { return address; }
private:
std::string name;
std::string address;
};
类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数称为它的友元。
利:允许其他类或者函数访问它的非公有成员
弊:如果我们希望类的用户能够调用某个友元函数,那么我们就必须在友元声明之外再专门对函数进行一次声明。
/* 创建一个头文件Sales_data.h,然后将下面代码放入其中 */
#ifndef HEAD_H
#define HEAD_H
#include
#include
class Sales_data
{
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::istream &read(std::istream &, Sales_data&);
friend std::ostream &print(std::ostream &, const Sales_data&);
public:
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(n * p) { }
Sales_data(std::istream &is) { read(is, *this); }
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
private:
double avg_price() const;
std::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.revenue;
return *this;
}
double Sales_data::avg_price() const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
std::istream &read(std::istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
std::ostream &print(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#endif
/* 创建一个Person.h头文件,将下面代码放入其中 */
#ifndef PERSON_H
#define PERSON_H
#include
#include
class Person
{
friend std::istream &read(std::istream &, Person &);
friend std::ostream &print(std::ostream &, Person &);
public:
std::string isname() const { return name; }
std::string isaddr() const { return address; }
private:
std::string name;
std::string address;
};
std::istream &read(std::istream &is, Person &item)
{
is >> item.name >> item.address;
return is;
}
std::ostream &print(std::ostream &os, Person &item)
{
os << item.isname() << item.isaddr();
return os;
}
#endif
class Screen
{
public:
using pos = std::string::size_type;
Screen() = default;
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;
std::string contents;
};
inline
Screen &Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
class Screen
{
public:
typedef std::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;
std::string contents;
};
inline
Screen &Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
可以,因为Screen类的数据成员都是带有赋值和拷贝函数的类型
/* 只截取一部分 */
class Sales_data
{
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::istream &read(std::istream &, Sales_data&);
friend std::ostream &print(std::ostream &, const Sales_data&);
public:
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(n * p) { }
Sales_data(std::istream &is) { read(is, *this); }
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
private:
inline double avg_price() const; // 嘿,内联
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
#include
#include
#include
using namespace std;
class Screen
{
public:
using pos = std::string::size_type;
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, pos, char);
Screen &display(std::ostream &os)
{
do_display(os); return *this;
}
const Screen &display(std::ostream &os) const
{
do_display(os); return *this;
}
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
void do_display(std::ostream &os) const { os << contents; }
};
inline
Screen &Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
inline Screen &Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
inline Screen &Screen::set(pos r, pos col, char ch)
{
contents[r * width + col] = ch;
return *this;
}
int main()
{
Screen myScreen(5, 5, 'X');
myScreen.move(4, 0).set('#').display(cout);
cout << "\n";
myScreen.display(cout);
cout << " \n";
return 0;
}
第二个display将会打印一连串X,没有#。
返回类型为引用:
优点:可以明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参
缺点:多余
class X
{
Y *ptr;
};
class Y
{
X val;
};
下午去上课,电脑睡眠,自动断WIFI,我又没保存,想哭。。。
仅以此希望大家一定要记得保存,记得保存,记得保存~
应该是explicit的,这样做可以自己弄一个构造函数,进行类型类型转换,节省工作量;缺点就是只能用该种类型,太狭窄。
string null_isbn("9-999-99999-9");
Sales_data item1(null_isbn);
Sales_data item2("9-999-99999-9");
不是explicit时,全部都是正确的;是explicit时,item2是错误的。
// string 转换为Sales_data,Sales_data构造一个临时变量
Sales_data &combine(Sales_data);
// string 转换为Sales_data, Sales_data初始化引用这个值(可改变)
Sales_data &combine(Sales_data&);
// string 转换为Sales_data, Sales_data初始化const引用这个值(不可改变)
Sales_data &combine(const Sales_data&) const; // string转换为Sales_data,
class Person
{
friend std::istream &read(std::istream &, Person &);
friend std::ostream &print(std::ostream &, Person &);
public:
Person() { }
Person(std::string s1, std::string s2) : name(s1), address(s2) { }
explicit Person(std::istream &is) { read(is, *this); } // 唯一一个
std::string isname() const { return name; }
std::string isaddr() const { return address; }
private:
std::string name;
std::string address;
};
std::istream &read(std::istream &is, Person &item)
{
is >> item.name >> item.address;
return is;
}
std::ostream &print(std::ostream &os, Person &item)
{
os << item.isname() << item.isaddr();
return os;
}
因为vector的参数都为同一类型,不存在类型转换的问题,故定义成explicit;而string的参数类型则不单一,需要进行隐式类型转换,故不能定义成explicit
978-0590353403为string类型bookNo
25为unsigned类型units_sold
15.99为double类型revenue
class Debug {
public:
constexpr Debug(bool b = true) : hw(b), io(b), other(b) { }
constexpr Debug(bool h, bool i, bool o) :
hw(h), io(i), other(o) { }
constexpr bool any() { return hw || io || other; }
void set_io(bool b) { io = b; }
void set_hw(bool b) { hw = b; }
void set_other(bool b) { hw = b; }
private:
bool hw;
bool io;
bool other;
};
不应该,因为constexpr需要一个返回值
是的,因为数据成员都是字面值类型
静态成员:与类本身直接相关,而不是与类的各个对象保持关联。
优点:静态成员不必实例化就能直接使用
区别:静态数据成员的类型可以就是它所属的类类型,而普通成员只能声明它所属类的指针或引用;
可以使用静态成员作为默认实参,而普通成员不行。
class Account {
public:
void calculate() { amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate(); // 不太清楚这个要干吗~
};
void Account::rate(double newRate)
{
interestRate = newRate;
}
// example.h
class Example {
public:
static double rate = 6.5; // 错误,带初始值的不能是static
static const int vecSize = 20;
static vector<double> vec(vecSize); // 错误,带初始值的不能是static
};
// example.C
#include "example.h"
double Example::rate;
vector<double> Example::vec;
修改:
// example.h
class Example {
public:
static constexpr double rate = 6.5; // 错误,带初始值的不能是static
static const int vecSize = 20;
static vector<double> vec; // 错误,带初始值的不能是static
};
// example.C
#include "example.h"
double Example::rate;
vector<double> Example::vec(Example::vecSize);