Home > database >  how to change values of a 2d C vector by manipulating its slice?
how to change values of a 2d C vector by manipulating its slice?

Time:12-29

my example code is:

#include <bits/stdc  .h>
using namespace std;

void print_vec(vector<vector<int>> v) {
    cout << "**********print start!!!**********" << endl;
    for (int i = 0; i < v.size();   i) {
        for (int j = 0; j < v[i].size();   j) {
            cout << v[i][j] << " ";
        }
        cout << endl;
    }
    cout << "**********print end!!!**********" << endl;
}

void change_vec(vector<vector<int>>& v) {
    for (int i = 0; i < v.size();   i) {
        for (int j = 0; j < v[i].size();   j) {
            v[i][j] *= 10000;
        }
    }
}

void change_vec(vector<vector<int>>& v, int pos1, int pos2) {
    for (int i = pos1; i < pos2;   i) {
        for (int j = 0; j < v[i].size();   j) {
            v[i][j] *= 10000;
        }
    }
}

int main() {
    vector<vector<int>> block_values = {{99,98},{97,96},{95,94},{93,92},{91,90},{89,88},{87,86},{85,84},{83,82},{81,80}};

    vector<std::vector<int>> sub = vector<std::vector<int>>(block_values.begin()   1, block_values.begin() 3);
    print_vec(sub);
    change_vec(sub);
    change_vec(block_values, 6, 7);
    print_vec(sub);
    print_vec(block_values);
}

The output is:

**********print start!!!**********
97 96 
95 94 
**********print end!!!**********
**********print start!!!**********
970000 960000 
950000 940000 
**********print end!!!**********
**********print start!!!**********
99 98 
97 96 
95 94 
93 92 
91 90 
89 88 
870000 860000 
85 84 
83 82 
81 80 
**********print end!!!**********

The modification from sub does not affect block_values. So my question is how can I initialize sub so that when I change values of sub, block_values also change? Thanks!

I compile this program and want: the change of the vector slice can "persist" on the whole vector.

CodePudding user response:

The problem is that sub is a copy of the range you want to modify. The unfortunate side effect of taking this approach is that once sub is modified the only real way to have those changes reflected in block_values is to copy those values back. Another approach would be to change your change_vec functions to work using iterators allowing you to instead work on a range of data. A nice benefit of taking this approach is that it opens up the door to also taking better advantage of the C Standard Library which is heavily rooted in the iterator model.

The following update to your code eliminates the use of sub altogether and changes the second overload of change_vec to rely on the first thus eliminating duplicate logic.

#include <vector>
#include <iostream>

void print_vec(const std::vector<std::vector<int>>& v) {
    std::cout << "**********print start!!!**********" << std::endl;
    for (const auto& row : v) {
        for (const auto& value: row) {
            std::cout << value << " ";
        }
        std::cout << std::endl;
    }
    std::cout << "**********print end!!!**********" << std::endl;
}

void change_vec(
    std::vector<std::vector<int>>::iterator begin,
    std::vector<std::vector<int>>::iterator end) {
    for (; begin != end;   begin) {
        for (auto& value : *begin) {
            value *= 10000;
        }
    }
}

void change_vec(std::vector<std::vector<int>>& v, size_t pos1, size_t pos2) {
    change_vec(v.begin()   pos1, v.begin()   pos2);
}

int main() {
    std::vector<std::vector<int>> block_values = {
        {99,98},{97,96},{95,94},{93,92},{91,90},
        {89,88},{87,86},{85,84},{83,82},{81,80}};

    print_vec(block_values);
    change_vec(block_values.begin()   1, block_values.begin()   3);
    change_vec(block_values, 6, 7);
    print_vec(block_values);
}

This produces the following output:

**********print start!!!**********
99 98
97 96
95 94
93 92
91 90
89 88
87 86
85 84
83 82
81 80
**********print end!!!**********
**********print start!!!**********
99 98
970000 960000
950000 940000
93 92
91 90
89 88
870000 860000
85 84
83 82
81 80
**********print end!!!**********
  • Related