第十六章习题 学习C++的后续方法

0 编译运行本章程序

头文件:

//
// Created by MacBook Pro on 2020-03-09.
//

#ifndef ACM_TEST_H
#define ACM_TEST_H
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

//选择何时共享数据句柄
template<class T> class Ptr{
public:

    Ptr():p(0), refptr(new size_t(1)){}
    Ptr(T* t):p(t), refptr(new size_t(1)){}
    Ptr(const Ptr& h):p(h.p), refptr(h.refptr){++*refptr;}

    Ptr& operator=(const Ptr& rhs){
        ++*rhs.refptr;
        if(--*refptr == 0){
            delete(refptr);
            delete(p);
        }
        refptr = rhs.refptr;
        p = rhs.p;
        return *this;
    }

    ~Ptr(){
        if(--*refptr == 0){
            delete(refptr);
            delete(p);
        }
    }

    operator bool() const {
        return p;
    }

    T&operator*() const{
        if(p){
            return *p;
        }
        throw std::runtime_error("unbound Ref_handle");
    }

    T* operator->() const{
        if(p){
            return p;
        }
        throw std::runtime_error("unbound Ref_handle");
    }
private:
    T* p;
    std::size_t* refptr;
};

class Picture;

class Pic_base{
    friend std::ostream& operator<<(std::ostream&, const Picture&);
    friend class Frame_Pic;
    friend class HCat_Pic;
    friend class VCat_Pic;
    friend class String_Pic;

    //没有公共接口
    typedef std::vector<std::string>::size_type ht_sz;//高
    typedef std::string::size_type wd_sz;//宽
    //抽象基类(纯虚拟性可以被继承)
    virtual wd_sz  width() const = 0;//纯虚函数,相等于隐式声明该类没有其相应的对象
    virtual ht_sz height() const = 0;//编译器会禁止为这个类生成相应的对象
    virtual void display(std::ostream&, ht_sz, bool) const = 0;

protected:
    //这个函数不隶属于类的某个对象
    //静态成员:减少定义全局函数或变量
    //定义为静态函数,使得在其他地方也可以定义pad
    static void pad(std::ostream&, wd_sz, wd_sz);
public:
    virtual ~Pic_base(){}
};


//公有接口类和操作
class Picture{
    friend std::ostream& operator<<(std::ostream&, const Picture&);
    friend Picture frame(const Picture&);
    friend  Picture hcat(const Picture&, const Picture&);
    friend  Picture vcat(const Picture&, const Picture&);

public:
    Picture(const std::vector<std::string>& = std::vector<std::string>());
    //由于没有显示声明为explicit
    //因此允许出现下面的语句
    /*
     vector<string> vs;
     Picture p = vs;
     */
private:
    Ptr<Pic_base> p;
    Picture(Pic_base* ptr):p(ptr){ }
};

//对Picture类型对象进行操作
Picture frame(const Picture&);
Picture hcat(const Picture&, const Picture&);
Picture vcat(const Picture&, const Picture&);
std::ostream& operator<<(std::ostream&, const Picture&);

//图形数据
class String_Pic:public Pic_base{
    friend Picture frame(const Picture&);
    friend class Picture;

    std::vector<std::string> data;
    String_Pic(const std::vector<std::string>& v):data(v){}

    ht_sz height() const { return data.size();}
    wd_sz width() const;
    void display(std::ostream&, ht_sz, bool) const;
};


//加边框
class Frame_Pic:public Pic_base{
    friend Picture frame (const Picture&);

    Ptr<Pic_base> p;

    Frame_Pic(const Ptr<Pic_base>& pic):p(pic){}

    wd_sz width() const { return p->width() + 4;}
    ht_sz height() const { return  p->height()+ 4;}

    void display(std::ostream&, ht_sz, bool) const;
};

//上下连接
class VCat_Pic: public Pic_base{
    friend Picture vcat(const Picture&, const Picture&);

    Ptr<Pic_base> top, bottom;
    VCat_Pic(const Ptr<Pic_base>& t, const Ptr<Pic_base>& b):
            top(t), bottom(b){}

    wd_sz width() const{
        return std::max(top->width(), bottom->width());
    }
    ht_sz height() const{
        return top->height() + bottom->height();
    }
    void display(std::ostream&, ht_sz, bool) const;

};

class HCat_Pic: public Pic_base{
    friend Picture hcat (const Picture&, const Picture&);

    Ptr<Pic_base> left, right;
    HCat_Pic(const Ptr<Pic_base>& l,const Ptr<Pic_base>& r):left(l),right(r){}

    wd_sz width() const{
        return left->width() + right->width();
    }
    ht_sz height() const{
        return std::max(left->height(), right->height());
    }

    void display(std::ostream&, ht_sz, bool) const;
};

#endif //ACM_TEST_H

//
// Created by MacBook Pro on 2020-01-13.
//

#ifndef ACM_Student_info
#define ACM_Student_info

#include <iostream>
#include <string>
#include <vector>

//struct student_info{
//    std::string name;
//    double midterm, final;
//    std::vector<double> homework;
//
//    std::istream& read(std::istream&);
//    double garde() const;
//};

class Student_info{
public:
    Student_info();//构造一个空的Student_info对象
    Student_info(std::istream&);//读一个流从而构造一个对象
    bool vaild() const{ return ! homework.empty();}//检查对象是否为空
    double grade() const;
    std::istream& read(std::istream& );
    std::string name() const {return n;}//存取器:容许对一部分数据结构的进行访问
private:
    std::string n;
    double midterm, final;
    std::vector<double> homework;
};

bool compare(const Student_info&, const Student_info&);

std::istream& read_hw(std::istream&, std::vector<double>&);

double grade(double, double, double);
double grade(double, double, const std::vector<double>&);

#endif

测试程序:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <stdexcept>
#include "test.h"
#include "Student_info.h"
#include "grade.h"

using std::cin; using std::endl;
using std::cout;
using std::ostream;
using std::string;
using std::vector;
using std::istream;
using std::domain_error;
using std::sort;

void Pic_base::pad(std::ostream& os, wd_sz beg, wd_sz end){
    while(beg != end){
        os << " ";
        ++beg;
    }
}

Pic_base::wd_sz String_Pic::width() const{
    Pic_base::wd_sz n = 0;
    for (Pic_base::ht_sz i = 0; i != data.size(); ++i) {
        n = std::max(n, data[i].size());
    }
    return n;
}

void String_Pic::display(ostream& os, ht_sz row, bool do_pad) const {
    wd_sz start = 0;
    //如果row没有超过范围,就输出第row行
    if(row < height()){
        os << data[row];
        start = data[row].size();
    }
    //如有必要,补齐输出各行
    if(do_pad){
        pad(os, start, width());
    }
}

void Frame_Pic::display(ostream& os, ht_sz row, bool do_pad) const {
    if(row >= height()){
        //超出范围
        if(do_pad){
            pad(os, 0, width());
        }
    }else{
        if(row == 0 || row == height() -1){
            //最顶行或最低行
            os << string(width(), '*');
        }else if(row == 1 || row == height() - 2){
            //在第二行或倒数第二行
            os << "*";
            pad(os, 1, width() - 1);
            os << "*";
        }else{
            //在内部图形
            os << "* ";
            p->display(os, row - 2, true);
            os << " *";
        }
    }
}

void VCat_Pic::display(ostream & os, Pic_base::ht_sz row, bool do_pad) const {
    wd_sz w = 0;
    if(row < top->height()){
        //处于上面的子图形中
        top->display(os, row, do_pad);
        w = top->width();
    }else if(row < height()){
        //处于下面的子图形中
        bottom->display(os, row - top->height(), do_pad);
        w = bottom->width();
    }
    if(do_pad){
        pad(os, w, width());
    }
}



void HCat_Pic::display(ostream& os, Pic_base::ht_sz row, bool do_pad) const {
    left->display(os, row, do_pad || row < right->height());
    right->display(os, row, do_pad);
}

Picture frame(const Picture& pic){
    return new Frame_Pic(pic.p);
}

Picture hcat(const Picture& l, const Picture& r){
    return new HCat_Pic(l.p, r.p);
}

Picture vcat(const Picture& t, const Picture& b){
    return new VCat_Pic(t.p, b.p);
}

Picture::Picture(const std::vector<std::string> &v):p(new String_Pic(v)) {}

ostream& operator<<(ostream& os, const Picture& picture){
    const Pic_base::ht_sz ht = picture.p->height();
    for (Pic_base::ht_sz i = 0; i != ht; ++i) {
        picture.p->display(os, i, false);
        os<<endl;
    }
    return os;
}

//默认构造函数
Student_info::Student_info() :midterm(0), final(0){ }
//带参构造函数
Student_info::Student_info(istream& is) { read(is); }



//按照字母顺序排列学生
bool compare(const Student_info& x, const Student_info& y){
    return x.name() < y.name();
}

istream& Student_info::read(istream& in){
    in >> n >> midterm >> final;
    read_hw(in, homework);
    return in;
}

istream& read_hw(istream& in, vector<double>& hw){
    if(in){
        hw.clear();
        double x;
        while(in >> x){
            hw.push_back(x);
        }
        in.clear();
    }
    return  in;
}

double median(vector<double> vec){
    typedef vector<double>::size_type vec_sz;
    vec_sz  size = vec.size();
    if(size == 0){
        throw domain_error("median of an empty vector");
    }

    sort(vec.begin(), vec.end());

    vec_sz mid = size/2;

    return size % 2 == 0 ? (vec[mid] + vec[mid -1]) /2 : vec[mid];
}

double Student_info::grade() const {
    //::使用这个名称的某一个版本,而所使用的这个版本不能称为任何事物的成员
    return ::grade(midterm, final, homework);
}

double grade(double midterm, double final, const vector<double>& hw){
    if(hw.size() == 0)
        throw  domain_error("student has done no homework");
    return grade(midterm, final, median(hw));//如果家庭作业非空,则调用grade3
}//grade2

double grade(double midterm, double final, double hw){
    return midterm * 0.2 + final * 0.4 + hw * 0.4;
}

Picture histogram(const vector<Student_info>& students){
    Picture names;
    Picture grades;

    for (vector<Student_info>::const_iterator it = students.begin(); it != students.end(); ++it) {
        names = vcat(names, vector<string>(1, it->name()));
        grades = vcat(grades, vector<string>(1, " " + string(it->grade()/5,'=')));
    }
    return hcat(names, grades);
}

int main(int argc, char** argv){
    vector<Student_info>students;
    Student_info s;

    while(s.read(cin)){
        students.push_back(s);
    }

    sort(students.begin(), students.end(), compare);

    cout <<frame(histogram(students))<<endl;

    return 0;
}

1 编写一个自我复制程序,该程序没有输入,在运行时复制一份自己的源代码,并将代码写入输入流。

#include <stdio.h>
int main() { char *s = "#include <stdio.h>%cint main() { char *s = %c%s%c; printf( s, 10, 34, s, 34 ); return 0; }"; printf( s, 10, 34, s, 34 ); return 0; }

结果:(由于长度原因不能一次截图完整)
在这里插入图片描述
右边的部分
在这里插入图片描述

C++版本:

#include <iostream>
#include <string>
using namespace std;
int main (){string a="#include <iostream>T#include <string>Tusing namespace std;Tint main (){string a=;a[19]=a[37]=a[58]=10;cout<<a.substr(0,80)<<(char)34;a[19]=a[37]=a[58]=84;cout<<a<<(char)34<<a.substr(80);return 0;}";a[19]=a[37]=a[58]=10;cout<<a.substr(0,80)<<(char)34;a[19]=a[37]=a[58]=84;cout<<a<<(char)34<<a.substr(80);return 0;} 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星蓝雨

如果觉得文章不错,可以请喝咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值