C++ primer习题记录——第十四章

14.2:

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
class Sales_data
{
	friend istream& read(istream& is, Sales_data& item);
	friend ostream& print(ostream& os, const Sales_data& item);
	friend Sales_data add(const Sales_data& s1, const Sales_data& s2);
	friend istream& operator>>(istream& , Sales_data&);
	friend ostream& operator<<(ostream& , const Sales_data&);
	friend Sales_data operator+(const Sales_data& s1, const Sales_data& s2);
public:
	Sales_data() = default;
	Sales_data(const string& s) :bookNo(s) {};
	Sales_data(const string& s, unsigned n, double p) :bookNo(s), unit_sold(n), revenue(n* p) {};
	Sales_data(istream& is) { read(cin, *this); }
	Sales_data& operator+=(const Sales_data& s);

	Sales_data& combine(const Sales_data& rhs);
	string isbn()const
	{
		return this->bookNo;
	}
private:
	inline double avg_price()const;
	string bookNo;
	unsigned unit_sold = 0;
	double revenue = 0.0;
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	this->unit_sold += rhs.unit_sold;
	this->revenue += rhs.revenue;
	return *this;
}
Sales_data add(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp.combine(s2);
	return temp;
}
istream& read(istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.unit_sold >> price;
	item.revenue = item.unit_sold * price;
	return is;
}
ostream& print(ostream& os, const Sales_data& item)
{
	os << item.bookNo << " " << item.unit_sold << " " << item.revenue;
	return os;
}
inline double Sales_data::avg_price()const
{
	return unit_sold ? revenue / unit_sold : 0;
}
istream& operator>>(istream& in, Sales_data& sd)
{
	double price = 0;
	in >> sd.bookNo >> sd.unit_sold >> price;
	if (in)
	{
		sd.revenue = sd.unit_sold * price;
	}
	else
	{
		sd = Sales_data();
	}
	return in;
}
ostream& operator<<(ostream& out, const Sales_data& item)
{
	out << item.bookNo << " " << item.unit_sold << " " << item.revenue << " " << item.avg_price();
	return out;
}
Sales_data operator+(const Sales_data& s1, const Sales_data & s2)
{
	Sales_data temp = s1;
	temp.unit_sold += s2.unit_sold;
	temp.revenue += s2.revenue;
	return temp;
}
Sales_data& Sales_data::operator+=(const Sales_data& s)
{
	this->unit_sold += s.unit_sold;
	this->revenue += s.revenue;
	return *this;
}

14.7:

String.h:

#pragma once
#include<iostream>
using namespace std;
#include<algorithm>

class String
{
	friend ostream& operator<< (ostream& os, const String& s);
public:
	String():String("") {}
	String(const String&);
	String(const char*);
	String& operator=(const String&);
	String(String&&)noexcept;
	String& operator=(String&&)noexcept;
	~String();
	const char* c_str() const { return elements; }
	size_t size() const { return end - elements; }
	size_t length() const { return end - elements - 1; }

private:
	pair<char*, char*>alloc_n_copy(const char*, const char*);
	void range_initializer(const char*, const char*);
	void free();
	char* elements;
	char* end;
	allocator<char>alloc;
};
ostream& operator<< (ostream& os, const String& s);

String.cpp:

#include"string.h"

pair<char*, char*>String::alloc_n_copy(const char*b, const char*e)
{
	auto str = alloc.allocate(e - b);
	return { str,uninitialized_copy(b,e,str) };
}
void String::range_initializer(const char*b, const char*e)
{
	auto newstr = alloc_n_copy(b, e);
	elements = newstr.first;
	end = newstr.second;
}
String::String(const char*s)
{
	char* s1 = const_cast<char*>(s);
	while (*s1)
	{
		++s1;
	}
	range_initializer(s, ++s1);
}
String::String(const String&rhs)
{
	range_initializer(rhs.elements, rhs.end);
	cout << "copy constructor" << endl;
}
void String::free()
{
	if (elements)
	{
		for_each(elements, end, [this](char& c) {alloc.destroy(&c); });
		alloc.deallocate(elements, end - elements);
	}
}
String::~String()
{
	free();
}
String& String::operator=(const String&rhs)
{
	auto newstr = alloc_n_copy(rhs.elements, rhs.end);
	free();
	elements = newstr.first;
	end = newstr.second;
	cout << "copy assignment" << endl;
	return *this;
}
String::String(String&&s)noexcept:elements(s.elements),end(s.end)
{
	s.elements = s.end = nullptr;
}
String& String::operator=(String&&s)noexcept
{
	if (this != &s)
	{
		free();
		elements = s.elements;
		end = s.end;
		s.elements = s.end = nullptr;
	}
	return *this;
}
ostream& operator<< (ostream& os, const String& s)
{
	char* c = const_cast<char*>(s.c_str());
	while (*c)
	{
		os << *c++;
	}
	return os;
}

14.13:

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
class Sales_data
{
	friend istream& read(istream& is, Sales_data& item);
	friend ostream& print(ostream& os, const Sales_data& item);
	friend Sales_data add(const Sales_data& s1, const Sales_data& s2);
	friend istream& operator>>(istream& , Sales_data&);
	friend ostream& operator<<(ostream& , const Sales_data&);
	friend Sales_data operator+(const Sales_data& s1, const Sales_data& s2);
	friend Sales_data operator-(const Sales_data& s1, const Sales_data& s2);
public:
	Sales_data() = default;
	Sales_data(const string& s) :bookNo(s) {};
	Sales_data(const string& s, unsigned n, double p) :bookNo(s), unit_sold(n), revenue(n* p) {};
	Sales_data(istream& is) { read(cin, *this); }
	Sales_data& operator+=(const Sales_data& s);
	Sales_data& operator-=(const Sales_data& s);

	Sales_data& combine(const Sales_data& rhs);
	string isbn()const
	{
		return this->bookNo;
	}
private:
	inline double avg_price()const;
	string bookNo;
	unsigned unit_sold = 0;
	double revenue = 0.0;
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	this->unit_sold += rhs.unit_sold;
	this->revenue += rhs.revenue;
	return *this;
}
Sales_data add(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp.combine(s2);
	return temp;
}
istream& read(istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.unit_sold >> price;
	item.revenue = item.unit_sold * price;
	return is;
}
ostream& print(ostream& os, const Sales_data& item)
{
	os << item.bookNo << " " << item.unit_sold << " " << item.revenue;
	return os;
}
inline double Sales_data::avg_price()const
{
	return unit_sold ? revenue / unit_sold : 0;
}
istream& operator>>(istream& in, Sales_data& sd)
{
	double price = 0;
	in >> sd.bookNo >> sd.unit_sold >> price;
	if (in)
	{
		sd.revenue = sd.unit_sold * price;
	}
	else
	{
		sd = Sales_data();
	}
	return in;
}

ostream& operator<<(ostream& out, const Sales_data& item)
{
	out << item.bookNo << " " << item.unit_sold << " " << item.revenue << " " << item.avg_price();
	return out;
}
Sales_data operator+(const Sales_data& s1, const Sales_data & s2)
{
	Sales_data temp = s1;
	temp.unit_sold += s2.unit_sold;
	temp.revenue += s2.revenue;
	return temp;
}
Sales_data& Sales_data::operator+=(const Sales_data& s)
{
	this->unit_sold += s.unit_sold;
	this->revenue += s.revenue;
	return *this;
}
Sales_data operator-(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp -= s2;
	return temp;
}
Sales_data& Sales_data::operator-=(const Sales_data& s)
{
	this->unit_sold -= s.unit_sold;
	this->revenue -= s.revenue;
	return *this;
}

14.16:

string.h:

#pragma once
#include<iostream>
using namespace std;
#include<algorithm>

class String
{
	friend ostream& operator<< (ostream& os, const String& s);
	friend bool operator==(const String& s1, const String& s2);
	friend bool operator!=(const String& s1, const String& s2);
public:
	String():String("") {}
	String(const String&);
	String(const char*);
	String& operator=(const String&);
	String(String&&)noexcept;
	String& operator=(String&&)noexcept;
	~String();
	const char* c_str() const { return elements; }
	size_t size() const { return end - elements; }
	size_t length() const { return end - elements - 1; }

private:
	pair<char*, char*>alloc_n_copy(const char*, const char*);
	void range_initializer(const char*, const char*);
	void free();
	char* elements;
	char* end;
	allocator<char>alloc;
};
ostream& operator<< (ostream& os, const String& s);
bool operator==(const String& s1, const String& s2);
bool operator!=(const String& s1, const String& s2);

string.cpp:

#include"string.h"

pair<char*, char*>String::alloc_n_copy(const char*b, const char*e)
{
	auto str = alloc.allocate(e - b);
	return { str,uninitialized_copy(b,e,str) };
}
void String::range_initializer(const char*b, const char*e)
{
	auto newstr = alloc_n_copy(b, e);
	elements = newstr.first;
	end = newstr.second;
}
String::String(const char*s)
{
	char* s1 = const_cast<char*>(s);
	while (*s1)
	{
		++s1;
	}
	range_initializer(s, ++s1);
}
String::String(const String&rhs)
{
	range_initializer(rhs.elements, rhs.end);
	cout << "copy constructor" << endl;
}
void String::free()
{
	if (elements)
	{
		for_each(elements, end, [this](char& c) {alloc.destroy(&c); });
		alloc.deallocate(elements, end - elements);
	}
}
String::~String()
{
	free();
}
String& String::operator=(const String&rhs)
{
	auto newstr = alloc_n_copy(rhs.elements, rhs.end);
	free();
	elements = newstr.first;
	end = newstr.second;
	cout << "copy assignment" << endl;
	return *this;
}
String::String(String&&s)noexcept:elements(s.elements),end(s.end)
{
	s.elements = s.end = nullptr;
}
String& String::operator=(String&&s)noexcept
{
	if (this != &s)
	{
		free();
		elements = s.elements;
		end = s.end;
		s.elements = s.end = nullptr;
	}
	return *this;
}
ostream& operator<< (ostream& os, const String& s)
{
	char* c = const_cast<char*>(s.c_str());
	while (*c)
	{
		os << *c++;
	}
	return os;
}
bool operator==(const String& s1, const String& s2)
{
	return s1.size() == s2.size() && equal(s1.elements, s1.end, s2.elements);
}
bool operator!=(const String& s1, const String& s2)
{
	return !(s1 == s2);
}

14.18:

string.h:

#pragma once
#include<iostream>
using namespace std;
#include<algorithm>

class String
{
	friend ostream& operator<< (ostream& os, const String& s);
	friend bool operator==(const String& s1, const String& s2);
	friend bool operator!=(const String& s1, const String& s2);
	friend bool operator< (const String& s1, const String& s2);
	friend bool operator<= (const String& s1, const String& s2);
	friend bool operator> (const String& s1, const String& s2);
	friend bool operator>= (const String& s1, const String& s2);
public:
	String():String("") {}
	String(const String&);
	String(const char*);
	String& operator=(const String&);
	String(String&&)noexcept;
	String& operator=(String&&)noexcept;
	~String();
	const char* c_str() const { return elements; }
	size_t size() const { return end - elements; }
	size_t length() const { return end - elements - 1; }

private:
	pair<char*, char*>alloc_n_copy(const char*, const char*);
	void range_initializer(const char*, const char*);
	void free();
	char* elements;
	char* end;
	allocator<char>alloc;
};
ostream& operator<< (ostream& os, const String& s);
bool operator==(const String& s1, const String& s2);
bool operator!=(const String& s1, const String& s2);
bool operator< (const String& s1, const String& s2);
bool operator<= (const String& s1, const String& s2);
bool operator> (const String& s1, const String& s2);
bool operator>= (const String& s1, const String& s2);

string.cpp:

#include"string.h"

pair<char*, char*>String::alloc_n_copy(const char*b, const char*e)
{
	auto str = alloc.allocate(e - b);
	return { str,uninitialized_copy(b,e,str) };
}
void String::range_initializer(const char*b, const char*e)
{
	auto newstr = alloc_n_copy(b, e);
	elements = newstr.first;
	end = newstr.second;
}
String::String(const char*s)
{
	char* s1 = const_cast<char*>(s);
	while (*s1)
	{
		++s1;
	}
	range_initializer(s, ++s1);
}
String::String(const String&rhs)
{
	range_initializer(rhs.elements, rhs.end);
	cout << "copy constructor" << endl;
}
void String::free()
{
	if (elements)
	{
		for_each(elements, end, [this](char& c) {alloc.destroy(&c); });
		alloc.deallocate(elements, end - elements);
	}
}
String::~String()
{
	free();
}
String& String::operator=(const String&rhs)
{
	auto newstr = alloc_n_copy(rhs.elements, rhs.end);
	free();
	elements = newstr.first;
	end = newstr.second;
	cout << "copy assignment" << endl;
	return *this;
}
String::String(String&&s)noexcept:elements(s.elements),end(s.end)
{
	s.elements = s.end = nullptr;
}
String& String::operator=(String&&s)noexcept
{
	if (this != &s)
	{
		free();
		elements = s.elements;
		end = s.end;
		s.elements = s.end = nullptr;
	}
	return *this;
}
ostream& operator<< (ostream& os, const String& s)
{
	char* c = const_cast<char*>(s.c_str());
	while (*c)
	{
		os << *c++;
	}
	return os;
}
bool operator==(const String& s1, const String& s2)
{
	return s1.size() == s2.size() && equal(s1.elements, s1.end, s2.elements);
}
bool operator!=(const String& s1, const String& s2)
{
	return !(s1 == s2);
}
bool operator< (const String& s1, const String& s2)
{
	return lexicographical_compare(s1.elements, s1.end, s2.elements, s2.end);
}
bool operator<= (const String& s1, const String& s2)
{
	return !(s2 < s1);
}
bool operator> (const String& s1, const String& s2)
{
	return s2 < s1;
}
bool operator>= (const String& s1, const String& s2)
{
	return !(s1 < s2);
}

14.22:

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
class Sales_data
{
	friend istream& read(istream& is, Sales_data& item);
	friend ostream& print(ostream& os, const Sales_data& item);
	friend Sales_data add(const Sales_data& s1, const Sales_data& s2);
	friend istream& operator>>(istream& , Sales_data&);
	friend ostream& operator<<(ostream& , const Sales_data&);
	friend Sales_data operator+(const Sales_data& s1, const Sales_data& s2);
	friend Sales_data operator-(const Sales_data& s1, const Sales_data& s2);
public:
	Sales_data() = default;
	Sales_data(const string& s) :bookNo(s) {};
	Sales_data(const string& s, unsigned n, double p) :bookNo(s), unit_sold(n), revenue(n* p) {};
	Sales_data(istream& is) { read(cin, *this); }
	Sales_data& operator+=(const Sales_data& s);
	Sales_data& operator-=(const Sales_data& s);
	Sales_data& operator=(const string& s);

	Sales_data& combine(const Sales_data& rhs);
	string isbn()const
	{
		return this->bookNo;
	}
private:
	inline double avg_price()const;
	string bookNo;
	unsigned unit_sold = 0;
	double revenue = 0.0;
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	this->unit_sold += rhs.unit_sold;
	this->revenue += rhs.revenue;
	return *this;
}
Sales_data add(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp.combine(s2);
	return temp;
}
istream& read(istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.unit_sold >> price;
	item.revenue = item.unit_sold * price;
	return is;
}
ostream& print(ostream& os, const Sales_data& item)
{
	os << item.bookNo << " " << item.unit_sold << " " << item.revenue;
	return os;
}
inline double Sales_data::avg_price()const
{
	return unit_sold ? revenue / unit_sold : 0;
}
istream& operator>>(istream& in, Sales_data& sd)
{
	double price = 0;
	in >> sd.bookNo >> sd.unit_sold >> price;
	if (in)
	{
		sd.revenue = sd.unit_sold * price;
	}
	else
	{
		sd = Sales_data();
	}
	return in;
}

ostream& operator<<(ostream& out, const Sales_data& item)
{
	out << item.bookNo << " " << item.unit_sold << " " << item.revenue << " " << item.avg_price();
	return out;
}
Sales_data operator+(const Sales_data& s1, const Sales_data & s2)
{
	Sales_data temp = s1;
	temp.unit_sold += s2.unit_sold;
	temp.revenue += s2.revenue;
	return temp;
}
Sales_data& Sales_data::operator+=(const Sales_data& s)
{
	this->unit_sold += s.unit_sold;
	this->revenue += s.revenue;
	return *this;
}
Sales_data operator-(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp -= s2;
	return temp;
}
Sales_data& Sales_data::operator-=(const Sales_data& s)
{
	this->unit_sold -= s.unit_sold;
	this->revenue -= s.revenue;
	return *this;
}
Sales_data& Sales_data::operator=(const string& s)
{
	*this = Sales_data(s);
	return *this;
}

14.27:

.h

#include "ex14_27_28_StrBlob.h"
#include <algorithm>

//==================================================================
//
//		StrBlob - operators
//
//==================================================================

bool operator==(const StrBlob &lhs, const StrBlob &rhs)
{
    return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob &lhs, const StrBlob &rhs)
{
    return !(lhs == rhs);
}

bool operator< (const StrBlob &lhs, const StrBlob &rhs)
{
    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}

bool operator> (const StrBlob &lhs, const StrBlob &rhs)
{
    return rhs < lhs;
}

bool operator<=(const StrBlob &lhs, const StrBlob &rhs)
{
    return !(rhs < lhs);
}

bool operator>=(const StrBlob &lhs, const StrBlob &rhs)
{
    return !(lhs < rhs);
}

//================================================================
//
//		StrBlobPtr - operators
//
//================================================================

bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
    return !(lhs == rhs);
}

bool operator< (const StrBlobPtr &x, const StrBlobPtr &y)
{
    return x.curr < y.curr;
}

bool operator>(const StrBlobPtr &x, const StrBlobPtr &y)
{
    return x.curr > y.curr;
}

bool operator<=(const StrBlobPtr &x, const StrBlobPtr &y)
{
    return x.curr <= y.curr;
}

bool operator>=(const StrBlobPtr &x, const StrBlobPtr &y)
{
    return x.curr >= y.curr;
}

//================================================================
//
//		ConstStrBlobPtr - operators
//
//================================================================

bool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return !(lhs == rhs);
}

bool operator< (const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return lhs.curr < rhs.curr;
}

bool operator>(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return lhs.curr > rhs.curr;
}

bool operator<=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return lhs.curr <= rhs.curr;
}

bool operator>=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return lhs.curr >= rhs.curr;
}

//==================================================================
//
//		copy assignment operator and move assignment operator.
//
//==================================================================

StrBlob& StrBlob::operator=(const StrBlob &lhs)
{
    data = make_shared<vector<string>>(*lhs.data);
    return *this;
}

StrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT
{
    if (this != &rhs) {
        data = std::move(rhs.data);
        rhs.data = nullptr;
    }

    return *this;
}

//==================================================================
//
//		members
//
//==================================================================

StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end()
{
    return StrBlobPtr(*this, data->size());
}

ConstStrBlobPtr StrBlob::cbegin() const
{
    return ConstStrBlobPtr(*this);
}

ConstStrBlobPtr StrBlob::cend() const
{
    return ConstStrBlobPtr(*this, data->size());
}

.cpp

#include "StrBlob.h"
#include <algorithm>

//==================================================================
//
//		StrBlob - operators
//
//==================================================================

bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
    return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
    return !(lhs == rhs);
}

bool operator< (const StrBlob& lhs, const StrBlob& rhs)
{
    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}

bool operator> (const StrBlob& lhs, const StrBlob& rhs)
{
    return rhs < lhs;
}

bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
    return !(rhs < lhs);
}

bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
    return !(lhs < rhs);
}

//================================================================
//
//		StrBlobPtr - operators
//
//================================================================

bool operator==(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
    return !(lhs == rhs);
}

bool operator< (const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr < y.curr;
}

bool operator>(const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr > y.curr;
}

bool operator<=(const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr <= y.curr;
}

bool operator>=(const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr >= y.curr;
}

//================================================================
//
//		ConstStrBlobPtr - operators
//
//================================================================

bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return !(lhs == rhs);
}

bool operator< (const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr < rhs.curr;
}

bool operator>(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr > rhs.curr;
}

bool operator<=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr <= rhs.curr;
}

bool operator>=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr >= rhs.curr;
}

//==================================================================
//
//		copy assignment operator and move assignment operator.
//
//==================================================================

StrBlob& StrBlob::operator=(const StrBlob& lhs)
{
    data = make_shared<vector<string>>(*lhs.data);
    return *this;
}

StrBlob& StrBlob::operator=(StrBlob&& rhs) NOEXCEPT
{
    if (this != &rhs) {
        data = std::move(rhs.data);
        rhs.data = nullptr;
    }

    return *this;
}

//==================================================================
//
//		members
//
//==================================================================

StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end()
{
    return StrBlobPtr(*this, data->size());
}

ConstStrBlobPtr StrBlob::cbegin() const
{
    return ConstStrBlobPtr(*this);
}

ConstStrBlobPtr StrBlob::cend() const
{
    return ConstStrBlobPtr(*this, data->size());
}

14.30:

.h:

#ifndef CP5_STRBLOB_H_
#define CP5_STRBLOB_H_
using namespace std;
#include<iostream>
#include <vector>
#include <string>
#include <initializer_list>
#include <memory>
#include <exception>

#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif

class StrBlobPtr;
class ConstStrBlobPtr;

//=================================================================================
//
//		StrBlob - custom vector<string>
//
//=================================================================================

class StrBlob {
    using size_type = vector<string>::size_type;
    friend class ConstStrBlobPtr;
    friend class StrBlobPtr;
    friend bool operator==(const StrBlob&, const StrBlob&);
    friend bool operator!=(const StrBlob&, const StrBlob&);
    friend bool operator< (const StrBlob&, const StrBlob&);
    friend bool operator> (const StrBlob&, const StrBlob&);
    friend bool operator<=(const StrBlob&, const StrBlob&);
    friend bool operator>=(const StrBlob&, const StrBlob&);

public:
    StrBlob() : data(make_shared<vector<string>>()) { }
    StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { }

    StrBlob(const StrBlob& sb) : data(make_shared<vector<string>>(*sb.data)) { }
    StrBlob& operator=(const StrBlob&);

    StrBlob(StrBlob&& rhs) NOEXCEPT : data(std::move(rhs.data)) { }
    StrBlob& operator=(StrBlob&&)NOEXCEPT;

    StrBlobPtr begin();
    StrBlobPtr end();

    ConstStrBlobPtr cbegin() const;
    ConstStrBlobPtr cend() const;

    string& operator[](size_t n);
    const string& operator[](size_t n) const;

    size_type size() const { return data->size(); }
    bool empty() const { return data->empty(); }

    void push_back(const string& t) { data->push_back(t); }
    void push_back(string&& s) { data->push_back(std::move(s)); }

    void pop_back();
    string& front();
    string& back();
    const string& front() const;
    const string& back() const;

private:
    void check(size_type, const string&) const;

    shared_ptr<vector<string>> data;
};

bool operator==(const StrBlob&, const StrBlob&);
bool operator!=(const StrBlob&, const StrBlob&);
bool operator< (const StrBlob&, const StrBlob&);
bool operator> (const StrBlob&, const StrBlob&);
bool operator<=(const StrBlob&, const StrBlob&);
bool operator>=(const StrBlob&, const StrBlob&);

inline void StrBlob::pop_back()
{
    check(0, "pop_back on empty StrBlob");
    data->pop_back();
}

inline string& StrBlob::front()
{
    check(0, "front on empty StrBlob");
    return data->front();
}

inline string& StrBlob::back()
{
    check(0, "back on empty StrBlob");
    return data->back();
}

inline const string& StrBlob::front() const
{
    check(0, "front on empty StrBlob");
    return data->front();
}

inline const string& StrBlob::back() const
{
    check(0, "back on empty StrBlob");
    return data->back();
}

inline void StrBlob::check(size_type i, const string& msg) const
{
    if (i >= data->size()) throw out_of_range(msg);
}

inline string& StrBlob::operator[](size_t n)
{
    check(n, "out of range");
    return data->at(n);
}

inline const string& StrBlob::operator[](size_t n) const
{
    check(n, "out of range");
    return data->at(n);
}

//=================================================================================
//
//		StrBlobPtr - custom iterator of StrBlob
//
//=================================================================================

class StrBlobPtr {
    friend bool operator==(const StrBlobPtr&, const StrBlobPtr&);
    friend bool operator!=(const StrBlobPtr&, const StrBlobPtr&);
    friend bool operator< (const StrBlobPtr&, const StrBlobPtr&);
    friend bool operator> (const StrBlobPtr&, const StrBlobPtr&);
    friend bool operator<=(const StrBlobPtr&, const StrBlobPtr&);
    friend bool operator>=(const StrBlobPtr&, const StrBlobPtr&);

public:
    StrBlobPtr() : curr(0) { }
    StrBlobPtr(StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) { }

    string& deref() const;
    StrBlobPtr& operator++();
    StrBlobPtr& operator--();
    StrBlobPtr operator++(int);
    StrBlobPtr operator--(int);
    StrBlobPtr& operator+=(size_t);
    StrBlobPtr& operator-=(size_t);
    StrBlobPtr operator+(size_t) const;
    StrBlobPtr operator-(size_t) const;
    string& operator*() const;
    string* operator->() const;

    string& operator[](size_t n);
    const string& operator[](size_t n) const;

private:
    shared_ptr<vector<string>> check(size_t, const string&) const;

    std::weak_ptr<vector<string>> wptr;
    size_t curr;
};

bool operator==(const StrBlobPtr&, const StrBlobPtr&);
bool operator!=(const StrBlobPtr&, const StrBlobPtr&);
bool operator< (const StrBlobPtr&, const StrBlobPtr&);
bool operator> (const StrBlobPtr&, const StrBlobPtr&);
bool operator<=(const StrBlobPtr&, const StrBlobPtr&);
bool operator>=(const StrBlobPtr&, const StrBlobPtr&);

inline string& StrBlobPtr::deref() const
{
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}

inline StrBlobPtr& StrBlobPtr::operator++()
{
    check(curr, "increment past end of StrBlobPtr");
    ++curr;
    return *this;
}

inline StrBlobPtr& StrBlobPtr::operator--()
{
    check(--curr, "decrement past begin of StrBlobPtr");
    return *this;
}

inline StrBlobPtr StrBlobPtr::operator++(int)
{
    StrBlobPtr ret = *this;
    ++* this;
    return ret;
}

inline StrBlobPtr StrBlobPtr::operator--(int)
{
    StrBlobPtr ret = *this;
    --* this;
    return ret;
}

inline StrBlobPtr& StrBlobPtr::operator+=(size_t n)
{
    curr += n;
    check(curr, "increment past end of StrBlobPtr");
    return *this;
}

inline StrBlobPtr& StrBlobPtr::operator-=(size_t n)
{
    curr -= n;
    check(curr, "increment past end of StrBlobPtr");
    return *this;
}

inline StrBlobPtr StrBlobPtr::operator+(size_t n) const
{
    StrBlobPtr ret = *this;
    ret += n;
    return ret;
}

inline StrBlobPtr StrBlobPtr::operator-(size_t n) const
{
    StrBlobPtr ret = *this;
    ret -= n;
    return ret;
}

inline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string& msg) const
{
    auto ret = wptr.lock();
    if (!ret) throw std::runtime_error("unbound StrBlobPtr");
    if (i >= ret->size()) throw std::out_of_range(msg);
    return ret;
}

inline string& StrBlobPtr::operator[](size_t n)
{
    auto p = check(n, "dereference out of range.");
    return (*p)[n];
}

inline const string& StrBlobPtr::operator[](size_t n) const
{
    auto p = check(n, "dereference out of range.");
    return (*p)[n];
}
inline string& StrBlobPtr::operator*() const
{
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}
inline string* StrBlobPtr::operator->() const
{
    return &this->operator*();
}

//=================================================================================
//
//		ConstStrBlobPtr - custom const_iterator of StrBlob
//
//=================================================================================

class ConstStrBlobPtr {
    friend bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);
    friend bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);
    friend bool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);
    friend bool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);
    friend bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);
    friend bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);

public:
    ConstStrBlobPtr() : curr(0) { }
    ConstStrBlobPtr(const StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) { }

    const string& deref() const;
    ConstStrBlobPtr& operator++();
    ConstStrBlobPtr& operator--();
    ConstStrBlobPtr operator++(int);
    ConstStrBlobPtr operator--(int);
    ConstStrBlobPtr& operator+=(size_t);
    ConstStrBlobPtr& operator-=(size_t);
    ConstStrBlobPtr operator+(size_t) const;
    ConstStrBlobPtr operator-(size_t) const;
    const string& operator*() const;
    const string* operator->() const;

    const string& operator[](size_t n) const;

private:
    std::shared_ptr<vector<string>> check(size_t, const string&) const;

    std::weak_ptr<vector<string>> wptr;
    size_t curr;
};

bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&);
bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);
bool operator< (const ConstStrBlobPtr&, const ConstStrBlobPtr&);
bool operator> (const ConstStrBlobPtr&, const ConstStrBlobPtr&);
bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);
bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&);

inline const string& ConstStrBlobPtr::deref() const
{
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}

inline ConstStrBlobPtr& ConstStrBlobPtr::operator++()
{
    check(curr, "increment past end of ConstStrBlobPtr");
    ++curr;
    return *this;
}

inline ConstStrBlobPtr& ConstStrBlobPtr::operator--()
{
    --curr;
    check(-1, "decrement past begin of ConstStrBlobPtr");
    return *this;
}

inline ConstStrBlobPtr ConstStrBlobPtr::operator++(int)
{
    ConstStrBlobPtr ret = *this;
    ++* this;
    return ret;
}

inline ConstStrBlobPtr ConstStrBlobPtr::operator--(int)
{
    ConstStrBlobPtr ret = *this;
    --* this;
    return ret;
}

inline ConstStrBlobPtr& ConstStrBlobPtr::operator+=(size_t n)
{
    curr += n;
    check(curr, "increment past end of ConstStrBlobPtr");
    return *this;
}

inline ConstStrBlobPtr& ConstStrBlobPtr::operator-=(size_t n)
{
    curr -= n;
    check(curr, "increment past end of ConstStrBlobPtr");
    return *this;
}

inline ConstStrBlobPtr ConstStrBlobPtr::operator+(size_t n) const
{
    ConstStrBlobPtr ret = *this;
    ret += n;
    return ret;
}

inline ConstStrBlobPtr ConstStrBlobPtr::operator-(size_t n) const
{
    ConstStrBlobPtr ret = *this;
    ret -= n;
    return ret;
}

inline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string& msg) const
{
    auto ret = wptr.lock();
    if (!ret) throw std::runtime_error("unbound StrBlobPtr");
    if (i >= ret->size()) throw std::out_of_range(msg);
    return ret;
}

inline const string& ConstStrBlobPtr::operator[](size_t n) const
{
    auto p = check(n, "dereference out of range.");
    return (*p)[n];
}
inline const string& ConstStrBlobPtr::operator*() const
{
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}
inline const string* ConstStrBlobPtr::operator->() const
{
    return &this->operator*();
}

#endif

.cpp:

#include "StrBlob.h"
#include <algorithm>

//==================================================================
//
//		StrBlob - operators
//
//==================================================================

bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
    return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
    return !(lhs == rhs);
}

bool operator< (const StrBlob& lhs, const StrBlob& rhs)
{
    return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}

bool operator> (const StrBlob& lhs, const StrBlob& rhs)
{
    return rhs < lhs;
}

bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
    return !(rhs < lhs);
}

bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
    return !(lhs < rhs);
}

//================================================================
//
//		StrBlobPtr - operators
//
//================================================================

bool operator==(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{
    return !(lhs == rhs);
}

bool operator< (const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr < y.curr;
}

bool operator>(const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr > y.curr;
}

bool operator<=(const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr <= y.curr;
}

bool operator>=(const StrBlobPtr& x, const StrBlobPtr& y)
{
    return x.curr >= y.curr;
}

//================================================================
//
//		ConstStrBlobPtr - operators
//
//================================================================

bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return !(lhs == rhs);
}

bool operator< (const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr < rhs.curr;
}

bool operator>(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr > rhs.curr;
}

bool operator<=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr <= rhs.curr;
}

bool operator>=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
    return lhs.curr >= rhs.curr;
}

//==================================================================
//
//		copy assignment operator and move assignment operator.
//
//==================================================================

StrBlob& StrBlob::operator=(const StrBlob& lhs)
{
    data = make_shared<vector<string>>(*lhs.data);
    return *this;
}

StrBlob& StrBlob::operator=(StrBlob&& rhs) NOEXCEPT
{
    if (this != &rhs) {
        data = std::move(rhs.data);
        rhs.data = nullptr;
    }

    return *this;
}

//==================================================================
//
//		members
//
//==================================================================

StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end()
{
    return StrBlobPtr(*this, data->size());
}

ConstStrBlobPtr StrBlob::cbegin() const
{
    return ConstStrBlobPtr(*this);
}

ConstStrBlobPtr StrBlob::cend() const
{
    return ConstStrBlobPtr(*this, data->size());
}

14.32:

.h

#ifndef STRBLOBPTR_POINTER_H
#define STRBLOBPTR_POINTER_H

class StrBlobPtr;

/**
 * @brief a class that holds a pointer to a StrBlobPtr.
 */
class StrBlobPtr_pointer
{
public:
    StrBlobPtr_pointer() = default;
    StrBlobPtr_pointer(StrBlobPtr* p) : pointer(p) { }

    StrBlobPtr& operator *() const;
    StrBlobPtr* operator->() const;

private:
    StrBlobPtr* pointer = nullptr;
};

#endif // STRBLOBPTR_POINTER_H

.cpp:

#include "ex14_32.h"
#include "ex14_30_StrBlob.h"
#include <iostream>

StrBlobPtr&
StrBlobPtr_pointer::operator *() const
{
    return *pointer;
}

StrBlobPtr*
StrBlobPtr_pointer::operator ->() const
{
    return pointer;
}

int main()
{
    StrBlob sb{ "hello", "world" };
    StrBlobPtr iter = sb.begin();
    StrBlobPtr_pointer p(&iter);
    std::cout << p->deref() << std::endl;
}

14.34:

#include<iostream>
using namespace std;

class if_then_else
{
public:
	int operator()(int a, int b, int c)
	{
		return (a ? b : c);
	}
};

int main()
{
	int a = 0, b = 1, c = 2;
	if_then_else f;
	cout << f(a, b, c) << endl;
}

14.35:

#include<iostream>
using namespace std;
#include<string>

class PrintString
{
public:
	PrintString(istream&i =cin):is(i){}
	string operator()()
	{
		string str;
		getline(is, str);
		return is ? str : string();
	}

private:
	istream& is;
};

int main()
{
	PrintString getinput;
	cout << getinput() << endl;
}

14.36:

#include<iostream>
using namespace std;
#include<string>
#include<vector>

class PrintString
{
public:
	PrintString(istream&i =cin):is(i){}
	string operator()()
	{
		string str;
		getline(is, str);
		return is ? str : string();
	}

private:
	istream& is;
};

int main()
{
	PrintString getinput;
	vector<string>ves;
	for (string temp; !((temp = getinput()).empty()); ves.push_back(temp));
	for (auto m : ves) { cout << m << " "; }cout << endl;
	return 0;
}

14.37:

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<algorithm>
class test
{
public:
	test(int a):i(a){}
	bool operator()(const int& b)
	{
		return i == b;
	}

private:
	int i;
};

int main()
{
	test t(1);
	vector<int>vec = { 1,2,3,4,5,6,7,9 };
	replace_if(vec.begin(), vec.end(), t, 2);
	for (int i : vec) cout << i << " ";
	cout << endl;
	return 0;
}

10.39:

哈哈哈

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<algorithm>
class SizeComp
{
public:
	SizeComp(size_t i):sz(i),lower(0),upper(0) {}
	SizeComp(size_t a,size_t b) :sz(0), lower(a), upper(b) {}
	SizeComp(size_t a, size_t b,size_t c) :sz(c), lower(a), upper(b) {}
	bool operator()(const string& s)const
	{
		if (sz==0)
		{
            return s.size() >= lower && s.size() <= upper;
		}
		else if(lower ==0)
		{
			return 	s.size() == sz;
		}
		else
		{
			return s.size() >= upper;
		}
	}

private:
	size_t sz;
	size_t lower;
	size_t upper;
};

int main()
{
	vector<string>ves = { "sdafsdf","asdfasdf","as","wre","qwer","a","sdfsdfsdfasdfsdf"};
	auto num = count_if(ves.begin(), ves.end(), SizeComp(2));
	cout << num << endl;
	num = count_if(ves.begin(), ves.end(), SizeComp(1,9));
	cout << num << endl;
	num = count_if(ves.begin(), ves.end(), SizeComp(10,10,10));
	cout << num << endl;
	return 0;
}

14.40:

class ShorterString {
public:
    bool operator()(string const& s1, string const& s2) const { return s1.size() < s2.size(); }
};

class BiggerEqual {
    size_t sz_;
public:
    BiggerEqual(size_t sz) : sz_(sz) { }
    bool operator()(string const& s) { return s.size() >= sz_; }
};

class Print {
public:
    void operator()(string const& s) { cout << s << " "; }
};

14.42:

	count_if(vec.begin(), vec.end(), bind(greater<int>(), _1, 1024));
	find_if(vec.begin(), vec.end(), bind(not_equal_to<string>(), _1, "ppoh"));
	transform(vec.begin(), vec.end(), vec.begin(), bind(multiplies<int>(), _1, 2));

14.43:

#include<iostream>
using namespace std;
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using placeholders::_1;
int main()
{
	vector<int>vec = { 2,4,8 };
	int i = 0;
	int input;
	cin >> input;
	bool b = any_of(vec.begin(), vec.end(), bind(modulus<int>(), input, _1));
	if (b)
		cout << "not!" << endl;
	else
		cout << "yes!" << endl;
	return 0;
}

14.44:

#include<iostream>
using namespace std;
#include<functional>
#include<map>
//普通函数
int add(int a, int b)
{
	return a + b;
}
//lambda
auto mod = [](int a, int b) {return a % b; };
//函数对象类
class divide
{
public:
	int operator()(int a, int b)
	{
		return a / b;
	}
};

int main()
{
	int(*p1)(int, int) = add;
	map<string, function<int(int, int)>>binops = {
		{"+",p1},
		{"-",minus<int>()},
		{"/",divide()},
		{"*",[](int i,int j) {return i * j; }},
		{"%",mod}
	};
	while (cout << "Pls enter as: num operator num :\n", true)
	{
		int lhs, rhs;string op;
		cin >> lhs >> op >> rhs;
		cout << binops[op](lhs, rhs) << endl;
	}
	return 0;
}

14.45:

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
class Sales_data
{
	friend istream& read(istream& is, Sales_data& item);
	friend ostream& print(ostream& os, const Sales_data& item);
	friend Sales_data add(const Sales_data& s1, const Sales_data& s2);
	friend istream& operator>>(istream& , Sales_data&);
	friend ostream& operator<<(ostream& , const Sales_data&);
	friend Sales_data operator+(const Sales_data& s1, const Sales_data& s2);
	friend Sales_data operator-(const Sales_data& s1, const Sales_data& s2);
public:
	Sales_data() = default;
	Sales_data(const string& s) :bookNo(s) {};
	Sales_data(const string& s, unsigned n, double p) :bookNo(s), unit_sold(n), revenue(n* p) {};
	Sales_data(istream& is) { read(cin, *this); }
	Sales_data& operator+=(const Sales_data& s);
	Sales_data& operator-=(const Sales_data& s);
	Sales_data& operator=(const string& s);
	explicit operator string() const { return this->bookNo; }
	explicit operator double() const { return this->avg_price(); }

	Sales_data& combine(const Sales_data& rhs);
	string isbn()const
	{
		return this->bookNo;
	}
private:
	inline double avg_price()const;
	string bookNo;
	unsigned unit_sold = 0;
	double revenue = 0.0;
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	this->unit_sold += rhs.unit_sold;
	this->revenue += rhs.revenue;
	return *this;
}
Sales_data add(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp.combine(s2);
	return temp;
}
istream& read(istream& is, Sales_data& item)
{
	double price = 0;
	is >> item.bookNo >> item.unit_sold >> price;
	item.revenue = item.unit_sold * price;
	return is;
}
ostream& print(ostream& os, const Sales_data& item)
{
	os << item.bookNo << " " << item.unit_sold << " " << item.revenue;
	return os;
}
inline double Sales_data::avg_price()const
{
	return unit_sold ? revenue / unit_sold : 0;
}
istream& operator>>(istream& in, Sales_data& sd)
{
	double price = 0;
	in >> sd.bookNo >> sd.unit_sold >> price;
	if (in)
	{
		sd.revenue = sd.unit_sold * price;
	}
	else
	{
		sd = Sales_data();
	}
	return in;
}

ostream& operator<<(ostream& out, const Sales_data& item)
{
	out << item.bookNo << " " << item.unit_sold << " " << item.revenue << " " << item.avg_price();
	return out;
}
Sales_data operator+(const Sales_data& s1, const Sales_data & s2)
{
	Sales_data temp = s1;
	temp.unit_sold += s2.unit_sold;
	temp.revenue += s2.revenue;
	return temp;
}
Sales_data& Sales_data::operator+=(const Sales_data& s)
{
	this->unit_sold += s.unit_sold;
	this->revenue += s.revenue;
	return *this;
}
Sales_data operator-(const Sales_data& s1, const Sales_data& s2)
{
	Sales_data temp = s1;
	temp -= s2;
	return temp;
}
Sales_data& Sales_data::operator-=(const Sales_data& s)
{
	this->unit_sold -= s.unit_sold;
	this->revenue -= s.revenue;
	return *this;
}
Sales_data& Sales_data::operator=(const string& s)
{
	*this = Sales_data(s);
	return *this;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值