使用类和函数的C ++分数计算器

时间:2018-01-15 03:46:00

标签: c++ function class

我是StackOverflow的新手,从一所新学校开始。我希望对任务有一些指导。赋值是计算涉及两个分数的表达式,并输出结果。我已经用我的教科书中的知识工作了几天这个程序,但我想我仍然对如何在一个类中实现函数感到困惑。我知道我想用我的价值做什么,但我很困惑在哪里分配它们。我尝试读取我的值,但在输出时,我得到了垃圾。任何帮助将不胜感激。

  #include <iostream>
  using namespace std;
  class fraction                                        // Fraction class definition
  {
int num,
    den;
public:
fraction()                                      // default constructor
{
    num = 0;
    den = 1;
}
void add(fraction f1, fraction f2)                  // addition fcn
{
    num = (f1.num*f2.den) + (f2.num*f1.den);
    den = f1.den*f2.den;
}
void subtract(fraction f1, fraction f2)             // subtraction fcn
{
    num = (f1.num*f2.den) - (f2.num*f1.den);
    den = f1.den*f2.den;
}
void multiply(fraction f1, fraction f2)     // multiplying fcn
{
    num = f1.num*f2.num;
    den = f1.den*f2.den;
}
void divide(fraction f1, fraction f2)           // dividing fcn
{
    num = f1.num*f2.den;
    den = f1.den*f2.num;
}
void output()
{
    cout << num << "/" << den << endl;
}
};                                      // end Fraction class 


int main()
{                                   // begin main
    fraction result;
    fraction n;
    fraction d;
    int n1, n2, d1, d2 = 0;
    char op;
    cout << "Please enter an expression containing two fractions:" << endl;
    cin >> n1 >> d1 >> op >> n2 >> d2;

    switch (op) 
    {                                               // begin switch
    case '+':
        result.add(n, d);
        result.output();
        break;
    case '-':
        result.subtract(n, d);
        result.output();
        break;
    case '*':
        result.multiply(n, d);
        result.output();
        break;
    case'/':
        result.divide(n, d);
        result.output();
        break;
    }                                               // end switch

    //fraction f1(n1, d1);
    //fraction f2(n2, d2);



}                                   // end main

1 个答案:

答案 0 :(得分:1)

实际答案在John3136的第一条评论中给出。因此,我有点挣扎,但终于意识到你可能没有认识到。所以,我会详细说明一下:

main()中,您可以这样做:

int n1, n2, d1, d2 = 0;
char op;
cout << "Please enter an expression containing two fractions:" << endl;
cin >> n1 >> d1 >> op >> n2 >> d2;

通过调试器逐步执行,您将意识到这部分程序按预期工作。输入例如

之后
1 2 + 3 4

变量将显示以下值:

n1: 1
d1: 2
n2: 3
d2: 4
op: '+'

ideone

上的现场演示

进一步步进,程序指针将移至

result.add(n, d);

嗯。您想要添加nd,但调试器会说:

n: { num: 0, den: 1 }
d: { num: 0, den: 1 }

n.numn.dend.numd.den的值在那里,因为您提供了class fraction的默认构造函数,它正好影响了这一点。< / p>

那么,您如何将n1移至n.numd1转移到n.den,等等?

真正缺少的是class fraction加载成员numden的构造函数(在这种情况下为nd)具有指定的值。

您可以引入第二个构造函数。在这种情况下,您可以修改(和扩展)现有的,也包括:

class fraction {

  private:
    int num, den; // numerator, denominator

  public:

    explicit fraction(int num = 0, int den = 1): num(num), den(den) { }

};
看起来很混乱?我会解释一下:

  1. 我给出了构造函数参数,但参数有默认值。 因此,它仍然可以用作默认构造函数。执行fraction a;将像以前一样构造分数0/1。但是,现在,您也可以fraction b(3, 2);来构建3/2分数。你甚至可以做fraction d(3);。这将构建对我来说合理的分数3/1。

  2. 我将参数命名为成员。看起来很有趣,可能有点令人困惑,但现在似乎很平常。 (实际上,我在很短的时间内就已经学到了这一点。)但是,编译器会正确理解这一点(即使它是MS的一个)。

  3. 我使用explicit为构造函数添加了前缀。这可以防止构造函数用于隐式转换。 explicit,以下内容也适用:fraction c; c = 1;,即从class fraction分配int。这是一个设计问题,是否要支持这一点。隐式转换可能非常方便,但编译器可能会在您不期望它的地方应用它。我个人习惯于制作几乎所有构造函数explicit,因为我不想“失去控制”#34;编译器正在做什么。

  4. 按照建议修改上述构造函数,然后可以使用您的类,例如:

    fraction a(3, 2), b(1, 2);
    fraction result; result.add(a, b);
    result.output();
    

    现在,它应该打印分数ab的总和。

    最后一点:

    我认为O&#Neil's暗示运营商超载基本上是合理的。您将在SO中找到代码示例的答案。 (其中一些,由我写。);-)另一方面,运算符重载只是另一个障碍。我不会为此烦恼太多。 (可能是第二个版本......)

    最后,我做了一个MCVE来演示上面提到的示例代码:

    #include <iostream>
    using namespace std;
    
    class fraction {
    
      private:
        int num, den; // numerator, denominator
    
      public:
    
        explicit fraction(int num = 0, int den = 1): num(num), den(den) { }
    
        void add(fraction f1, fraction f2) // addition fcn
        {
          num = (f1.num * f2.den) + (f2.num * f1.den);
          den = f1.den * f2.den;
        }
    
        void output() { cout << num << "/" << den << endl; }
    };
    
    int main()
    {
      fraction a0;
      cout << "fraction a0: "; a0.output();
      fraction a(3, 2), b(1);
      cout << "fraction a(3, 2): "; a.output();
      cout << "fraction b(1): "; b.output();
      fraction c; c.add(a, b);
      cout << "fraction c = a + b: "; c.output();
      // assignment (using default assignment operator)
      fraction d; d = c;
      cout << "faction d = c; d: "; d.output();
    #if 0 // disabled code
      // This will work only if constructor is not explicit:
      fraction e = 1; e = 1;
      cout << "fraction e; e = 1; e: "; e.output();
    #endif // 0
      // fraction from input
      int n1, n2;
      cout << "Input n1 n2: "; cin >> n1 >> n2;
      fraction in(n1, n2);
      cout << "fraction in(n1, n2): "; in.output();
      // done
      return 0;
    }
    

    输入:

    123 321
    

    输出:

    fraction a0: 0/1
    fraction a(3, 2): 3/2
    fraction b(1): 1/1
    fraction c = a + b: 5/2
    faction d = c; d: 5/2
    Input n1 n2: fraction in(n1, n2): 123/321
    

    ideone上的现场演示。

    在阅读完您的评论之后,我怀疑您是否已经理解了class和成员函数的概念。我会尽我所能:

    您是否知道您的功能add()会员功能?正如您在class fraction中定义的功能一样。这意味着,如果没有对象(即add()的实例),则无法调用fraction

    如果将此内容写入main()函数,则会出现编译错误:

    fraction a, b;
    fraction::add(a, b);
    

    ideone

    上的现场演示

    该对象是另一个参数,即(非static)成员函数(如fraction::add())的调用迫切需要。可能是,你没有认识到点前面的东西是函数参数,但确实如此。

    fraction c; c.add(a, b);
    /*          ^     ^  ^
     *          |     |  +--- 2nd argument
     *          |     +------ 1st argument
     *          +------------ object (which becomes THE this POINTER inside fraction::add())
     */
    

    因此,fraction.add()实际上有三个参数。那么,如何访问该对象?为此,C ++提供了一个特殊的关键字thisthis是一个指向class的指针,它提供了一个指向已为其调用成员函数的对象的指针。使用this,您可以访问此类的所有(其他)成员 - 成员变量以及成员函数。

    (几十年前,当我试图自己理解C ++和OOP是如何工作的时候,我看了一下编译后的汇编代码。我真的很惊讶地发现dot之前的对象就像其他参数一样处理完全在括号中。这是我个人的Heureka!-moments之一。)

    可以在具有this->的成员函数内部对(同一类的)成员进行访问,但是如果适用的话,编译器可以将其静默添加。

    您的会员功能fraction::add()实际上是对此的证明。 它有两个参数f1f2,处理其成员(f1.numf1.denf2.numf2.den)以执行添加分数,并存储分配。导致成员变量numden。在这种情况下,numthis->num相同,denthis->den相同。那么,this指向哪里?这取决于调用成员函数的对象。例如:

    result.add(n, d);
    

    fraction::add()内,this将指向result