проблема перегрузки операторов с добавлением - PullRequest
0 голосов
/ 06 февраля 2020

Проблемы с добавлением объектов. Кажется, что работает при добавлении двух, например: 2,34 + 34,57 = 36,81, но не удается при добавлении 3 или более, например: 6,78 + 9,81 + 4,59 = 79,59 <- по некоторым причинам общее количество резко возрастает. </p>

Функции преобразователя можно игнорировать, поскольку они просто переводят числовую сумму в формат engli sh и работают. Медиана, функции сортировки и> также работают, поэтому проблема может быть в функциях ostream, istream или +. Я использовал cout целую кучу мест, и большинство неправильных чисел, кажется, появляются в функции +.

Заранее спасибо.

Заголовок:

#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., $1.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., $1.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;
}

1 Ответ

0 голосов
/ 06 февраля 2020

TL; DR - Сохраняйте класс максимально простым, чтобы адекватно представлять одну вещь. Проверка ввода может быть кроличьей ношей, так что просто беспокойтесь о ваших текущих требованиях. Делайте всю математику вне класса (потому что это не связано).

Вы работаете усерднее, чем нужно. Во-первых, ваш класс беспорядок. У класса должна быть особая цель, и мне ясно, что у вас ее нет.

Начните с класса Money:

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. Он принадлежит везде, где вам нужна такая работа, выполняемая как функции. Обратите внимание, что вместо отдельных долларов и центов теперь вы храните только центы. 5 долларов - 500 копеек, и это упрощает все простые математические расчеты лот . Если бы вы имели дело с процентными ставками и биржевыми сделками, то вам не безразличны доли копейки, но, полагаю, вам все равно.

Я пользуюсь преимуществами C ++ 11 такие функции, как инициализация элемента по умолчанию и default использование конструктора по умолчанию теперь, когда 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, и никто не делает это). Проверка входных данных не проста, и как далеко от этой кроличьей норы вы go зависит от того, что требует ваш учитель. Я признаю, что мой код легко сломается при некоторых недопустимых входных данных, потому что я не чувствовал, что стал очень полным (и мы все еще говорим только о ASCII).

Я также решил просто сделать объект Money сохранить значения по умолчанию на нескольких неверных входных данных, которые я обнаружил. Сообщение об ошибке с циклами в перегрузке оператора - плохая идея (эти операторы ведут себя не так, как следует; перегрузки должны вести себя так, как ожидается). Либо обработайте ошибку в фоновом режиме, либо сгенерируйте исключение. Это решение в каждом конкретном случае, и я думаю, что молчаливое решение проблемы находится в этой ситуации.

Если вам разрешено предполагать, что всегда вводится правильное число, перегрузка этого оператора становится очень простой.

Перегрузка оператора потокового вывода может как минимум печатать отрицательные деньги.

Вот короткая основная функция для тестирования класса Money:

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";
}

Несколько общих советов: первое, что вы должны сделать при решении проблемы программирования, это редко писать код. Подумайте об этом, визуализируйте это, запишите требования своими словами и подумайте, как бы вы решили это (не с помощью кода, а реальных шагов, которые вам нужно будет предпринять). Код - это инструмент, а не решение.

...