c++ primer中文版第五版作业第十八章
仓库地址
文章目录
- 18.1
- 18.2
- 18.3
- 18.4
- 18.5
- 18.6
- 18.7
- 18.8
- 18.9
- 18.10
- 18.11
- 18.12
- 18.13
- 18.14
- 18.15
- 18.16
- 位置一
- using声明
- 位置二
- using声明
- 位置一
- using指示
- 位置二
- using指示
- 18.17
- 18.18
- 18.19
- 18.20
- 18.21
- 18.22
- 18.23
- 18.24
- 18.25
- 18.26
- 18.26
- 18.28
- 18.29
- 18.30
18.1
- 此时r是一个range_error类型的局部对象
- 此时p是exception类型的指针,指向局部对象r
如果throw p
就会抛出一个指向局部对象的指针,那么有可能在执行catch语句之前,该局部对象已经被销毁。
18.2
v和in可以调用其析构函数释放资源,而p无法正确释放资源,导致内存泄漏。
18.3
- 使用智能指针管理p
unique_ptr<int []> p(new int[v.size()])
- 使用类来控制资源的分配
class ptr
{public:explicit ptr(size_t len):p(new int[len]) {}ptr(const ptr&)=delete;ptr & operator=(const ptr&)=delete;~ptr(){delete [] p;}private:int *p;
};
18.4
catch语句是按照其出现的顺序逐一进行匹配的,所以根据继承体系catch(exception)
后面的catch子句永远无法被匹配到。
try{
//
}catch(overflow_error eobj){
//
}catch(const runtime_error &re){
//
}catch(exception){/**/}
18.5
#include <iostream>
#include <exception>
#include <stdexcept>
#include <cstdlib>
int main(){try{//使用c++标准库
}catch(const exception &e){std::cout<<e.what()<<std::endl;abort();
}
}
18.6
throw exceptionType * eobj
,注意不能抛出一个指向局部对象的指针- 抛出的所有异常都能被捕获
int a=1;throw a;
抛出的所有int类型值都能被捕获,但是其余的整型类型无法进行算数类型转换为int。
18.7
#ifndef BLOB_H
#define BLOB_H
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <string>
#include <initializer_list>
#include <stdexcept>
template <typename> class BlobPtr;
template <typename> class Blob;
//Blob
template <typename T> bool operator==(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator!=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>=(const Blob<T> &,const Blob<T> &);
template <typename T> class Blob
{friend class BlobPtr<T>;friend bool operator==<T>(const Blob<T> &,const Blob<T> &);friend bool operator!=<T>(const Blob<T> &,const Blob<T> &);friend bool operator< <T>(const Blob<T> &,const Blob<T> &);friend bool operator<= <T>(const Blob<T> &,const Blob<T> &);friend bool operator> <T>(const Blob<T> &,const Blob<T> &);friend bool operator>= <T>(const Blob<T> &,const Blob<T> &);public:typedef T value_type;typedef typename std::vector<T>::size_type size_type;Blob() try:data(std::make_shared<std::vector<T>>()){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(std::initializer_list<T> il) try:data(std::make_shared<std::vector<T>>(il)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(const Blob &org) try:data(std::make_shared<std::vector<T>>(*org.data)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}template <typename it> Blob(it b,it e) try:data(std::make_shared<std::vector<T>>(b,e)) {} catch(std::bad_alloc &ba){std::cout<<ba.what()<<std::endl;}Blob &operator=(const Blob &);T & operator[](size_type i);const T & operator[](size_type i) const;size_type size() const {return data->size();}bool empty() const {return data->empty;}void push_back(const T &t){data->push_back(t);}void push_back(T &&t){data->push_back(std::move(t));}void pop_back();T & front();T & back();const T & front() const;const T & back() const;BlobPtr<T> begin();BlobPtr<T> end();private:std::shared_ptr<std::vector<T>> data;void check(size_type i,const std::string &msg) const;
};
//BlobPtr
template <typename T> bool operator==(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator!=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> class BlobPtr
{friend bool operator==<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator!=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator< <T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator<=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator><T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator>=<T>(const BlobPtr<T> &,const BlobPtr<T> &);public:typedef typename std::vector<T>::size_type size_type;BlobPtr():curr(0){}BlobPtr(const Blob<T> &blob,size_type sz=0):wptr(blob.data),curr(sz){}T & operator[](size_type i);const T & operator[](size_type i) const;BlobPtr & operator++();BlobPtr & operator++(int);BlobPtr & operator--();BlobPtr & operator--(int);BlobPtr operator+(size_type) const;BlobPtr operator-(size_type) const;BlobPtr operator+=(size_type) const;BlobPtr operator-=(size_type) const;T & operator*() const;T * operator->() const;private:std::shared_ptr<std::vector<T>> check(size_type i,const std::string &msg) const;std::weak_ptr<std::vector<T>> wptr;size_type curr=0;
};
//Blob
template <typename T> Blob<T> & Blob<T>::operator=(const Blob &rhs)
{data=std::make_shared<std::vector<T>>(*rhs.data);return *this;
}
template <typename T> T & Blob<T>::operator[](size_type i)
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> const T & Blob<T>::operator[](size_type i) const
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> void Blob<T>::pop_back()
{check(0,"pop_back on empty Blob");data->pop_back();
}
template <typename T> T & Blob<T>::front()
{check(0,"front on empty Blob");return data->front();
}
template <typename T> const T & Blob<T>::front() const
{check(0,"front on empty Blob");return data->front();
}
template <typename T> T & Blob<T>::back()
{check(0,"back on empty Blob");return data->back();
}
template <typename T> const T & Blob<T>::back() const
{check(0,"back on empty Blob");return data->back();
}
template <typename T> BlobPtr<T> Blob<T>::begin()
{return BlobPtr<T>(*this);
}
template <typename T> BlobPtr<T> Blob<T>::end()
{return BlobPtr<T>(*this,data->size());
}
template <typename T> inline void Blob<T>::check(size_type i,const std::string &msg) const
{if(i>=data->size())throw std::out_of_range(msg);
}
template <typename T> bool operator==(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data==*rhs.data;
}
template <typename T> bool operator!=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data<*rhs.data;
}
template <typename T> bool operator<=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data>*rhs.data;
}
template <typename T> bool operator>=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs<rhs);
}
//BlobPtr
template <typename T> std::shared_ptr<std::vector<T>> BlobPtr<T>::check(size_type i,const std::string &msg) const
{auto ret=wptr.lock();if(!ret)throw std::runtime_error("unbound BlobPtr");if(i>=ret->size())throw std::out_of_range(msg);return ret;
}
template <typename T> T & BlobPtr<T>::operator[](size_type i)
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> const T & BlobPtr<T>::operator[](size_type i) const
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++()
{check(curr,"increment past end of BlobPtr");++curr;return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++(int)
{BlobPtr ret=*this;++*this;return ret;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--()
{--curr;check(curr,"decrement past the begin of BlobPtr");return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--(int)
{BlobPtr ret=*this;--*this;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+(size_type i) const
{BlobPtr ret(*this);ret+=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-(size_type i) const
{BlobPtr ret(*this);ret-=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+=(size_type i) const
{check(curr+i,"increment past end of range");while(--i)++*this;return *this;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-=(size_type i) const
{check(curr-i,"decrement past begin of range");while(--i)--*this;return *this;
}
template <typename T> T & BlobPtr<T>::operator*() const
{auto p=check(curr,"dereference past end");return (*p)[curr];
}
template <typename T> T * BlobPtr<T>::operator->() const
{return & this->operator*();
}
template <typename T> bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r)return (!r||lhs.curr==rhs.curr);elsereturn false;
}
template <typename T> bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r&&l)return lhs.curr<rhs.curr;elsereturn false;
}
template <typename T> bool operator<=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return rhs<lhs;
}
template <typename T> bool operator>=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs<rhs);
}
#endif
18.8
#ifndef BLOB_H
#define BLOB_H
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <string>
#include <initializer_list>
#include <stdexcept>
template <typename> class BlobPtr;
template <typename> class Blob;
//Blob
template <typename T> bool operator==(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator!=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator<=(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>(const Blob<T> &,const Blob<T> &);
template <typename T> bool operator>=(const Blob<T> &,const Blob<T> &);
template <typename T> class Blob
{friend class BlobPtr<T>;friend bool operator==<T>(const Blob<T> &,const Blob<T> &);friend bool operator!=<T>(const Blob<T> &,const Blob<T> &);friend bool operator< <T>(const Blob<T> &,const Blob<T> &);friend bool operator<= <T>(const Blob<T> &,const Blob<T> &);friend bool operator> <T>(const Blob<T> &,const Blob<T> &);friend bool operator>= <T>(const Blob<T> &,const Blob<T> &);public:typedef T value_type;typedef typename std::vector<T>::size_type size_type;Blob() noexcept(false) try:data(std::make_shared<std::vector<T>>()){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(std::initializer_list<T> il) noexcept(false) try:data(std::make_shared<std::vector<T>>(il)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}Blob(const Blob &org) noexcept(false) try:data(std::make_shared<std::vector<T>>(*org.data)){} catch(std::bad_alloc &e){std::cout<<e.what()<<std::endl;}template <typename it> Blob(it b,it e) noexcept(false) try:data(std::make_shared<std::vector<T>>(b,e)) {} catch(std::bad_alloc &ba){std::cout<<ba.what()<<std::endl;}Blob &operator=(const Blob &);T & operator[](size_type i);const T & operator[](size_type i) const;size_type size() const {return data->size();}bool empty() const {return data->empty;}void push_back(const T &t){data->push_back(t);}void push_back(T &&t){data->push_back(std::move(t));}void pop_back();T & front();T & back();const T & front() const;const T & back() const;BlobPtr<T> begin();BlobPtr<T> end();~Blob() noexcept {};private:std::shared_ptr<std::vector<T>> data;void check(size_type i,const std::string &msg) const;
};
//BlobPtr
template <typename T> bool operator==(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator!=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator<=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> bool operator>=(const BlobPtr<T> &,const BlobPtr<T> &);
template <typename T> class BlobPtr
{friend bool operator==<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator!=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator< <T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator<=<T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator><T>(const BlobPtr<T> &,const BlobPtr<T> &);friend bool operator>=<T>(const BlobPtr<T> &,const BlobPtr<T> &);public:typedef typename std::vector<T>::size_type size_type;BlobPtr():curr(0){}BlobPtr(const Blob<T> &blob,size_type sz=0):wptr(blob.data),curr(sz){}T & operator[](size_type i);const T & operator[](size_type i) const;BlobPtr & operator++();BlobPtr & operator++(int);BlobPtr & operator--();BlobPtr & operator--(int);BlobPtr operator+(size_type) const;BlobPtr operator-(size_type) const;BlobPtr operator+=(size_type) const;BlobPtr operator-=(size_type) const;T & operator*() const;T * operator->() const;private:std::shared_ptr<std::vector<T>> check(size_type i,const std::string &msg) const;std::weak_ptr<std::vector<T>> wptr;size_type curr=0;
};
//Blob
template <typename T> Blob<T> & Blob<T>::operator=(const Blob &rhs)
{data=std::make_shared<std::vector<T>>(*rhs.data);return *this;
}
template <typename T> T & Blob<T>::operator[](size_type i)
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> const T & Blob<T>::operator[](size_type i) const
{check(i,"subscript out of range");return (*data)[i];
}
template <typename T> void Blob<T>::pop_back()
{check(0,"pop_back on empty Blob");data->pop_back();
}
template <typename T> T & Blob<T>::front()
{check(0,"front on empty Blob");return data->front();
}
template <typename T> const T & Blob<T>::front() const
{check(0,"front on empty Blob");return data->front();
}
template <typename T> T & Blob<T>::back()
{check(0,"back on empty Blob");return data->back();
}
template <typename T> const T & Blob<T>::back() const
{check(0,"back on empty Blob");return data->back();
}
template <typename T> BlobPtr<T> Blob<T>::begin()
{return BlobPtr<T>(*this);
}
template <typename T> BlobPtr<T> Blob<T>::end()
{return BlobPtr<T>(*this,data->size());
}
template <typename T> inline void Blob<T>::check(size_type i,const std::string &msg) const
{if(i>=data->size())throw std::out_of_range(msg);
}
template <typename T> bool operator==(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data==*rhs.data;
}
template <typename T> bool operator!=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data<*rhs.data;
}
template <typename T> bool operator<=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const Blob<T> &lhs,const Blob<T> &rhs)
{return *lhs.data>*rhs.data;
}
template <typename T> bool operator>=(const Blob<T> &lhs,const Blob<T> &rhs)
{return !(lhs<rhs);
}
//BlobPtr
template <typename T> std::shared_ptr<std::vector<T>> BlobPtr<T>::check(size_type i,const std::string &msg) const
{auto ret=wptr.lock();if(!ret)throw std::runtime_error("unbound BlobPtr");if(i>=ret->size())throw std::out_of_range(msg);return ret;
}
template <typename T> T & BlobPtr<T>::operator[](size_type i)
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> const T & BlobPtr<T>::operator[](size_type i) const
{auto ret=check(i,"index out of range");return (*ret)[i];
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++()
{check(curr,"increment past end of BlobPtr");++curr;return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator++(int)
{BlobPtr ret=*this;++*this;return ret;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--()
{--curr;check(curr,"decrement past the begin of BlobPtr");return *this;
}
template <typename T> BlobPtr<T> & BlobPtr<T>::operator--(int)
{BlobPtr ret=*this;--*this;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+(size_type i) const
{BlobPtr ret(*this);ret+=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-(size_type i) const
{BlobPtr ret(*this);ret-=i;return ret;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator+=(size_type i) const
{check(curr+i,"increment past end of range");while(--i)++*this;return *this;
}
template <typename T> BlobPtr<T> BlobPtr<T>::operator-=(size_type i) const
{check(curr-i,"decrement past begin of range");while(--i)--*this;return *this;
}
template <typename T> T & BlobPtr<T>::operator*() const
{auto p=check(curr,"dereference past end");return (*p)[curr];
}
template <typename T> T * BlobPtr<T>::operator->() const
{return & this->operator*();
}
template <typename T> bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r)return (!r||lhs.curr==rhs.curr);elsereturn false;
}
template <typename T> bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs==rhs);
}
template <typename T> bool operator<(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{auto l=lhs.wptr.lock();auto r=rhs.wptr.lock();if(l==r&&l)return lhs.curr<rhs.curr;elsereturn false;
}
template <typename T> bool operator<=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs>rhs);
}
template <typename T> bool operator>(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return rhs<lhs;
}
template <typename T> bool operator>=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{return !(lhs<rhs);
}
#endif
18.9
Sales_data.h
#include <iostream>
#include <string>
#include <stdexcept>
class isbn_mismatch: public std::logic_error
{
public:explicit isbn_mismatch(const std::string &s):std::logic_error(s) {}isbn_mismatch(const std::string &s,const std::string &lhs,const std::string &rhs):std::logic_error(s),left(lhs),right(rhs) {}const std::string left,right;
};
class Sales_data
{friend std::istream & operator>>(std::istream &,Sales_data &);friend std::ostream & operator<<(std::ostream &,const Sales_data &);friend Sales_data operator+(const Sales_data &,const Sales_data &);public:std::string isbn() const {return bookNo;}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 & operator+=(const Sales_data &);operator std::string() const {return bookNo;}operator double() const {return revenue;}private:std::string bookNo;unsigned units_sold=0;double revenue=0.0;double avg_price() const;
};
std::istream & operator>>(std::istream &,Sales_data &);
std::ostream & operator<<(std::ostream &,const Sales_data &);
Sales_data operator+(const Sales_data &,const Sales_data &);
bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs);
Sales_data.cpp
#include "Sales_data.h"
inline double Sales_data::avg_price() const
{if(units_sold)return revenue/units_sold;elsereturn 0;
}
std::istream & operator>>(std::istream &is,Sales_data &src)
{double price=0.0;is>>src.bookNo>>src.units_sold>>price;if(is)src.revenue=src.units_sold*price;elsesrc=Sales_data();return is;
}
std::ostream & operator<<(std::ostream &os,const Sales_data &src)
{os<<src.isbn()<<" "<<src.units_sold<<" "<<src.revenue<<" "<<src.avg_price();return os;
}
Sales_data & Sales_data::operator+=(const Sales_data & rhs)
{*this=*(this)+rhs;return *this;
}
Sales_data operator+(const Sales_data &lhs,const Sales_data &rhs)
{Sales_data tmp;if(lhs.isbn()!=rhs.isbn())throw isbn_mismatch("wrong isbns!",lhs.isbn(),rhs.isbn());tmp.bookNo=lhs.bookNo;tmp.units_sold=lhs.units_sold+rhs.units_sold;tmp.revenue=lhs.revenue+rhs.revenue;return tmp;
}
bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs)
{return lhs.isbn()<rhs.isbn();
}
test1.cpp
#include <iostream>
#include "Sales_data.h"
int main(void)
{Sales_data a("111",2,30),b("112",3,50);a+b;return 0;
}
不处理异常的输出
terminate called after throwing an instance of ‘isbn_mismatch’
what(): wrong isbns!
Aborted
test2.cpp
#include <iostream>
#include "Sales_data.h"
int main(void)
{Sales_data a("111",2,30),b("112",3,50);try{a+b;}catch(const isbn_mismatch &e){std::cerr<<e.what()<<": left isbn ("<<e.left<<") right isbn ("<<e.right<<")"<<std::endl;}return 0;
}
处理异常的输出
wrong isbns!: left isbn (111) right isbn (112)
18.10
见18.9
18.11
如果what函数抛出异常的话,没有对应的catch子句捕获处理,就会调用terminate使程序结束,破坏正常逻辑。
18.12
Query.h
#ifndef _QUERY_H
#define _QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
namespace chapter15
{class QueryResult;class TextQuery{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);QueryResult query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;};class QueryResult{friend std::ostream &print(std::ostream &,const QueryResult &);public:QueryResult(std::string s,std::shared_ptr<std::set<std::vector<std::string>::size_type>> l,std::shared_ptr<std::vector<std::string>> f):sought(s),lines(l),file(f){}std::set<std::vector<std::string>::size_type>::iterator begin() const {return lines->begin();}std::set<std::vector<std::string>::size_type>::iterator end() const {return lines->end();}std::shared_ptr<std::vector<std::string>> get_file(){return file;}private:std::string sought;std::shared_ptr<std::set<std::vector<std::string>::size_type>> lines;std::shared_ptr<std::vector<std::string>> file;};std::ostream &print(std::ostream &,const QueryResult &);inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending){return (count>1)?word+ending:word;}class Query_base{friend class Query;protected:using line_no=TextQuery::line_no;virtual ~Query_base()=default;private:virtual QueryResult eval(const TextQuery &) const=0;virtual std::string rep() const=0;};class Query{friend Query operator~(const Query &);friend Query operator&(const Query &,const Query &);friend Query operator|(const Query &,const Query &);public:Query(const std::string &);QueryResult eval(const TextQuery &t) const {return q->eval(t);}std::string rep() const {return q->rep();}private:Query(std::shared_ptr<Query_base> query):q(query) {}std::shared_ptr<Query_base> q;};class WordQuery:public Query_base{friend class Query;private:WordQuery(const std::string &s):query_word(s) {}virtual QueryResult eval(const TextQuery &t) const {return t.query(query_word);}virtual std::string rep() const {return query_word;}std::string query_word;};inline Query::Query(const std::string &s):q(new WordQuery(s)) {}class NotQuery:public Query_base{friend Query operator~(const Query &);private:NotQuery(const Query &q):query(q) {}virtual QueryResult eval(const TextQuery &) const;virtual std::string rep() const {return "~("+query.rep()+")";}Query query;};inline Query operator~(const Query &q) {return std::shared_ptr<Query_base>(new NotQuery(q));}class BinaryQuery:public Query_base{protected:BinaryQuery(const Query &left,const Query &right,const std::string &s):lhs(left),rhs(right),opSym(s) {}virtual std::string rep() const {return "("+lhs.rep()+" "+opSym+" "+rhs.rep()+")";}Query lhs,rhs;std::string opSym;};class AndQuery:public BinaryQuery{friend Query operator&(const Query&,const Query&);private:AndQuery(const Query &left,const Query &right):BinaryQuery(left,right,"&") {}virtual QueryResult eval(const TextQuery &) const;};inline Query operator&(const Query &left,const Query &right) {return std::shared_ptr<Query_base>(new AndQuery(left,right));}class OrQuery:public BinaryQuery{friend Query operator|(const Query &,const Query &);private:OrQuery(const Query &left,const Query &right):BinaryQuery(left,right,"|") {}virtual QueryResult eval(const TextQuery &) const;};inline Query operator|(const Query &left,const Query &right) {return std::shared_ptr<Query_base>(new OrQuery(left,right));}inline std::ostream & operator<<(std::ostream &os,const Query &q) {return os<<q.rep();}
}
#endif
Query.cpp
#include <sstream>
#include <algorithm>
#include <cctype>
#include "Query.h"
namespace chapter15
{TextQuery::TextQuery(std::ifstream &infile):file(new std::vector<std::string>){std::string text;while(getline(infile,text)){file->push_back(text);std::size_t line_number=file->size()-1;std::istringstream line(text);std::string word;while(line>>word){std::string key_word;for(auto c:word){if(!ispunct(c))key_word+=c;}std::shared_ptr<std::set<line_no>> &lines=wm[key_word];if(!lines)lines.reset(new std::set<line_no>);lines->insert(line_number);}}}QueryResult TextQuery::query(const std::string &sought) const{static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>);std::map<std::string,std::shared_ptr<std::set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return QueryResult(sought,nodata,file);elsereturn QueryResult(sought,map_it->second,file);}std::ostream &print(std::ostream &os,const QueryResult &qr){os<<"Executing Query for: "<<qr.sought<<std::endl;os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(),"time","s")<<std::endl;for(auto num:*(qr.lines))os<<"\t(line "<<num+1<<") "<<*(qr.file->begin()+num)<<std::endl;return os;}QueryResult NotQuery::eval(const TextQuery &text) const{auto result=query.eval(text);auto beg=result.begin(),end=result.end();auto ret_lines=std::make_shared<std::set<line_no>>();auto sz=result.get_file()->size();for(std::size_t n=0;n!=sz;++n){if(beg==end||*beg!=n)ret_lines->insert(n);else if(beg!=end)++beg;}return QueryResult(rep(),ret_lines,result.get_file());}QueryResult OrQuery::eval(const TextQuery &text) const{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>(left.begin(),left.end());ret_lines->insert(right.begin(),right.end());return QueryResult(rep(),ret_lines,left.get_file());}QueryResult AndQuery::eval(const TextQuery &text) const{auto left=lhs.eval(text),right=rhs.eval(text);auto ret_lines=std::make_shared<std::set<line_no>>();set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));return QueryResult(rep(),ret_lines,left.get_file());}
}
TextQuery.h
#ifndef TEXT_QUERY_H
#define TEXT_QUERY_H
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <fstream>
#include <tuple>
namespace chapter10
{class TextQuery{public:using line_no=std::vector<std::string>::size_type;TextQuery(std::ifstream &);std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> query(const std::string &) const;private:std::shared_ptr<std::vector<std::string>> file;std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;};inline std::string make_plural(std::size_t count,const std::string &word,const std::string &ending){return (count>1)?word+ending:word;}std::ostream &print(std::ostream &,const std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> &);
}
#endif
TextQuery.cpp
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <string>
#include <memory>
#include "TextQuery.h"
using namespace std;
namespace chapter10
{TextQuery::TextQuery(ifstream &infile):file(new vector<string>){string text;while(getline(infile,text)){file->push_back(text);size_t line_number=file->size()-1;istringstream line(text);string word;while(line>>word){shared_ptr<set<line_no>> &lines=wm[word];if(!lines)lines.reset(new set<line_no>);lines->insert(line_number);}}}std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> TextQuery::query(const string &sought) const{static shared_ptr<set<line_no>> nodata(new set<line_no>);map<string,shared_ptr<set<line_no>>>::const_iterator map_it=wm.find(sought);if(map_it==wm.end())return tuple(sought,nodata,file);elsereturn tuple(sought,map_it->second,file);}std::ostream &print(std::ostream &os,const std::tuple<std::string,std::shared_ptr<std::set<std::vector<std::string>::size_type>>,std::shared_ptr<std::vector<std::string>>> &tp){os<<std::get<0>(tp)<<" occurs "<<std::get<1>(tp)->size()<<" "<<make_plural(std::get<1>(tp)->size(),"time","s")<<std::endl;for(auto num:*(get<1>(tp)))os<<"\t(line "<<num+1<<")"<<*(get<2>(tp)->begin()+num)<<std::endl;return os;}
}
test.cpp
#include <fstream>
#include "Query.h"
using namespace std;
using chapter15::Query;
using chapter15::TextQuery;
int main(int argc,char *argv[])
{ifstream infile(argv[1]);TextQuery text(infile);Query q=Query("fiery")&Query("bird")|Query("wind");print(cout,q.eval(text));return 0;
}
18.13
需要使用文件作用域或者命名空间作用域的静态变量时可以使用未命名的命名空间。
18.14
mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*(const matrix &,const matrix &);
18.15
using声明:一次只引入命名空间的一个成员,它的有效范围从using声明的地方开始,到using声音所在作用域结束为止。
using指示:使特定的命名空间中所有的名字都可见,这些名字一般被看作是出现在最近的外层作用域中,如果遇到成员冲突的情况,需要使用作用域运算符指明所需的版本。
18.16
位置一
using声明
ivar成员冲突
位置二
using声明
dvar成员冲突
位置一
using指示
++ivar
这句将有二义性错误
位置二
using指示
++ivar
这句将有二义性错误
18.17
1
#include <iostream>
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;using Exercise::ivar;
using Exercise::dvar;
using Exercise::limit;void manip()
{double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}
2
#include <iostream>
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;void manip()
{using Exercise::ivar;
using Exercise::dvar;
using Exercise::limit;double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}
3
#include <iostream>
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;using namespace Exercise;void manip()
{double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}
4
#include <iostream>
namespace Exercise
{int ivar=0;double dvar=0;const int limit=1000;
}
int ivar=0;void manip()
{using namespace Exercise;double dvar=3.1416;int iobj=limit+1;++ivar;++::ivar;
}
int main(void)
{return 0;
}
18.18
当mem1是一个string时程序因为更特例化的原因,会调用string中定义的swap版本,而int是内置类型,内置类型没有特定版本的swap,所以会调用std::swap。
18.19
如果使用std::swap的形式,则是直接指明调用std命名空间中的swap版本。
18.20
- 命名空间primerLib中声明的compte将被加入候选函数集
候选函数void compute()
void compute(const void *)
void compute(int)
void compute(double,double=3.4)
void compute(char*,char*=0)
可行函数
void compute(const void *)
0能转换成任意指针类型
void compute(int)
精确匹配
void compute(double,double=3.4)
int向double的算术类型转换
void compute(char*,char*=0)
0能转换成任意指针类型 - 如果将using声明置于f函数中compute的调用点之前,将隐藏全局作用域中声明的compute.
候选函数void compute()
void compute(const void *)
可行函数
void compute(const void *)
0能转换成任意指针类型
18.21
1 正确,public继承CAD,private继承Vehicle
2 错误,在一个派生列表中重复继承了同一个基类
3 正确,public继承istream,public继承ostream
18.22
构造函数的执行顺序是A->B->C->X->Y->Z->MI
18.23
都允许
18.24
ZooAnimal *pz=new Panda("ying_yang")
pb->print();//调用Panda::print()
pb->cuddle();//错误,不属于ZooAnimal的接口
pb->highlight();//错误,不属于ZooAnimal的接口
delete->pb;//正确,Panda::~Panda()
18.25
- MI::print()
- MI::print()
- MI::print()
- MI::~MI()
- MI::~MI()
- MI::~MI()
18.26
因为派生类的名字将隐藏基类的同名成员,所以MI不加前缀限定符的print函数只有接受std::vector参数的版本,而42无法隐式转换为该类型,所以调用失败。
可以这样修改:
struct MI:public Derived,public Base2
{void print(std::vector<double>);void print(int i){Base1::print(i);}protected:int *ival;std::vector<double> dvec;
}
18.26
- 所有可见的名字:
函数内:int dval;double cval;
类内:int *ival;std::vector<double> dvec;void print(std::vector<double>);
Derived:void Derived::print(std::string) const;std::string sval;double Derived::dval;
Base1:void Base1::print(int) const;int Base1::ival;double Base1::dval;char Base1::cval;
Base2:void Base2::print(double) const;int Base2::ival;double fval;char Base2::cval;
全局作用域:int ival;double dval;
dval cval ival print都是继承自多个基类。
dval:Derived::dval Base1::dval
cval:Base1::cval Base2::cval
ival:Base1::ival Base2::ival
print:Derived::print Base1::print Base2::print
void MI::foo(double cval)
{int dval;dval=Base1::dval+Derived::dval;
}
void MI::foo(double cval)
{int dval;Base2::fval=dvec.back();
}
void MI::foo(double cval)
{int dval;sval[0]=Base1::cval;
}
18.28
无需前缀限定符:
Derived1::bar
Derived2::ival
需要前缀限定符:
Derived1::foo
Derived2::foo
Base::bar
Base::ival
Derived1::cval
Derived2::cval
18.29
构造函数顺序:Class() Base() D1() D2() MI() Class() Final()
析构函数顺序:Final() Class() MI() D2() D1() Base() Class()
2. 1个base部分,两个Class部分。
3.
pb=new Class
错误,不存在基类指针向派生类的隐式转换
pc=new Final
错误,Class接口的使用会导致二义性错误
pmi=pb
错误,不存在基类指针向派生类的隐式转换
pd2=pmi
正确
18.30
这样定义的话,由于存在歧义,直接基类Class在Final中无法访问
class Class{};
class Base:public Class
{public:Base()=default;Base(const Base &b):i(b.i) {}Base(const int &ri):i(ri) {}private:int i;
};
class D1:public virtual Base
{public:D1()=default;D1(const D1 &d):Base(d) {}D1(const int &ri):Base(ri) {}
};
class D2:public virtual Base
{public:D2()=default;D2(const D2 &d):Base(d) {}D2(const int &ri):Base(ri) {}
};
class MI:public D1,public D2
{public:MI()=default;MI(const MI &mi):Base(mi),D1(mi),D2(mi) {}MI(const int &ri):Base(ri),D1(ri),D2(ri) {}
};
class Final:public MI,public Class
{public:Final()=default;Final(const Final &fi):Base(fi),MI(fi),Class() {}Final(const int &ri):Base(ri),MI(ri),Class() {}
};
相关文章:
c++ primer中文版第五版作业第十八章
仓库地址 文章目录 18.118.218.318.418.518.618.718.818.918.1018.1118.1218.1318.1418.1518.16位置一using声明 位置二using声明 位置一using指示 位置二using指示 18.1718.1818.1918.2018.2118.2218.2318.2418.2518.2618.2618.2818.2918.30 18.1 此时r是一个range_error类型…...
vue触发真实的点击 事件 跟用户行为一致
<template><div><button ref"myButton" click"handleClick">按钮</button></div> </template><script> export default {methods: {handleClick() {const button this.$refs.myButton;// 创建一个鼠标点击事件…...

Java进程CPU高负载排查
Java进程CPU高负载排查步骤_java进程cpu使用率高排查_YouluBank的博客-CSDN博客 【问题定位】使用arthas定位CPU高的问题_arthas cpu高_秋装什么的博客-CSDN博客 CPU飙升可能原因 CPU 上下文切换过多。 对于 CPU 来说,同一时刻下每个 CPU 核心只能运行-个线程&…...
Linux编程4.1 网络编程-前导
1、内容概述 网络的基本概念TCP/IP协议概述OSI和TCP/IP模型掌握TCP协议网络基础编程掌握UDP协议网络基础檹网络高级编程 2、计算机联网的目的 使用远程资源共享信息、程序和数据分布处理 3、基本概念 单服务与多客户端的进程间通信C/S client server 由于,跨计…...

【微信小程序】传参存储
目录 一、本地数据存储 wx.setStorage wx.setStorageSync 1.1、异步缓存 存取数据 1.2、同步缓存 存取数据 二、使用url跳转路径携带参数 2.1、 wx.redirectTo({}) 2.2、 wx.navigateTo({}) 2.3、 wx.switchTab({}) 2.4 、wx.reLaunch({}) 2.5、组件跳转 三、…...

计算机设计大赛 深度学习花卉识别 - python 机器视觉 opencv
文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &a…...

ping多个IP的工具
Ping Tool 项目地址 python开发的IP搜索小工具 ping一个网段所有IP,显示结果查看某个ip地址开放监听的端口配置可保存...
Rust 的 Error 如何使用?
在 Rust 中,错误处理是一个重要且核心的概念。Rust 提供了一种强大的类型系统,允许你明确地处理可能出现的错误。std::error::Error trait 是 Rust 标准库中用于表示错误的基础 trait。实现这个 trait 的类型可以被用作错误类型,并且可以使用…...

Hack The Box-Crafty
目录 信息收集 rustscan whatweb WEB 漏洞利用 漏洞说明 漏洞验证 提权 get user.txt get Administrator 总结 信息收集 rustscan ┌──(root㉿ru)-[~/kali/hackthebox] └─# rustscan -a 10.10.11.249 --range0-65535 --ulimit5000 -- -A -sC [~] Automatically…...

高电平复位电路工作原理详解
单片机复位电路的作用是:使单片机恢复到起始状态,让单片机的程序从头开始执行,运行时钟处于稳定状态、各种寄存器、端口处于初始化状态等等。目的是让单片机能够稳定、正确的从头开始执行程序。一共分为:高电平复位,低…...
了AI而强行AI的做法,构成了人与AI对抗的宿命论
从 ChatGPT到文生图的 Stable Diffusion,再到文生视频的 Sora ,每次大语言模型的迭代,以及由此衍生的新产品,都让各行各业的企业主、从业者们,感到无所适从。 普通人可以借助AI的力量“逆天改命”吗? 10多…...

【性能测试】Jmeter+InfluxDB+Grafana 搭建性能监控平台
一、背景 为什么要搭建性能监控平台? 在用 Jmeter 获取性能测试结果的时候,Jmeter自带的测试报告如下: 这个报告有几个很明显的缺点: 只能自己看,无法实时共享;报告信息的展示比较简陋单一,不…...

【YOLOv8模型网络结构图理解】
YOLOv8模型网络结构图理解 1 YOLOv8的yaml配置文件2 YOLOv8网络结构2.1 Conv2.2 C3与C2f2.3 SPPF2.4 Upsample2.5 Detect层 1 YOLOv8的yaml配置文件 YOLOv8的配置文件定义了模型的关键参数和结构,包括类别数、模型尺寸、骨干(backbone)和头部…...

付强:基于注意力机制的听觉前端处理 | 嘉宾公布
一、智能家居与会议系统专题论坛 智能家居与会议系统专题论坛将于3月28日同期举办! 智能会议系统它通过先进的技术手段,提高了会议效率,降低了沟通成本,提升了参会者的会议体验。对于现代企业、政府机构和学术界是不可或缺的。在这…...

C++_包装器
目录 1、包装器的用法 2、包装器的类型 3、包装器的作用 4、包装成员函数 5、bind(绑定) 5.1 bind的用法 5.2 bind减少参数个数 结语 前言: C11的包装器,总称为function包装器,而包装器又称适配器…...

3588板子部署yoloV5
一 :准备 ubuntu linux X86_64系统 a.安装anaconda b.创建虚拟环境 python3.8 二: 下载rknn-toolkit2 传送门 unzip 解压文件夹 三:pt转onnx模型 四:onnx转rknn模型 a:cd到rknn-toolkit2-master/rknn-toolkit2/packag…...
解决GitHub提交时不显示自己的头像 显示另一个账号(其实也是自己)
git show 看看是否是自己的githup 账号的邮箱 如果不是进行下列操作 git config user.email “你的邮箱地址”,修改邮箱 修改完以后输入git config user.email 检查是否修改成了你的邮箱 如果你想其他项目提交时,也避免此类情况,把上面的两条命令改成 (1&#…...
VUE_vue2/3点击区域外触发方法,点击除某个元素触发监听
Vue2 1、自定义指令 // 自定义指令,用于处理点击外部区域的事件 const clickOutside {bind(el, binding) {// 在元素上绑定一个点击事件监听器el.clickOutsideEvent function (event) {// 检查点击事件是否发生在元素的内部if (!(el event.target || el.contai…...

SpringCloud(20)之Skywalking Agent原理剖析
一、Agent原理剖析 使用Skywalking的时候,并没有修改程序中任何一行 Java 代码,这里便使用到了 Java Agent 技术,我 们接下来展开对Java Agent 技术的学习。 1.1 Java Agent Java Agent 是从 JDK1.5 开始引入的,算是一个比较老的…...

容器(0)-DOCKERFILE-安装-常用命令-部署-迁移备份-仓库
1.安装 启动 systemclt start docker //启动 systemctl status docker //状态 docker info systemclt stop docker systemctl status docker systemctl enable docker //开机启动 2.常用命令 镜像查看 docker images 镜像查看 docker status 镜像拉取 docker pull centos:…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...