Pointer for array to calculate average in C++ - c++

I got a question on pointer in C++ :
Write a function that computes the average value of an array of floating-point data:
double average(double* a, int size)
In the function, use a pointer variable, not an integer index, to traverse the array elements.
And here is my solution :
int main()
{
const int size = 5;
double num_array[] = {2,2,3,4,5};
double* a = num_array;
cout << average(a,size);
cout << endl;
system("PAUSE");
return 0;
}
double average(double* a,const int size)
{
double total = 0;
for (int count =0; count< size; count++){
total = total + *(a + count);
}
return total/size;
}
It works fine but I have question on the for loop on pointer in average function. If I replace the statement in for loop with :
total = total + a*;
(I thought we supposed to do like this to add up all the number in array but unfortunately it gives me the wrong answer)
So what does the *(a + count) do? If possible, can somebody please simply brief me on how it works?
Thanks in advance.

a is a pointer to a double.
If you write *a, this pointer gets dereferenced and you get the data where the pointer points at, i.e. the double value. Note that the asterisk has to be in front of the pointer. (It's a "prefix" unary operator.)
a* is no valid syntax (it tries to multiply a with something which still has to follow ...)
a + count is pointer arithmetic. It gives you a but with count numbers of elements offset to the original a pointer. So it now points to the count-th element in the array.
*(a + count) now dereferences exactly this pointer, which gives you the count-th element of the array.
a[count] is exactly the same; it's just a nicer syntax.
Note: You can also use a++ in your loop. What it does is it increments the pointer by one position in the array. The next time you dereference a using *a, it returns the next entry. So your loop can be rewritten like this:
double total = 0;
for (int count = 0; count < size; count++){
total = total + *a; // Access the element a currently points to
a++; // Move the pointer by one position forward
}
You can even combine the increment and dereferencing operations into one expression. The postfix-increment syntax a++ will return the old pointer and increment the pointer by one position. Dereferencing a++ now means that you dereference the old pointer.
double total = 0;
for (int count = 0; count < size; count++){
total = total + *(a++);
}
The second note I want to give you is that you don't need your integer variable here to count the element. Since your pointer now already carries the information, your counter is now only used to stop the loop. This can also be done by comparing the pointer with some "end pointer", which we keep in a variable:
double total = 0;
double *end = a + size; // Store the end of the array
while(a < end) {
total = total + *(a++);
}
As you can see, I converted the for loop into a while loop since I no longer need to initialize or increment something (remember: going to the next entry of the array is done in the body!).
I hope this illustrates pointer arithmetic a little bit. You can "calculate" with pointers similarly as with indexing variables (your count variable). You can even subtract them to calculate offsets between pointers, for example.

* is the dereferencing operator, operating on the address a increased by count.
Read Pointers.

Related

C++: Syntax of passing a pointer array through a function

So I have these 2 methods: the first is meant to take in 5 integer values, sum them up, then call the findLowest() method that returns the lowest found value, and subtracts that from the sum (then divides by 4 and prints results to screen).
I think the issue I'm having is the values it's returning are memory addresses. I've tried to understand how to dereference integers to get the value, but truth be told all of the online resources I've looked up have gone over my head.
Below is what I have so far:
void calcAverage(int* arr[5])
{
int sum = 0;
for (int a = 0; a < 5; a++)
sum += *arr[a];
sum -= findLowest(*arr);
cout << "AVERAGE " << (sum / 4) << endl;
}
int findLowest(int* arr[5])
{
int lowest = *arr[0];
for (int a = 1; a < 5; a++)
{
if ((int)arr[a] < lowest)
lowest = *arr[a];
}
return lowest;
}
On top of that, on the line that says
sum -=findLowest(*arr);
it pops up an error that reads
argument of type "int *" is incompatible with parameter of type "int **"
Thanks for the help in advance, and sorry if the post's a bit scattershot: I'm not really confident with this pointer/reference stuff to begin with.
You are almost there, but you should not dereference on this line:
sum -= findLowest(*arr);
Instead, just pass in the array, because that is what the function expects:
sum -= findLowest(arr);
Unrelated:
If you can, use a std::vector or std::array, the former for dynamically sized arrays, the latter for a compile time array. These both are safer, have more functions, and are easier to pass around.
Also use smart pointers for ownership of pointers instead of raw pointers. Smart pointers manage the ownership of an object so that you do not need to manually call new and delete.

Why can't I pass a 2D array as a pointer to pointer but can pass a 1D array as a pointer

Apperantly this code works
void printD(int * ar,int r)
{
for(int i = 0; i < r; i++)
cout<<ar[i]<<endl;
}
int main()
{
int ar[3] = {1,2,3};
printD(ar,3);
return 0;
}
But this code does not work
void print2D(int ** ar,int r,int c)
{
for( int i = 0; i< r;i++)
for(int j = 0; j < c;j++)
cout<<ar[i][j]<<endl;
}
int main()
{
int ar2[1][2] = {{3,1}};
print2D(ar2,1,2);
return 0;
}
I do not understand why this does not work?
The problem lies within how the memory addresses are calculated. a[0] is the first element, and a[1] is the second element, so the address of a[1] is the position of a[0] plus the size of the element. No problem here, the address of any element can be calculated with the position of the first element multiplied with the offset times the element size.
How does this work with multi-dimensional arrays? What's the distance between a[0][5] and a[1][5]? Well, that depends on the row size (I'm using this terminology for the sake of this example, in reality, there aren't any "rows"), since in the end it's just one block of memory. If a row has 10 elements, then the distance is 10 times the size of an element. So this row size is important, the exact location of the elements in the array can't be calculated without it. Now with this here:
void print2D(int ** ar,int r,int c)
How could it know that row size? ar[1][0] is the first element of the second row, so if a row had size 10, then that would be the 10th element in the memory block. However, if the row size is 20, then it would be the 20th element, and that would be a different address. So how would it know?
The code doesn't work because it would require information to calculate the addresses, but it doesn't have that information.
This array int ar2[1][2] actually decays to int(*)[2].
There is no intermediate pointer to pointer that gets allocated, there is a contiguous 1D array that has can be accessed in 2D, hence the remaining [2] that gives the stride to go from one row to another.
A 2-dimensional array is implicitly converted to a pointer to a 1D array, not to a pointer to a pointer.
void print2D(int (*ar)[2],int r,int c)
{
// definition omitted for brevity
}
int main()
{
int ar2[1][2] = {{3,1}};
print2D(ar2,1,2);
return 0;
}
There is also no conversion from a pointer to an array (as in the above sample) into a pointer to pointer.
For more dimensions, this also works - except that all dimensions other than the first must be known at compile time.

After passing by reference to modify an array, why it stays the same?

I am practicing pointers by creating a Big Number struct, which has numDigits (number of digits) and digits (contents of the big number).
I create a function called removeZero(). After passing the integer array and the size n into it, because of passing by reference, I am supposed to cut down the leading zeros for my input. It works, when the integer array is in main function. However, when I pass an array that is in readDigits, it does not return with a non-leading-zero version. Why? How to fix it?
struct BigNum{
int numDigits;
int *digits; //the content of the big num
};
int main(){
int A[] = {0,0,0,0,0,0,1,2,3};
int n=9;
int *B=A;
//removeZero(A,n); If I use this, it cannot compile
//error: invalid initialization of non-const reference of type ‘int*&’ from an rvalue of type ‘int*’
removeZero(B,n);
for (int i=0; i<n; i++){
std::cout << *(B+i) << std::endl;
}
BigNum *num = readDigits();
return 0;
}
BigNum* readDigits(){
std::string digits;
std::cout << "Input a big number:" << std::endl;
std::cin >> digits;
//resultPt in heap or in stack?
int *resultPt = new int[digits.length()]; //in heap
int n = digits.length();
toInt(digits,resultPt);
removeZero(resultPt,n);
//Output the leading zeros, why?
for (int i=0; i<n; i++){
std::cout << *(resultPt +i) << std::endl;
}
BigNum *numPtr = new BigNum();
numPtr->numDigits = n;
numPtr->digits = resultPt;
return numPtr;
}
void toInt(std::string& str, int *result){
for (int i=0;i<str.length() ;i++ ){
result[str.length()-i-1] = (int)(str[i]-'0');
}
}
void removeZero(int* &A,int& n){
int i=0;
while (A[i]==0){
i++;
}
A=A+i; //memory leak?
n=n-i;
}
bool areDigits(std::string num){
for(int i=0;i<num.length();i++){
if(num[i]<'0' || num[i] >'9'){
return false;
}
}
return true;
}
Note that an array and a pointer are two different things. When you pass an array to a function, it degrades to a const pointer. This means that you cannot pass an array to a function which expects a int*&.
It could be the problem of scope of numPtr.numPtr is local variable of function readDigits(). Instead of returning pointer. Pass num to readDigits().
The signature of your removeZero function is:
void removeZero(int* &A,int& n);
That means the forst parameter is a reference of a pointer but the pointer is a non-const one, and you cannot therefore pass an array there, as array is a constant pointer (starting address cannot be changed).
In fact you are changing the starting address within removeZero.
With removeZero, the while loop shopuld be changed from:
while (A[i]==0){
to:
while ((A[i]==0) && (i<n)){
You have a logic error in toInt.
void toInt(std::string& str, int *result){
for (int i=0;i<str.length() ;i++ ){
// This stores the digits in the reverse order.
result[str.length()-i-1] = (int)(str[i]-'0');
}
}
That line should be
result[i] = (int)(str[i]-'0');
If you intend to keep the digits in reverse order, then removeZero has to be changed keeping that in mind.
`
When you say
int *B=A;
you are just creating a pointer to point to the same memory
of the Array A. Just by incrementing the pointer(*B) within the function
removeZero
A=A+i;
you are not deleting anything but you are just incrementing the pointer(*B)
to point to subsequent memory location within the array.
The original array memory pointed to by A remains the same, since you
have not changed any contents of the array, but you have just
incremented a pointer pointing to the same memory location as that of the array.
Also there are so many problems, like "Debasish Jana" mentioned,
you have to change your while loop. ""Code-Apprentice" gave you the reason for your
compilation error when you uncomment your commented code.
Also within "removeZero" you are incrementing A by i instead of "1" like
A=A+1;
This is one of the reason for the strange behavior you experience
Even after changing all this, you cannot see your array getting changed,
since you are not modifying any of the contents of your array.
If you really want to delete the contents of the array and change it dynamically,
you have to go for Vector<>. With static memory allocation you cannot cut the
array size short by removing some elements here and there. Learn Vector<>!

C++ Returning Pointers

I am trying to write a program that will: The function returns a pointer to the maximum value of an array of double values. If size is 0, then return the special pointer value NULL (or 0).
I am not sure if my logic is correct or if the function is returning a address or the value of temp.
const double * pMax(const double a[], size_t size){
double * ptr;
for(size_t i = 0; i < size; i++){
if(a[i] > a[i+1]){
ptr = a[i];
}
}
return ptr;
}
error: cannot convert 'const double' to 'double*' in assignment
ptr = a[i];
Get rid of your temp variable: you should never return a pointer to a local variable within a function, because by the time the caller receives the returned pointer, the variable it points to has gone out of scope. Instead, you should return a pointer to one of the elements in the the a array.
An overview of the algorithm to use:
Initialize ptr to NULL. This is the default value, until it's changed by checking at least one number in the array.
Iterate through the array with a loop. (If the array is empty, i.e. size is 0, the loop will run zero times.)
Each time through the loop, if ptr is NULL or the value that it points to (i.e. *ptr) is less than the current array element, change ptr to point to the current array element. This'll make it point to the first value initially, and then modify it to point to a different element whenever a greater one is found.
When the loop finishes, ptr points to the greatest element in the array that was found by the loop. If the loop didn't run any iterations (because size is 0), ptr is still NULL. Either way, this is the result you want, so return it.
You need to initialize ptr to NULL to take care of the case when array contains no element. For all other cases, it iterates through the array, to find out pointer to the max element and returns that. Also, In the program snippet, if the last element in the array is the largest, it does not compute pointer to that. Because, when the loop ends at i == (size-1), a[i+1] will cause array index to go out of bounds, risky. Here's the corrected version:
const double * pMax(const double a[], size_t size){
const double * ptr = (size == 0) ? NULL : &a[0];
for(size_t i = 1; i < size -1; i++){
if (a[i] > *ptr){
ptr = &a[i];
}
}
return ptr;
}

Pointer to Elements of an Array printing the memory address rather than the value of the element

I am currently writing a program for a class that takes user input to either add or remove a number from a dynamic array, and then print all the values of the array in ascending order.
From what I have already researched, all I need to do to get the value of the element in the array to print is to ensure the dereference operator is inserted next to the pointer name. However, when done as below (newArray[i]) I get a compile-time error saying that the operand to the right of the '' must be a pointer, even though newArray is declared as pointer at the beginning of the function.
void output(int *arrayPtr, int size){
int small;
int i, j;
int *newArray;
newArray = new int[size];
for (i = 0; i < size; i++){
*newArray[i] = arrayPtr[i];
}
for (i = 0; i < size; i++){
small = *newArray[i];
for (j = 0; j < size; j++){
if (*newArray[j] < small){
*newArray[j] = small;
}
std::cout << small;
}
int number = small;
removeNumber(*& arrayPtr, number, size);
}
}
I feel like there is something totally obvious I am missing, but I would greatly appreciate any help or ideas!!
small = *newArray[i];
That should just be:
small = newArray[i];
(Same thing in the other places you compare/assign *newArray[i]
What your first operation is doing is first dereferencing newArray, which means it gets the value of the first element in the array, and then attempting to index that. The element is not a pointer, so this of course fails. When you index, it also implicitly dereferences the pointer. You could also write:
small = *(newArray + i);
However, generally you only use pointer arithmetic when you need the actual pointer, since indexing is easier to read if you need the value.
Going through your code, a few other things seem off:
for (i = 0; i < size; i++){
*newArray[i] = arrayPtr[i];
}
This might compile but I don't think it is right, I'm guessing you mean:
for (i = 0; i < size; i++){
newArray[i] = arrayPtr[i];
}
Also:
removeNumber(*& arrayPtr, number, size);
While this is technically correct, *& first returns a pointer reference, then turns around and dereferences it again. I wouldn't be surprised if the compiler optimizes it away anyway, but it is unnecessary.