BJFU - C++ - 练习题目

一、预备练习

函数重载

描述

用C++语言编写Max函数,使其满足以下的main函数

int main()

{

 int a, b;

 float d, e, f;

 cin >> a >> b;

 cin >> d >> e >> f;

 int m;

 m = Max(a, b);

 cout << "max_i=" << m << endl;

 float n;

 n = Max(d, e, f);

 cout << "max_f=" << n << endl;

 return 0;

}

输入

输入2行数据,第一行2个整数,第2行3个float数

输出

输出2行,第一行输出整数的最大值,第二行输出float数的最大值

输入样例 1

2 9 1.2 7.8 9.7

输出样例 1

maxi=9 maxf=9.7


string字符串

描述

输入string字符串str(可以包含空格字符),替换把其中的字符'c'替换成'C'。

int main(){

    string str;

    //补充输入

    Replace(str, 'c', 'C');

    cout << str << endl;

    return 0;

}

输入

字符串

输出

结果

输入样例 1

abcdedgc

输出样例 1

abCdedgC


new和delete

描述

编写一个程序,要求用new申请空间,用delete运算符释放空间。申请1个整型的空间,然后赋值为100;申请1个整型,并且初始化为10;申请1个整型数组(长度为3),从键盘上输入数组的值。最后输出所有的值,释放内存空间。

输入

输入3个整数

输出

第一行为100,第二行为10,第三行为输入的数组的值(用逗号,分隔)

输入样例 1

1 2 3

输出样例 1

100 10 1,2,3


二、类与对象

计算圆面积

描述

 编写一个圆类Circle,实现半径的输入、面积的计算和输出。要求在类中分别写3个函数实现输入半径、计算面积、输出面积。

输入

输入一行,输入圆的半径(double类型)。

输出

输出一行,输出圆的面积(保留小数点后两位)。

输入样例 1

3

输出样例 1

28.27

提示

1、在输出面积前使用如下语句:cout<<setiosflags(ios::fixed)<<setprecision(2);来设置输出格式,因此需要包含iomanip头文件

2、使用acos(-1.0)来得到圆周率的值,可将其设置为常量,因此:const double PI=acos(-1.0);需要包含cmath头文件


图书类

描述

以下是图书类Book的声明,缺少实现部分,请实现成员函数并编写main函数测试Book类。

class Book

{

private:

char *name; //书名

char *author; //作者

int sale; //销售量

public:

Book(); //无参构造函数

Book(char* _name, char* _author, int _sale); //有参构造函数

Book(const Book &); //拷贝构造函数

void print(); //显示数据

~Book(); //析构函数

};

输入

在main函数中,我们输入三行数据,第一行是书的名称(长度不超过100,可能含有空格),第二行是作者的名字(长度不超过100,可能含有空格),第三行是销量(整数类型)。 类中有三个对应的成员变量,分别为name,author和sale,利用题目中所给的构造函数来实例化对象。 需要注意的是,题目中有三个构造函数,分别是有参构造函数和无参构造函数还有拷贝构造函数,在此我们特别声明,当输入的name,author和sale都为-1的时候,请使用无参构造函数来实例化对象,此时我们将name的默认值设置为"No name",author的默认值设置为"No author",sale的默认值设置为0。当输入都为0的时候,我们使用拷贝构造函数来处理,这种情况具体在main函数中的实现是这样的:Book bk1;Book bk2(bk1);bk2.print();其他情况下一律用有参数的构造函数来构造对象。

输出

使用类中的void print()方法来输出一定格式的字符串,详见样例。

输入样例 1

The Art of Computer Programming Donald Ervin Knuth 1000

输出样例 1

Name: The Art of Computer Programming Author: Donald Ervin Knuth Sale: 1000

class Book

{

private:

char *name; //书名

char *author; //作者

int sale; //销售量

public:

Book():name(new char[strlen("no name")+1])chushihua

Book(char* _name, char* _author, int _sale);

Book(const Book &); //拷贝构造函数

void print(); //显示数据

~Book(); //析构函数

};

过道和栅栏的造价

描述

一矩形体育场如下图所示,现在需在其周围建一矩形过道,并在四周围安上栅栏。栅栏价格为50元/米,过道造价为240元/平方米。过道宽为1.5米,体育场的长宽由键盘输入。

http://www.bjfuacm.com/public/upload/95868ce7b7.png

体育场和矩形过道都是如下Rectangle的对象,请实现以下Rectagnle类,编写main函数计算并输出过道和栅栏的造价。

class Rectangle

{

private:

  double length; //长

  double width; //宽


public:

  `Rectangle(double Length=10.,double Width=5.);

  double Area(); //获取面积

  double Perimeter();//获取周长`


};

输入

体育场的长和宽

输出

输出2行

第一行是栅栏的造价

第二行是过道的造价

输入样例 1

2.4 1.2

输出样例 1

960 4752

输入样例 2

2 1

输出样例 2

900 4320

提示

体育场用对象 rect1(x, y)来表示的话,过道外的矩形就用对象 rect2(x + 3, y + 3)表示


评分程序

描述

为一门课写一个评分程序,评分原则如下:

(1)有两次随堂考试,每次满分50分;

(2)有一次期中考试和一次期末考试,每次满分100分;

(3)期末考试占总评成绩的50%,期中考试占总评成绩的25%,两次随堂考试总共占25%;

(4)总评成绩90~100分为A,80~89分为B,70~79分为C,60~69分为D,低于60分为E;

设计一个Socre类,数据成员如下:

string name;//记录学生姓名
double s[4];//存储4次成绩,s[0]和s[1]存储2次随堂考试,s[2]存储期中考试,s[3]存储期末考试
double total;//记录总评成绩
char grade;  //记录对应的等级

学生信息由键盘录入,默认总评成绩的等级为B,其他数据项无默认值。计算总评成绩并给出等级,输出某个同学的全部信息。

主函数如下:

int main()
{
    Score *s1=new Score;
    s1->Input();
    s1->Evalauate();
    s1->Output();
    return 0;
}

输入

输入5行

第1行是学生姓名

第2和3行是两次随堂考试成绩

第4行是期中考试成绩

第5行是期末考试成绩

输出

如果输入的成绩超出了范围,则显示:error

如果输入的成绩在题目要求的范围内,则显示:姓名,总分和等级,详见样例

输入样例 1

Jack 90 90 100 100

输出样例 1

error

输入样例 2

Mary 50 50 90 100

输出样例 2

name: Mary, total: 97.5, grade: A

提示

冒号和逗号后各有一个空格


类与对象

#include<iostream>
using namespace std;
class Array 
{
public:
    Array(int size = 100);  //初始化数据成员:MaxSize置为size,为data动态分配内存空间,length置为0
    Array(const Array& r);//深拷贝构造函数
    ~Array();           //析构函数
    void Insert(int i, double x);  //在下标i处插入x
    void Display();              //输出数组中的元素   
    int Locate(double x);
    void Invert();
private:
    int MaxSize;              //数组中可存储的元素最大个数
    double* data;            //存储元素
    int length;                    //数组中有效元素个数
};
Array::Array(int size)
{
    MaxSize = size;
    data = new double[MaxSize];
    length = 0;
}
Array::Array(const Array& r)
{
    MaxSize = r.MaxSize;
    data = new double[MaxSize];
    for (int i = 0; i < r.length; i++)
    {
        data[i] = r.data[i];
    }
    length = r.length;
}
Array::~Array()
{
    delete []data;
}
void Array::Insert(int i, double x)
{
    int j;
    for (j = length - 1; j >= i; j--)
        data[j + 1] = data[j];
    data[i] = x;
    length++;
}
void Array::Display()
{
    cout << "Length:" << length << endl;
    cout << "Elements:";
    for (int i = 0; i < length; i++)
    {
        cout << data[i] << " ";
    }
    cout << endl;
}
int Array::Locate(double x)
{
    int i;
    for (i = 0; i < length; i++)
    {
        if (data[i] == x)
            break;
    }
    if (i < length)
        return i;
    else
        return -1;
}
void Array::Invert()
{
    int i;
    for (i = 0; i < length / 2; i++)
    {
        double temp = data[i];
        data[i] = data[length - 1 - i];
        data[length - 1 - i] = temp;
    }
}
int main()
{
    double m,x;
    int i=0;
    Array arr1;
    cin >> m;
    while (m)
    {
        arr1.Insert(i, m);
        i++;
        cin >> m;
    }
    arr1.Display();
    cin >> x;
    if (arr1.Locate(x))
    {
        cout << "Position of " << x << ":" << arr1.Locate(x) << endl;
    }
    else
        cout << "No found" << endl;
    Array arr2 = arr1;
    arr2.Invert();
    arr2.Display();
    return 0;
}

三、类与对象进阶

拷贝构造函数

描述

完成以下拷贝构造函数

#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:    
         int num;    
         char *name;
public:
    Person(int n, char *str)
    {    
        num = n;
        name = new char[strlen(str)+1];
        strcpy(name, str);    
    }
    Person(const Person &x)
    {    
         //添加代码
   }
     ~Person()
    {    cout<<"Destructor:"<<name<<endl;
        delete[] name;
    }
    void show()
    {    cout<<"num="<<num<<"\nname="<<name<<endl;
    }
};

int main()
{
    Person per1(1001,"Sheldon");
    per1.show();
    Person per2(per1);
    per2.show();
    return 0;
}

输入

输出

见样例

输入样例 1

输出样例 1

num=1001 name=Sheldon num=1001 name=Sheldon Destructor:Sheldon Destructor:Sheldon

#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:    
         int num;    
         char *name;
public:
    Person(int n, char *str)
    {    
        num = n;
        name = new char[strlen(str)+1];
        strcpy(name, str);    
    }
    Person(const Person &x)
    {    
        num = x.num;
        name = new char[strlen(x.name)+1];
        strcpy(name, x.name); 
   }
     ~Person()
    {    cout<<"Destructor:"<<name<<endl;
         delete[] name;
    }
    void show()
    {    cout<<"num="<<num<<"\nname="<<name<<endl;
    }
};

int main()
{
    Person per1(1001,"Sheldon");
    per1.show();
    Person per2(per1);
    per2.show();

    return 0;
}

对象成员

描述

实现Circle类的成员函数

#include <iostream>
using namespace std;
class Point
{
private: 
    double x;
    double y;
public:
    Point(double a=0,double b=0)
    {  
          x = a;
          y = b;
    }
    void set(double a, double b);
    double getx();
    double gety();
};
void Point::set(double a, double b)
{
      x = a;
      y = b;
}
double Point::getx()
{
      return x;
}
double Point::gety()
{
     return y;
}
class Circle
{
private:
     double r;
     Point cen;         //对象成员
public:
     Circle(double a,double b,double c);   //实现该函数
     void show();                                       //实现该函数
};
 int main()
{
      Circle cir(1,2,1);
      cir.show();
      return 0;
}

输入

输出

见样例

输入样例 1

输出样例 1

center:(1,2),radius:1

#include <iostream>
using namespace std;
class Point
{
private: 
    double x;
    double y;
public:
    Point(double a=0,double b=0)
    {  
          x = a;
          y = b;
    }
    void set(double a, double b);
    double getx();
    double gety();
};
void Point::set(double a, double b)
{
      x = a;
      y = b;
}
double Point::getx()
{
      return x;
}
double Point::gety()
{
     return y;
}
class Circle
{
private:
     double r;
     Point cen;         //对象成员
public:
     Circle(double a,double b,double c)::cen(a,b),r(c){};//实现该函数
     void show(){
         cout<<"center:("<<cen.getx()<<","<<cen.gety()<<"),radius:"<<r<<endl;
     }                                      //实现该函数
};

 int main()
{
      Circle cir(1,2,1);
      cir.show();
      return 0;
}

静态数据成员

描述

定义一个学生类Student如下:

    class Student
   {
   private:
            int age;   //年龄
            string name;  //姓名
   public:
            static int count; //静态成员,表示学生人数
            Student(int a, string n);
            Student();
            ~Student();
             void Print();
     };

主函数的定义及程序的运行结果如下,请完成类的定义及类中各函数的实现代码,补充成一个完整的程序。

int main()
{
       cout<<"count="<<Student::count<<endl;
       Student s1, *p=new Student(23,"ZhangHong");
       s1.Print();
       p->Print();
      delete p;
      s1.Print();
     Student Stu[4];
     cout<<"count="<<Student::count<<endl;
     return 0;
}

输入

输出

见样例,注意输出时,逗号后有一空格。

输入样例 1

输出样例 1

count=0 Name=NoName, age=0 Name=ZhangHong, age=23 Name=NoName, age=0 count=5

#include <iostream> 
 #include<string> 
 using namespace std; 
 class Student 
 { 
 private: 
 int age; //年龄 
 string name; //姓名 
 public: 
 static int count; //静态成员,表示学生人数 
 Student(int a, string n); 
 Student(); 
 ~Student(); 
 void Print(); 
 }; 
int Student::count=0; 
Student::Student(int a,string n){ 
 age=a; 
 name=n; 
 count++; 
} 
void Student::Print(){ 
 cout<<"Name="<<name<<", age="<<age<<endl; 
} 
Student::Student(){ 
 name="NoName"; 
 age=0; 
 count++; 
} 
Student::~Student(){ 
 count--; 
} 
   int main() 
 { 
 cout<<"count="<<Student::count<<endl; 
 Student s1, *p=new Student(23,"ZhangHong"); 
 s1.Print(); 
 p->Print(); 
 delete p; 
 s1.Print(); 
 Student Stu[4]; 
 cout<<"count="<<Student::count<<endl; 
 return 0; 
 }

友元函数

描述

实现友元函数,并用主函数进行测试。

class Time
{
private:
      int hour;     
      int minute;
public:
      Time(int h, int m);
      Time();
      void set(int h, int m);
      friend void show(Time t);//以12小时的方式输出时间
};
Time::Time(int h, int m)
{
    hour = h;
    minute = m;
}
Time::Time()
{
    hour = 0;
    minute = 0;
}
void Time::set(int h, int m)
{
    hour = h;
    minute = m;
}
int main()
{
    Time t1,t2(11,12);
    show(t1);
    show(t2);
     t1.set(21,50);
    show(t1);
   return 0;
}

输入

输出

见样例

输入样例 1

输出样例 1

Now is 0:0AM Now is 11:12AM Now is 9:50PM

#include <iostream>
#include <cstring>
using namespace std;
class Time
{
private:
      int hour;     
      int minute;
public:
      Time(int h, int m);
      Time();
      void set(int h, int m);
      friend void show(Time t);//以12小时的方式输出时间
};
Time::Time(int h, int m)
{
    hour = h;
    minute = m;
}
Time::Time()
{
    hour = 0;
    minute = 0;
}
void Time::set(int h, int m)
{
    hour = h;
    minute = m;
}
void show(Time t){
    if(t.hour>12){
        t.hour-=12;
        cout<<"Now is "<<t.hour<<":"<<t.minute<<"PM"<<endl;
    }
    else cout<<"Now is "<<t.hour<<":"<<t.minute<<"AM"<<endl;



}
int main()
{
    Time t1,t2(11,12);
    show(t1);
    show(t2);
     t1.set(21,50);
    show(t1);
   return 0;
}

常成员

描述

实现以下Point类和Area函数,并用主函数测试。

class Point
{
private:
    double x,y;
public:
    Point(double a = 0, double b = 0);
    double GetX()const;
    double GetY()const;
    void Change(double a, double b);
};
double Area( const Point & a1,  const Point & a2)//计算以形参指定的两个点之间的长度为半径的圆面积
{
      //添加代码
}
int main()
{
    const Point p1;00
    Point p2(-5,3);
    cout<<"s1="<<Area(p1,p2)<<endl;
    p2.Change(56,34);
    cout<<"s2="<<Area(p1,p2)<<endl;
    return 0;
}

输入

输出

见样例

输入样例 1

输出样例 1

s1=106.814 s2=13483.7

#include<iostream>
#include<cmath>
using namespace std;
const double PI = acos(-1.0);
class Point
{
private:
    double x,y;
    friend double Area( const Point & a1,  const Point & a2);
public:
    Point(){
        x=0;
        y=0;
    };
    Point(double a,double b){
        x=a;
        y=b;
    }
    double GetX()const;
    double GetY()const;
    void Change(double a, double b);
};

double Point::GetX()const{
    return x;
}
double Point::GetY()const{
    return y;
}

void Point::Change(double a, double b)
{
    x=a;
    y=b;
}
double Area( const Point & a1,  const Point & a2)
{
    return ((a1.GetX()-a2.GetX())*(a1.GetX()-a2.GetX())+(a1.GetY()-a2.GetY())*(a1.GetY()-a2.GetY()))*PI;
}
int main()
{
    const Point p1;
    Point p2(-5,3);
    cout<<"s1="<<Area(p1,p2)<<endl;
    p2.Change(56,34);
    cout<<"s2="<<Area(p1,p2)<<endl;
    return 0;
}

四、运算符重载

Singer

描述

实现一个Singer类,通过以下测试:【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    Singer s1, s2;
    cin >> s1 >> s2;
    cout << s1 << "\n" << s2 << endl;

    if (s1 > s2)
        cout << s1.getName() << "'s score is higher than " << s2.getName() << "'s.\n";
    else if (s1 == s2)
        cout << s1.getName() << "'s score is equal to " << s2.getName() << "'s.\n";
    else
        cout << s1.getName() << "'s score is lower than " << s2.getName() << "'s.\n";

    return 0;
}

输入

输入包含两行。

第一行为歌手s1的信息。第二行为歌手s2的信息,每位歌手的信息包括姓名(不包含空格)、性别、年龄 和 分数;姓名、性别、年龄和分数之间用空格分隔

输出

输出为三行。

前两行分别是歌手s1和s2的信息,第三行根据s1和s2比较结果输出(s1和s2的比较结果和他们的分数的比较结果一致),具体参见主函数

输入样例 1

Mary F 28 99.5
Peter M 26 98

输出样例 1

Mary F 28 99.5
Peter M 26 98
Mary's score is higher than Peter's.

输入样例 2

Zhang M 28 90
Wang F 30 100

输出样例 2

Zhang M 28 90
Wang F 30 100
Zhang's score is lower than Wang's.
// 注意:无需提交main函数
#include<iostream>
using namespace std;

class Singer {
public:
    string m_name;
    char m_sex;
    int m_age;
    double m_score;
public:
    string getName();
    friend istream& operator>>(istream& in, Singer &s);
    friend ostream& operator<<(ostream& out, const Singer &s);
    friend bool operator>(const Singer s1, const Singer s2);
    friend bool operator==(const Singer s1, const Singer s2);
};
bool operator>(const Singer s1, const Singer s2) {
    if (s1.m_score > s2.m_score)
        return true;
    else
        return false;
}

bool operator==(const Singer s1, const Singer s2) {
    if (s1.m_score == s2.m_score)
        return true;
    else
        return false;
}

istream& operator>>(istream& in, Singer &s) {
    in >> s.m_name >> s.m_sex >> s.m_age >> s.m_score;
    return in;
}

ostream& operator<<(ostream& out, const Singer &s) {
    out << s.m_name <<" " << s.m_sex <<" "<<s.m_age << " " << s.m_score ;
    return out;
}

string Singer::getName() {
    return m_name;
}

Sales_data

描述

实现Sales_data类(包括它的友元函数):

class Sales_data
{
    //输入书号、销量和收入 
    friend istream & operator>>(istream&, Sales_data &);
    //输出书号、销量、收入和均价 
    friend ostream & operator<<(ostream &, const Sales_data &);
    friend bool operator==(const Sales_data &, const Sales_data &);
    friend bool operator!=(const Sales_data &, const Sales_data &);
    // for "+", assume that both objects refer to the same book
    friend Sales_data operator+(const Sales_data &, const Sales_data &);

public:
    Sales_data() : units_sold(0), revenue(0.0) {}
    Sales_data(const string & s, unsigned n, double r) :
        bookNo(s), units_sold(n), revenue(r)
    {}
    string get_bookNo() const;
    // for "+=", assume that both objects refer to the same book
    Sales_data & operator+=(const Sales_data &);

private:
    double avg_price() const;  //均价,等于收入除以销量 
    string bookNo;        //书号  
    unsigned units_sold; //销量 
    double revenue;      //收入 
};

通过以下main函数的测试【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    Sales_data item1, item2;
    while(std::cin >> item1 >> item2)
    {
        std::cout << item1 << "\n" << item2 << "\n";
        if (item1 == item2){
            std::cout << item1.get_bookNo() << " equals " << item2.get_bookNo() << "\n";
            std::cout << (item1 + item2) << "\n";
            item1 += item2;
            std::cout << item1 << "\n";
        }
        else if (item1 != item2)
            std::cout << item1.get_bookNo() << " doesn't equal " << item2.get_bookNo() << "\n";
    }
    return 0;
}

输入

输入多组数据,每组数据两行,每行表示1个Sales_data对象,依次是书号、销量和收入

输出

对于每组数据,输出5行,具体参见main函数和输出样例

输入样例 1

001 10 100.0
001 10 100.0

输出样例 1

001 10 100 10
001 10 100 10
001 equals 001
001 20 200 10
001 20 200 10

输入样例 2

002 5 250
003 8 400

输出样例 2

002 5 250 50
003 8 400 50
002 doesn't equal 003
// 注意:无需提交main函数
#include<iostream>
using namespace std;

class Sales_data {
    friend istream& operator>>(istream&, Sales_data&);
    friend ostream& operator<<(ostream&, const Sales_data&);
    friend bool operator==(const Sales_data&, const Sales_data&);
    friend bool operator!=(const Sales_data&, const Sales_data&);
    friend Sales_data operator+(const Sales_data&, const Sales_data&);
public:
    Sales_data() : units_sold(0), revenue(0.0) {}
    Sales_data(const string& s, unsigned n, double r) : bookNo(s), units_sold(n), revenue(r) {}
    string get_bookNo() const;
    Sales_data& operator+=(const Sales_data& s);
private:
    double avg_price() const;
    string bookNo;        //书号
    unsigned units_sold; //销量
    double revenue;      //收入
};

istream& operator>>(istream&in, Sales_data&s) {
    in >> s.bookNo >> s.units_sold >> s.revenue;
    return in;
}

ostream& operator<<(ostream& out, const Sales_data& s) {
    out << s.bookNo <<" "<< s.units_sold << " " << s.revenue << " " << s.avg_price();
    return out;
}

bool operator==(const Sales_data&s1, const Sales_data&s2) {
    if (s1.bookNo == s2.bookNo && s1.units_sold == s2.units_sold && s1.revenue == s2.revenue)
        return true;
    else
        return false;
}
bool operator!=(const Sales_data&s1, const Sales_data&s2) {
    if (s1.bookNo != s2.bookNo || s1.units_sold != s2.units_sold || s1.revenue != s2.revenue)
        return true;
    else
        return false;
}

Sales_data operator+(const Sales_data&s1, const Sales_data&s2) {
    Sales_data temp;
    temp.bookNo = s1.bookNo;
    temp.units_sold = s1.units_sold + s2.units_sold;
    temp.revenue = s1.revenue + s2.revenue;
    return temp;
}

Sales_data&Sales_data::operator+=(const Sales_data& s2) 
{
    units_sold += s2.units_sold;
    revenue += s2.revenue;
    return *this;
}

string Sales_data::get_bookNo() const {
    return bookNo;
}
double Sales_data::avg_price() const {
    return revenue / units_sold;
}

String类

描述

实现String类并使用以下的main函数进行测试:

class String{
private:
    char * s;
public:
    String();
    String(const char *);
    String(const String &);
    ~String();
    String & operator=(const char *);
    String & operator=(const String &);
    String operator+(const char *);
    String operator+(const String &);
    String & operator+=(const char *);
    String & operator+=(const String &);
    friend istream & operator>>(istream &, String &);
    friend ostream & operator<<(ostream &, const String &);
    friend bool operator==(const String &, const char *);
    friend bool operator==(const String &, const String &);
    friend bool operator!=(const String &, const char *);
    friend bool operator!=(const String &, const String &);
};

【注意,下述主函数代码默认存在,提交代码时不能包括以下代码】

int main()
{
    String s;
    s += "hello";
    std::cout << s << std::endl;
    String s1("String1");
    String s2("copy of ");
    s2 += "String1";
    std::cout << s1 << "\n" << s2 << std::endl;
    String s3;
    std::cin >> s3;
    std::cout << s3 << std::endl;
    String s4("String4"), s5(s4);
    std::cout << (s5 == s4) << std::endl;
    std::cout << (s5 != s4) << std::endl;
    String s6("End of "), s7("my string.");
    s6 += s7;
    std::cout << s6 << std::endl;

    return 0;
}

输入

s3的值

输出

一连串String类的字符串,详见样例

输入样例 1

String3

输出样例 1

hello
String1
copy of String1
String3
1
0
End of my string.

提示

使用c语言字符串函数,请引用

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

class String
{
private:
    char* s;
public:
    String();
    String(const char*);
    String(const String&);
    ~String();
    String& operator=(const char*);
    String& operator=(const String&);
    String operator+(const char*);
    String operator+(const String&);
    String& operator+=(const char*);
    String& operator+=(const String&);
    friend istream& operator>>(istream&, String&);
    friend ostream& operator<<(ostream&, const String&);
    friend bool operator==(const String&, const char*);
    friend bool operator==(const String&, const String&);
    friend bool operator!=(const String&, const char*);
    friend bool operator!=(const String&, const String&);
};

String::String() {
    s = new char[100];
    s[0] = '\0';
}
String::String(const char*str) {
    s = new char[strlen(str) + 1];
    strcpy(s, str);
}
String::String(const String&str) {
    s = new char[strlen(str.s) + 1];
    strcpy(s, str.s);
}
String::~String() {
    if (s != nullptr)
      delete []s;
}
String& String::operator=(const char*str) {

    s = new char[strlen(str) + 1];
    strcpy(s, str);
    return *this;
}
String& String::operator=(const String&str) {
    s = new char[strlen(str.s) + 1];
    strcpy(s, str.s);
    return *this;
}
String String::operator+(const char*str) {
    return String(s) + String(str);
}
String String::operator+(const String&str) {
    return String(s) + str;
}
String& String::operator+=(const char*str) {
    return operator+=(String(str));
}
String& String::operator+=(const String& str) {
    char* temp = new char[strlen(s) + strlen(str.s) + 1];
    temp = this->s;
    strcat(temp, str.s);
    this->s = temp;
    return *this;
}
istream& operator>>(istream&in, String&str) {
    in >> str.s;
    return in;
}
ostream& operator<<(ostream& out, const String& str) {
    out << str.s;
    return out;
}
bool operator==(const String&str1, const char*str2) {
    if (strcmp(str1.s, str2) == 0)
        return true;
    else
        return false;
}
bool operator==(const String&str1, const String&str2) {
    if (strcmp(str1.s, str2.s) == 0)
        return true;
    else
        return false;
}
bool operator!=(const String&str1, const char*str2) {
    if (strcmp(str1.s, str2) != 0)
        return true;
    else
        return false;
}
bool operator!=(const String&str1, const String&str2) {
    if (strcmp(str1.s, str2.s) != 0)
        return true;
    else
        return false;
}

CheckedPtr

描述

自增(++)和自减(--)操作符经常由诸如迭代器这样的类实现,这样的类提供类似于指针的行为访问序列中的元素。例如,可以定义一个类,该类指向一个数组并为该数组中的元素提供访问检查。假设,有以下类,它将处理int数组。实现这个类并使用main函数测试此类。

class CheckedPtr{
public:
    CheckedPtr(int * b, int * e) : begin(b), end(e), current(b){
    }
    CheckedPtr & operator ++(); // prefix ++
    CheckedPtr & operator --(); // prefix --
    CheckedPtr   operator ++(int); // postfix ++
    CheckedPtr   operator --(int); // postfix --
    int* Begin();
    int* End();
    int* Current();
private:
    int *begin;        //pointer to beginning of the array
    int *end;        //one past the end of the array
    int *current;    //current position within the array
};

【注意,下述主函数代码默认存在,提交代码时不能包括以下代码】

int main()
{
    int n;
    std::cin >> n;
    int* array = new int[n];

    for(int i = 0; i < n; i++)
        std::cin >> array[i];

    CheckedPtr cp(array, array+n);
    for(;cp.Current()<cp.End(); cp++)
        std::cout << *cp.Current() << " ";
    std::cout << std::endl;

    for(--cp; cp.Current()>cp.Begin(); cp--)
        std::cout << *cp.Current() << " ";
    std::cout << *cp.Current() << std::endl;

    delete[] array;
    return 0;
}

输入

输入为两行,第一行表示数组的长度n,第二行表示这n个数

输出

输出为两行,第一行依次输出数组的第0个到最后一个元素,第二行反向输出数组的所有元素(参考输出样例)

输入样例 1

5
1 2 3 4 5

输出样例 1

1 2 3 4 5 
5 4 3 2 1
#include<iostream>
using namespace std; 
class CheckedPtr
{
public:
CheckedPtr(int * b, int * e) : beg(b), end(e), curr(b) {}
CheckedPtr & operator ++(); // prefix ++      //前++前-- 
CheckedPtr & operator --(); // prefix --
CheckedPtr   operator ++(int); // postfix ++  //后++后-- 
CheckedPtr   operator --(int); // postfix --
int * GetBeg();
int * GetEnd();
int * GetCurr();
private:
int * beg;  // pointer to beginning of the array
int * end;  // one past the end of the array
int * curr; // current position within the array
};

CheckedPtr&CheckedPtr::operator ++()
{
    ++ curr;  
      return *this;  
} 

CheckedPtr &CheckedPtr::operator--()  
{  

    -- curr;  
      return *this;  
} 

CheckedPtr CheckedPtr::operator++(int)  
{  
    CheckedPtr s(*this);  
    ++ *this;  

    return s;  
}  

CheckedPtr CheckedPtr::operator--(int)  
{  
    CheckedPtr s(*this);  
    -- *this;  

    return s;  
}  

int *CheckedPtr::GetBeg() //注意调用方式!!*在前面 
{
    return beg;
}

int *CheckedPtr::GetEnd()
{
    return end;
}
int *CheckedPtr::GetCurr()
{
    return curr;
}

int main(){
int n;
cin>>n;
int * array = new int[n];
for(int i=0;i<n;i++)
cin>>array[i];
CheckedPtr cp(array, array+n);
for(;cp.GetCurr()<cp.GetEnd();cp++)
cout<<*cp.GetCurr()<<" ";
cout<<endl;
for(--cp;cp.GetCurr()>cp.GetBeg();cp--)
cout<<*cp.GetCurr()<<" ";
cout<<*cp.GetCurr()<<endl;
delete [] array;
return 0;
}

Bign【选做】

描述

编写高精度运算类Bign,完成大整数的运算,类的数据成员有两个,一个是int型数据用来存储大数数据的有效长度,另一个是整型数组用来存储大整数。

要求支持字符串赋值和整数赋值,重载+ - * / >> < >= <= == !=等运算符。使用如下main函数测试你的程序【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    UnsignedBigInt a, b, c;
    a = "12349987654321999999";
    c = 123456;
    std::cout << c << std::endl;
    while(std::cin >> b)
    {
        std::cout << a + b << std::endl;
        std::cout << a - b << std::endl;
        std::cout << (a < b) << std::endl;
        a += b;
        std::cout << a << std::endl;
    }
    return 0;
}

输入

一个大整数

输出

用以上main函数输出的结果

输入样例 1

65146746545641888888454524888

输出样例 1

123456
65146746557991876542776524887
-65146746533291901234132524889
1
65146746557991876542776524887

输入样例 2

65146746545641888888454524888
-6746545641454524

输出样例 2

123456
65146746557991876542776524887
-65146746533291901234132524889
1
65146746557991876542776524887
65146746557985129997135070363
65146746557998623088417979411
0
65146746557985129997135070363

Vector

描述

构造一个三维向量类(class Vector),成员如下:数据:分向量、向量模函数:取模、显示向量重载:加、自减、内积、外积、数乘、是否相等、是否共线、是否正交、拷贝、输入、输出

注意重载cout输出流的输出格式:x y z(行末无空格)成员函数void print()的输出格式:(x,y,z)【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main(int argc, char const *argv[])
{
    double a, b, c;
    std::cin >> a >> b >> c;
    Vector p1(a, b, c), p2, p3(p1), p4, x;
    p2 = p3;  //拷贝

    std::cin >> p4;

    p4.print(); //显示向量

    std::cout << p4.model() << std::endl;  //取模

    x = p1 + p4;
    std::cout << x << std::endl;

    p2 -= p4;
    std::cout << p2 << std::endl;

    x = p2*p3;
    std::cout << x << std::endl; //向量积

    std::cout << p2.a*p3.a + p2.b*p3.b + p2.c*p3.c << std::endl; //数量积

    int flag = p1 == p2;
    std::cout << flag << std::endl; //是否相等

    x = 1.5*p3;
    flag = p1 || x;
    std::cout << flag << std::endl; //是否平行(数乘)

    flag = (p1.a*p4.a + p1.b*p4.b + p1.c*p4.c) ? 0 : 1;
    std::cout << flag; //是否正交

    return 0;
}

输入

见样例

输出

见测试样例

输入样例 1

3 4 5
-1 7 -4

输出样例 1

(-1,7,-4)
8.12404
2 11 1
4 -3 9
-51 7 25
45
0
1
0

Complex

描述

设计一个复数类Complex,要求对运算符“+”“-”“”“/”和“+=”“-=”“=”“/=”进行重载,完成复数的加减乘除以及加减乘除复合赋值运算;并且重载“>”操作符完成复数的输入和输出。最后,重载“==”和“!=”比较两个复数是否相等。使用以下main函数测试你的复数类【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    Complex c1, c2;
    cin >> c1 >> c2;
    cout << "c1 = " << c1 << "\n" << "c2 = " << c2 << endl;
    cout << "c1+c2 = " << c1 + c2 << endl;
    cout << "c1-c2 = " << c1 - c2 << endl;
    cout << "c1*c2 = " << c1 * c2 << endl;
    cout << "c1/c2 = " << c1 / c2 << endl;
    cout << (c1 += c2) << endl;
    cout << (c1 -= c2) << endl;
    cout << (c1 *= c2) << endl;
    cout << (c1 /= c2) << endl;
    cout << (c1 == c2) << " " << (c1 != c2) << endl;

    return 0;
}

输入

输入有两行,每行输入两个表示复数c1和c2的浮点数。

输出

输出一共有11行,分别表示复数之间的各项操作,具体参见主函数和输出样例

输入样例 1

-4 6
2 5

输出样例 1

c1 = -4 + 6i
c2 = 2 + 5i
c1+c2 = -2 + 11i
c1-c2 = -6 + 1i
c1*c2 = -38 + -8i
c1/c2 = 0.758621 + 1.10345i
-2 + 11i
-4 + 6i
-38 + -8i
-4 + 6i
0 1

提示

复数加法公式:(a+bi)+(c+di)=(a+c)+(b+d)i 复数减法公式:(a+bi)-(c+di)=(a-c)+(b-d)i 复数乘法公式:(a+bi)(c+di)=(ac-bd)+(ad+bc)i

#include <iostream>
using namespace std;

class Complex
{
private:
    double x;
    double y;
public:
    Complex(double x = 0.0, double y = 0.0);
    Complex& operator+=(const Complex&);
    Complex& operator-=(const Complex&);
    Complex& operator*=(const Complex&);
    Complex& operator/=(const Complex&);
    friend Complex operator+(const Complex&, const Complex&);
    friend Complex operator-(const Complex&, const Complex&);
    friend Complex operator*(const Complex&, const Complex&);
    friend Complex operator/(const Complex&, const Complex&);
    friend bool operator==(const Complex&, const Complex&);
    friend bool operator!=(const Complex&, const Complex&);
    friend ostream& operator<<(ostream&, const Complex&);
    friend istream& operator>>(istream&, Complex&);
};

Complex::Complex(double x, double y) {
    this->x = x;
    this->y = y;
}

Complex operator*(const Complex& s1, const Complex& s2)
{
    Complex s;
    s.x = s1.x * s2.x - s1.y * s2.y;
    s.y = s1.x * s2.y + s1.y * s2.x;
    return s;
}

Complex operator/(const Complex& s1, const Complex& s2)
{
    Complex s;
    s.x = (s1.x * s2.x + s1.y * s2.y) / (s2.x * s2.x + s2.y * s2.y);
    s.y = (s1.y * s2.x - s1.x * s2.y) / (s2.x * s2.x + s2.y * s2.y);
    return s;
}
Complex& Complex::operator+=(const Complex& s)
{
    x += s.x;
    y += s.y;
    return *this;
}

Complex& Complex::operator-=(const Complex& s)
{
    x -= s.x;
    y -= s.y;
    return *this;
}


Complex& Complex::operator*=(const Complex& c)   //错了无数次的地方
{
    *this = *this * c;
    return *this;
}

Complex& Complex::operator/=(const Complex& p)
{
    *this = *this / p;
    return *this;
}
Complex operator+(const Complex& s1, const Complex& s2)
{
    Complex s;
    s.x = s1.x + s2.x;
    s.y = s1.y + s2.y;
    return s;
}

Complex operator-(const Complex& s1, const Complex& s2)
{
    Complex s;
    s.x = s1.x - s2.x;
    s.y = s1.y - s2.y;
    return s;
}


bool operator==(const Complex& s1, const Complex& s2)
{
    if (s1.x == s2.x || s1.y == s2.y)
        return true;
    else
        return false;
}

bool operator!=(const Complex& s1, const Complex& s2)
{
    if (s1.x != s2.x || s1.y != s2.y)
        return true;
    else
        return false;
}

istream& operator>>(istream& stream, Complex& s)
{
    stream >> s.x >> s.y;
    return stream;
}
ostream& operator<<(ostream& stream, const Complex& s)
{
    stream << s.x << " + " << s.y << "i";
    return stream;
}



int main()
{
    Complex c1, c2;
    cin >> c1 >> c2;
    cout << "c1 = " << c1 << "\n" << "c2 = " << c2 << endl;
    cout << "c1+c2 = " << c1 + c2 << endl;
    cout << "c1-c2 = " << c1 - c2 << endl;
    cout << "c1*c2 = " << c1 * c2 << endl;
    cout << "c1/c2 = " << c1 / c2 << endl;
    cout << (c1 += c2) << endl;
    cout << (c1 -= c2) << endl;
    cout << (c1 *= c2) << endl;
    cout << (c1 /= c2) << endl;
    cout << (c1 == c2) << " " << (c1 != c2) << endl;
    return 0;
}

学生选课

描述

已知选课类Subject和学生类Student定义如下,学生类是选课类的友元类

class Subject    //选课类
{
private:
    double score[2]; //2门课成绩
    static const int SMath=4, SCpp=2; //2门课的学分,分别为4、2
public:
    Subject(int math = 0, int cpp = 0);
    void Input(); //输入2门课的成绩
    friend class Student; //友元类
};
class Student
{
private:
    std::string ID; //学号
    std::string name; //姓名
    double GPA; //平均学分积
    Subject sub; //选课,注意本题假设大家选课一样
public:
    Student(std::string id = "00000", std::string na = "Noname");
    void CalculateGPA(); //计算平均学分积
    void Input(); //输入学号和姓名
    void Show()const; //输出所有信息
};

请实现以上两个类,并用如下main函数进行测试:【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    int n; //学生人数
    std::cin >> n;
    Student *stu = new Student[n];
    for (int i = 0; i < n; i++)
    {
        stu[i].Input();
    }
    for (int i = 0; i < n; i++)
    {
        stu[i].CalculateGPA();
        stu[i].Show();
    }
    delete[] stu;

    return 0;
}

输入

第一行输入学生人数n,然后依次输入n个学生的学号、姓名、2门课的成绩

输出

见测试样例

输入样例 1

3
001
Mary
88
89
002
Bob
93
89
003
Lily
78
90

输出样例 1

ID: 001, Name: Mary
Math Cpp
88 89
GPA: 88.3333
ID: 002, Name: Bob
Math Cpp
93 89
GPA: 91.6667
ID: 003, Name: Lily
Math Cpp
78 90
GPA: 82

输入样例 2

2
00001
John
89
99
00002
Peter
100
100

输出样例 2

ID: 00001, Name: John
Math Cpp
89 99
GPA: 92.3333
ID: 00002, Name: Peter
Math Cpp
100 100
GPA: 100

提示:输出时,冒号和逗号后各有一个空格,成绩后面有一个空格,课程名称之间有一个空格,“Cpp”后无空格


五、继承和虚函数

TableTennisPlayer

描述

编写TableTennisPlayer类和RatedPlayer类(RatedPlayer类继承TableTennisPlayer类),其中TableTennisPlayer类的定义如下所示:

class TableTennisPlayer 
{
private:
    string firstname;
    string lastname;
    bool hasTable;
public:
    TableTennisPlayer(const string &, const string &, bool);
    string FirstName() const;
    string LastName() const;
    bool HasTable() const;
};

实现后,通过以下main函数的测试:

int main() 
{
    string firstname, lastname;
    bool hasTable;
    int rating;
    char flag;
    while (cin >> flag)
    {
        if (flag == 'T') 
        {
            cin >> firstname >> lastname >> hasTable;
            TableTennisPlayer tp(firstname, lastname, hasTable);
            if (tp.HasTable())
                cout << tp.FirstName() << " " << tp.LastName() << " has a table.\n";
            else
                cout << tp.FirstName() << " " << tp.LastName() << " hasn't a table.\n";
        }
        else if (flag == 'R')
        {
            cin >> firstname >> lastname >> hasTable >> rating;
            RatedPlayer rp(rating, firstname, lastname, hasTable);
            if (rp.HasTable())
                cout << rp.FirstName() << " " << rp.LastName() 
                << " has a table. The rating is " << rp.Rating() << ".\n";
            else
                cout << rp.FirstName() << " " << rp.LastName() 
                << " hasn't a table. The rating is " << rp.Rating() << ".\n";
        }
    }
    return 0;
}

输入

输入多行,每一行以'T'或'R'开头,'T'表示本行接下来输入一个TableTennisPlayer对象的信息,包括firstname,lastname和hasTable(是否有乒乓球台);'R'表示本行接下来输入一个RatedPlayer对象的信息,包括firstname,lastname,hasTable和rating(选手的得分)。

输出

一行输入对应一行输出,输出详见main函数

输入样例 1

T Bill Gates 1

输出样例 1

Bill Gates has a table.

输入样例 2

R Jike Zhang 0 19000

输出样例 2

Jike Zhang hasn't a table. The rating is 19000.
#include<iostream>
using namespace std;

class TableTennisPlayer {
private:
    string firstname;
    string lastname;
    bool hasTable;
public:
    TableTennisPlayer(const string&, const string&, bool);
    string FirstName() const;
    string LastName() const;
    bool HasTable() const;
};
TableTennisPlayer::TableTennisPlayer(const string&f, const string&l, bool h) 
{
    firstname = f;
    lastname = l;
    hasTable = h;
}

string TableTennisPlayer::FirstName() const
{
    return firstname;
}

string TableTennisPlayer::LastName() const
{
    return lastname;
}

bool TableTennisPlayer::HasTable() const
{
    return hasTable;
}

class RatedPlayer :public TableTennisPlayer 
{
private:
    int rating;
public:
    RatedPlayer(const int, const string&, const string&, bool);
    int Rating();
};

RatedPlayer::RatedPlayer(const int r,const string& f, const string& l, bool h):TableTennisPlayer(f,l,h)
{
    rating = r;
}

int RatedPlayer::Rating()
{
    return rating;
}

int main() {
    string firstname, lastname;
    bool hasTable;
    int rating;
    char flag;
    while (cin >> flag) {
        if (flag == 'T') {
            cin >> firstname >> lastname >> hasTable;
            TableTennisPlayer tp(firstname, lastname, hasTable);
            if (tp.HasTable())
                cout << tp.FirstName() << " " << tp.LastName() << " has a table.\n";
            else
                cout << tp.FirstName() << " " << tp.LastName() << " hasn't a table.\n";
        }
        else if (flag == 'R') {
            cin >> firstname >> lastname >> hasTable >> rating;
            RatedPlayer rp(rating, firstname, lastname, hasTable);
            if (rp.HasTable())
                cout << rp.FirstName() << " " << rp.LastName() << " has a table. The rating is " << rp.Rating() << ".\n";
            else
                cout << rp.FirstName() << " " << rp.LastName() << " hasn't a table. The rating is " << rp.Rating() << ".\n";
        }
    }
    return 0;
}

Person和Student

描述

实现一个Person类,再实现一个Student类,要求Student类继承Person类,通过以下测试:

int main()
{
    Person * p;

    p = new Person;
    p->input();
    p->display();
    delete p;

    p = new Student;
    p->input();
    p->display();
    delete p;

    return 0;
}

输入

输入包含两行,第一行为一个姓名(不包含空格);第二行为一个学号和一个姓名(学号、姓名都不包含空格),学号和姓名之间用空格间隔。学号和姓名用string类型。

输出

输出为两行,第一行为一个姓名;第二行为学号和姓名,学号和姓名之间用空格间隔

输入样例 1

Mary
001 Mary

输出样例 1

Mary
001 Mary
#include<bits/stdc++.h>
using namespace std;
class Person{
    protected:
    string name;
    public:
        virtual void input(){
            cin>>name;
        }
        virtual void display(){
            cout<<name<<endl;
        }
};
class Student:public Person{
    int id;
    public:
        void input(){
            cin>>id>>name;
        }
        void display(){
            cout<<id<<" "<<name<<endl;
        }
};
int main()
{
    Person * p;

    p = new Person;
    p->input();
    p->display();
    delete p;

    p = new Student;
    p->input();
    p->display();
    delete p;

    return 0;
}


图书商品

描述

编写以下两个类,请实现并使得以下的main函数成立

class Item_base 
{  //图书商品
public:
    Item_base(const string & book_ISBN = "", double sales_price = 0.0);
    string Get_ISBN() const;
    virtual double Net_price(int) const;  //返回购买指定数量的图书的总价
    virtual ~Item_base();
protected:
    string ISBN;   //图书序列号
    double price;   //单价
};

class Bulk_Item : public Item_base 
{  //根据购买数量打折
public:
    Bulk_Item(const string & book_ISBN = "", double sales_price = 0.0, int min_qty = 0, double discount = 0.0);
    double Net_price(int) const;  //返回根据购买数量打折后的总价
private:
    int min_qty;   // 买够这个数量可以打相应的折扣
    double discount;  //折扣
};

int main()
{
    Item_base book("0-001-0001-1", 10.0);
    Bulk_Item bulk1("0-001-0001-1", 10.0, 5, 0.1);
    Bulk_Item bulk2("0-001-0001-1", 10.0, 10, 0.2);

    int num;
    while (cin >> num) {

        cout << bulk1.Get_ISBN() << "\t" << num << "\t";

        Item_base * p;
        if (num >= 10) p = &bulk2;
        else if (num >= 5) p = &bulk1;
        else p = &book;

        cout << p->Net_price(num) << "\n";
    }
    return 0;
}

输入

图书的数量。

输出

输出购买的图书的ISBN,它的数量以及总的价格。(用main函数中输出的形式即可)

输入样例 1

2
6
11

输出样例 1

0-001-0001-1     2     20
0-001-0001-1     6     54
0-001-0001-1     11    88
#include<iostream>
using namespace std;

class Item_base
{
protected:
    string ISBN;
    double price;
public:
    Item_base(const string& book_ISBN = "", double sales_price = 0.0);
    string get_ISBN() const;
    virtual double net_price(int) const;
    virtual ~Item_base();
};

Item_base::Item_base(const string& book_ISBN, double sales_price)
{
    ISBN = book_ISBN;
    price = sales_price;
}
string Item_base::get_ISBN() const
{
    return ISBN;
}

double Item_base::net_price(int num) const
{
    return num * price;
}
Item_base::~Item_base()
{ }

class Bulk_Item : public Item_base
{
public:
    Bulk_Item(const string& book_ISBN = "", double sales_price = 0.0, int min_qty = 0, double discount = 0.0);
    double net_price(int) const;
private:
    int min_qty;
    double discount;
};

Bulk_Item::Bulk_Item(const string& book_ISBN, double sales_price, int min_qty, double discount) :Item_base(book_ISBN, sales_price)
{
    this->min_qty = min_qty;
    this->discount = discount;
}

double Bulk_Item::net_price(int num) const
{
    return num * price * (1 - discount);
}

int main()
{
    Item_base book("0-001-0001-1", 10.0);
    Bulk_Item bulk1("0-001-0001-1", 10.0, 5, 0.1);
    Bulk_Item bulk2("0-001-0001-1", 10.0, 10, 0.2);
    int num;
    while (cin >> num)
    {
        cout << bulk1.get_ISBN() << "\t" << num << "\t";
        Item_base* p;
        if (num >= 10) p = &bulk2;
        else if (num >= 5) p = &bulk1;
        else p = &book;
        cout << p->net_price(num) << "\n";
    }
    return 0;
}

Vehicle类

描述

设计一个抽象类Vehicle,由它派生出类Car和类Truck

类Car包含名称、颜色和载客数三个数据成员

类Truck包含名称、颜色和载重量三个数据成员

使用如下函数测试你的程序:

int main() 
{
    char type;
    while (cin >> type)
    {
        Vehicle *p;
        string name, color;
        cin >> name >> color;
        if (type == 'C') 
        {
            int pas;
            cin >> pas;
            Car car(name, color, pas);
            p = &car;
            p->display();
        }
        else if (type == 'T') 
        {
            double cap;
            cin >> cap;
            Truck truck(name, color, cap);
            p = &truck;
            p->display();
        }
    }
    return 0;
}

输入

多组输入。

每组输入的开头是'C'或者'T',代表此时我们要输入的车的信息分别为Car和Truck.

当输入的是Car的时候,我们要输入它的名称,颜色和载客数;

当输入的是Truck的时候,我们要输入它的名称,颜色和载重量。

然后用抽象类的Vehicle的指针来指向派生类对象,从而实现不同类中display()函数的多态性。

输出

根据不同车种类,输出不同信息,具体见样例输出。

输入样例 1

C Benz black 3
T Dongfeng white 8.5

输出样例 1

Benz car, black, passenger volume: 3
Dongfeng truck, white, cargo capacity: 8.5(t)

提示

Vehicle中可包含名称和颜色数据成员,并且有纯虚函数以提供接口完成信息的显示;

在派生类Car和Truck中根据需要实现纯虚函数以及添加成员。

#include<iostream>
using namespace std;

class Vehicle
{
protected:
    string m_name;
    string m_color;
public:
    Vehicle(string name, string color);
    virtual void display() = 0;
};

Vehicle::Vehicle(string name, string color)
{
    m_name = name;
    m_color = color;
}

class Car :public Vehicle
{
private:
    int m_passager;
public:
    Car(string name, string color, int passsager);
    void display();
};

Car::Car(string name, string color, int passager): Vehicle(name, color)
{
    m_passager = passager;
}

void Car::display()
{
    cout << "Car name:" << m_name << " " << "Car color:" << m_color << " " << "Car passager:" << m_passager << endl;
}

class Truck :public Vehicle
{
private:
    double m_capacity;
public:
    Truck(string name, string color, double capacity);
    void display();
};

Truck::Truck(string name, string color, double capacity) : Vehicle(name, color)
{
    m_capacity = capacity;
}

void Truck::display()
{
    cout << "Truck name:" << m_name << " " << "Truck color:" << m_color <<" "<<"Truck capacity:" << m_capacity << endl;
}

int main()
{
    Vehicle* p;
    char type;
    char name[110], color[110];
    int pas;
    double cap;
    while (cin >> type)
    {
        cin >> name >> color;
        if (type == 'C')
        {
            cin >> pas;
            Car car(name, color, pas);
            p = &car;
            p->display();
        }
        else if (type == 'T')
        {
            cin >> cap;
            Truck truck(name, color, cap);
            p = &truck;
            p->display();
        }
    }
    return 0;
}

表面积和体积

描述

编写程序计算长方体、圆柱体和球的表面积和体积。要求先定义一个抽象类Shape如下:

class Shape 
{
public:
    Shape() {}
    virtual ~Shape() {}
    virtual double Area() = 0;
    virtual void Input() = 0;
    virtual double Volume() = 0;
};

使用Shape类派生出长方体类、圆柱体类、球类,在这些类里分别实现继承的纯虚函数。使用如下代码测试运行。

void work(Shape *s)
{
    s->Input();
    cout << s->Area() << " " << s->Volume() << endl;
}

int main()
{
    char c;
    while (cin >> c)
    {
        switch (c)
        {
        case 'y':
        {
            Shape *s = new Cylinder();
            work(s);
            delete s;
            break;
        }
        case 'c':
        {
            Shape *s = new Cuboid();
            work(s);
            delete s;
            break;
        }
        case 'q':
        {
            Shape *s = new Ball();
            work(s);
            delete s;
            break;
        }
        default:
            break;
        }
    }
    return 0;
}

输入

输入包含多行,每行首先是一个字符'c','y','q',分别表示输入长方体、圆柱体或球的信息,接下来是对应的输入。

输出

每行输入对应一行输出,表示该形状的表面积和体积,以空格分隔。

输入样例 1

c 3 4 5
y 3 5
q 5

输出样例 1

94 60
150.796 141.372
314.159 523.599

提示

pi的精度要足够,比如使用 const double pi = acos(-1);

#include<iostream>
#include<cmath>
using namespace std;
const double pi = acos(-1);

class Shape 
{
public:
    Shape() {}
    virtual double area() = 0;
    virtual void input() = 0;
    virtual double volume() = 0;
    virtual ~Shape() {}
};

class Cuboid :public Shape
{
private:
    int a, b, c;
public:
    void input() { cin >> a >> b >> c; }
    double area() {return  2 * a * b + 2 * a * c + 2 * b * c; }
    double volume() { return a * b * c; }
};

class Cylinder :public Shape
{
private:
    double r, h;
public:
    void input() { cin >> r >> h; }
    double area() { return  2 * pi * r * r + 2 * pi * r * h; }
    double volume() { return  pi * r * r * h; }
};

class Ball :public Shape
{
private:
    double r;
public:
    void input() { cin >> r; }
    double area() { return 4 * pi * r * r; }
    double volume() { return  4.0/3 * pi * r * r * r; }
};

void work(Shape* s) {
    s->input();
    cout << s->area() << " " << s->volume() << endl;
    delete s;
}

int main() {
    char c;
    while (cin >> c) 
    {
        switch (c) 
        {
        case 'y':
            work(new Cylinder());
            break;
        case 'c':
            work(new Cuboid());
            break;
        case 'q':
            work(new Ball());
            break;
        default:
            break;
        }
    }
    return 0;
}

多态

#include <iostream>
#include <algorithm>
#include <vector>
#include <math.h>

using namespace std;

class CShape{
public:
    virtual double Area() = 0; // 纯虚函数
    virtual void PrintInfo() = 0;
};

class CTriangle : public CShape{
public:
    CTriangle(double x, double y, double z) {a = x, b = y, c = z;}
    double Area(){
        double p = (a + b + c) / 2.0;
        return sqrt(p * (p-a) * (p-b) * (p-c));
    }
    void PrintInfo(){
        cout << "Triangle's Area is " << Area() << endl;
    }
private:
    double a, b, c;
};

class CCricle : public CShape{
public:
    CCricle(double a) {r = a;}
    double Area(){
        return 3.14 * r * r;
    }
    void PrintInfo(){
        cout << "Cricle's Area is " << Area() << endl;
    }
private:
    double r;
};

class CRectangle : public CShape{
public:
    CRectangle(double a, double b) {width = a, hight = b;}
    double Area(){
        return width * hight;
    }
    void PrintInfo(){
        cout << "rectangle's Area is " << Area() << endl;
    }
private:
    double width, hight;
};

// CShape* pShapes[100]; // 用基类指针数组存放指向各种派生类对象的指针,然后遍历该数组,就能对各个派生类对象做各种操作,是很常见的做法
vector<CShape*> vec;
bool cmp(CShape* s1, CShape* s2){
    return s1->Area() < s2->Area(); // 此句为多态,s1的类型是CShape*,是基类指针
}

int main(){
    int n;
    cin >> n;
    CRectangle* pr; 
    CCricle* pc;
    CTriangle* pt;
    for (int i = 0; i < n; i++){
        char c; 
        cin >> c;
        switch(c){
            case 'R':
                double width, hight;
                cin >> width >> hight;
                pr = new CRectangle(width, hight);
                // pShapes[i] = pr;
                vec.push_back(pr);
                break;
            case 'T':
                double a, b, c;
                cin >> a >> b >> c;
                pt = new CTriangle(a, b, c);
                // pShapes[i] = pt;
                vec.push_back(pt);
                break;
            case 'C':
                double r;
                cin >> r;
                pc = new CCricle(r);
                // pShapes[i] = pc;
                vec.push_back(pc);
                break;
        }
    }
    // sort(pShapes, pShapes + n, cmp);
    // for (int i = 0; i < n; i++){
    //     vec.push_back(pShapes[i]);
    //     pShapes[i]->PrintInfo();
    // }

    sort(vec.begin(), vec.end(), cmp);
    for (int i = 0; i < n; i++){
        vec[i]->PrintInfo();
    }
    return 0;
}

纯虚函数:我们定义一个Point基类,Point类中没有求面积的area函数,因为点是没有面积的。. 但是在其直接派生类cricle和间接派生类cylinder中都需要有area函数,而且这两个area函数功能不同,一个求圆面积,一个求圆柱体表面积


六、文件

Reading papers

描述

论文 "Fair Allocation of Scarce Medical Resources in the Time of Covid-19" 探讨了Covid-19疫情中稀缺医疗资源分配的公平性问题。现摘取其中一段,请使用C++字符串流对其进行分析,完成以下功能:

  • 统计这段文字的单词总数(以空格分隔为准)

  • 统计这段文字的标点总数(仅考虑半角句号、逗号、双引号)

注意本题要求:

  • main函数已写好如下,只提交readPapers()函数

  • 头文件需由自己包含

int main() {
    std::string content;
    std::getline(std::cin, content, '\n');
    readPapers(content);
    return 0;
}

输入

一段不换行、含句号、逗号、双引号的英文文字。

输出

分别输出单词总数和标点总数,如

30,6

输入样例 1

No matter what difficulties we encounter, don't be afraid and face them with a smile. The best way to eliminate fear is to face the fear itself. "Persistence is victory".

输出样例 1

30,6

提示

  • 根据英文书写规则,标点符号与单词之间可能没有空格。

  • 双引号为 " "

#include<iostream>
#include<string>
using namespace std;
void readPapers(string s)
{
    int count = 0;
  int j=0;
    for(int i=0;i<s.length();i++){
      if(s[i]==' ') count++;
      if(s[i]==','||s[i]=='.'||s[i]=='"'){count++;j++}
    }
    cout << count << "," << j << endl;
}

Counting words

描述

在上一题基础上,试图进一步对论文进行词频分析。现摘取其中一段,请使用C++字符串流结合常用STL容器完成以下功能:

  • 统计这段文字的不重复的单词个数(即多次出现的单词只计为一个)

  • 纯数字的单字不作为单词

注意本题要求:

  • main函数已写好如下,只提交termFrequency()和alphabetSortedFrequency()函数

  • 头文件需由自己包含

int main() {

    // 从标准输入获取文本串
    std::string content;
    std::getline(std::cin, content, '\n');

    map<string, unsigned> msu;

    // 要求termFrequency实现分词,去掉标点
    // 获取单词存放在map中,记录词频(出现次数)
    // 最后返回不重复的单词数量    
    unsigned nWords = termFrequency(content, msu);

    // 按首字母A-Z排序一行一词输出词频
    // 提示: map默认按key值排序
    alphabetSortedFrequency(msu);

    return 0;
}

输入

一段不换行、含句号、逗号、双引号的英文文字。

输出

按单词首字母A-Z排序,一行一词输出小写单词和频数,如

apple:10
banana:5
cherry:1

输入样例 1

No matter what difficulties we encounter, don't be afraid and face them with a smile. The best way to eliminate fear is to face the fear itself. "Persistence is victory".

输出样例 1

a:1
afraid:1
and:1
be:1
best:1
difficulties:1
don't:1
eliminate:1
encounter:1
face:2
fear:2
is:2
itself:1
matter:1
no:1
persistence:1
smile:1
the:2
them:1
to:2
victory:1
way:1
we:1
what:1
with:1

提示

  • 仅考虑半角句号、逗号、双引号 " " 三种标点

  • 应考虑大小写差异,可包含头文件用transform函数进行大小写转换

  • 可使用stringstream类判断字符串是否表示数字

#include <bits/stdc++.h>
#include <map>
#include <string>
#include <sstream> 
#include<iostream>
#include<algorithm>
using namespace std;
unsigned termFrequency(string content, map<string, unsigned>& msu) {
    int L = content.length();
    for (int i = 0; i < L; i++) {
        if (content[i] == '.' || content[i] == ',' || content[i] == '"')
            content[i] = ' ';
    }
    string word;
    stringstream ss(content);//基于字符串的流上的输入与输出操作
    while (ss >> word)//去除空格
    {
        int flag = 0;
        for (int i = 0; i < word.size(); i++)//数字
        {
            if (word[i] < '0' || word[i]>'9') {
                flag = 1;
                break;
            }
        }
        if (flag == 1)
        {
            transform(word.begin(), word.end(), word.begin()/*把结果保存在此*/, ::tolower);
          //tolower函数是把字符串都转化为小写字母;
          //touppre函数是把字符串都转化为大写字母
            map<string, unsigned>::iterator ite = msu.find(word);//查重
            if (msu.count(word) == 0)
                msu.insert(map<string, unsigned>::value_type(word, 1));
            else
                ite->second++;
        }
    }
    return msu.size();
}
void alphabetSortedFrequency(map<string, unsigned> msu) {
    map<string, unsigned>::iterator it;
    for (it = msu.begin(); it != msu.end(); it++) {
        cout << it->first << ":" << it->second << endl;
    }
}
int main() {

    // 从标准输入获取文本串
    std::string content;
    std::getline(std::cin, content, '\n');

    map<string, unsigned> msu;

    // 要求termFrequency实现分词,去掉标点
    // 获取单词存放在map中,记录词频(出现次数)
    // 最后返回不重复的单词数量    
    unsigned nWords = termFrequency(content, msu);

    // 按首字母A-Z排序一行一词输出词频
    alphabetSortedFrequency(msu);

    return 0;
}

Point cloud

描述

逗号分隔值(Comma-Separated Values,CSV)文件以纯文本形式存储类似表格形式的数据(数字和文本)。points.csv存放了一组由三维坐标 [x,y,z] 表示的点云信息,每行表示一个点,每个点由3个浮点数分别表示x、y和z坐标(单位为米),3个整型数表示颜色RGB信息,均以半角逗号分隔。首行为文件头信息。请使用C++文件流实现以下功能:

  • 读入点云信息

  • 统计这些点的重心位置(xyz分别求平均值),按相同坐标格式 [xxxx,yyyy,zzzz] 写入points.csv最后一行

  • 将所有点朝x正方向偏移100米(即x=x+100),y负方向偏移50米,按原顺序、格式写入points_offset.csv

注意本题要求:

  • 使用题目下方数据保存为points.csv,在本地测试正确后提交

  • main函数已写好如下,只提交processPoints()函数

  • 头文件需由自己包含

  • 绝不可在你的代码中进行屏幕输出!否则影响OJ判题,无法AC!

int main() {
    std::cout << "Point cloud in processing..." << endl;
    processPoints();
    return 0;
}

输入

将以下内容保存为points.csv作为你的本地测试数据:

X,Y,Z,R,G,B
244407.100,6010942.604,19.256,140,131,124
244407.097,6010942.547,19.244,142,131,126
244407.080,6010942.541,19.242,144,135,128
244407.124,6010942.599,19.253,144,131,126
244407.120,6010942.553,19.240,140,130,124
244407.125,6010942.565,19.241,144,133,128
244407.090,6010942.570,19.249,142,131,126
244407.072,6010942.575,19.253,145,135,126
244407.119,6010942.576,19.246,140,130,124
244407.079,6010942.575,19.248,161,151,147
244407.096,6010942.581,19.250,142,133,126
244407.089,6010942.604,19.255,140,131,124
244407.066,6010942.598,19.253,144,135,128
244407.112,6010942.599,19.252,137,128,121
244407.089,6010942.598,19.255,138,130,124
244407.067,6010942.569,19.247,149,142,133
244407.103,6010942.524,19.238,147,137,130
244407.057,6010942.512,19.240,161,153,144
244407.127,6010942.525,19.235,144,135,128
244407.074,6010942.524,19.241,154,142,135

输出

Point cloud in processing…

输入样例 1

输出样例 1

Point cloud in processing...

提示

  • 文件保存在本地磁盘时,注意路径的书写方式,既可以使用相对路径,亦可使用绝对路径。路径中使用双斜杠避免字符被转义。

  • 可运用stringstream类将字符串转为数字类型

  • 文件流输出可用setprecision函数控制小数点后位数,如ofs << fixed << setprecision(3);

  • 向文件末尾附加数据时,注意末尾是否已有换行符,若无可事先在原始文件内加入

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<fstream>
#include<iomanip>
using namespace std;
void processPoints()
{
    double points_x, points_y, points_z, point_r, point_g, point_b;
    double sum_x = 0, sum_y = 0, sum_z = 0;
    int pr = 0, ps = 0, pb = 0;
    double X[20], Y[20];
    double x[] = { 244407.100,244407.097,244407.080,244407.124,244407.120,244407.125,244407.090,244407.072,244407.119,244407.079,244407.096,244407.089,244407.066,244407.112,244407.089,244407.067,244407.103,244407.057,244407.127,244407.074 };
    double y[] = { 6010942.604,6010942.547,6010942.541,6010942.599,6010942.553,6010942.565,6010942.570,6010942.575,6010942.576,6010942.575,6010942.581,6010942.604,6010942.598,6010942.599,6010942.598,6010942.569,6010942.524,6010942.512,6010942.525,6010942.524 };
    double z[] = { 19.256,19.244,19.242,19.253,19.240,19.241,19.249,19.253,19.246,19.248,19.250,19.255,19.253,19.252,19.255,19.247,19.238,19.240,19.235,19.241 };
    int R[] = { 140,142,144,144,140,144,142,145,140,161,142,140,144,137,138,149,147,161,144,154 };
    int G[] = { 131,131,135,131,130,133,131,135,130,151,133,131,135,128,130,142,137,153,135,142 };
    int B[] = { 124,126,128,126,124,128,126,126,124,147,126,124,128,121,124,133,130,144,128,135 };
    fstream myfile;
    myfile.open("D:\\points.csv", ios::out | ios::in | ios::trunc);
    if (!myfile) {
        exit(0);
    }
    myfile << "X, Y, Z, R, G, B\n";
    for (int i = 0; i < 20; i++)
    {
        myfile << fixed << setprecision(3) << x[i] << "," << y[i] << "," << z[i] << "," << R[i] << "," << G[i] << "," << B[i] << endl;
    }
    for (int i = 0; i < 20; i++)
    {
        sum_x += x[i];
        sum_y += y[i];
        sum_z += z[i];
        pr += R[i];
        ps += G[i];
        pb += B[i];
    }
    points_x = sum_x / 20;
    points_y = sum_y / 20;
    points_z = sum_z / 20;
    point_r = pr / 20;
    point_g = ps / 20;
    point_b = pb / 20;
    myfile << fixed << setprecision(3) << points_x << "," << points_y << "," << points_z << "," << point_r << "," << point_g << "," << point_b;
    myfile.close();
    myfile.open("D:\\points_offset.csv", ios::trunc | ios::app);
    for (int i = 0; i < 20; i++)
    {
        X[i] = x[i] + 100;
        Y[i] = y[i] - 50;
    }
    myfile << "X, Y, Z, R, G, B\n";
    for (int i = 0; i < 20; i++)
    {
        myfile << fixed << setprecision(3) << X[i] << "," << Y[i] << "," << z[i] << "," << R[i] << "," << G[i] << "," << B[i] << endl;
    }
    myfile.close();
}
int main() {
    std::cout << "Point cloud in processing..." << endl;
    processPoints();
    return 0;
}

七、模板

TSwap

描述

用模板函数Swap实现对不同类型的数据进行交换。

并使用如下主函数测试。【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    int a1, a2;
    std::cin >> a1 >> a2;
    Swap(a1, a2);
    std::cout << a1 << "," << a2 << std::endl;

    double b1, b2;
    std::cin >> b1 >> b2;
    Swap(b1, b2);
    std::cout << b1 << "," << b2 << std::endl;

    char c1, c2;
    std::cin >> c1 >> c2;
    Swap(c1, c2);
    std::cout << c1 << "," << c2 << std::endl;

    return 0;
}

输入

输入共三行。第一行两整数,第二行两浮点数,第三行两字符

输出

输出共三行。每一行为对应输入处理后的结果,输出的两个数用逗号隔开

输入样例 1

2 3
1.2 2.3
a b

输出样例 1

3,2
2.3,1.2
b,a
#include<iostream>
using namespace std;

template<typename T>
void Swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

TSort

描述

用模板函数实现数组的输入、排序和输出。并使用如下主函数测试你的模板【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    const int LEN = 5;
    int type;
    while (std::cin >> type)
    {
        switch (type) 
        {
            case 0: 
            {
                int a1[LEN];
                Input<int>(a1, LEN); Sort<int>(a1, LEN); Output<int>(a1, LEN);
                break;
            }
            case 1: 
            {
                char a2[LEN];
                Input(a2, LEN); Sort(a2, LEN); Output(a2, LEN); 
                break; 
            }
            case 2: 
            {
                double a3[LEN];
                Input(a3, LEN); Sort(a3, LEN); Output(a3, LEN);
                break;
            }
        }
    }

    return 0;
}

输入

输入包含多组测试数据。每组数据为两行,第一行整数type(0、1、2)。第二行为相应数组的5个元素。

输出

对于每一组测试数据,将其排序后在一行内输出,相邻元素逗号空格分离,最后为换行。

输入样例 1

0 
3 6 1 4 5
1 
A B C B A
2
1.1 3.2 4.5 0.6 3.3

输出样例 1

1, 3, 4, 5, 6
A, A, B, B, C
0.6, 1.1, 3.2, 3.3, 4.5
#include<iostream>
using namespace std;

template<typename T>
void Input(T arr[], int len) {
    for (int i = 0; i < len; i++) {
        cin >> arr[i];
    }
}

template<typename T>
void Sort(T arr[], int len) {
    for (int i = 0; i < len; i++) {
        for (int j = i + 1; j < len; j++) {
            if (arr[i] > arr[j]) {
                T temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

template<typename T>
void Output(T arr[], int len) {
    for (int i = 0; i < len-1; i++) {
        cout << arr[i] << ", ";
    }
    cout << arr[len - 1] << endl;
}

TSearch

描述

设计一个模板函数,实现在一个给定的数组中查找给定数据是否存在,如果存在则输出该数据在数组中最小的下标,如果不存在,输出-1。以下为测试函数【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    int n;
    std::cin >> n;
    int *nValues  = new int[n];
    for (int i = 0; i < n; i++) 
    {
        std::cin >> nValues[i];
    }    
    int d;
    std::cin >> d;
    std::cout << Search(nValues, n, d) << std::endl;
    delete[] nValues;

    double f;
    std::cin >> n;
    double *dValues = new double[n];
    for (int i = 0; i < n; i++) 
    {
        std::cin >> dValues[i];
    }
    std::cin >> f;
    std::cout << Search(dValues, n, f) << std::endl;
    delete[] dValues;

    std::cin >> n;
    char *cValues = new char[n];
    for (int i = 0; i < n; i++)
    {
        std::cin >> cValues[i];
    }
    char c;
    std::cin >> c;
    std::cout << Search(cValues, n, c) << std::endl;
    delete[] cValues;

    return 0;
}

输入

输入共三组数据,每组数据占三行。

第一组第一行整数n1,第二行是n1个整数,第三行待查找整数n

第二组第一行整数n2,第二行是n2个浮点数,第三行待查找浮点数d

第三组第一行整数n3,第二行是n3个字符,第三行待查找字符c

输出

对于每一组输入,如果查找数据存在,则输出其最小下标(下标从0开始计),否则输出-1。

输入样例 1

7
1 1 2 5 8 10 13
8
5
-1.0 1.1 1.2 1000.10101 8.9
3.5
4
B J F U
j

输出样例 1

4
-1
-1

提示

使用模板函数

template <class T>
int Search(const T * array, int arrayLen, const T & value)
template<typename T>
int Search(const T * array, int arrayLen, const T & value){
    for(int i=0;i<arrayLen;i++){
        if(array[i]==value) return i;
    }
    return -1;
}

TVector3

描述

构造一个模板类(Vector),数据成员如下:

template<typename T>
class Vector
{
private:
    T x, y, z;
};

完成Vector,并用以下函数测试【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    double a, b, c;
    std::cin >> a >> b >> c;
    Vector<double> v1(a, b, c), v2(v1), v3, v4;
    double d;
    std::cin >> d;
    v4 = d * v1 + v2;

    std::cout << v4 <<std::endl;

    Vector<double>  v;
    std::cin >> v;

    int flag = (v4 == v);
    std::cout << flag << std::endl; 

    return 0;
}

输入

见样例

输出

见样例

输入样例 1

3 4 5
2.2
9.6 12.8 16

输出样例 1

9.6 12.8 16
1
#include<iostream>
#include<cmath>

template<typename T>
class Vector {
private:
    T x, y, z;
public:
    Vector() : x(0), y(0), z(0) {}
    Vector(T x_, T y_, T z_) : x(x_), y(y_), z(z_) {}
    Vector(const Vector<T>& v) : x(v.x), y(v.y), z(v.z) {}

    friend Vector<T> operator*(T d, const Vector<T>& v) {
        return Vector<T>(d * v.x, d * v.y, d * v.z);
    }

    Vector<T> operator+(const Vector<T>& v) const {
        return Vector<T>(x + v.x, y + v.y, z + v.z);
    }
    friend std::ostream& operator<<(std::ostream& out, const Vector<T>& v) {
        out << v.x << " " << v.y << " " << v.z;
        return out;
    }
    friend std::istream& operator>>(std::istream& in, Vector<T>& v) {
        in >> v.x >> v.y >> v.z;
        return in;
    }
    friend bool operator==(const Vector<T>& v1, const Vector<T>& v2) {
        if ((fabs(v1.x - v2.x) < 1e-6) && (fabs(v1.y - v2.y) < 1e-6) && (fabs(v1.z - v2.z) < 1e-6)) {
            return true;
        }
        else {
            return false;
        }
    }
};

int main()
{
    double a, b, c;
    std::cin >> a >> b >> c;
    Vector<double> v1(a, b, c), v2(v1), v3, v4;
    double d;
    std::cin >> d;
    v4 = d * v1 + v2;

    std::cout << v4 << std::endl;

    Vector<double>  v;
    std::cin >> v;

    int flag = (v4 == v);
    std::cout << flag << std::endl;

    return 0;
}

TStack

描述

实现一个Stack类模板并测试这一模板.

template<class T, int SIZE = 20>
class Stack
{
private: 
    T    array[SIZE];        //数组,用于存放栈的元素
    int top;                //栈顶位置(数组下标)
public:
    Stack();                //构造函数,初始化栈
    void Push(const T & );  //元素入栈
    T Pop();                //栈顶元素出栈
    void Clear();           //将栈清空
    const T & Top() const;  //访问栈顶元素
    bool Empty() const;     //测试栈是否为空
    bool Full() const;     //测试是否栈满
    int Size();            //返回当前栈中元素个数
};

测试函数:【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    Stack<int, 10> intStack;

    int n;
    cin >> n; //n<=10
    for (int i = 0; i < n; i++)
    {
        int temp;
        cin >> temp;
        intStack.Push(temp);
    }

    for (int i = 0; i < n; i++)
    {
        cout << intStack.Top() << " ";
        intStack.Pop();
    }
    cout<<endl;

    if(intStack.Empty())
        cout<<"Now, intStack is empty."<<endl;

    Stack<string,5> stringStack;
    stringStack.Push("One");
    stringStack.Push("Two");
    stringStack.Push("Three");
    stringStack.Push("Four");
    stringStack.Push("Five");
    cout<<"There are "<<stringStack.Size()<<" elements in stringStack."<<endl;
    stringStack.Clear();
    if(stringStack.Empty()) 
        cout<<"Now, there are no elements in stringStack"<<endl;

    return 0;
}

输入

参考样例

输出

参考样例

输入样例 1

3
1
2
3

输出样例 1

3 2 1 
Now, intStack is empty.
There are 5 elements in stringStack.
Now, there are no elements in stringStack
#ifndef STACK_STACK_H
#define STACK_STACK_H

#include <cassert>

//模板的定义,SIZE为栈的大小
template<class T, int SIZE=50>
class Stack{
private:
    T list[SIZE];     //数组,用于存放栈的元素
    int top;          //栈顶位置(数组下标)
public:
    Stack();         //构造函数
    void push(const T &item);  //将元素item压入栈
    T pop();                   //将栈顶元素弹出栈
    void clear();              //将栈清空
    const T &peek() const;     //访问栈顶元素
    bool isEmpty() const;      //测试是否栈空
    bool isFull()  const;      //测试是否栈满
};

//模板的实现
template<class T,int SIZE>
Stack<T,SIZE>::Stack() :top(-1) {}  //构造函数,栈顶初始化为-1

template <class T, int SIZE>
void Stack<T,SIZE>::push(const T &item) {    //将元素item压入栈
    assert(!isFull());                       //如果栈满了,则报错
    list[++top] = item;                      //将新元素压入栈顶
}

template <class T, int SIZE>
T Stack<T,SIZE>::pop(){                      //访问栈顶元素
    assert(!isEmpty());                     //如果栈为空,则报错
    return list[top--];                     //返回栈顶元素
};

template <class T, int SIZE>
bool Stack<T,SIZE>::isEmpty() const {         //测试栈是否为空
    return top==-1;
}

template <class T, int SIZE>
bool Stack<T,SIZE>::isFull() const {          //测试是否栈满
    return top==SIZE-1;
}

template <class T, int SIZE>
void Stack<T,SIZE>::clear() {
    top = -1;                                //清空栈
}

TList

描述

设计一个单向链表的类模板,类模板的说明如下:

template <class T>
class List{
private:
    T data;
    List * next;
    List * tail;      //指向最后一个结点
    List * head;      //指向头结点
public:
    List():next(NULL)                  //构造头结点
    {
        head = tail = this;
    }
    List(T newnode):data(newnode),next(NULL)    //构造新结点
    {}
    void Append(T node);               //往后面添加结点
    bool Insert(T node, T posnode);   //在结点posnode第一次出现的后面插入新结点, 插入成功返回true,否则false
    void DeleteNode(T node);          //删除结点,注意可能有多个相同的结点需要删除
    void DeleteList();                   //删除整个链表
    void DisplayList();                  //显示链表
};

你的任务是实现这个类模板中的成员函数,然后使用如下所示的main()函数测试你实现的类模板。【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    List<int> list1;
    list1.Append(1);
    list1.DeleteNode(1);
    list1.Append(2);
    list1.Append(3);
    list1.Append(4);
    list1.Insert(10,2);
    list1.Append(5);
    list1.Append(3);
    list1.Append(3);
    list1.DisplayList();
    list1.DeleteNode(3);
    list1.DisplayList();
    list1.DeleteList();
    list1.DisplayList();

    List<char> list2;
    list2.Append('A');
    list2.Append('B');
    list2.Append('C');
    list2.Append('D');
    list2.Insert('E','B');
    list2.Insert('F','D');
    list2.Append('G');
    list2.Append('G');
    list2.Append('G');
    list2.DisplayList();
    list2.DeleteNode('G');
    list2.DisplayList();
    list2.DeleteList();
    list2.DisplayList();

    return 0;
}

输入

见样例

输出

见样例

输入样例 1

输出样例 1

2 10 3 4 5 3 3 
2 10 4 5 

A B E C D F G G G 
A B E C D F 

提示

(1)Append函数是在链表尾部(即tail指向的结点)后面增加一个新节点,因此tail指针有变化。 (2)在Insert函数中,需要先找到posnode,因此要定义一个指针指向posnode;然后新建一个 结点(该结点的数据是node);如果posnode是最后一个结点,插入新节点还需要修改tail指针,否则直插入新节点不需要修改tail指针。 (3)在DeleteNode函数中,需要两个临时指针find,pre,其中find指向pre的next,最终find指向删除的结点。在循环中,如果需要删除的是最后一个节点,需要修改tail指针,删除find,然后find=NULL;如果不是最后一个结点,把find指向的结点从链表中分离出来,删除find,find指向pre的next;如果没有找到删除的结点,则继续找下一个结点:pre =find;find=find->next (4)在DeleteList函数中,从头循环将要删除的结点从链表中分离出来,头指针相应修改,然后删除(delete)分离的结点。最后将tail和head指向同一个,next指针为NULL。

(5)在DisplayList函数中,从头到尾显示结点。

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

template <class T>
class List
{
private:
    T data;
    List<T> * next;
     List<T> * tail;      //指向最后一个结点
     List<T> * h;      //指向头结点
public:
    List():next(NULL)                  //构造头结点
    {
        h = tail = this;
    }
    List(T newnode):data(newnode),next(NULL)    //构造新结点
    {}
    void append(T node)
    {
        tail->next=new List<T>(node);
        tail=tail->next;
    }//往后面添加结点
    bool insert(T node, T posnode)
    {
        List<T> *cur,*flag;
        cur=h;
        while(cur->data!=posnode&&cur!=tail->next)//遇到第一个数值相等的就跳出循环,保证是第一个
        {
            cur=cur->next;
        }
        if(cur!=NULL)//防止是因为循环到尾部而跳出循环
        {
            if(cur->next!=NULL)//如果是尾部就按append函数的方式插入
            {
                List<T> *p=new List<T>(node);
                flag=cur->next;
                cur->next=p;
                p->next=flag;
            }
            else//如果是链表中间就改变下前面一个和加入节点的next
            {
                cur->next=new List<T>(node);
                tail=cur->next;
            }
            return true;
        }
        return false;
    }//在结点posnode第一次出现的后面插入新结点node, 插入成功返回true,否则false
    void deleteNode(T node)
    {
        List<T> *now;
        now=h->next;
        if(now->data==node)
        {
            if(tail==h->next)//如果b链表尾在头节点后两个节点,tail不太好写,所以拆开来写
            {
                h->next=NULL;
                tail=h;
            }
            else if(tail==h->next->next)
            {
                h->next=h->next->next;
                tail=h->next;
            }
        }
        while(now->next!=NULL)
        {
            if(now->next->data==node)
                now->next=now->next->next;
            else
                now=now->next;
        }
    }//删除结点,注意可能有多个值相同的结点需要删除
    void delList()
    {
        h->next=NULL;
        tail=h;
    }//删除整个链表
    void dispList()
    {
        List<T> *now;
        if(h->next!=NULL)//链表不为空
        {
            now=h->next;
            while(now!=tail->next)
            {
                cout<<now->data<<" ";
                now=now->next;
            }
        }
        cout<<endl;
    }//显示链表
    friend void print(List<T> *now);
};
template<class T>
List<T>*List<T>::tail=NULL;
template<class T>
List<T>*List<T>::h=NULL;

TComplex

描述

复数模板类Complex包含实部和虚部,复数的模为实部和虚部的平方和再开根号。完成这个模板类,并通过测试函数【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    int ir, ii;
    cin >> ir >> ii;
    Complex<int> ci1(ir, ii);
    Complex<int> ci2(2, 3);
    Complex<int> ci = ci1 + ci2;
    cout << ci.Mag() << endl;

    double dr, di;
    cin >> dr >> di;
    Complex<double> cd(dr, di);
    cout << setiosflags(ios::fixed) << setprecision(2);
    cout << cd.Mag() << endl;

    return 0;
}

输入

实部 虚部实部 虚部

输出

见测试样例

输入样例 1

1 1
1.5 1.5

输出样例 1

5
2.12

提示

函数模板,类模板,基本操作符重载,cin/cout重载,友元


TMyQueue

描述

设计一个MyQueue类模板,类模板说明如下:

template <typename T> class MyQueue;//前置声明
template <typename T> std::ostream & operator<<(std::ostream &, const MyQueue<T> &); 

template <typename T> 
class QueueItem
{
public:
    QueueItem(const T & t) :item(t), next(0)
    {} 
private:
    T item; //value stored in this element
    QueueItem *next; // pointer to next element in the MyQueue

    friend class MyQueue<T>;//友元类    
    //通过友元函数重载<<运算符模板函数,要写上<<后的<Type>
    friend ostream & operator<< <T> (ostream & os, const MyQueue<T> & q);
};

template <typename T> 
class MyQueue
{
public:
    MyQueue() : head(0), tail(0) {} // Empty MyQueue

    MyQueue(const MyQueue &Q) //拷贝构造函数
        :head(0), tail(0) 
    { CopyElements(Q); };

    ~MyQueue() { Destroy(); }

    MyQueue & operator=(const MyQueue &);

    // return element from head of MyQueue
    T & Front() { return head->item; }
    const T & Front() const { return head->item; }
    void Push(const T &); //add element to back of MyQueue
    void Pop(); // remove element from head of MyQueue
    bool Empty() const { return head == 0; }
    void Display() const;
private:
    QueueItem<T> *head;
    QueueItem<T> *tail;
    void Destroy(); //delete all the elements
    void CopyElements(const MyQueue &);

    //设置友元函数
    friend ostream & operator<< <T> (ostream & os, const MyQueue<T> & q);
};

实现这个类模板中的成员函数,然后使用如下所示的main()函数测试这一类模板。【注意,下述代码默认存在,提交代码时不能包括以下代码】

int main()
{
    MyQueue<int> qi;
    qi.Push(1);
    qi.Push(2);
    qi.Push(3);
    qi.Push(4);
    qi.Push(5);
    qi.Pop();
    qi.Display();
    cout<<"\n";
    cout<<qi;
    cout<<endl;

    MyQueue<int> qi2(qi);
    qi2.Display();
    cout<<endl;

    MyQueue<int> qi3;
    qi3 = qi;
    cout<<qi3;

    return 0;
}

输入

输出

见测试样例

输入样例 1

输出样例 1

2 3 4 5 
< 2 3 4 5 >
2 3 4 5 
< 2 3 4 5 >

八、string+STL

StringSort

描述

编写程序,利用std::sort完成一个字符串(std::string类型)的排序(降序)并输出。

输入

输入一行:由大小写字母和数字组成的字符串。

输出

输出排序后的字符串。

输入样例 1

abcde

输出样例 1

edcba
#include<bits/stdc++.h>
using namespace std;
bool cmp(char x,char y){
    return x>y;
}
int main(){
  string s;
  cin>>s;
  sort(s.begin(), s.end(),cmp);
  cout<<s;
  return 0;
}

StringsSort

描述

编写程序,利用std::sort进行排序。

使用vector容器输入若干个string类型字符串。

对每个字符串中的字符,根据字典序排序(A到Z, a到z)。

对处理之后的字符串,根据字符的逆字典序(z到a,Z到A)排序。

输入

输入第一行为一个正整数N,然后依次输入N个不带空格的字符串。

输出

参考输出样例

输入样例 1

4
C++
ACM
AHa
MomoDa

输出样例 1

DMamoo
AHa
ACM
++C
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main() {
    vector<string> v;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        string temp;
        cin >> temp;
        sort(temp.begin(), temp.end());
        v.push_back(temp);
    }
    sort(v.begin(), v.end(), greater<string>());
    for (int i = 0; i < v.size(); i++) {
        cout << v[i] << endl;
    }

    return 0;
}

SimpleList

描述

编写程序,定义一个结构体struct Student{ int no; string name;};并用这个结构体练习使用list。包含往list里添加元素以及输出list的所有元素。

struct Student {
    int no;
    string name;
};

并使用以下main函数测试

int main()
{
    std::list<Student> li;

    Input(li); //输入
    Show(li); //输出

    return 0;
}

输入

第一行一个整数n,表示共有n个学生信息

接下来n行,每行是一个整数和一个字符串,分别表示学生的学号和姓名。

输出

按顺序输出list中的所有元素,每个结构体元素占一行。结构体成员之间以逗号空格隔开。

输入样例 1

3
1010101 zhangsan
1010102 lisi
1010103 wangwu

输出样例 1

1010101, zhangsan
1010102, lisi
1010103, wangwu

CardGame

描述

桌上有一叠牌,从第一张牌(即位于顶面的牌)开始从上往下依次编号为1~n。

当至少还剩两张牌时进行以下操作:把第一张牌扔掉,然后把新的第一张放到整叠牌的最后。

请用std::queue模拟这个过程,依次输出每次扔掉的牌以及最后剩下的牌的编号。

输入

输入正整数n(n<1000000)。

输出

在一行内依次输出每次扔掉的牌以及最后剩下的牌的编号,编号之间用一个空格隔开。所有输出最后加一个换行符。

输入样例 1

7

输出样例 1

1 3 5 7 4 2 6

提示

可以用std::queue实现


Marble

描述

现有N个大理石,每个大理石上写了一个非负整数。首先对这些整数从小到大排序,然后回答Q个问题。每个问题问是否有一个大理石写着某个整数x,如果是,就回答哪个大理石上写着x(如果有多个大理石上出现x,那么回答第一次出现的大理石编号)。排序后的大理石从左到右编号为1~N。

输入

输入包含多组测试数据,每组数据分三行第一行是两个正整数N(N<1000)和Q(Q<1000)第二行是N个非负整数第三行是Q个非负整数。

输出

对于每一个询问(x),如果有第i个大理石上写着x,则输出x found at i,否则输出x not found。格式详见样例。

输入样例 1

4 1
2 3 5 1
5
5 2
1 3 3 3 1
2 3

输出样例 1

5 found at 4
2 not found 
3 found at 3

提示

可以直接使用algorithm头文件中的std::sort和std::lower_bound函数,后者的功能是查找大于等于x的第一个位置,

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很好,我了解了你的问题。以下是2019BJFU C++实验习题的题和解答: 1. 编写一个程序,输入一个整数n,输出n的阶乘。 代码实现: ```c++ #include <iostream> using namespace std; int main() { int n; cin >> n; int result = 1; for (int i = 1; i <= n; i++) { result *= i; } cout << result << endl; return 0; } ``` 2. 编写一个程序,输入一个字符串,将其中的小写字母全部转换成大写字母,并输出转换后的字符串。 代码实现: ```c++ #include <iostream> #include <cstring> using namespace std; int main() { char str[100]; cin.getline(str, 100); int len = strlen(str); for (int i = 0; i < len; i++) { if (str[i] >= 'a' && str[i] <= 'z') { str[i] = str[i] - 'a' + 'A'; } } cout << str << endl; return 0; } ``` 3. 编写一个程序,输入一个字符串,将其中的所有数字字符相加,并输出和。 代码实现: ```c++ #include <iostream> #include <cstring> using namespace std; int main() { char str[100]; cin.getline(str, 100); int len = strlen(str); int sum = 0; for (int i = 0; i < len; i++) { if (str[i] >= '0' && str[i] <= '9') { sum += str[i] - '0'; } } cout << sum << endl; return 0; } ``` 4. 编写一个程序,输入一个整数n,输出所有小于n的正整数中,能被3或5整除的数的和。 代码实现: ```c++ #include <iostream> using namespace std; int main() { int n; cin >> n; int sum = 0; for (int i = 1; i < n; i++) { if (i % 3 == 0 || i % 5 == 0) { sum += i; } } cout << sum << endl; return 0; } ``` 5. 编写一个程序,输入一个字符串,判断它是否为回文字符串,即正读和反读都一样(例如,"abcba"就是回文字符串)。 代码实现: ```c++ #include <iostream> #include <cstring> using namespace std; int main() { char str[100]; cin.getline(str, 100); int len = strlen(str); bool isPalindrome = true; for (int i = 0; i < len / 2; i++) { if (str[i] != str[len - i - 1]) { isPalindrome = false; break; } } if (isPalindrome) { cout << "Yes" << endl; } else { cout << "No" << endl; } return 0; } ``` 希望这些代码能够帮助你解决问题。如果你还有其他问题,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值