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;}