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>
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
.