Delete an element from 2d array of pointers

Hello Everybody!

I have a 2d array and I created it with pointers.

int **array;
array = new int* [size];

for (int i = 0; i < size; i++)
array[i] = new int [K];

for (int i = 0; i < size; i++)
for (int j = 0; j < K; j++)
array[i][j] = -1;

for (int i = 0; i < size; i++){
delete [] array[i];
}
delete [] array;
}

With this code, I can obtain an output like this depending on the parameters:

1 1 2 3 0
2 0 2 0 1
2 3 0 1 1

What I want is to remove a specific value, say 0. But I don't want to replace it with another element. The desired output is:

1 1 2 3
2 2 1
2 3 1 1

Thanks in advance!
Those methods are a bit 'old school' now, and many here would discourage using them.
That said however, I'm 'old school' and have been doing dynamic allocation with raw (dumb) pointers for years, so I'm OK with it. I've also learned some of the newer 'safer' methods (using std::vector for instance) and I use them more and more.

By erasing some elements from each row you would need some way to keep track of the number of elements in each row, since this would vary from row to row.
I would allocate an extra row to int** array (with K elements ) and store the number of elements in each row there. This way,
number of elements in row r = array[size][r]

Here is some code for this.
I've stored the array data in a text file so the values can be read from there, instead of having to enter values by hand each program run.

I've stored the number of rows and columns as the 1st entries in the file. For the example you gave the file looks like this:

3 5

1 1 2 3 0
2 0 2 0 1
2 3 0 1 1


Here's my code, which worked for the case you gave but hasn't been tested any further:

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
#include <iostream>
#include <fstream>
#include <string>

// relegating tasks to functions (keeps main() simple)
int** Alloc_Init( unsigned& rows, const std::string& fileName );
void display( int** ppi, unsigned rows );
void eraseAllOf( int val, int** ppi, unsigned rows );
void DLT( int** ppi, unsigned rows );

int main()
{
    unsigned ROWS = 0;
    int** arr2D = Alloc_Init( ROWS, "test2.txt" );

    if( arr2D )
    {
        display( arr2D, ROWS );
        eraseAllOf( 0, arr2D, ROWS );
        display( arr2D, ROWS );
        DLT( arr2D, ROWS );
    }

    return 0;
}

int** Alloc_Init( unsigned& rows, const std::string& fileName )
{
    int** ppi = NULL;
    rows = 0;
    unsigned cols = 0;
    std::ifstream fin( fileName.c_str() );// Enter values by hand each time? No thanks!

    if( fin )
    {
        fin >> rows >> cols;

        unsigned r=0, c=0;
        ppi = new int*[rows+1];// extra row for number of elements in each row
        for(r=0; r<rows; ++r)
        {
            ppi[r] = new int[cols];
            for(c=0; c<cols; ++c) ppi[r][c] = 0;
        }
        ppi[rows] = new int[rows];
        for(r=0; r<rows; ++r) ppi[rows][r] = 0;// indicating 0 valid elements in each row initially
        // get values from file
        r = 0; c = 0;
        while( fin >> ppi[r][c] && r < rows )
        {
            ++c;
            ppi[rows][r] = c;// increase valid element count
            if( c%cols == 0 )
            {
                c = 0;
                ++r;
            }
        }
        fin.close();
    }
    return ppi;
}

void display( int** ppi, unsigned rows )
{
    for(unsigned r=0; r<rows; ++r)
    {
        for(int c=0; c < ppi[rows][r]; ++c)
            std::cout << ppi[r][c] << ' ';

        std::cout << '\n';
    }
    std::cout << '\n';
}

void eraseAllOf( int val, int** ppi, unsigned rows )
{
    unsigned r=0;
    int c=0;

    for( r=0; r<rows; ++r )
    {
        int keepCount = 0;
        for( c=0; c < ppi[rows][r]; ++c )
            if( ppi[r][c] != val ) ++keepCount;

        if( keepCount < ppi[rows][r] )
        {
            int* newRow = new int[keepCount];// new shorter row allocated
            unsigned i = 0;
            for( c=0; c < ppi[rows][r]; ++c )
                if( ppi[r][c] != val ) newRow[ i++ ] = ppi[r][c];

            delete [] ppi[r];// out with old row
            ppi[r] = newRow;// keep the new row
            ppi[rows][r] = keepCount;// new row length
        }
    }
}

void DLT( int** ppi, unsigned rows )
{
    for(unsigned r=0; r<=rows; ++r)
        delete [] ppi[r];

    delete [] ppi;
}


It produces this output:

1 1 2 3 0
2 0 2 0 1
2 3 0 1 1

1 1 2 3
2 2 1
2 3 1 1


EDIT: Made some improvements to the code.
Last edited on
First of all, thank you so much for the quick response! It perfectly works, and does what I want. But I was wanting to add some more lines to my current code to get that because I will combine it with some another code that I previously created. So, any suggestions for that. Also, I just added the function eraseAllof to my code, but it didn't work properly.

Thanks-
The eraseAllOf() function relies on an extra row which holds the row lengths.

You can use the function, but modify the code you gave so the extra row is added. 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
int **array;
array = new int* [size+1];// for one extra row

for (int i = 0; i < size; i++)
array[i] = new int [K];

array[size] = new int[size];// for the row holding the column lengths

for (int i = 0; i < size; i++)
for (int j = 0; j < K; j++)
array[i][j] = -1;

for (int i = 0; i < size; i++)
array[size][i] = K;// record the column lengths

// use the array as you wish here
// use the display() function. It takes account of the varying row lengths.

// cleanup
for (int i = 0; i <= size; i++){// note the <= here
delete [] array[i];
}
delete [] array;
Hi again,

I have the following code but I am afraid it doesn't do what I want. What is wrong with it?

#include <string>
#include <iostream>
#include <fstream>

using namespace std;

void display( int** array, unsigned rows );
void eraseAllOf( int val, int** array, unsigned rows );

int main()
{

int m = 4, n =7;
int **array;
array = new int* [m+1];


for (int i = 0; i < m; i++)
array[i] = new int [n];

array[m] = new int[m];

for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
array[i][j] =0;


for (int i = 0; i < m; i++)
array[m][i] = n;

if( array )
{
display( array, m-1 );
eraseAllOf( 0, array, m-1 );
}


for(int i=0; i<m; i++) //This loops on the rows.
{
for(int j=0; j<n; j++) //This loops on the columns
{
cout << array[i][j] << " ";
}
cout << endl;
}


for (int i = 0; i <= m; i++){
delete [] array[i];
}
delete [] array;

}


void display( int** array, unsigned rows )
{
for(unsigned r=0; r<rows; ++r)
{
for(int c=0; c < array[rows][r]; ++c)
std::cout << array[r][c] << ' ';

std::cout << '\n';
}
std::cout << '\n';
}

void eraseAllOf( int val, int** ppi, unsigned rows )
{
unsigned r=0;
int c=0;

for( r=0; r<rows; ++r )
{
int keepCount = 0;
for( c=0; c < ppi[rows][r]; ++c )
if( ppi[r][c] != val ) ++keepCount;

if( keepCount < ppi[rows][r] )
{
int* newRow = new int[keepCount];// new shorter row allocated
unsigned i = 0;
for( c=0; c < ppi[rows][r]; ++c )
if( ppi[r][c] != val ) newRow[ i++ ] = ppi[r][c];

delete [] ppi[r];// out with old row
ppi[r] = newRow;// keep the new row
ppi[rows][r] = keepCount;// new row length
}
}
}


Thanks!
Try replacing
1
2
display( array, m-1 );
eraseAllOf( 0, array, m-1 );

with
1
2
display( array, m );
eraseAllOf( 0, array, m );


The code you have for displaying the matrix:
1
2
3
4
5
6
7
8
for(int i=0; i<m; i++) //This loops on the rows.
{
for(int j=0; j<n; j++) //This loops on the columns
{
cout << array[i][j] << " ";
}
cout << endl;
}

won't work after the call to eraseAllOf because the row lengths aren't all=n anymore (so line 3 is wrong). This is why I said to just call the display() function. The inner for loop in that function is:
for(int c=0; c < array[rows][r]; ++c)
which accounts for the variable length rows.

I hope that part starts making sense because you will have other problems using the matrix if you can't work with the variable row lengths.
Good luck!

EDIT: I know the method I cooked up may be confusing. It's not any kind of standard algorithm, it's just something I thought up on the spot. Maybe someone else will post a more sensible solution.
Last edited on
Thank you so much for your time "fun2code"! I made the changes that you pointed out, and will try to figure out what is going on.
You're welcome. If you can't get it working, post back with a description of what's wrong and I can try to get it working for you.
I wonder if there may be another efficient method to get that output. What I want is to store values (i.e. reading from a file) without deleting any values but getting the same output. That is, I will create a matrix that has different number of elements in each row.

Thanks
Last edited on
Topic archived. No new replies allowed.