简体   繁体   中英

Adding objects to 2D Vector in C++

I want to make a matrix using vector and instead of int I use objects of the class Fraction .

However, I am trying to add elements to it but with no luck so far.

class Fraction
{
public:
    int num;
    int den;

    friend ostream& operator<< (ostream& os, Fraction& fr);
    void operator= (const Fraction& fr);
};

ostream& operator << (ostream& os, Fraction& fr)
{
     os << fr.num << "/" << fr.den;

     return os;
}

void Fraction::operator=(const Fraction& fr)
{
    num = fr.num;
    den = fr.den;
}

int main()
{
    Fraction fr;

    int colunas = 2, linhas = 2;

    vector<vector<Fraction>> mat(linhas, vector<Fraction>(colunas));

    for (int i = 0; i < colunas; ++i)
    {
        cout << endl << "Coluna " << i + 1 << endl;

        for (int j = 0; j < linhas; ++j)
        {
            int x;
            vector<Fraction> temp;
            cin >> x;

            fr.num = x;
            fr.den = 1;

            temp.push_back(fr);

            mat.push_back(temp);
        }

        cout << endl;
    }

    int len = mat.size();

    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < mat[i].size(); j++)
            {
                cout << mat[ i ] [ j ].num << " ";
            }

       cout << endl;
    }
}

With this I do iniatialize the matrix but it will only initialize to the rows. It will be mat[0][0] , mat[1][0] , and if I try to access mat[0][1] it will give me garbage.

I have tried this line

mat[i][j] = temp;

but it throws an error:

no matching operator =

Edit: following a suggestion and changing the code accordingly

class Fraction
{
public:
    int num;
    int den;

    friend ostream& operator<< (ostream& os, Fraction& fr);
    void operator= (const Fraction& fr);
};

ostream& operator << (ostream& os, Fraction& fr)
{
    os << fr.num << "/" << fr.den;

    return os;
}

void Fraction::operator=(const Fraction& fr)
{
    num = fr.num;
    den = fr.den;
}

int main()
{
    Fraction fr;

    int colunas = 2, linhas = 2;

    vector<vector<Fraction>> mat;//(linhas, vector<Fraction>(colunas));
    vector<Fraction> temp;
    for (int i = 0; i < colunas; ++i)
    {
        cout << endl << "Coluna " << i + 1 << endl;

        for (int j = 0; j < linhas; ++j)
        {
            int x;

            cin >> x;

            fr.num = x;
            fr.den = 1;

            temp.push_back(fr);
        }

        mat.push_back(temp);

        cout << endl;
    }

    //cout << mat[0][1];
    //cin.get();
    //cin.get();

    int len = mat.size();
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < mat[i].size(); j++)
        {
            cout << mat[ i ] [ j ].num << " ";
        }

        cout << endl;
    }
}

What I want the code to do is the following:

when I run it this is how it behaves

input

34
3
2
4

output

34 3
34 3 2 4

That is not the output I expect however, the first two input numbers make up the first column and second two make up the second column. So the output should be like this:

Expected output

34 2
3 4

If I access mat[0][1] I expect it to give me 2/1 but instead it gives me 3/1

The vector constructor used in this line:

vector<vector<Fraction>> mat(linhas, vector<Fraction>(colunas));

fills the vector with linhas copies of vector<Fraction>(colunas) , which itself is a vector of colunas many default-constucted Fraction s.

Faction 's default constructor is implicitly defined (because you did not declare any constructor yourself) and it does nothing. It leaves the int members with indeterminate values.

push_back later adds new elements to the vectors, after the ones that are already there from the default constructed ones. push_back does not replace elements already in the vector.

You probably don't want to prefill the vector with default constructed elements, so just default-initialize mat , which will leave it empty. The later push_back calls will add elements to it:

vector<vector<Fraction>> mat;

As mentioned in the comments, you don't need to write a copy assignment operator. The compiler will generate one automatically for you that has the correct behavior.


If you want to avoid creating Fraction objects with uninitialized values, such as you do in the mat constructor, then you can write your own constructor (which will disable the implicitly declared one), eg:

class Fraction
{
public:
    int num;
    int den;

    Fraction(int num_, int den_) : num(num_), den(den_) {}

    friend ostream& operator<< (ostream& os, Fraction& fr);
    void operator= (const Fraction& fr);
};

//...

        for (int j = 0; j < linhas; ++j)
        {
            int x;
            vector<Fraction> temp;
            cin >> x;

            temp.push_back(Fraction(x, 1));

            mat.push_back(temp);
        }

Instead of temp.push_back(Fraction(x, 1)); you can also write just temp.push_back({x, 1}); or temp.emplace_back(x, 1); .


You probably also intend to collect one inner vector in the inner loop and add it to the outer vector, ie:

    for (int i = 0; i < colunas; ++i)
    {
        cout << endl << "Coluna " << i + 1 << endl;

        vector<Fraction> temp;
        for (int j = 0; j < linhas; ++j)
        {
            int x;
            cin >> x;

            temp.push_back(Fraction(x,1));
        }
        mat.push_back(temp);

        cout << endl;
    }

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