Search code examples
c++qtclassvectorsetter

Setter not changing the data from a vector within a class


In my program, I have a class that holds a vector of type integer. It is used to store distances. I have a function, that when called, should set values in the vector to 0's. (used for initializing). But when I go to check the size of the vector, it still says the vector is empty.

I have created multiple functions that check whether the vector is adding any elements, and it is not. I have a function, that within main, I call to see if the vector is empty, and it returns 0 (the vector has 0 elements in it).

int MLB::getDistanceSize()
{
    return distances.size();
}

void MLB::setInitialDistances(int size)
{
    for(int i = 0; i < size; i++)
    {
        this->distances.push_back(0);
    }
}
class MLB
{
public:
    //constructor
    MLB();
    ~MLB();

    int getDistanceSize();
    void setInitialDistances(int size);

private:
    vector<int> distances;
};

The input file is a csv file with each line consisting of:

stadium1,stadium2,distance

so sample input file is:

AT&T Park,Safeco Field,680
AT&T Park,Oakland–Alameda County Coliseum,50
Angel Stadium,Petco Park,110
Angel Stadium,Dodger Stadium,50
Busch Stadium,Minute Maid Park,680
Busch Stadium,Great American Ball Park,310
Busch Stadium,Target Field,465
Busch Stadium,Kauffman Stadium,235

etc...

I am using qt, and this is where I am calling the functions themselves. All information is stored into a map, and the other getters work perfectly fine. Sorry for making this a lot more confusing than the problem really is, any help is greatly appreciated.

// key and value, key is the team name, value is the MLB stadium information
struct entry
{
    string key;
    MLB value;
};

class Map
{
    public:
        //Public default constructor
        Map();

        //Public default destructor
        ~Map();

        // returns entry of the map
        entry atIndex(int index);

        // Inserts a key and its value using linear algorithm
        void insert(const string& theKey, const MLB& value);

    private:

    vector<entry> thisTable;
    int currentSize;    //Integer variable for current size
};

functions for Map:

Map::Map()
{
    currentSize = 0;
}

Map::~Map()
{
}

void Map::insert(const string& theKey, const MLB& value)
{
    entry thisEntry;
    thisEntry.key = theKey;
    thisEntry.value = value;

    thisTable.push_back(thisEntry);

    currentSize+=1;
}

entry Map::atIndex(int index)
{
    return thisTable.at(index);
}
//mainwindow constructor
mainWindow::mainWindow()
{

    //Reads in input from first csv file, all works fine all data stored and can access it

    string iStadium1;
    string iStadium2;
    string iDistance;
    string previous;
    int distance;
    int index1;
    int index2;
    bool found;

    ifstream csvFile2;
    csvFile2.open("inputDistance.csv");

    getline(csvFile2, iStadium1, ',');
    while(!csvFile2.eof())
    {
        index1 = 0;
        found = false;
        while(!found)
        {
            if(thisMap.atIndex(index1).value.getStadiumName() == iStadium1)
            {
                thisMap.atIndex(index1).value.setInitialDistances(thisMap.mapSize());
                cout << "Distance Size Test 1: " << thisMap.atIndex(index1).value.getDistanceSize() << endl;
                found = true;
            }
            else
            {
                index1++;
            }
        }

        previous = iStadium1;

        while(iStadium1 == previous)
        {
            getline(csvFile2, iStadium2, ',');
            getline(csvFile2, iDistance, '\n');
            distance = stoi(iDistance);

            index2 = 0;
            found = false;

            while(!found)
            {
                if(thisMap.atIndex(index2).value.getStadiumName() == iStadium2)
                {
                    found = true;
                    cout << "Distance Size Test 2: " << thisMap.atIndex(index1).value.getDistanceSize() << endl;
                    // crashes here. Index out of bounds, size is 0 for some reason
                    thisMap.atIndex(index1).value.setDistance(index2, distance);
                }
                else
                {
                    index2++;
                }
            }
            getline(csvFile2, iStadium1, ',');
        }
    }

    csvFile2.close();
}

I expect the vector to hold 30 slots (assuming the desired size passed into the function is 30) of value 0, rather than having an empty vector.


Solution

  • The code in your question works as expected after adding constructor and destructor (doing both nothing) :

    #include <iostream>
    #include <vector>
    using namespace std;
    
    class MLB
    {
    public:
        //constructor
        MLB();
        ~MLB();
    
        int getDistanceSize();
        void setInitialDistances(int size);
    
    private:
        vector<int> distances;
    };
    
    int MLB::getDistanceSize()
    {
        return distances.size();
    }
    
    void MLB::setInitialDistances(int size)
    {
        for(int i = 0; i < size; i++)
        {
            this->distances.push_back(0);
        }
    }
    
    MLB::MLB() {
    }
    
    MLB::~MLB() {
    }
    
    
    int main()
    {
      MLB mlb;
    
      mlb.setInitialDistances(30);
      cout << mlb.getDistanceSize() << endl;
    }
    
    pi@raspberrypi:/tmp $ g++ d.cc
    pi@raspberrypi:/tmp $ ./a.out
    30
    

    the vector is not empty but contains 30 times 0


    if thisMap.atIndex(index1).value.setDistance(index2, distance); does nothing this is probably because atIndex(index1) returns a copy rather than a reference, so you modify a copy and the original is unchanged

    For instance :

    #include <iostream>
    #include <vector>
    using namespace std;
    
    class C {
      public:
        vector<int> getv() { return v; } // return a copy
        vector<int> & getvref() { return v; } // return the ref to the vector, not a copy
        int len() { return v.size(); }
    
      private:
        vector<int> v;
    };
    
    int main()
    {
      C c;
    
      c.getv().push_back(0); // modify a copy of v
      cout << c.len() << endl;
    
      c.getvref().push_back(0); // modify v
      cout << c.len() << endl;
    }
    

    Compilation and execution :

    pi@raspberrypi:/tmp $ g++ vv.cc
    pi@raspberrypi:/tmp $ ./a.out
    0
    1
    

    you edited you question and this is what I supposed :

    entry Map::atIndex(int index)
    {
        return thisTable.at(index);
    }
    

    return a copy, must be

    entry & Map::atIndex(int index)
    {
        return thisTable.at(index);
    }