Moving the next value to the left to replace the removed value

Hi everyone. I am new to C++ programming. I need some help from anyone here. I got a task to remove two values which is 1 and 2 in 2d array. I had successfully removed it, but i don't know how to move the next value to replace the removed values position.

This is my input file (matrix 3x15):
0 4 8 9 5 11 10 2 12 7 3 6 1 0 0
0 10 11 9 8 5 4 1 7 3 6 12 1 0 0
0 0 8 9 5 4 11 10 2 12 7 3 6 1 0

After remove value 1 and 2, the output should be:
0 4 8 9 5 11 10 12 7 3 6 0 0 0 0
0 10 11 9 8 5 4 7 3 6 12 0 0 0 0
0 0 8 9 5 4 11 10 12 7 3 6 0 0 0

After i run the code, the answer I got as follows:
initial_route[0][0]=0
initial_route[0][1]=4
initial_route[0][2]=8
initial_route[0][3]=9
initial_route[0][4]=5
initial_route[0][5]=11
initial_route[0][6]=10
initial_route[0][8]=12
initial_route[0][9]=7
initial_route[0][10]=3
initial_route[0][11]=6
initial_route[0][13]=0
initial_route[0][14]=0
.
.
initial_route[2][14]=0

What i need to do, if i want to move the next value to replace the deleted value position and the remaining position will be filled with value 0 as follows:

After i run the code, the answer:
initial_route[0][0]=0
initial_route[0][1]=4
initial_route[0][2]=8
initial_route[0][3]=9
initial_route[0][4]=5
initial_route[0][5]=11
initial_route[0][6]=10
initial_route[0][7]=12
initial_route[0][8]=7
initial_route[0][9]=3
initial_route[0][10]=6
initial_route[0][11]=0
initial_route[0][12]=0
initial_route[0][13]=0
initial_route[0][14]=0
.
.
initial_route[2][14]=0

I hope you understand what I'm trying to do here.
Hoping for help from anyone. Thank for your kindness.

Attached is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

//declare functions
void input();		//assign all input data into arrays
void eliminate();


//declare variables & files
const int pop_size = 3;				//population size
const int column_initialR = 15;		//number of column for initial route matrix

vector< vector <long double>> initial_route (column_initialR, vector <long double> (column_initialR,0));  //initial route 

int i, j; 
const int removeValue1 = 1;
const int removeValue2 = 2;

//output files

 
void main() 
{
	input();
	eliminate();
	
}

void input()
{
	//open input files
	ifstream inpInitialRoute("Initial route 13.txt");	//read initial route

	//assign initial routes into array                    
	for ( i = 0; i < pop_size; i++ )
	{
		for ( j = 0; j < column_initialR; j++)
		{
			inpInitialRoute >> initial_route[i][j];
			//cout << "Initial route [" << i << "][" << j << "] = " << initial_route[i][j] << endl;
		}
	}
	
	//close input files
	inpInitialRoute.close();
}

void eliminate()
{
	for (int i = 0; i < pop_size; i++)
	{
		for (int j = 0; j < column_initialR; j++)
		{
			if ((initial_route[i][j] != removeValue1) && (initial_route[i][j] != removeValue2))
			{

				cout << "Initial route [" << i << "][" << j << "] = " << initial_route[i][j] << endl;
			}
		}
	}
	system("pause");
}
closed account (E0p9LyTq)
Each row of a 2D array (or vector) is a 1D array, and the logic for erasing, moving and replacing elements is a manageable task for a 1D array (or vector).

A std::vector has member functions which make erasing, moving and replacing elements much easier than having to write the logic for a C-style array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <vector>

int main()
{
   // add a type alias to make typing easier
   using USHORT = unsigned short;

   // create a 1D vector for testing purposes
   // scaling up to a 2D vector is not much more work
   std::vector<USHORT> vec = { 0, 4, 8, 9, 5, 11, 10, 2, 12, 7, 3, 6, 1, 0, 0 };

   // lets display the vector
   for (USHORT i = 0; i < vec.size(); i++)
   {
      std::cout << vec[i] << ' ';
   }
   std::cout << "\n\n";

   // to record the number of erased elements, if any
   USHORT num_removed = 0;

   // walk through the array and erase any found elements
   for (USHORT i = 0; i < vec.size(); i++)
   {
      if (vec[i] == 1 || vec[i] == 2)
      {
         vec.erase(vec.begin() + i);
         num_removed++;
      }
   }

   // display the number of erased elements
   std::cout << num_removed << "\n\n";

   // add zeroes for every erased element
   while (num_removed > 0)
   {
      vec.push_back(0);
      num_removed--;
   }

   // use a range-based loop to display the modified array
   for (const auto& i : vec)
   {
      std::cout << i << ' ';
   }
   std::cout << "\n\n";
}

STL containers have standardized member functions for getting iterators, they make "out of bounds" errors almost impossible to do:
23
24
25
26
27
28
29
30
31
   // walk through the array and erase any found elements
   for (auto i = vec.begin(); i <= vec.end(); i++)
   {
      if (*i == 1 || *i == 2)
      {
         vec.erase(i);
         num_removed++;
      }
   }

The <algorithm> header provides several find and search functions that work with STL containers. Your given task doesn't require using them IMO.

One thing to note: my quick and dirty solution requires the last element in the array isn't one you remove.

To remove more than the current two elements and/or remove elements from the end would require using the find() functions in <algorithm>.


Last edited on
Hi FurryGuy, thank you for your given guidance. I would like to ask, is it possible for me to delete the those values (1 and 2) in 2d arrays as i stored it before in 2d array? or I need to delete one by one .. this means I need to store the particular data one by one in 1d array.
closed account (E0p9LyTq)
I made a serious mistake with my vector logic, when I erased an element (1 or 2) I invalidated the for loop relying on the vector's size. A VERY DUMB ROOKIE MISTAKE.

I should have restarted from the beginning to find new elements that could be erased. Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <vector>

int main()
{
   using USHORT = unsigned short;

   std::vector<USHORT> vec = { 1, 4, 8, 9, 5, 11, 10, 2, 12, 7, 3, 6, 1, 0, 2 };

   for (USHORT i = 0; i < vec.size(); i++)
   {
      std::cout << vec[i] << ' ';
   }
   std::cout << "\n\n";

   bool not_done = false;

   while (not_done == false)
   {
      not_done = true;

      for (USHORT i = 0; i < vec.size(); i++)
      {
         if (vec[i] == 1 || vec[i] == 2)
         {
            vec.erase(vec.begin() + i);
            vec.push_back(0);
            not_done = false;
            break;
         }
      }
   }

   for (const auto& i : vec)
   {
      std::cout << i << ' ';
   }
   std::cout << '\n';
}

1 4 8 9 5 11 10 2 12 7 3 6 1 0 2

4 8 9 5 11 10 12 7 3 6 0 0 0 0 0

Scaling up for a 2D vector, using your data set:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <vector>

int main()
{
   using USHORT = unsigned short;

   // create a 2D vector for testing purposes
   std::vector<std::vector<USHORT>> vec = { { 0, 4, 8, 9, 5, 11, 10, 2, 12, 7, 3, 6, 1, 0, 0 },
                                            { 0, 10, 11, 9, 8, 5, 4, 1, 7, 3, 6, 12, 1, 0, 0, },
                                            { 0, 0, 8, 9, 5, 4, 11, 10, 2, 12, 7, 3, 6, 1, 0 } };

   // lets display the vector
   for (USHORT i = 0; i < vec.size(); i++)
   {
      for (USHORT j = 0; j < vec[i].size(); j++)
      {
         std::cout << vec[i][j] << ' ';
      }
      std::cout << '\n';
   }
   std::cout << '\n';

   for (USHORT j = 0; j < vec.size(); j++)
   {
      bool not_done = false;

      // walk through the array and erase any found elements
      while (not_done == false)
      {
         not_done = true;

         for (USHORT i = 0; i < vec[j].size(); i++)
         {
            if (vec[j][i] == 1 || vec[j][i] == 2)
            {
               vec[j].erase(vec[j].begin() + i);
               vec[j].push_back(0);
               not_done = false;
               break;
            }
         }
      }
   }

   // use a range-based loop to display the modified array
   for (const auto& i : vec)
   {
      for (const auto& j : i)
      {
         std::cout << j << ' ';
      }
      std::cout << '\n';
   }
   std::cout << '\n';
}

0 4 8 9 5 11 10 2 12 7 3 6 1 0 0
0 10 11 9 8 5 4 1 7 3 6 12 1 0 0
0 0 8 9 5 4 11 10 2 12 7 3 6 1 0

0 4 8 9 5 11 10 12 7 3 6 0 0 0 0
0 10 11 9 8 5 4 7 3 6 12 0 0 0 0
0 0 8 9 5 4 11 10 12 7 3 6 0 0 0

Populating a 2D vector isn't that hard, just a bit of different logic than populating a C-style 2D array.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>

int main()
{
   using USHORT = unsigned short;

   // create a 2D (empty) vector, manually filled 3 x 3.
   std::vector<std::vector<USHORT>> vec;

   // create the first row
   std::vector<USHORT> temp;
   temp.push_back(1);
   temp.push_back(2);
   temp.push_back(3);
   vec.push_back(temp);

   // create the second row
   temp.erase(temp.begin(), temp.end());
   temp.push_back(2);
   temp.push_back(4);
   temp.push_back(6);

   // let's sneak in an extra element
   temp.push_back(12);
   vec.push_back(temp);

   // create the third row
   temp.erase(temp.begin(), temp.end());
   temp.push_back(3);
   temp.push_back(6);
   temp.push_back(9);
   vec.push_back(temp);

   for (const auto& i : vec)
   {
      for (const auto& j : i)
      {
         std::cout << j << ' ';
      }
      std::cout << '\n';
   }
   std::cout << '\n';
}

1 2 3
2 4 6 12
3 6 9
Hi FurryGuy, thank you for helping. I've tested the code provided by you but it does not work. I think this is due to my c++ version. Currently I'm using c++ 2008.
closed account (E0p9LyTq)
Code samples 1 and 2 use an initializer list constructor for the vector. That is C++11. It was the easiest way to show how to work with vectors without adding the complexity of reading the data from a file. Or manually pushing back a huge chunk of data.

Sample 3 shows the steps needed to manually populate a vector one element at a time. Easy to adapt for reading file data into a 2D vector:

1. create an empty 2D vector.
2. create/erase a temp 1D vector.
3. read a line of data in one element at a time, pushing it back into the vector.
4. when all the data elements in a line are in the 1D vector, push that vector back into the 2D vector.
5. check the file if there is more data lines to read. If yes, loop back to 2. If no, the 2D vector is filled and continue.

Sample 2 shows how to manipulate individual elements in a 2D vector, treat each "row" as the 1D vector that it is.

Currently I'm using c++ 2008.

You really should think about upgrading to a newer standard, no matter what compiler you use.

Visual Studio 2017, the compiler/IDE I use primarily, has a free version that supports C++17.
Hi FurryGuy, thanks your help and guidance.

You really should think about upgrading to a newer standard, no matter what compiler you use.


I did think so but other task i had successfully solve it using the previous version.

Sorry for asking this. If i upgrade to a newer, the tasks/code that i had successfully solved before can still be used in newer version or i need to make improvement.

It was the easiest way to show how to work with vectors without adding the complexity of reading the data from a file.


Actually I need to read the data from a text file as in our early conversation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void input()
{
	//open input files
	ifstream inpInitialRoute("Initial route 13.txt");	//read initial route

	//assign initial routes into array                    
	for ( i = 0; i < pop_size; i++ )
	{
		for ( j = 0; j < column_initialR; j++)
		{
			inpInitialRoute >> initial_route[i][j];
			//cout << "Initial route [" << i << "][" << j << "] = " << initial_route[i][j] << endl;
		}
	}
	
	//close input files
	inpInitialRoute.close();
}


The current task i need to do is delete the unwanted value which is 1 and 2 (i had done it), but the particular index also being removed. Whereas, the task want the next undeleted value replace the deleted value and the empty index at the back is replace by zero.

0 4 8 9 5 11 10 2 12 7 3 6 1 0 0
0 10 11 9 8 5 4 1 7 3 6 12 1 0 0
0 0 8 9 5 4 11 10 2 12 7 3 6 1 0

0 4 8 9 5 11 10 12 7 3 6 0 0 0 0
0 10 11 9 8 5 4 7 3 6 12 0 0 0 0
0 0 8 9 5 4 11 10 12 7 3 6 0 0 0


Sorry for troubling you. Thanks again for your valuable time in teaching me.
Sorry for asking this. If i upgrade to a newer, the tasks/code that i had successfully solved before can still be used in newer version or i need to make improvement.


C++ is largely backwards compatible, a relatively very small number of things get deprecated with each version of the standard, which comes out every 3 years from 2011 onwards.

So whatever you have written in 2008 (C++2003 standard) will probably still work. However there are some big improvements in later versions of C++. For example in FurryGuy's code there are range based for loops and use of the auto keyword. So this just means there are better ways to write the code. It also means there is potential for you to learn a lot more: there were lots of changes made in the 2011 C++ standard ; more made for each successive standard (although not as much as in 2011).

It shouldn't be hard to upgrade to the latest version of the compiler,I would strongly recommend that you do so.

Good Luck !! :+)
closed account (E0p9LyTq)
If i upgrade to a newer [compiler], the tasks/code that i had successfully solved before can still be used in newer version or i need to make improvement.

The only problem when upgrading to a newer compiler is if you are using older C++ functions that have been deprecated/removed from the newer standard. Very few have. Most of the changes to the standard is adding new ways to do tasks with new tools.

Most likely you haven't been using any of those few tools. std::random_shuffle for example is one that was removed in C++17, replaced with std::shuffle.

Going with an updated compiler is always a good idea, even if you have to tweak your older code a bit to be standard compliant. Most older code written for an older standard will still work and compile with a newer standard.
The current task i need to do is delete the unwanted value which is 1 and 2 (i had done it), but the particular index also being removed. Whereas, the task want the next undeleted value replace the deleted value and the empty index at the back is replace by zero.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;

//----------------------------

bool notOK( int i )          // decide what you don't want
{
   return i == 1 || i == 2; 
}

//----------------------------

int main()
{
   vector< vector<int> > V = { { 0,  4,  8, 9, 5, 11, 10,  2, 12,  7, 3,  6, 1, 0, 0 },
                               { 0, 10, 11, 9, 8,  5,  4,  1,  7,  3, 6, 12, 1, 0, 0 },
                               { 0,  0,  8, 9, 5,  4, 11, 10,  2, 12, 7,  3, 6, 1, 0 } };

   for ( auto &vec : V )          // For each row vector in V ...
   {
      // Eliminate what you don't want; the total size of container is unchanged
      //    http://www.cplusplus.com/reference/algorithm/remove_if/
      auto it = remove_if( vec.begin(), vec.end(), notOK );

      // Fill the unwanted elements with 0
      //    http://www.cplusplus.com/reference/algorithm/fill/
      fill( it, vec.end(), 0 );
   }

   // Check
   for ( auto &vec : V )
   {
      for ( int i : vec ) cout << setw( 2 ) << i << " ";
      cout << '\n';
   }
}


 0  4  8  9  5 11 10 12  7  3  6  0  0  0  0 
 0 10 11  9  8  5  4  7  3  6 12  0  0  0  0 
 0  0  8  9  5  4 11 10 12  7  3  6  0  0  0 




If your compiler doesn't like 'auto' then you will have to include the full types:
for ( vector<int> &vec : V )
and
vector<int>::iterator it = remove_if( vec.begin(), vec.end(), notOK );
and you will have to replace your brace-enclosed initialiser list by whatever routine you are using to put values in V.
Last edited on
Usually when you compile you can tell your compiler which standard adopt. The GNU compiler, for example, provides the flag -std=c++number to take advantage of such opportunity.
So, if I want to compile a code which is not ready for the 2011 standard, I can do it just omitting that flag. On the other hand, if I want to specify let’s say the 2014 standard, I just need to add: -std=c++14.
You can look through you compiler documentation to check if that’s true even for it, but I’m pretty sure you can safely upgrade it.

Just to play with code, these are other two possible answers to your original question, one based on std::vectors and the other on C-style arrays, but I’m afraid both require at least the 2011 standard:

Initial_route_13.dat:
1
2
3
0   4   8   9   5  11  10   2  12   7   3   6   1   0   0
0  10  11   9   8   5   4   1   7   3   6  12   1   0   0
0   0   8   9   5   4  11  10   2  12   7   3   6   1   0


Based on std::vector:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>


using vec2d = std::vector<std::vector<int>>;


vec2d loadDataIntoVector(const std::string& fname);
int purge(vec2d& to_be_purged, const std::vector<int>& values);
void output2Dvec(const vec2d& myv);


int main()
{
    vec2d myv { loadDataIntoVector("Initial_route_13.dat") };
    output2Dvec(myv);
    const std::vector<int> targets { 1, 2 };
    std::cout << "Removed " << purge(myv, targets) << " unwanted values.\n";
    output2Dvec(myv);
}


vec2d loadDataIntoVector(const std::string& fname)
{
    // Open and check input file:
    std::ifstream init_route(fname);
    if(!init_route) {
        std::cerr << "Cannot open " << fname << ".\nExtiting now.\n";
        return vec2d();
    }

    vec2d my2dv;        // a 2d vector (what we are going to return)

    for(std::string line; std::getline(init_route, line); /**/) {
        // ...just read an entire line (of ints) into a std::string.

        // Create a stream from that std::string:
        std::istringstream iss { line };

        std::vector<int> v;
        // Read (one by one) the ints from the newly created stream into
        // an int variable and then push each value into a std::vector<int>:
        for(int i; iss >> i; /**/) {
            v.push_back(i);
        }

        // Add the above std::vector<int> as a new line into the 2d vector:
        my2dv.push_back(v);
    }

    return my2dv;
}


int purge(vec2d& to_be_purged, const std::vector<int>& values)
{
    int count {};
    for(auto& v : to_be_purged) {
        for(auto it {
                std::remove_if(v.begin(),
                               v.end(),
                               [&values](auto i) {
                                    if(std::find(values.begin(), values.end(), i)
                                       != values.end() ) {
                                        return true;
                                    }
                                    return false;
                               } )
            };
            it != v.end();
            ++it)
        {
            *it = 0;
            ++count;
        }
    }
    return count;
}


void output2Dvec(const vec2d& myv)
{
    for(const auto& v : myv) {
        for(const auto i : v) {
            std::cout << std::setw(2) << i << ' ';
        }
        std::cout << '\n';
    }
}


Based on C-style arrays:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <fstream>
#include <iomanip>
#include <iostream>


struct Arr2d {
    int** ptop { nullptr };
    std::size_t cols {};
    std::size_t rows {};

    Arr2d() = default;
    explicit Arr2d(std::size_t cols_arg, std::size_t rows_arg);
    Arr2d(const Arr2d& other) = delete;
    Arr2d& operator=(Arr2d other) = delete;
    // etc. etc...
    ~Arr2d();

    void loadDataFromFile(const std::string& fname);
    int purgeFromVals(const int * const values, std::size_t size);
    int purgeAllValsFromRow(std::size_t row,
                            const int * const values,
                            std::size_t size);
    friend std::ostream& operator<<(std::ostream& os, const Arr2d& rhs);
};


Arr2d::Arr2d(std::size_t cols_arg, std::size_t rows_arg)
    : cols { cols_arg },
      rows { rows_arg }
{
    ptop = new int*[rows];
    for(std::size_t i {}; i < rows; ++i) {
        ptop[i] = new int[cols] {};
    }
}


Arr2d::~Arr2d()
{
    for(std::size_t i {}; i < rows; ++i) {
        delete[] ptop[i];
        ptop[i] = nullptr;
    }
    delete[] ptop;
    ptop = nullptr;
}


void Arr2d::loadDataFromFile(const std::string& fname)
{
    // Open and check input file:
    std::ifstream init_route(fname);    // or fname.c_str()
    if(!init_route) {
        std::cerr << "Cannot open " << fname << ".\nExtiting now.\n";
        return;
    }

    std::size_t row {};
    for(std::string line;
        std::getline(init_route, line) && row < rows;
        ++row)
    {
        // ...just read an entire line (of ints) into a std::string.

        // Create a stream from that std::string:
        std::istringstream iss { line };

        std::size_t col {};
        for(int i; iss >> i && col < cols; ++col) {
            ptop[row][col] = i;
        }
    }
}


int Arr2d::purgeFromVals(const int * const values, std::size_t size)
{
    int count {};
    for(std::size_t i {}; i < rows; ++i) {
        count += purgeAllValsFromRow(i, values, size);
    }
    return count;
}


int Arr2d::purgeAllValsFromRow(std::size_t row,
                               const int * const values,
                               std::size_t size)
{
    int count {};
    for(std::size_t i {}; i < cols; ++i) {
        for(std::size_t j {}; j < size; ++j) {
            if(ptop[row][i] == values[j]) {
                ++count;
                // if it is the last element in ptop[row], just set it to 0
                if(i == cols - 1) {
                    ptop[row][i] = 0;
                    continue;
                }
                for(std::size_t h { i }; h < cols - 1; ++h) {
                    ptop[row][h] = ptop[row][h + 1];
                }
                ptop[row][cols - 1] = 0;
            }
        }
    }
    return count;
}


std::ostream& operator<<(std::ostream& os, const Arr2d& rhs)
{
    for(std::size_t i {}; i < rhs.rows; ++i) {
        for(std::size_t j {}; j < rhs.cols; ++j) {
            std::cout << std::setw(2) << rhs.ptop[i][j] << ' ';
        }
        std::cout << '\n';
    }
    return os;
}


constexpr std::size_t Arr_Rows {  3 };
constexpr std::size_t Arr_Cols { 15 };


int main()
{
    Arr2d arr(Arr_Cols, Arr_Rows);
    std::cout << "Just created:\n" << arr << '\n';
    arr.loadDataFromFile("Initial_route_13.dat");
    std::cout << "Just populated:\n" << arr << '\n';
    const int targets[] { 1, 2 };
    std::cout << "Removed "
              << arr.purgeFromVals(targets, sizeof(targets)/sizeof(targets[0]))
              << " unwanted values:\n";
    std::cout << arr << '\n';
}

Topic archived. No new replies allowed.