重载运算符问题与加法

overloading operators issue with addition

添加 objects 时遇到问题。添加两个时似乎有效,例如:2.34 + 34.57 = 36.81,但添加 3 个或更多时失败,例如:6.78 + 9.81 + 4.59 = 79.59 <- 由于某种原因,总数似乎急剧增加。

可以忽略转换器函数,因为它们只是将数字总数转换为英文格式并且可以正常工作。中位数和排序以及 > 函数也能正常工作,因此问题可能出在 ostream、istream 或 + 函数中的某个地方。我在很多地方都使用了 cout,大多数异常数字似乎都出现在 + 函数中。

提前致谢。

Header:

#ifndef LAB2_H
#define LAB2_H 
#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

class DollarAmount
{
    double dollar = 0.00;
    double cents = 0.00;
    double avg = 0.00;
    int maxsequence = 0;
    string number;
    public:

        DollarAmount(double num1 = 0, double num2 = 0);

        double getavg() const { return avg; };

        double getDollar() const { return dollar; };

        double getCent() const { return cents; };

        int getmaxsequence() const { return maxsequence; };

        friend istream& operator >> (istream& ins, DollarAmount& arg);

        friend ostream& operator << (ostream& out, const DollarAmount& arg);

        friend DollarAmount operator + (const DollarAmount& arg1, const DollarAmount& arg2);

        friend bool operator > (const DollarAmount& arg1, const DollarAmount& arg2);

        void sortobjects(DollarAmount a[], int length);

        void median(DollarAmount a[], int length);

        //All of the below functions are from lab 1

        void converter1(string array1[], string array2[], string array3[], double m);

        void converter2(double n);

函数:

#include <iostream>
#include <string>
#include <cstdlib>
#include "lab2.h"

using namespace std;


DollarAmount::DollarAmount(double num1, double num2)
{

    dollar = num1;
    cents = num2;

}

istream& operator >> (istream& ins, DollarAmount& arg)
{
    double num1 = 0.00;
    double num2 = 0.00;
    //int num1 = 0;
    //int num2 = 0;
    char ch;
    string s;
    double num3;
    bool wrongInput = false;

   //ins >> num1 >> ch >> num2;
    ins >> num3;
    s = to_string(num3);
    arg.number = s;
    int index = s.find(".");
    num1 = atof(s.substr(0, index).c_str());
    num2 = atof(s.substr(index, 3).c_str()); 

    do
    {
        if (wrongInput == true)
        {
            cout << "Enter the expenditure record (e.g., .95, coffee, enter -1 to end):$";
            ins >> num1 >> ch >> num2;
        }

        else if (cin.fail() || num1 < 0 || num1 > 9999 || num2 > 99) //in case the above fails, e.g., ten dollor five cents...
        {
            cout << "Wrong input types. Try again:\n";
            cin.clear(); //clear the error flags in cin 
            cin.ignore(2048, '\n'); //ignore everthing in the input buffer, up to 2048 char, 
            //up to the newline char =< ignore the rest of the line
            wrongInput = true;
        }
        else
            wrongInput = false;
    } while (wrongInput == true || num1 < 0 || num1 > 9999 || num2 > 99); // if input false ask for input again

    arg.dollar = num1;
    arg.cents = num2;
    arg.maxsequence = arg.getmaxsequence() + 1;
    return ins;
}

ostream& operator << (ostream& out, const DollarAmount& arg)
{
    out << arg.getDollar() + arg.getCent();
    return out;
}

DollarAmount operator + (const DollarAmount& arg1, const DollarAmount& arg2)
{
    DollarAmount temp;
    double sum = 0.00;
    double x = 0.00;
    double y = 0.00;
    string z;

    temp.dollar = 0.00;
    temp.cents = 0.00;

    x = arg1.dollar + arg1.cents;

    y = arg2.dollar + arg2.cents;
    sum = x + y;
    cout << "This is the sum: " << sum << endl;

    z = to_string(sum);
    int index = z.find(".");

    temp.dollar = atof(z.substr(0, index).c_str());
    temp.cents = atof(z.substr(index + 1, 2).c_str());
    cout << "This is the dollar: " << temp.getDollar() << endl;
    cout << "This is the cents: " << temp.getCent() << endl;

    return temp;
}

bool operator > (const DollarAmount& arg1, const DollarAmount& arg2)
{
    DollarAmount temp;
    double x, y;

    x = arg1.dollar + arg1.cents;

    y = arg2.dollar + arg2.cents;

    if (x > y)
        return true;
    else
        return false;
}

void DollarAmount::sortobjects(DollarAmount a[], int length)
{
    int i;
    int last = length - 1;  //point to the index of last element in unsorted part of the array 

    for (int pass = 0; pass < length; pass++)
    {
        //a[0]...a[last] is not sorted 
        //repeated bubble the largest element in this range to the end ... 
        for (i = 0; i <= last - 1; i++)
        {
            if (a[i] > a[i + 1])
            {
                //swap 
                DollarAmount tmp;
                tmp = a[i + 1];
                a[i + 1] = a[i];
                a[i] = tmp;
            }
        }
        //at this point, the largest element in a[0...last] is stored in a[last]

        //unsorted part is now a[0...last-1]
        last = last - 1;
    }
}


void DollarAmount::median(DollarAmount a[], int length)
{
    DollarAmount temp;
    int mid;
    double average = 0.00;
    double x = 0.00;
    double y = 0.00;

    if (length % 2 == 0)
    {
        mid = length / 2;
        int test = mid - 1;
        x = a[mid].dollar + a[mid].cents;
        y = a[test].dollar + a[test].cents;
        average = (x + y) / 2.00;
        temp.avg = average;
        cout << temp.getavg();
    }
    else
    {
        mid = length / 2;
        x = a[mid].dollar + a[mid].cents;
        average = x;
        temp.avg = average;
        cout << temp.getavg();
    }

}

void DollarAmount::converter1(string array1[], string array2[], string array3[], double m)
{
    string a;
    string b;
    string c;
    string d;
    int num1 = 0;

    d = to_string(m);
    int index = d.find(".");
    int x = atoi(d.substr(0, index).c_str());

    if (x < 100)
    {

        if (x > 0 && x < 10)
        {
            a = array1[x - 1];
            cout << a;
        }

        else if (x == 10)
        {
            a = array2[0];
            cout << a;
        }

        else if (x > 10 && x < 20)
        {
            a = array2[x - 10];
            cout << a;
        }

        else if (x == 20)
        {
            a = array3[0];
            cout << a;
        }

        else if (x > 20 && x < 30)
        {
            num1 = x - 20;
            b = array3[0];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 30)
        {
            a = array3[1];
            cout << a;
        }

        else if (x > 30 && x < 40)
        {
            num1 = x - 30;
            b = array3[1];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 40)
        {
            a = array3[2];
            cout << a;
        }

        else if (x > 40 && x < 50)
        {
            num1 = x - 40;
            b = array3[2];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 50)
        {
            a = array3[3];
            cout << a;
        }

        else if (x > 50 && x < 60)
        {
            num1 = x - 50;
            b = array3[3];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 60)
        {
            a = array3[4];
            cout << a;
        }

        else if (x > 60 && x < 70)
        {
            num1 = x - 60;
            b = array3[4];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 70)
        {
            a = array3[5];
            cout << a;
        }

        else if (x > 70 && x < 80)
        {
            num1 = x - 70;
            b = array3[5];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 80)
        {
            a = array3[6];
            cout << a;
        }

        else if (x > 80 && x < 90)
        {
            num1 = x - 80;
            b = array3[6];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }

        else if (x == 90)
        {
            a = array3[7];
            cout << a;
        }

        else
        {
            num1 = x - 90;
            b = array3[7];
            a = array1[num1 - 1];
            cout << b << " " << a;
        }
    }

    else if (x < 1000)
    {
        if (x == 100)
        {
            a = array1[0] + " hundred ";
            cout << a;
        }

        else if (x == 200)
        {
            a = array1[1] + " hundred ";
            cout << a;
        }

        else if (x == 300)
        {
            a = array1[2] + " hundred ";
            cout << a;
        }

        else if (x == 400)
        {
            a = array1[3] + " hundred ";
            cout << a;
        }

        else if (x == 500)
        {
            a = array1[4] + " hundred ";
            cout << a;
        }

        else if (x == 600)
        {
            a = array1[5] + " hundred ";
            cout << a;
        }

        else if (x == 700)
        {
            a = array1[6] + " hundred ";
            cout << a;
        }

        else if (x == 800)
        {
            a = array1[7] + " hundred ";
            cout << a;
        }

        else if (x == 900)
        {
            a = array1[8] + " hundred ";
            cout << a;
        }

        else
        {
            // a + "hundred + b + c
            num1 = x / 100;
            a = array1[num1 - 1];
            cout << a << " hundred ";
            converter1(array1, array2, array3, (x % 100));
        }
    }

    else
    {
        if (x == 1000)
        {
            a = array1[0] + " thousand";
            cout << a;
        }

        else if (x == 2000)
        {
            a = array1[1] + " thousand";
            cout << a;
        }

        else if (x == 3000)
        {
            a = array1[2] + " thousand";
            cout << a;
        }

        else if (x == 4000)
        {
            a = array1[3] + " thousand";
            cout << a;
        }

        else if (x == 5000)
        {
            a = array1[4] + " thousand";
            cout << a;
        }

        else if (x == 6000)
        {
            a = array1[5] + " thousand";
            cout << a;
        }

        else if (x == 7000)
        {
            a = array1[6] + " thousand";
            cout << a;
        }

        else if (x == 8000)
        {
            a = array1[7] + " thousand";
            cout << a;
        }

        else if (x == 9000)
        {
            a = array1[8] + " thousand";
            cout << a;
        }

        else
        {
            //a + "thousand" + b + "hundred" + c + d
            num1 = x / 1000;
            a = array1[num1 - 1];
            cout << a << " thousand ";
            converter1(array1, array2, array3, (x % 1000));
        }
    }
}


void DollarAmount::converter2(double n)
{
    cout << n << "/100)" << endl;

}

主要:

#include <iostream>
#include <string>
#include <cstdlib>
#include "lab2.h"

using namespace std;

const int INIT_SIZE = 10;
const int a = 9;
const int b = 10;
const int c = 8;

int main()
{
    string one[a] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
    string two[b] = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
    string three[c] = { "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety" };

    DollarAmount* arr = new DollarAmount[INIT_SIZE];
    DollarAmount* ptr = NULL;
    int avg = 0;
    int arr_size = INIT_SIZE;
    int arr_len = 0; // actual number of objects stored in it , also the index
      // of next free slot in arr

    bool lastInput = false;

    do 
    {
        if (arr_len == arr_size)
        { // the array is full, need to grow! 

           //allocate an array double the cur_size
            ptr = new DollarAmount[arr_size * 2];

            //copy each element in arr into the new array that ptr points to... 
            // Todo: please figure out how to do this...(hint: use a for loop)
            for (int i = 0; i < arr_size; i++)
            {
                ptr[i] = arr[i];
            }

            //now we delete the current arr
            delete[] arr;
            arr = ptr;
            arr_size = arr_size * 2;
        }

        cout << "Enter the expenditure record (e.g., .95, coffee, enter 0.0 to end):$";
        cin >> arr[arr_len];  //read in a dollar amount from cin we will allow input such as 0.0

        //If the last read dollar amount is 0.0, then it's the end 
        if (arr[arr_len].getDollar() == 0 && arr[arr_len].getCent() == 0)
            lastInput = true;
        else //we only increment arr_len for input that's not 0.0
            arr_len++;


    } while (lastInput == false);

    DollarAmount total, temp, loopingtotal;


    total = arr[0] + arr[1];
    //cout << "The first total: " << total << endl;
    //cout << "This is sum of first two: " << total;

    //A loopt to add all DollarAmount up, and display the total 

    for (int i = 2; i < arr_len; i++)
    {
        total = total + arr[i];
        cout << "The total for this " << i << " time is: " << total << endl;
    }
    //cout << "This is the sum after loop " << total;

    //Call Sort function to sort the array of DollarAmount 
    temp.sortobjects(arr, arr_len);
    //Display the sorted array, and the median 
    cout << "Sorted list of expenditure:" << endl;
    for (int i = 0; i < arr_len; i++)
    {
        cout << arr[i] << endl;
    }

    //cout << "This is the total cents: " << total.getCent();
    //cout << "This is the total dollar: " << total.getDollar();
    cout << "The total is $" << total.getDollar() << "." << total.getCent();
    cout << " (";
    temp.converter1(one, two, three, total.getDollar());
    cout << " and "; 
    temp.converter2(total.getCent());
    cout << "The median is ";
    temp.median(arr, arr_len);
    cout << "." << endl;
    cout << "Bye!";
    return 0;
}

TL;DR - 让你的 class 尽可能简单,以充分代表一件事。输入验证可能是一个兔子洞,所以只需担心您当前的要求即可。在 class 之外进行所有计算(因为它不相关)。

您比需要更加努力地工作。首先,你的 class 很乱。 class 应该有一个单一的目的,我很清楚你的没有。

从钱开始 class:

class Money {
public:
    Money() = default;
    Money(int d, int c)
        : cents_m(d * 100 + c)
    {
    }
    inline int dollars() const { return cents_m / 100; }
    inline int cents() const { return cents_m % 100; }
    friend std::istream& operator>>(std::istream& sin, Money& obj);
    friend std::ostream& operator<<(std::ostream& sout, const Money& obj);
    friend const Money operator+(const Money& lhs, const Money& rhs);

private:
    int cents_m = 0;
};

排除所有多余的数学垃圾,它不属于 Money class。它属于您需要将这种工作作为函数完成的任何地方。请注意,您现在只存储美分,而不是分开的美元和美分。 5 美元是 500 便士,这使得所有简单的货币计算变得更容易 很多。如果您处理利率和股票交易,那么您会关心几分钱,但我猜您在这里不关心。

我正在利用一些 C++11 功能,例如默认成员初始化和 defaulting 默认构造函数,现在 cents_m 已为我默认初始化。我也在使用初始化部分,你也应该使用。

为了展示货币数学变得多么简单,这里是 operator+() 函数:

const Money operator+(const Money& lhs, const Money& rhs)
{
    int sum = lhs.cents_m + rhs.cents_m;

    return Money(sum / 100, sum % 100);
}

以下是其他运算符:

std::istream& operator>>(std::istream& sin, Money& obj)
{
    std::string tmp;
    std::getline(sin, tmp);
    if (!(tmp.length() > 0)) {
        obj = Money();
        return sin;
    }

    if (tmp[0] == '$') {
        tmp = tmp.substr(1);
    }

    std::size_t location;
    double value = std::stod(tmp, &location);
    if (location != tmp.length()) {
        obj = Money();
    } else {
        int cents = std::lround(value * 100);
        obj = Money(cents / 100, cents % 100);
    }

    return sin;
}

std::ostream& operator<<(std::ostream& sout, const Money& obj)
{
    bool isNegative = obj.cents_m < 0;
    std::string tmp;
    int dollars = abs(obj.cents_m / 100);
    int cents = abs(obj.cents_m % 100);

    if (isNegative) {
        tmp += "(";
    }
    tmp += ("$" + std::to_string(dollars) + ".");
    if (cents < 10) {
        tmp += ("0" + std::to_string(cents));
    } else {
        tmp += std::to_string(obj.cents_m % 100);
    }
    if (isNegative) {
        tmp += ")";
    }

    return sout << tmp;
}

注意事项:输入流运算符重载可以解释输入的“$”(但仅作为第一个字符),但它可能无法解释负数钱(因为必须输入 $-3.50,但没有人这样做)。输入验证并不简单,你走多远取决于你的老师的要求。我承认我的代码很容易在一些无效输入下崩溃,因为我不想变得非常全面(而且我们仍然只谈论 ASCII)。

我还选择简单地让 Money 对象在我检测到的几个无效输入上存储默认值。运算符重载中带有循环的错误消息是个坏主意(这不是这些运算符对其他任何事物的行为方式;重载应该按预期运行)。要么在后台处理错误,要么抛出异常。这是一个个案的决定,我认为在这种情况下可以默默地处理这个问题。

如果允许您假设始终输入有效数字,则运算符重载会变得非常简单。

流输出运算符重载至少可以打印负货币。

这里有一个简短的主要功能来测试金钱 class:

int main()
{
    Money one(6, 78);
    Money two(9, 81);
    Money thr(4, 59);

    std::cout << (one + two + thr) << '\n';

    Money fou;
    std::cout << "Give me some money: ";
    std::cin >> fou;
    std::cout << "You only gave me " << fou << "?\n";
}

一些一般性建议:在处理编程问题时,您应该做的第一件事是很少编写代码。思考它,想象它,用你自己的话写出需求,并思考你将如何解决它(不是用代码,而是你需要采取的实际步骤)。代码是工具,不是解决方案。