0

I'm new to programming and currently working on an app to assist with managing my home budget. All the data is stored in an XML file. To sort vectors by date, I've implemented a bubble sort algorithm. However, I'm encountering issues with incorrect results. Could someone please provide guidance on identifying the mistake?

#include <iostream>
#include <vector>
#include <string>
#include "Markup.h"

using namespace std;

class income{
    int userId;
    int amount;
    int itemId;
    string item;
    string date;
    public:
    void setUserId(int i) {userId = i;}
    void setAmount(int a) {amount = a;}
    void setItemId(int i ) {itemId = i;} // Corrected function name
    void setDate(string d) {date = d;}
    void setItem(string i) {item = i;}

    int getUserId()   {return userId;}
    int getAmount()   {return amount;}
    int getItemId()  {return itemId;}
    string getItem() {return item;}
    string getDate()  {return date;}
};

bool returnOlderDate(string date1,string date2) {

    int year1 = stoi(date1.substr(0,2));
    int month1 = stoi(date1.substr(3,2)); // Corrected substring indices
    int day1 = stoi(date1.substr(6,2));   // Corrected substring indices

    int year2 = stoi(date2.substr(0,2));
    int month2 = stoi(date2.substr(3,2)); // Corrected substring indices
    int day2 = stoi(date2.substr(6,2));   // Corrected substring indices

    if (year1 != year2) {
        return year1 < year2;
    }
    if (month1 != month2) {
        return month1 < month2;
    }
    return day1 < day2;
}
void sortVector(vector <income> &incomes) {

    int n = incomes.size();

    for (int i = 0; i < n - 1; ++i) {
        for (int j = 0; j < n - i - 1; ++j) {
            if (returnOlderDate(incomes[j].getDate(), incomes[j + 1].getDate())) {

                swap(incomes[j], incomes[j + 1]);
            } else {

            }
        }
    }
}

vector <income> LoadIncome() {

    CMarkup xml;

    vector <income> incomes;
    bool fileExists = xml.Load("income.xml");

    if(!fileExists) {
        cout << "Empty File" << endl;
        return incomes;
    }

    xml.ResetPos();
    xml.FindElem();
    xml.IntoElem();

    while(xml.FindElem()) {
        income newIncome; // Create a new income object
        xml.FindChildElem("userId");// userId
        newIncome.setUserId(stoi(xml.GetChildData())); // Use newIncome instead of income
        xml.FindChildElem("itemId");
        newIncome.setItemId(stoi(xml.GetChildData())); // Use newIncome instead of income
        xml.FindChildElem("amount");
        newIncome.setAmount(stoi(xml.GetChildData())); // Use newIncome instead of income
        xml.FindChildElem("item");
        newIncome.setItem(xml.GetChildData()); // Use newIncome instead of income
        xml.FindChildElem("date");
        newIncome.setDate(xml.GetChildData()); // Use newIncome instead of income
        incomes.push_back(newIncome); // Push newIncome into the vector
    }

    return incomes;
}

void showIncomes(vector <income>& incomes) { // Corrected function declaration

    for(auto i : incomes) {
        cout << "date: " << i.getDate() << endl;
    }
}

int main()
{
    vector <income> incomes; // Corrected vector declaration
    incomes = LoadIncome();

    sortVector(incomes);// Added to show sorted incomes
    showIncomes(incomes);



    return 0;
}

XMl File

<Income>
<income>
<userId>1878039312</userId>
<incomeId>1877999744</incomeId>
<amount>23</amount>
<item>23</item>
<date>02-05-2024</date>
</income>
<income>
<userId>1878039312</userId>
<incomeId>1877999744</incomeId>
<amount>1243</amount>
<item>1243</item>
<date>01-06-2024</date>
</income>
<income>
<userId>1878039312</userId>
<incomeId>1877999744</incomeId>
<amount>1243</amount>
<item>1243</item>
<date>02-03-2023</date>
</income>
<income>
<userId>1878039312</userId>
<incomeId>1877999744</incomeId>
<amount>1243</amount>
<item>1243</item>
<date>28-05-2024</date>
</income>
5
  • 1
    Please try to create a minimal reproducible example to show us, with emphasis on the minimal part. And please edit your question to show it. Commented May 5, 2024 at 10:15
  • 1
    To sort vectors by date, I've implemented a bubble sort algorithm. -- I will be honest with you -- implementing bubble sort is a waste of time. As mentioned, there is already std::sort, and even if you don't want to use that, the bubble sort is an algorithm that is not worth the time trying to implement. If you want to implement a better sorting algorithm in C++, see this link. You see that "bubble sort" isn't listed there, for the reason that it is not worth implementing. Commented May 5, 2024 at 12:32
  • void sortVector(vector <income> &incomes) { std::sort(incomes.begin(), incomes.end(), [](auto& i1, auto& i2) { return returnOlderDate(i1.getDate(), i2.getDate()); }); } -- That is the entire function using std::sort. Commented May 5, 2024 at 12:37
  • Please don't be discouraged by some of the above comments. Implementing bubble sort is fine: you should do it once in your life as a coder so to get a feel on what it is about, what its efficiency is, and how it compares to other sort methods. Commented May 5, 2024 at 20:29
  • In returnOlderDate() you expect year is 2 digits at position 0, month is 2 digits at position 3, day is 2 digits at position 6. In your XML year is 4 digits at position 6, month at position 3 and day at position 0. Change year to substr(6,4) and day to substr(0,2) for both dates. Commented May 6, 2024 at 9:13

1 Answer 1

1

The problem is how you parse date strings. The function returnOlderDate assumes that the dates are given in YY-MM-DD format, as can be seen from this code:

    int year1 = stoi(date1.substr(0,2));
    int month1 = stoi(date1.substr(3,2));
    int day1 = stoi(date1.substr(6,2));

...while your actual input data (XML) is formatted in DD-MM-YYYY format, as for example can be seen here:

    <date>28-05-2024</date>

and here:

    xml.FindChildElem("date");
    newIncome.setDate(xml.GetChildData());

The correction is straightforward. Also, you could rely on string comparison instead of converting each date part to a number. I would however use a helper function to avoid the code repetition you have in returnOlderDate, like so:

string DD_MM_YYYYtoYYYYMMDD(string date) {
    return date.substr(6,4) + date.substr(3,2) + date.substr(0,2);
}

bool returnOlderDate(string date1, string date2) {
    return DD_MM_YYYYtoYYYYMMDD(date1) < DD_MM_YYYYtoYYYYMMDD(date2);
}

Not a problem, but I find the name returnOlderDate misleading, as this function does not return the older date. It returns a boolean that indicates whether the first date comes chronologically before the second date. So maybe rename this function to something like isDateLessThan.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.