C++ Returning Pointers - c++

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;
}

Related

Shift array elements to the right using pointers

I am having trouble figuring out how to shift the elements of an array to the right using pointers (and not using swap). I have tried to play around with where the pointer starts and how it increments but it always messes up the output of the array when I test it just by printing the array values. Please help I am so frustrated.
// REQUIRES: there are at least n elements in arr;
// n >= 1
// MODIFIES: the elements in arr
// EFFECTS: All elements are "shifted" right by one unit, with the
// last element wrapping around to the beginning.
// EXAMPLE: If arr contains [0,1,3,3,4], it would be modified to
// contain [4,0,1,3,3]
// NOTE: You must use traversal by pointer.
// You may not use an extra array.
void slideRight(int arr[], int n) {
int *temp = arr;
for(int *ptr = arr+1; ptr < arr + n - 1;) {
arr[*ptr] = arr[*ptr-1];
}
arr[0] = *temp;
}
Your code has several problems.
First, it contains an infinite loop:
ptr < arr + n - 1
is true for arrays of size larger than 1.
This is unchanged throughout the loop.
Only the contents of arr is changed.
Second, it has a potential out-of-bounds, accessing arr[*ptr],
since *ptr is some arbitrary integer stored in the array.
There is a standard algorithm that does exactly this operation:
void slideRight(int arr[], int n) {
std::rotate(arr, arr + n - 1, arr + n);
}

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<>!

Double Pointer to Array of Integer Pointers; returning int&

So I made a variation of this class project.
Class project was originally like this:
int* array;
array = new int[size];
// int& method
return array[index];
Why does this work? array[index] returns the value not address right? [] dereferences the pointer?
--- Variation --
int** array;
array = new int*[size];
int& RA::setget(int index)
{
if ((index >= 0) && (index < capacity))
{
return **(array + index); // this part isn't working
}
else
throw out_of_range("blah"); // forgot the () out_of_range(). needed to put text in the exception!!!
}
This doesn't work, but isn't it the same? int** array, so I do **(array+index)?
The second part **(array + index) is not working, because you probably have not allocated memory for the second dimension.
When you do *(array + index), you get a pointer to int int*. When you now dereference once more **(array + index), you get the value, this pointer points to.
But when this pointer is not initialized, you get a segmentation fault.
To make this work, you must initialize the int* array
for (int i = 0; i < size; ++i)
array[i] = new int[other_size];
Olaf is correct , also to add in first part func returns int& reference to existing variable, so it correct. It would giv error if func is returnin int *, pointer/address to int

Pointer for array to calculate average in 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.