首页 > 解决方案 > 我怎样才能简化这个程序?

问题描述

我正在编写一个程序,该程序使用异常处理来查找二次方程的根,我想知道是否有一种方法可以简化程序,我有一堆用于 catch 案例的空类

// Program to solve quadratic equation
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;


class all_zero{
};

class negative{
};

class zero_division{
};

void roots(double a, double b, double c) throw (all_zero,negative,zero_division);

int main(){
    double a, b, c; // coefficient of ax“2 + bx + c= 0
    cout << "Enter the three coefficients \n";
    cin >> a >> b >> c;

    try
    {
        roots(a, b, c);
    }
    catch(all_zero) {cout << "All values are zero \n";}
    catch(negative) {cout << "Square root of negative values is not defined \n";}
    catch(zero_division) {cout << "Division by zero, not defined \n";}
    return 0;
}

void roots(double a, double b, double c) throw (all_zero,negative,zero_division){
    double x1, x2; // The two roots
    double temp;
    if(!(a== 0 && b== 0 && c==0)){
        if(a != 0){
            temp = b*b - 4*a*c;
            if(temp >= 0){
                x1 =(-b + sqrt(temp))/2*a;
                x2 = (-b - sqrt(temp))/2*a;
                cout << "The two roots are: "<< x1 <<" and " << x2 << endl;
            }else{throw negative();}
        }else{throw zero_division();}
    }else{throw all_zero();}
}

有没有办法可以做到,所以我没有空类或将它们放入结构的方法?

标签: c++exception

解决方案


请注意,您使用的动态异常规范在 C++11 中已弃用,并在 C++17 中删除:

void roots(double a, double b, double c) throw (all_zero,negative,zero_division)
                                      // ^^ 

你可以删除它。


using namespace std;认为是不好的做法


不要std::endl用于添加换行符。std::endl添加一个新行并刷新流。大多数时候这是不必要的。用于'\n'添加换行符。


有没有办法可以做到,所以我没有空类或将它们放入结构的方法?

实际上,我认为为不同类型的异常设置单独的类并没有什么坏处。您的方法的缺点是“什么”在 中catch,而不是异常的一部分或来自异常发生的地方。我将向您展示第一个(消息是类型的一部分),并希望您能看到如何实现后者(消息来自引发异常的位置)。

您可以继承std::runtime_errorwhich 提供的what()方法,该方法返回传递给构造函数的字符串。这也使其他人更容易捕获您的异常,因为std::runtime_error反过来继承自std::excpetionwhich 是所有标准异常的基类:

// Program to solve quadratic equation
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <stdexcept>


struct all_zero : std::runtime_error {
    all_zero() : std::runtime_error("All values are zero") {}
};

struct negative : std::runtime_error {
    negative() : std::runtime_error("Square root of negative values is not defined") {}
};

struct zero_division : std::runtime_error {
    zero_division() : std::runtime_error("Division by zero, not defined") {}
};

void roots(double a, double b, double c);

int main(){
    double a, b, c; // coefficient of ax“2 + bx + c= 0
    std::cout << "Enter the three coefficients \n";
    std::cin >> a >> b >> c;

    try
    {
        roots(a, b, c);
    }
    catch(std::runtime_error& ex) {std::cout << ex.what() << '\n';}
    return 0;
}

void roots(double a, double b, double c) {
    double x1, x2; // The two roots
    double temp;
    if(!(a== 0 && b== 0 && c==0)){
        if(a != 0){
            temp = b*b - 4*a*c;
            if(temp >= 0){
                x1 =(-b + sqrt(temp))/2*a;
                x2 = (-b - sqrt(temp))/2*a;
                std::cout << "The two roots are: "<< x1 <<" and " << x2 << "\n";
            }else{throw negative();}
        }else{throw zero_division();}
    }else{throw all_zero();}
}

现场演示

注意异常应该作为引用被捕获,否则在导出异常时会有对象切片。通常你不知道你会捕获什么类型的异常,你需要小心避免这种情况。

或者,您可以使用更通用的异常类型(roots_exception?),而不是硬编码“什么”,然后将它传递给构造函数throw

您可能还有更多可以改进的地方,为此我建议您https://codereview.stackexchange.com/


PS:我试图将样式放在一边,尽管您应该更改的另一件事是从函数返回结果,而不是仅仅将其打印到屏幕上。如果您想将结果用于目前无法进行的其他计算。也许您对如何返回两个值感到困惑。std::pair很简单:

std::pair<double,double> roots(...) {
      // ...
          return {x1,x2};
}

接着:

try {
   auto result = roots(a,b,c);
   std::cout << "The two roots are: "<< result.first <<" and " << result.second << "\n";
}

推荐阅读