一、预备练习
函数重载
描述
用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米,体育场的长宽由键盘输入。
体育场和矩形过道都是如下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的第一个位置,