1

For example if I have an array and I want to extract elements of this array with a specified value as a new array. I did as the following:

int a[10] = { 1, 2, 1, 3, 2, 3, 4, 1, 2, 6 };
int i, k;

int count = 0;
for (i = 0; i < 10; i++) {
    if (a[i] == 1) {
        count = count + 1;
    }
}

int b[count];
k = 0;
for (i = 0; i < 10; i++) {
    if (a[i] == 1) {
        b[k] = a[i];
        k = k + 1;
    }
}

So, for the array "a" I extracted all the elements of value 1, and make them as a new array "b". How can I achieve the same thing by using pointers? Will it be conciser than this way? If it is possible, is there any other advantages?

3
  • 2
    There is no need to extract out of the specific indexes of a once you know the count. Should just be able to do for(i=0; i < count; i++) b[i] = 1; This doesn't answer your pointers question, but if you are looking for conciseness, there you go! Commented Jun 14, 2017 at 18:22
  • @EastonBornemeier Oh,yes you are right. Thanks for your comment. Commented Jun 14, 2017 at 18:23
  • What is your problem ? I don't understand. Commented Jun 14, 2017 at 18:24

3 Answers 3

3

I think you already noticed that you just had to write 1 several times; yet I suppose you want that it works for arbitrary conditions.

"Using a pointer" can mean dynamic memory allocation instead of a variable length array. Just for the sake of having use a pointer, you could then write:

int *b = malloc(count * sizeof(int));
k = 0;
for (i = 0; i < 10; i++) {
    if (a[i] == 1) {
        b[k] = a[i];
        k = k + 1;
    }
}

If, just for sake of using a pointer for the writing process, too, you could adapt the program as follows:

int *b = malloc(count * sizeof(int));
int *bPtr = b;
for (i = 0; i < 10; i++) {
    if (a[i] == 1) {
        *bPtr++ = a[i];
    }
}

Hope it helps a bit.

Sign up to request clarification or add additional context in comments.

Comments

3

If you don't know which portion of the array your target values will be in, as in your case, where you're searching the entire unsorted array for a specific value, then there is no advantage to using pointers rather than a linear search to find the elements in the array you are after.

If, however, you are trying to access or copy a contiguous set of elements starting at a known index in the array, then you could use a pointer to simplify things. For example, if I'm after the last few elements in an array of chars, this works:

#include <stdio.h>
int main()
{
    char str[100] = "I don\'t want anyone to think I hate the Calgary Flames";
    char *c = (str + 29);
    printf("%s\n", c);
    return 0;
}

Output:

I hate the Calgary Flames

Comments

2

In this case, no, there is no benefit. a[i] is already basically a + (sizeof(int) * i). Even if you used pointers, you'd still have to do all the counting anyway to make sure you don't walk off the end of the array.

Where its often handy is with a null terminated array of pointers, such as a string, where you don't know the length. But it's not really about performance. As you can see below, they have to do roughly the same things.

char string[] = "foo bar";

// Allocate and initialize i.
// `string + i` twice, compare, increment.
for( int i = 0; string[i] != '\0'; i++ ) {
    printf("%c", string[i]);
}
puts("");

// Allocate and initialize s.
// Dereference s twice, compare, increment.
for( char *s = string; *s != '\0'; s++ ) {
    printf("%c", *s);
}
puts("");

Where iterating by pointer is handy is when you need to iterate through an array in several steps. Instead of passing around the original array pointer plus your last index, and changing all your function signatures to accommodate, just pass around the incremented pointer and return the incremented pointer. This allows you to use standard string functions on the middle of a string.

#include <stdio.h>

char *findVal( char *string, char delim ) {
    char *val = string;
    for( ; *val != '\0' && *val != delim; val++ ) {
    }

    if( val == '\0' ) {
        return NULL;
    }
    else {
        // val is sitting on the ':'
        return val+1;
    }
}

int main() {
    char string[] = "this:that";

    char *val = findVal(string, ':');
    if( val != NULL ) {
        // Just use val, not string[valIdx].
        printf("%s\n", val);
    }
}

This is also safer. With an offset there's two things which must remain in sync, the pointer and the offset; that opens the possibility that the wrong offset will be used with the wrong pointer. An incremented pointer carries its offset with it.


As has been pointed out in the comments, you can tighten up the second loop like so:

int b[count];
for (i = 0; i < count; i++) {
    b[i] = 1;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.