【问题标题】:Triangle , C++ construction, problem with calculating angles三角形,C++ 构造,计算角度的问题
【发布时间】:2018-11-06 16:50:26
【问题描述】:

我的作业有问题。

1) 我应该用输入 a、b 和 c 编写函数 SSS。我需要输出 alpha、beta 和 gamma。

2) 我应该用输入 a、b 和 gamma 编写函数 SWS。而且我需要输出 c、alpha 和 beta。

这是我的代码:

#include <iostream>
#include <cmath>
#include <math.h>
#include <cstdio>

using namespace std;

double SSS_alpha(double a, double b, double c){

    int bot1 = -2*b*c;
    if(bot1==0.0){
        return 0.0;
    }

    double alpha = acos((a*a-b*b-c*c)/bot1);
    const double rad = 0.5729577951308232088;
    return alpha*rad;

}

double SSS_beta(double a, double b, double c){

    double bot2 = -2*c*a;
    if(bot2==0.0){
        return 0.0;
    }

    double beta = acos((b*b-c*c-a*a)/bot2);
    const double rad = 0.5729577951308232088;
    return beta*rad;
}

double SSS_gamma(double a, double b, double c){

    double bot3 = -2*b*a;
    if(bot3==0.0){
        return 0.0;
    }

    double gamma = acos((c*c-a*a-b*b)/bot3);
    const double rad = 0.5729577951308232088;
    return gamma*rad;
}


double WSW_seite_c(double a, double b, double gamma){
    double c_1 = (a*a+b*b-2*a*b*cos(gamma));
    double c = sqrt(c_1);
    return c;

}



int main(){
    cout << SSS_alpha(5.0, 7.0, 8.0)<<endl;
    cout <<SSS_beta(5.0, 7.0, 8.0)<<endl;
    cout <<SSS_gamma(5,7,8)<<endl;
    cout <<"Seite c: "<<WSW_seite_c(5, 7, 0.81)<<endl;

}

我只能在一个函数中返回一个参数。我有很多任务 1 的功能:对于 alpha,对于 beta,对于 gamma。而且我不知道如何在一个函数中编写它。我只写了一个函数来查找任务 2 的 c。

我是 C++ 新手。如果你能帮助我,我会很高兴。:)

【问题讨论】:

  • 您可以在struct 中分组一些值。然后传递对该struct 的引用。在函数内部,您可以更改这些结构值。
  • @Ripi2 这是个好主意,但为什么不直接从函数中返回结构(作为返回值)呢?
  • @Rulle。您的想法也是有效的,例如当您不想更改原始结构时。
  • 请逐字引用您的作业。 “输出”可能意味着您的函数应该打印这些结果而不是返回它们。

标签: c++ triangle-count


【解决方案1】:

按照建议返回结构或使用类 Triangle 是完美的解决方案,这是我通常使用的。

但是,在一些简单的情况下,通过一个元组返回多个值可能非常方便。
我在下面展示了一个简单的“工作”示例。
请注意,对于超过 3 个返回对象,我通常会避免这种解决方案,以避免混淆。

#include    <iostream>
#include    <tuple>
std::tuple<double, double, double> f(double x, double y){
    double a = x;
    double b = x+y;
    double c = x-y;
    return std::make_tuple(a, b, c);
}
int main() {
    double a, b, c;
    std::tie (a, b, c) = f (1.0, 2.0);
    std::cout << "a = " << a << "\n";
    std::cout << "b = " << b << "\n";
    std::cout << "c = " << c << "\n";
    return 0;
}

我希望代码是自我解释的。
可以使用 C++17 简化语法。我没有使用这些简化,因为我当前的编译器不兼容!
这种方法可以与结构一结合,因为可以通过一个元组返回多个结构。

编辑:我刚刚看到 NathanOliver 已经在评论中提到了元组的可能性......

【讨论】:

    【解决方案2】:

    首先,如果包含 iostream,则不需要 cstdio,最好在 C++ 中使用,因为 cstdio 只是迁移到 C++ 的 C 库。

    至于您的问题,听起来您需要按值传递变量。您最喜欢的 C++ 书籍应该告诉您,在某些情况下,您需要“返回”多个值。在这种情况下,您可以传递指针(C 风格)或更安全的对函数的引用,这些函数类似于指针。

    所以你实际上会这样定义你的函数:

    void SSS(double a, double b, double c, double & alpha, double & beta, double & gamma);
    

    或者如@Ripi2 所述,将值打包到struct 中并返回该类型的值:

    /* Thanks to NathanOliver in the comments */
    struct Values {
        double a;
        double b;
        double c;
    };
    
    Values SSS(double a, double b, double c) {
        Values values;
        /* Do stuff */
        return values;
    }
    

    【讨论】:

    • 输出参数是一种反模式。它们强制您在调用函数之前声明返回值,您可能会错过非常方便的优化,例如 RVO 和 NRVO。如果你需要返回多个对象,你应该通过结构/类/对/元组返回
    • @NathanOliver 我同意这一点。我相信使用输出参数是(错误的?)相信您将通过避免将结果复制到堆栈或类似的东西来避免额外的复制操作。但是编译器通常足够聪明,可以优化它……至少对于简单的值。
    • @NathanOliver “他们强迫你在调用函数[...]之前声明返回值”是什么意思?因为声明函数时变量有固定类型?
    • 要调用void SSS(double a, double b, double c, Values &amp; values);我必须做Values values; SSS(a, b, c, values);(必须声明一个未初始化的对象才能将它传递给函数)而不是能够做Values values = SSS(a, b, c);
    • 另外,struct 不是数组
    【解决方案3】:

    struct 将是做你想做的最简单的方法。您也可以创建一个类,但这可能是家庭作业的过度解决方案(它们基本上是相同的,但请参阅我的评论线程以了解我对此事的看法)。

    结构声明是这样的:

    struct containerName
    {
        int val_a;
        double val_b;
        //and so on : you put what ever you need
    }
    

    结构体基本上变成了一种你可以使用的类型,就像intdoublebool 等。

    Here's a nice reading on struct 以及如何使用它

    【讨论】:

    • A structclass,它们只是具有不同的默认访问权限指定。任何可以使用struct的地方也可以使用class
    • 在 C++ 中,类是一个结构,而不是相反。在 C++ 中实现类之前,结构体可以在 C 中使用
    • @Sirmyself 不是 C-Struct 意义上的。在 C 中,结构只能包含数据成员并且没有任何访问说明符。在 C++ 中出现了类,C++ 结构与 C++ 类相同。
    • @Sirmyself 他们是一回事。两者都可以有构造函数,都可以有成员函数,都可以是多态的。没有区别,除了默认的访问说明符。
    • 无论如何,这基本上是正确的,并且可能过于哲学化而与此答案无关。对我来说,一个类有函数声明,而结构没有。 (我知道我们可以在结构中拥有函数,但我个人更喜欢这样看)
    【解决方案4】:

    是的,你只能从一个函数中返回一个对象。但是你可以让它返回一个复合对象,比如结构或类。传统上,您将结构用于仅数据对象,因为它们在 C 中就是如此。

    struct Triangle
    {
        double a;
        double b;
        double c;
    };
    

    然后你可以从一个函数返回一个Triangle 对象。并以这种方式访问​​其成员:

    Triangle tri1;     // first, create an instance of the struct
    tri1.a = 5.0f;      // assign a value to a member
    

    为您的数据类型选择有意义的名称(就像使用变量一样)并始终设计数据类型以表示它们的名称是一种很好的做法。


    为了使代码更具表现力,您可以使用更面向对象的方法进一步改进。您可以给数据类型Triangle 提供计算其角度的成员函数,以便您可以“询问”Triangle 它的角度是多少。

    (此时您还应该将其命名为类,因为它不再是纯数据结构,但这是约定俗成的问题。在 C++ 中,结构和类几乎相同。)

    class Triangle
    {
        public:
        // everything in this section can be accessed from outside
    
        // this is a constructor. It is a special function that lets you create a Triangle
        Triangle(double pa, double pb, double pc)
            : a(pa), b(pb), c(pc)   // initialize the members
        {}
    
        // getters for the private members (not needed but that way they can't directly be changed)
        double get_a() const
        {
            return a;
        }
        double get_b() const
        {
            return b;
        }
        double get_c() const
        {
            return c;
        }
    
        double alpha() const;
        double beta() const;
        double gamma() const;
        // should be const because they dont change anything about the object
    
        private:   
        // the default access for classes, everything in this section can only be accessed by member functions
    
        double a;
        double b;
        double c;
    };
    
    // member function definitions outside of class declaration
    double Triangle::alpha() const
    {
        // calculate and return alpha...
    }
    double Triangle::beta() const
    {
        // calculate and return beta...
    }
    double Triangle::gamma() const
    {
        // ...
    }
    

    你可以这样使用这个类:

    int main()
    {
        // create a Triangle by calling the constructor
        Triangle tri1(5.0, 7.0, 8.0);
        std::cout << "Alpha: " << tri1.alpha() << std::endl;
        std::cout << "Beta: " << tri1.beta() << std::endl;
        std::cout << "Gamma: " << tri1.gamma() << std::endl;
        return 0;
    };
    

    【讨论】:

    • 构造函数基本上是用来初始化一个类的所有成员的函数。可能让您感到困惑的是初始化列表,这是: a(pa), b(pb), c(pc) 的这一部分。这对于构造函数来说是特殊的,基本上只是直接将值放入成员中。构造函数还有一个主体({} curly brats),它与任何其他函数主体一样。
    • 对于您的第二个任务,我将编写一个独立函数,它只将边 a 和 b 以及角度 gamma 作为输入,并返回一个所有边都已初始化的三角形。您也可以将该函数编写为 Triangle 的构造函数,但这需要您首先引入“TriangleSide”和“Angle”的类型,因为如果您调用具有 3 个双精度值(a、b 和 gamma)的构造函数,编译器将不会知道你是想调用构造函数取 3 边还是取 2 边和角度的构造函数。
    • 谢谢,我选择了 2 个边和一个角度 gamma。而且我认为效果很好
    • tri1 是 Triangle 对象的名称。 Triangle name; 创建一个名为nameTriangle 类型的对象,该对象未初始化,就像intdouble 等其他类型一样。当你想初始化它时,你必须调用构造函数:Triangle name(5.0, 7.0, 8.0);Triangle name = Triangle(5.0, 7.0, 8.0);是一样的东西)。
    猜你喜欢
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多