西安石油大学C++上机实验 上机五:模板和异常处理程序设计(2 学时)

简介: 西安石油大学C++上机实验 上机五:模板和异常处理程序设计(2 学时)

上机五:模板和异常处理程序设计(2 学时)

实验目的

1.了解参数多态性的概念。

2.熟悉函数模板和类模析的设计和使用方法。

3.掌握 C++异常处理方法和异常类的设计。

了解参数多态性的概念。

熟练掌握函数模板和类模析的设计和使用方法。

实验内容

P197:7.9

设计一个考虑异常情况的分数类模板,实现基本分数运算和分数的输出,并编写测试程序进行测试。

测试例题

[例 7.2] 设计一下复数类模板。要求:

(1)复数类模板的成员函数包括加和输出;

(2)成员函数加既可以是两个复数类模板对象相加,也可以是一个复数类模板对象与另一个模板参数作为实部的数值相加;

(3)设计一个测试主函数,要求测试主函数中同时定义实参为 float 的复数类对象和实参为 double 的复数类对象。

// TemplateComplex.h
template <class T>
class Complex{
 T real;
 T imag;
public:
 Complex(T x=0, T y=0);
 Complex Add(const Complex x);
 Complex Add(const T x);
void show() const;
};
template <class T>
Complex<T>::Complex(T x, T y)
{
real = x;
imag = y;
}
template <class T>
Complex<T> Complex<T>::Add(const Complex<T> x)
{
return Complex<T>(real+x.real, imag+x.imag);
}
template <class T>
Complex<T> Complex<T>::Add(const T x)
{
return Complex<T>(real+x, imag);
}
template <class T>
void Complex<T>::show() const
{
cout<<"real is "<<real;
cout<<" imag is "<<imag<<endl;
}
在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "TemplateComplex.h"
int main(int argc, char* argv[])
{
Complex<float> x(1.1, 1.1), y(2.2, 2.2), z;
Complex<double> u(1.111111, 1.111111), v(2.22222, 2.22222), w;
z = x.Add(y);
cout<<"z is: ";
z.show();
w = u.Add(v);
cout<<"w is: ";
w.show();
return 0;
}
[例 7.3] 设计一个求两个数中较大数的函数模板
//Max.h
template <class T>
T max(T x, T y)
{
 return (x>y)? x:y;
}
在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "Max.h"
int main(int argc, char* argv[])
{
int myIntX = 5, myIntY = 8, myIntC;
float myFloatX = 5.6, myFloatY = 8.9, myFloatC;
54
myIntC = max(myIntX, myIntY);
cout<<"myIntC = "<<myIntC<<endl;
myFloatC = max(myFloatX, myFloatY);
cout<<"myFloatC = "<<myFloatC<<endl;
}
//SeqStack.h
class PushOnFull{ //入栈满异常类
 int value;
public:
 PushOnFull(int x) : value(x){}
 int Value(void){ return value; }
};
class PopOnEmpty{};
class SeqStack{
int *data;
int MaxStackSize;
int top;
public:
SeqStack(int n)
{
top = 0;
MaxStackSize = 0;
data = new int[n];
}
~SeqStack(){ delete data; }
void Push(const int item);
int Pop();
};
void SeqStack::Push(const int item)
{
 if(top==MaxStackSize)
 throw PushOnFull(item);
 data[top] = item;
 top++;
}
int SeqStack::Pop()
{
if(top == 0) throw PopOnEmpty();
top--;
return data[top];
}
在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "SeqStack.h"
int main(int argc, char* argv[])
{
SeqStack myStack(10);
try{
for(int i=0; i<11; i++)
myStack.Push(i+1);
}
catch(PushOnFull obj){
cout<<"Stack is full"<<endl;
cout<<"the element is: "<<obj.Value()<<endl;
}
try{
for(int i=0; i<11; i++)
cout<<myStack.Pop()<<" ";
}
catch(PopOnEmpty){
cout<<"Stack is empty"<<endl;
}
}

P197:7.9

设计一个考虑异常情况的分数类模板,实现基本分数运算和分数的输出,并编写测试程序进行测试。

class Fract{
public:
int n; //分子
int m; //分母
 Fract(int a=0, int b=1):n(a), m(b){}
 Fract Add(const Fract x);
Fract Div(const Fract x);
void show() const;
int MaxComm(int a, int b);
};
Fract Fract::Div(const Fract x)
{
57
58
int a = n*x.m;
int b = m*x.n;
if(b == 0)throw 0;
int c = MaxComm(a, b);
return Fract(a/c, b/c);
}
Fract Fract::Add(const Fract x)
{
int a = n*x.m + m*x.n;
int b = m*x.m;
int c = MaxComm(a, b);
return Fract(a/c, b/c);
}
int Fract::MaxComm(int a, int b)//求 a,b 的最大公约数
{
int r=a%b;
while(r!=0)
{
a = b;
b = r;
r = a%b;
}
return(b);
}
void Fract::show() const
{
cout<<n<<"/"<<m<<endl;
}
(3)在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "Fract.h"
int main(int argc, char* argv[])
{
Fract f1(3, 4), f2(7, 16), f3;
try{
59
f1.Div(f3);
}
catch(int){
cout<<"Divided by Zero!"<<endl;
}
f3 = f1.Add(f2);
f3.show();
}

CHATgpt 会怎么来处理?

好的,下面是一个考虑异常情况的分数类模板,并实现了基本分数运算和分数输出的代码:
~~~c++
#include<iostream>
#include<exception>
using namespace std;
//自定义除数为0异常
struct DIVBYZERO: public exception
{
    const char* what() const throw()
    {
        return "Error: Division by zero!\n";
    }
};
template<class T>
class Fraction
{
    private:
        T numerator; // 分子
        T denominator; // 分母
    public:
        // 构造函数
        Fraction(T num, T den);
        // getter 方法
        T getNumerator();
        T getDenominator();
        // setter 方法
        void setNumerator(T num);
        void setDenominator(T den);
        // 重载"+"
        Fraction operator+(Fraction f);
        // 重载"-"
        Fraction operator-(Fraction f);
        // 重载"*"
        Fraction operator*(Fraction f);
        // 重载"/"
        Fraction operator/(Fraction f);
        // 输出分数
        void print();
};
// 构造函数实现
template<class T>
Fraction<T>::Fraction(T num, T den)
{
    if(den == 0) // 如果分母为0则抛出DIVBYZERO异常
        throw DIVBYZERO();
    numerator = num;
    denominator = den;
}
// getter 方法实现
template<class T>
T Fraction<T>::getNumerator()
{
    return numerator;
}
template<class T>
T Fraction<T>::getDenominator()
{
    return denominator;
}
// setter 方法实现
template<class T>
void Fraction<T>::setNumerator(T num)
{
    numerator = num;
}
template<class T>
void Fraction<T>::setDenominator(T den)
{
    // 如果分母为0则抛出DIVBYZERO异常
    if(den == 0)
        throw DIVBYZERO();
    else
        denominator = den;
}
// 重载"+" 实现
template<class T>
Fraction<T> Fraction<T>::operator+(Fraction f)
{
    T num = numerator * f.denominator + f.numerator * denominator;
    T den = denominator * f.denominator;
    return Fraction(num, den);
}
// 重载"-" 实现
template<class T>
Fraction<T> Fraction<T>::operator-(Fraction f)
{
    T num = numerator * f.denominator - f.numerator * denominator;
    T den = denominator * f.denominator;
    return Fraction(num, den);
}
// 重载"*" 实现
template<class T>
Fraction<T> Fraction<T>::operator*(Fraction f)
{
    T num = numerator * f.numerator;
    T den = denominator * f.denominator;
    return Fraction(num, den);
}
// 重载"/" 实现
template<class T>
Fraction<T> Fraction<T>::operator/(Fraction f)
{
    // 如果除数为0则抛出DIVBYZERO异常
    if(f.numerator == 0)
        throw DIVBYZERO();
    T num = numerator * f.denominator;
    T den = denominator * f.numerator;
    return Fraction(num, den);
}
//输出分数
template<class T>
void Fraction<T>::print()
{
    cout << " " << numerator << "/" << denominator << " ";
}
//测试
int main()
{
    try
    {
        Fraction<int> f1(3,8), f2(1,4);
        Fraction<int> f3 = f1 + f2;
        Fraction<int> f4 = f1 - f2;
        Fraction<int> f5 = f1 * f2;
        Fraction<int> f6 = f1 / f2;
        cout << "f1:"; f1.print(); cout << endl;
        cout << "f2:"; f2.print(); cout << endl;
        cout << "f1+f2:"; f3.print(); cout << endl;
        cout << "f1-f2:"; f4.print(); cout << endl;
        cout << "f1*f2:"; f5.print(); cout << endl;
        cout << "f1/f2:"; f6.print(); cout << endl;
        Fraction<double> f7(3.2, 1.5), f8(0, 4);
        Fraction<double> f9 = f7 + f8;
    }
    catch(DIVBYZERO &e)
    {
        cout << e.what() <<endl;
    }
    return 0;
~~~`
代码上注释已经比较详细了,主要实现了以下功能:
1. 自定义除数为 0 异常(DIVBYZERO)。
2. 分别用构造函数和 setter 方法对分子和分母进行初始化,并提供 getter 方法获取成员变量值。
3. 实现基本分数运算符重载( + , - , \* , / )。
4. 实现分数的输出功能。
在测试程序中,我们创建了两个不同数据类型的分数类(int 型和 double 型),并对其+、-、\*、/四种运算符进行了使用。同时,也考虑到了除数为 0 时抛出错误处理。
目录
相关文章
|
1月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
94 10
|
1月前
|
编译器 程序员 C++
【C++打怪之路Lv7】-- 模板初阶
【C++打怪之路Lv7】-- 模板初阶
16 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
41 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
1月前
|
算法 编译器 C++
【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧
【C++篇】领略模板编程的进阶之美:参数巧思与编译的智慧
79 2
|
1月前
|
存储 编译器 C++
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
38 2
|
1月前
|
存储 算法 编译器
【C++】初识C++模板与STL
【C++】初识C++模板与STL
|
1月前
|
编译器 C++
【C++】模板进阶:深入解析模板特化
【C++】模板进阶:深入解析模板特化
|
7天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
33 4
|
8天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
28 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4