Adding a number to each element in array using pointers - c

There is a function, which I wish to add numbers to each element in arrays, with only pointers. But I'm failing it. The main problem is what to do with adding the sum. The pointer results in errors in the while loop.
void f(int *a, const int len) {
const int *pointer = a;
const int *add;
while (pointer < a + len) {
(a + pointer) += add; //this is like a[p], but with pointers, it's not working
++ pointer;
}
}

The following is the original code with the minimal corrections to make it work, and some comments to explain the changes:
void f(int *a, const int len) {
const int add = 101; // must initialize `add` here, since it's `const` and can't be modified later
int *pointer = a; // initialize `pointer` to point to the first element in the array
// can not be `const int *` since `*pointer` must be writeable
while (pointer < a + len) {
*pointer += add; // add `add` to the current element that `pointer` points to
++pointer; // increment `pointer` to point to the next element
}
}
Looking at the while loop, it gets executed len times if len > 0, or not at all if len <= 0. Then the whole function can be rewritten in a more idiomatic C way as follows:
void f(int *ptr, int len) {
const int add = 101;
while (len-- > 0) { // loop 'len' times
*ptr++ += add; // equivalent to `*ptr += add; ptr++;` due to operators precedence
}
}

Related

How do I do a word search without using strcmp?

int function(char * WordList[], int nSize, char * param_str)
{
int i = 0;
int bFlag = 0;
while(i < nSize && !bFlag)
{
if(WordList[i] == param_str){
return bFlag = 1;
}
i++;
}
return bFlag;
i tried using strcmp and made it work [if(strcmp(WordList[i], param_str) == 0)] but im wondering whats wrong with my current code.
WordList[i] is a pointer
param_str is another pointer.
WordList[i] == param_str tests if the 2 pointers point to the same location.
What these pointers reference is not considered. WordList[i] == param_str is not a string compare, just an address compare.
strcmp(a,b) compares the data at locations a and b.
To do the same, without strcmp(), form your own ...
int my_strcmp(const char *a, const char *b) {
// Pseudo code
while what `a` points to is the same as what `b` points to and `*a` is not 0
advance both pointers
return the sign of the difference of `*a` and `*b`.
}

Small confusion: using pointers only to write array program

I'm now writing a program to first find smallest element in an array, reverse the array, and then negate the smallest element in the array reversed. This is only using pointers. But, there's no use of integer variables, or array notation similar as arr[1], arr[0], etc. But there's chance to use pointer integers. Here's incomplete code:
void reverse_norm(int *arr, const int length) {
const int *i = arr;
int *least = *(arr + (length - 1));
while (i < arr + length) {
if (*(arr + *i) < least) {
*least = (arr + *i);
}
i++;
}
}
I have many problems here. The first, it's not done. The second, it's very problematic, with bugs and not able to run. There is just the part to find the smallest element.
This is one right way to write the function you need :
void reverse_norm(int *arr, const int length) {
const int *i = arr;
const int *least = (arr + (length - 1));
while (i < arr + length) {
if (*i < *least) {
least = i;
}
i++;
}
printf("least is %d\n", *least);
}
I did not rename any variable since it is not the problem here, but at least i should be renamed as something like current_element

Updating a pointer to a c array from a function

Say I have a function called array_push in c.
void array_push(int *array_pointer, int array_length, int val) {
int i;
int *temp_array = malloc(sizeof(int) * (array_length + 1));
for (i = 0; i < array_length; i++) {
temp_array[i] = *array_pointer;
array_pointer++;
}
temp_array[array_length] = val;
*array_pointer = temp_array;
}
How can I update the pointer *array_pointer so that it points to temp_array and other parts of my program can use the new array? Allowing me to do something like
int t[2] = {0,2};
array_push(t, 2);
/* t should now contain {0,2,3} */
You need to turn array_pointer into a pointer-to-pointer:
void array_push(int **array_pointer, int array_length, int val) {
(note the extra asterisk).
Also, you'll need to change the call site so that t is a pointer, not an array (you can't make an array point someplace else). Finally, to make the caller aware of the new size of the array, array_length also needs to be passed by pointer.
Thus, the overall structure of your code could be something like:
void array_push(int **array_pointer, int *array_length, int val) {
int *temp_array = malloc(sizeof(int) * (*array_length + 1));
memcpy(temp_array, *array_pointer, sizeof(int) * *array_length);
temp_array[(*array_length)++] = val;
free(*array_pointer);
*array_pointer = temp_array;
}
int main() {
int n = ...;
int* t = malloc(sizeof(int) * n);
/* ... */
array_push(&t, &n, 2);
/* ... */
free(t);
}
Note how I've allocated t on the heap, and have freed *array_pointer inside array_push(). With this in mind, much of the array_push()'s logic can be simplified by using realloc():
void array_push(int **array_pointer, int *array_length, int val) {
*array_pointer = realloc(*array_pointer, sizeof(int) * (*array_length + 1));
(*array_pointer)[(*array_length)++] = val;
}
There are two problems here: You seem confused about pass-by-value, but the more significant problem is that you seem confused about pointers. int *array_pointer array_pointer points to an int, not an array. It may be that it points to the first int in an array. On an unrelated note, a "pointer to an int array" looks like: int (*array_pointer)[array_length].
Back to the point: int *array_pointer array_pointer points to an int. In *array_pointer = temp_array;, the expression *array_pointer gives you the object pointed to, which can store an int. temp_array isn't an int value, though.
I can see that you're attempting to work around the issue that changes made to array_pointer aren't visible to the caller, due to the semantics of pass-by-value. Hence, you need to change array_pointer so that it points to an int * that the caller supplies, so that you're modifying the caller's int *, or use the return type to return the new pointer. As it turns out, both of these options solve both of your problems.
PROBLEM 1:
If you want to create or modify an *int array inside of a function, then you need to pass a "pointer to a pointer":
// WRONG:
void array_push(int *array_pointer, int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
*array_pointer = temp_array;
Instead:
// BETTER:
void array_push(int **array_pointer, int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
*array_pointer = temp_array;
Or:
// BETTER YET:
int * array_push(int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
return temp_array;
PROBLEM 2:
If you want to declare a static array like this int t[2] = {0,2};, then you can't arbitrarily change it's size. Here's a good description of "arrays vs pointers":
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1069897882&id=1073086407
One of the first things a new student learns when studying C and C++
is that pointers and arrays are equivalent. This couldn't be further
from the truth...

C: Copy array without knowing its type

I have function, it receive pointer to array and pointer to function and should return new array with order defined by function passed in parameter.
My problem how I copy element of one array to another without knowing its type
void * scrambleArr(void * arr, int numElem, int elemSize, int (*func)(void*)) {
void * newArr;
int cPos, newPos,i;
newArr = (void *)malloc(numElem*elemSize);
for (i=0 ; i < numElem ; i++)
{
cPos = i*elemSize;
newPos = func((char*)arr+cPos);
*((char*)newArr+newPos) = *((char*)arr+cPos);
}
return newArr;
}
Function that passed in the last parameter
int posArrayBySize(void *el) {
ARRAY* arr = (ARRAY *)el;
return arr->size - 1;
}
And code in main:
int main( ) {
ARRAY * arrSorted;
int a[2] = {1,2};
int b[3] = {1,1,1};
int c[1] = {9};
int d[4] = {3,3,3,3};
ARRAY arr[4] = {{a,2},{b,3},{c,1},{d,4}};
arrSorted =(ARRAY *)scrambleArr(arr,4,sizeof(ARRAY),posArrayBySize);
free(arrSorted);
return 0;
}
After running arrSorted contain garbage,
Can someone point me, what i miss?
Another option for me is not to copy, just to point one array to elements of other, is it possible?
Thanks.
memcpy is the function you are looking for.
This won't work
*((char*)newArr+newPos) = *((char*)arr+cPos);
because you're dereferencing arr+cPos as it is char, so it will copy only the first byte.

C: Accessing a pointer from outside a function

I have the following code:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
-1
2088999640
2088857728
If I try printing the first element of the newlist pointer before returning the function (printf("First number found %d\n", *newlist);), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
You need to pass in a pointer to pointer, i.e. int **newlist. Specifically, newlist is being passed into your function by value, so the newlist in main and inside your function are two completely different variables.
There is also a bug in your test for even numbers:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
The newlist you have at the end of the function is not the same as you have when calling the function.
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
You're passing a pointer by value here:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free:
free(evenNums);
In C, everything is passed by value. So you are passing a copy of evenNums to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int** as the third parameter.

Resources