Reputation: 873
I have an array of values x = {0,0,1,2,3,0,0,7,8}
and I want to remove the zero entries using C.
Attempt:
I am attempting to loop through each value in the array and check if the entry is not equal to zero. If this condition is true, then I am attempting to populate a new array with original array value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i;
int x_upd[100];
for (i = 0; i < 9; i++) {
if (x[i] != 0) {
x_upd[i] = x[i]; // if true, populate new array with value
}
}
for (i = 0; i < 9; i++) {
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
The output is not giving me the values {1,2,3,7,8}
as desired. Instead, I am getting garbage values at the location where the zeros used to be.
Any advice on what I am doing wrong here? Do I need an else statement?
Upvotes: 3
Views: 12957
Reputation: 1
First, we must know the index of the "first non-zero" value in the array:
idx = 0;
while((idx < arrySize) & (arry[idx] == 0)) idx++;
and from here we can:
for ( j = 0; j < arrySize-idx; j++) newarry[j] = arry[j+idx];
Upvotes: 0
Reputation: 68089
no indexes needed
int populate(int *src, int *dest, int size)
//usage: - src - source table
//src - source table
//dest - destination table
//size of the source table - source table
//Return: -1 if pointers are null, -2 if source table has zero elements, or number of non zero elements copied
{
int result = (src == NULL || dest == NULL) * -1;
// it an equivalen of:
// int result;
// if(src == NULL || dest == NULL)
// result = -1;
// else
// result = 0;
if(size == 0) result = -2;
if (!result)
{
while(size--)
if (*src)
{
*dest++ = *src;
result++;
}
src++;
}
return result;
}
int main()
{
int x[] = { 0,0,1,2,3,0,0,7,8 };
int x_upd[100];
int result = populate(x,x_upd, sizeof(x) / sizeof(x[0]))
for (int i = 0; i<result; i++)
{
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
Upvotes: 1
Reputation: 56
You should increment x_upd array index separately. Something like:
int y = 0;
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[y] = x[i]; // if true, populate new array with value
y++;
}
}
Upvotes: 2
Reputation: 410
You should use separate counter variables, otherwise you will "skip" the indexes where the original array contains zeroes when assigning to the new array.
#include <stdio.h>
int main() {
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i;
int j = 0;
int x_upd[100];
for (i = 0; i < 9; i++) {
if (x[i] != 0) {
x_upd[j++] = x[i]; // if true, populate new array with value
}
}
for (i = 0; i < j; i++) {
printf(" Peak updated %d\t", x_upd[i]); //
}
return 0;
}
Upvotes: 3
Reputation: 113
The problem lies here:
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[i] = x[i]; // if true, populate new array with value
}
}
and
for(i=0;i<9;i++) {
printf(" Peak updated %d\t",x_upd[i]); //
}
You need to maintain separate index for x and x_upd, since they will be of different size(x_upd wont have the '0').
Try this:
int j;
for(i=0,j=0;i<9;i++) {
if(x[i] != 0)
{
x_upd[j] = x[i]; // if true, populate new array with value
j++; // index for values inserted
}
}
and to print, use the correct count, obtained from the above code:
int k;
for(k=0;k<=j;k++) {
printf(" Peak updated %d\t",x_upd[k]); //
}
Upvotes: 2
Reputation: 311166
There is already such a function in C++. It is named remove_copy
. In C such a function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
int * remove_copy(const int *in, size_t n, int *out, int value)
{
for (size_t i = 0; i != n; i++)
{
if (in[i] != value) *out++ = in[i];
}
return out;
}
int main( void )
{
int a[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int b[sizeof(a) / sizeof(*a)];
const size_t N = sizeof(a) / sizeof(*a);
int *last = remove_copy(a, N, b, 0);
for (int *first = b; first != last; ++first)
{
printf("%d ", *first);
}
putchar('\n');
return 0;
}
The program output is
1 2 3 7 8
Or the function can return the number of the copied values
size_t remove_copy(const int *in, size_t n, int *out, int value)
{
size_t m = 0;
for (size_t i = 0; i != n; i++)
{
if (in[i] != value) out[m++] = in[i];
}
return m;
}
As for your code then you need to use an additional variable that will keep the index in the destination array. For example
int m = 0;
for ( i = 0; i < sizeof( x ) / sizeof( *x ); i++ )
{
if ( x[i] != 0 )
{
x_upd[m++] = x[i]; // if true, populate new array with value
}
}
for ( i = 0; i < m; i++ )
{
printf(" Peak updated %d\t", x_upd[i] ); //
}
In fact the first loop corresponds to the second function implementation shown above.
Upvotes: 5
Reputation: 1044
You go through the values 0-9 once, in order, and you skip values that are 0
, so you get {garbage, garbage, 1, 2, 3, garbage, garbage, 7, 8}
. You'd have to keep a separate counter for the number of values that aren't 0
:
int position = 0;
for(i = 0; i < 9; i++)
{
if(x[i] != 0)
{
x_upd[position] = x[i]; // if true, populate new array with value
position++;
}
}
//loop until you get to counter
for(i = 0; i < position; i++)
{
printf(" Peak updated %d\t", x_upd[i]);
}
Upvotes: 3
Reputation: 24788
This problem can be solved by using two indexes: one for the source array (x
) and another for the destination array (x_upd
), which are i
and j
, respectively, in the code below.
int i, j;
for(i=0,j=0; i<9; i++) {
if (!x[i]) // is x[i] zero?
continue; // then skip this element
// otherwise copy current element and update destination index
x_upd[j++] = x[i];
}
As you can see, the index j
is only being updated (i.e.: incremented by one) when an element from x
is being copied to x_upd
, whereas the index i
is being updated in each iteration of the for
loop.
Upvotes: 2
Reputation: 27159
This
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[i] = x[i]; // if true, populate new array with value
}
}
is skipping places in the x_upd
array, since i
is still being incremented even when you don't insert values in your new array.
You should do this:
int j = 0;
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[j++] = x[i]; // if true, populate new array with value
}
}
Then, here
for(i=0;i<9;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
You should just count till j
:
for(i=0;i<j;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
Upvotes: 2
Reputation: 2707
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x[] = {0,0,1,2,3,0,0,7,8};
int i;
int count = 0;
int x_upd[100];
for(i=0;i<9;i++)
{
if(x[i] != 0)
{
x_upd[count] = x[i]; // if true, populate new array with value
count++;
}
}
for(i=0;i<count;i++)
{
printf(" Peak updated %d\t",x_upd[i]); //
}
return 0;
}
Output
Peak updated 1 Peak updated 2 Peak updated 3 Peak updated 7 Peak updated 8
Upvotes: 1
Reputation: 6465
No need to create a new array, see the working code with one array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
int i, n;
for (i = 0, n = 0; i<9; i++)
{
if (x[i] != 0)
{
x[n++] = x[i];
}
}
for (i = 0; i<n; i++)
{
printf("%d,", x[i]);
}
return 0;
}
OUTPUT:
1,2,3,7,8,
Upvotes: 2
Reputation: 8142
The trick in this situation, is to use a different variable to index into your other array.
So instead of this:
x_upd[i] = x[i];
You could have another variable j
that only increments when you assign a value to x_upd
x_upd[j++] = x[i];
Upvotes: 2