简体   繁体   中英

Iterator value for multimap not changing - C++

I have a multimap, which stores Dates (custom class objects) and floating point values inside of it. I then create a for loop by creating an iterator for this map, to perform some operations. For some reason, the date values in my it->first, are never changing from the first date. But i used this method of doing it the exact same way in other functions and it worked fine. What could be a possible reason?

Code:

multimap<Date, float> mapOption5Solar;
    multimap<Time, float> mapOption5Time;
    Vector<Time> timeVec;

    for(int i = 1; i < SIZE; i++)
    {
        mapOption5Solar.insert(make_pair(windlog[i].d, windlog[i].solar.GetSolar()));
        mapOption5Time.insert(make_pair(windlog[i].t, windlog[i].solar.GetSolar()));
    }

    float maxVal = 0;
    cout << "Original values: " << maxVal << endl;
    for(std::multimap<Date, float>::iterator it = mapOption5Solar.begin(); it!=mapOption5Solar.end(); it++)
    {
        //cout << "Entered Date: " << entryDate << " Vector Date: " << it->first << endl;
        //cout << "CheckDate Day: " << checkDate.GetDay() << endl;
        //cout << "CheckDate Month: " << checkDate.GetMonth() << endl;
        //cout << "CheckDate Year: " << checkDate.GetYear() << endl;
        //cout << "it Day: " << it->first.GetDay() << endl;
        //cout << "it Month: " << it->first.GetMonth() << endl;
        //cout << "it Year: " << it->first.GetYear() << endl;
        if(checkDate == it->first)
        {
            if(it->second > maxVal)
            {
                maxVal = it->second;
                cout << "Just checking iterator value: " << it->second << endl;
            }
        }
    }
    cout << "Updated values: " << maxVal << endl;

CheckDate is a date object i have created in which the user enters the date. it->first should store my date objects, but only prints out the values of the first day I have input, for all iterations.

Minimal reproducible example:

Date tempDate;
Date tempDate2;
Date tempDate3;
tempDate.SetDay("3");
tempDate.SetMonth("2");
tempDate.SetYear("2013");

tempDate2.SetDay("7");
tempDate2.SetMonth("1");
tempDate2.SetYear("2015");

tempDate3.SetDay("4");
tempDate3.SetMonth("2");
tempDate3.SetYear("2017");
//cout << "Date entered: " << checkDate << endl;

multimap<Date, float> mapOption5Solar;
mapOption5Solar.insert(make_pair(tempDate, 35));
mapOption5Solar.insert(make_pair(tempDate2, 56));
mapOption5Solar.insert(make_pair(tempDate3, 37));


float maxVal = 0;
Date checkDate;
checkDate.SetDay("4");
checkDate.SetMonth("2");
checkDate.SetDay("2017");
for(std::multimap<Date, float>::iterator it = mapOption5Solar.begin(); it!=mapOption5Solar.end(); it++)
{
    //cout << "Entered Date: " << entryDate << " Vector Date: " << it->first << endl;
    //cout << "CheckDate Day: " << checkDate.GetDay() << endl;
    //cout << "CheckDate Month: " << checkDate.GetMonth() << endl;
    //cout << "CheckDate Year: " << checkDate.GetYear() << endl;
    //cout << "it Day: " << it->first.GetDay() << endl;
    //cout << "it Month: " << it->first.GetMonth() << endl;
    //cout << "it Year: " << it->first.GetYear() << endl;
    if(checkDate == it->first)
    {
        if(it->second > maxVal)
        {
            maxVal = it->second;
            cout << "Just checking iterator value: " << it->second << endl;
        }
    }
}

Date.h:

#if !defined(_DATE_H)
#define _DATE_H

#include <iostream>
#include <string>
#include <tuple>

using namespace std;

    /**
     * @class Date
     * @brief  Manages and holds all dates
     *
     * This class is used to convert string from the input file into numerical values
     * and then store them as date values
     * @author Darren Fernando
     *
     * @date 05/05/2020 Darren Fernando, Started
     * @bug No bugs founds as of yet
     */
class Date
{
public:
    Date();
    Date(unsigned day1, unsigned month1, unsigned year1);

        /**
        * @brief A set method that is used to set the day value
        * It takes a string parameter and calls another method to convert it, and then assign it to the variable day
        * @param day1 - A string variable that is converted
        * @return void
        */
    void SetDay(string day1);

        /**
        * @brief A set method that is used to set the month value
        * It takes a string parameter and calls another method to convert it, and then assign it to the variable month
        * @param month1 - A string variable that is converted
        * @return void
        */
    void SetMonth(string month1);

        /**
        * @brief A set method that is used to set the year value
        * It takes a string parameter and calls another method to convert it, and then assign it to the variable year
        * @param year - A string variable that is converted
        * @return void
        */
    void SetYear(string year1);

        /**
        * @brief A get method that is used to get the day value by returning it
        * @return unsigned
        */
    unsigned GetDay() const;

        /**
        * @brief A get method that is used to get the month value by returning it
        * @return unsigned
        */
    unsigned GetMonth() const;

        /**
        * @brief A get method that is used to get the year value by returning it
        * @return unsigned
        */
    unsigned GetYear() const;

        /**
        * @brief A method that converts a string to an unsigned numerical value
        * @param time - A string parameter that is converted
        * @return unsigned
        */
    unsigned convertString(string date) const;

        /**
        * @brief A method that takes an input stream and perfoms some operations to set the date from this stream
        * This method isn't used but may be valuable later on
        * @param input - An input stream
        * @return void
        */
    void SetDate(istream &input);

        /**
        * @brief A method that takes an output stream and outputs it
        * This method isn't used but may be valuable later on
        * @param os - An output stream
        * @return void
        */
    void GetDate(ostream & os) const;
    unsigned GetDateRaw() const;

private:

    int day; /// Variable to store the day
    int month; /// Variable to store the month
    int year; /// Variable to store the year

};

bool operator==(const Date& firstDate, const Date& secondDate);
bool operator>(const Date& firstDate, const Date& secondDate);
bool operator<(const Date& firstDate, const Date& secondDate);
bool operator!=(const Date& firstDate, const Date& secondDate);
ostream & operator <<(ostream & os, const Date & D); /// Operator << overload
istream & operator >>(istream & input, Date & D); /// Operator >> overload
#endif  //_DATE_H

Date.cpp:

//
//
//  Generated by StarUML(tm) C++ Add-In
#include "Date.h"

    // Default constructor
Date::Date(){}

    /* Date constructor to initialize an object of date with the passed parameters
    */
Date::Date(unsigned day1, unsigned month1, unsigned year1) {

    day = day1;
    month = month1;
    year = year1;

}

void Date::SetDay(string day1) {

    day = convertString(day1); // Calls method convertString to convert the string parameter and assign the new value to day.

}

void Date::SetMonth(string month1) {

    month = convertString(month1); // Calls method convertString to convert the string parameter and assign the new value to month.

}

void Date::SetYear(string year1) {

    year = convertString(year1); // Calls method convertString to convert the string parameter and assign the new value to year.

}

unsigned Date::GetDay() const {

    return day; // Returns the day of the object

}

unsigned Date::GetMonth() const {

    return month; // Returns the month of the object

}

unsigned Date::GetYear() const {

    return year; // Returns the year of the object

}

    /* This method is used for directly setting the date from a file. It is not used now,
    but may prove handy in the future.*/
void Date::SetDate(istream &input){

    string day1;
    string month1;
    string year1;


    getline(input, day1, '/'); //Reads line until '/' is found and stores the string in day1
    getline(input, month1, '/'); //Reads line until '/' is found and stores the string in month1
    getline(input, year1, ' '); //Reads line until ' ' is found and stores the string in year1

    /*Sets the strings with setters which convert them automatically
    */
    SetDay(day1);
    SetMonth(month1);
    SetYear(year1);


}
    //This method is designed to convert a string to an integer
inline unsigned Date::convertString(string date) const{

    int date2 = 0;

    date2 = stoi(date); //Uses stoi from cmath library to convert a string to an integer

    return date2;

}

    // A get function that uses the overloaded output stream to output the date in a specific format.
void Date::GetDate(ostream &os) const{

    os << GetDay() << "/" << GetMonth() << "/" << GetYear() << " ";

}

bool operator==(const Date& firstDate, const Date& secondDate)
{
    if(firstDate.GetYear() == secondDate.GetYear() && firstDate.GetMonth() == secondDate.GetMonth() && firstDate.GetDay() == secondDate.GetDay())
    {

        return true;

    }
    else
    {
        return false;
    }

}

/*bool operator!=(const Date& firstDate, const Date& secondDate)
{
    if(firstDate!=secondDate)
    {
        return true;
    }
    return false;
}*/

bool operator>(const Date& firstDate, const Date& secondDate)
{
    if(firstDate.GetYear() > secondDate.GetYear())
    {
        return true;
    }
    else
        if(firstDate.GetYear() < secondDate.GetYear())
        {
            return false;
        }
        else
        {
            if(firstDate.GetMonth() > secondDate.GetMonth())
            {
                return true;
            }
            else
                if(firstDate.GetMonth() < secondDate.GetMonth())
                {
                    return false;
                }
                else
                {

                    if(firstDate.GetDay() > secondDate.GetDay())
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
        }
}



    // Input stream operator overload
istream & operator >>( istream & input, Date & D) {

    D.SetDate(input);
    return input;

}
    // Output stream operator overload
ostream & operator <<( ostream & os, const Date & D) {

    D.GetDate(os);

    return os;

}

Since your code (modified to cater for the missing information) works correctly, I can only gather that your problem lies with what you're populating your multimap with.

Specifically, the code:

#include <iostream>
#include <map>

using namespace std;

int main() {
    multimap<int, float> mapOption;

    for(int i = 1; i < 5; i++) {
        mapOption.insert(make_pair(i, i / 100.0));
    }

    auto maxVal = 0.0f;
    cout << "Original values: " << maxVal << endl;
    for(auto it = mapOption.begin(); it != mapOption.end(); it++) {
        if(it->second > maxVal) {
            maxVal = it->second;
            cout << "Just checking iterator value: " << it->second << endl;
        }
    }
    cout << "Updated values: " << maxVal << endl;
}

has no trouble outputting the correct items:

Original values: 0
Just checking iterator value: 0.01
Just checking iterator value: 0.02
Just checking iterator value: 0.03
Just checking iterator value: 0.04
Updated values: 0.04

Hence you should probably start by dumping the items as they're placed into the multimap, with something like:

for(int i = 1; i < SIZE; i++) {
    auto one = windlog[i].d;
    auto two = windlog[i].solar.GetSolar();
    cout << "Inserting " << one << " : " << two << '\n';
    mapOption5Solar.insert(make_pair(one, two));
}

For your updated code, I can see one reason why it's not working (other than the fact it won't actually compile in its current form).

You limit what gets printed with the checkDate so, based on your input (or what you think it is), you would only see one item, the one matching the date. However, you won't even see that, because of this code:

checkDate.SetDay("4");
checkDate.SetMonth("2");
checkDate.SetDay("2017");  // This is probably too big for a day :-)

I suggest you change that final line to a SetYear and try again.


And, after a bit of effort (adding the missing functions), it will compile and generate the results it seems to be after. I will mention that your code is rather verbose and can be cleaned up quite a bit, so I've taken the opportunity to do so:

#include <iostream>
#include <map>

using namespace std;

// Nominal date.h

class Date {
public:
    Date();
    Date(unsigned day1, unsigned month1, unsigned year1);
    void SetDate(unsigned day1, unsigned month1, unsigned year1);
    unsigned GetDay() const;
    unsigned GetMonth() const;
    unsigned GetYear() const;
    void SetDate(istream &input);
    void GetDate(ostream & os) const;
private:
    unsigned day;
    unsigned month;
    unsigned year;
};

bool operator==(const Date& firstDate, const Date& secondDate);
bool operator>(const Date& firstDate, const Date& secondDate);
bool operator<(const Date& firstDate, const Date& secondDate);
bool operator!=(const Date& firstDate, const Date& secondDate);

// Nominal date.cpp

Date::Date(unsigned day1 = 0, unsigned month1 = 0, unsigned year1 = 0)
    : day(day1), month(month1), year(year1) {}

void Date::SetDate(unsigned day1, unsigned month1, unsigned year1) {
    day = day1;
    month = month1;
    year = year1;
}

unsigned Date::GetDay() const { return day; }
unsigned Date::GetMonth() const { return month; }
unsigned Date::GetYear() const { return year; }

void Date::SetDate(istream &input) {
    string day1;
    string month1;
    string year1;

    getline(input, day1, '/');
    getline(input, month1, '/');
    getline(input, year1, ' ');

    SetDate(stoi(day1), stoi(month1), stoi(year1));
}

void Date::GetDate(ostream &os) const {
    os << GetDay() << "/" << GetMonth() << "/" << GetYear() << " ";
}

bool operator==(const Date& firstDate, const Date& secondDate) {
    return firstDate.GetYear() == secondDate.GetYear()
        && firstDate.GetMonth() == secondDate.GetMonth()
        && firstDate.GetDay() == secondDate.GetDay();
}

bool operator!=(const Date& firstDate, const Date& secondDate) {
    return ! (firstDate == secondDate);
}

bool operator>(const Date& firstDate, const Date& secondDate) {
    if(firstDate.GetYear() > secondDate.GetYear()) return true;
    if(firstDate.GetYear() < secondDate.GetYear()) return false;
    if(firstDate.GetMonth() > secondDate.GetMonth()) return true;
    if(firstDate.GetMonth() < secondDate.GetMonth()) return false;
    return firstDate.GetDay() > secondDate.GetDay();
}

bool operator<(const Date& firstDate, const Date& secondDate) {
    return ! (firstDate > secondDate || firstDate == secondDate);
}

// Nominal test program.

int main() {
    Date tempDate(3, 2, 2013);
    Date tempDate2(7, 1, 2015);
    Date tempDate3(4, 2, 2017);

    multimap<Date, float> mapOption5Solar;
    mapOption5Solar.insert(make_pair(tempDate, 35));
    mapOption5Solar.insert(make_pair(tempDate2, 56));
    mapOption5Solar.insert(make_pair(tempDate3, 37));

    auto maxVal = 0f;
    Date checkDate(4, 2, 2017);
    for (auto it = mapOption5Solar.begin(); it != mapOption5Solar.end(); ++it) {
        if (checkDate == it->first) {
            if (it->second > maxVal) {
                maxVal = it->second;
                cout << "Just checking iterator value: " << it->second << '\n';
            }
        }
    }
}

I don't doubt there may be other improvements but I'll leave that as an exercise for you:-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM