#include <iostream>
using namespace std;
void merge(int *& toMerge, int lo, int mid, int hi)
{
int merged[hi+1];
int i = lo, j = mid+1;
for (int k = lo; k <= hi; k++)
{
if (i > mid) {merged[k] = toMerge[j]; j++;}
else if (j > hi) {merged[k] = toMerge[i]; i++;}
else if (toMerge[j] < toMerge[i]) {merged[k] = toMerge[j]; j++;}
else {merged[k] = toMerge[i]; i++;}
}
toMerge = merged;
}
int main(int argc, const char * argv[])
{
int x[8] = {1,7,4,6,2,7,3,2};
merge(x, 0, 7, 3);
return 0;
}
I am trying to pass a pointer by reference here such that the end result will be that the array x will be sorted. However, my compiler is throwing an error that there is no matching function call for the merge(x, 0, 7, 3).
I am not sure as to why this is happening because the merge function requires a pointer, and x is a pointer to the first element in the array -- so it should work. Why doesn't it?
An array decays to a pointer when you pass it as an argument to a function call but not to a reference to a pointer.
Imagine this:
void foo(int*& p)
{
p = new int;
}
int main()
{
int arr[6] = {0};
foo(arr);
// You don't want arr to be an invalid object here.
// If the compiler allowed you to do that, that's what will happen.
// Not only that, foo(arr); is equivalent to:
// arr = new int;
// which is not allowed in the language.
}
You really should NOT pass a reference, because you don't really want merge changing the value of the pointer. You just want to allow it to change the values stored in the array, which it can do without the reference (i.e., just from the pointer).
Related
I made a function the returns an array like so
void array_function(int i){
int* a = NULL;
a = new int[3];
a = {i-1, i, i+1};
return a;
}
Now I want to call this function in the a new function
int main(){
int n = 3
for(int i = 0; i < n; i++){
//call the function
}
}
I am not sure how I can call the function to give me the array, any help will be appreciated
Use std::array instead. It has more friendly value semantics:
#include <array>
std::array<int, 3> array_function(int const i) {
return {{ i - 1, i, i + 1 }};
}
int main() {
for(int i = 0; i < 3; i++){
auto arr = array_function(i);
// Use array
}
}
First your function is void, which translates as no-return-function. Make it return int* like
int* array_function(int i)
Now, to call the function you need to assign it to a temporary variable, which you can do work and then you should delete it. Full code:
int* array_function(int i){
int* a = new int[3];
a[0] = i-1, a[1] = i, a[2] = i+1;
return a;
}
int main(){
int n = 3;
for(int i = 0; i < n; i++){
int* a = array_function(i); // if you are going to do something with this array, which you will
// some work with a
delete[] a; // delete it to release memory from heap, everytime you do new, you should use delete at the end of your program
}
}
You want something like this to create the array, since the method in your question does not have a return type assigned (void means that it returns nothing), you have to define a return type for the method to work, in this case a pointer to an array:
int* array_function(int i){
int* a = NULL;
a = new int[3];
a = {i-1, i, i+1};
return a;
}
And then just store the result of the method in a local variable like this:
int* myArray = array_function(n);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I got the below snippet from Algorithms in a nut shell
void sortPointers (void **ar, int n,
int (*cmp)(const void *, const void *)) {
int j;
for (j = 1; j < n; j++) {
int i = j-1;
void *value = ar[j];
while (i >= 0 && cmp (ar[i], value) > 0) {
ar[i+1] = ar[i];
i--;
}
ar[i+1] = value;
}
}
https://www.amazon.com/Algorithms-Nutshell-OReilly-George-Heineman/dp/059651624X
They do not provide the main() implementation of
sortPointers
so i have some problems figuring out what does **ar do
when i attempted to do a test code on
**arrPtr = x
it returns the error that you cannot cast void ** on a int *.
this surprises me as the book clearly says you feed an array into the function.
int main()
{
var x[3] = { 2 , 4 , 3};
void **arrPtr = x[0];
return 0;
}
a side question as well.
void *value = ar[j];
is this a unneeded step? the CMP function was able to take ar[i] as a argument, shouldnt it be able to take ar[j] as is?
In C we have the function qsort which is a generic function to sort arrays. It can sort all kind of arrays (e.g. arrays of int, arrays of double and even arrays of custom structs). All it requires is that the user provide a "compare" function for comparing two elements.
The sortPointers seems to be pretty much the same except it does not sort arrays of elements but instead sorts an array of pointers to elements.
As far a I can see the idea is to use it like:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void * a, const void * b)
{
int* pa = (int*)a;
int* pb = (int*)b;
if (*pa > *pb) return 1;
if (*pa < *pb) return -1;
return 0;
}
void sortPointers (void **ar, int n,
int (*cmp)(const void *, const void *))
{
int j;
for (j = 1; j < n; j++) {
int i = j-1;
void *value = ar[j];
while (i >= 0 && cmp (ar[i], value) > 0) {
ar[i+1] = ar[i];
i--;
}
ar[i+1] = value;
}
}
void pp(int **ar, int n)
{
for(int i=0; i<n; ++i)
printf("Address %p holds the value %p and points to %d, i.e. arr[%d] points to %d\n", (void*)(&ar[i]), (void*)ar[i], *ar[i], i, *ar[i]);
}
#define ELEM 3
int main(void)
{
int* arr[3];
for(int i=0; i<ELEM; ++i) arr[i] = malloc(sizeof(int));
*arr[0] = 5;
*arr[1] = 8;
*arr[2] = 2;
pp(arr, ELEM);
sortPointers((void**)arr, ELEM, cmp);
printf("------------------------\n");
pp(arr, ELEM);
for(int i=0; i<ELEM; ++i) free(arr[i]);
return 0;
}
Output:
Address 0x7fff9a7d0270 holds the value 0xeeb010 and points to 5, i.e. arr[0] points to 5
Address 0x7fff9a7d0278 holds the value 0xeeb030 and points to 8, i.e. arr[1] points to 8
Address 0x7fff9a7d0280 holds the value 0xeeb050 and points to 2, i.e. arr[2] points to 2
------------------------
Address 0x7fff9a7d0270 holds the value 0xeeb050 and points to 2, i.e. arr[0] points to 2
Address 0x7fff9a7d0278 holds the value 0xeeb010 and points to 5, i.e. arr[1] points to 5
Address 0x7fff9a7d0280 holds the value 0xeeb030 and points to 8, i.e. arr[2] points to 8
However, the whole function seems to be a waste of time. The standard qsort can do this for you so why write a special function? As written above qsort can sort all kind of arrays so it can also sort an array of pointers. The compare function just needs to be a bit different. Simply use qsort like:
// Compare function
int cmp_qsort(const void * a, const void * b)
{
int** pa = (int**)a;
int** pb = (int**)b;
if (**pa > **pb) return 1;
if (**pa < **pb) return -1;
return 0;
}
// Call from main like:
qsort(arr, ELEM, sizeof(int*), cmp_qsort);
The output will be the same (except for the address that change every time you run it) and you don't need a custom sort function like sortPointers.
I'm having trouble trying to come up with the pointer version of this function:
void strncpy(char t[], const char s[], const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n and s[i]; i++)
t[i]=s[i];
t[i] = '\0'
}
This function is supposed to copy the first "n" characters of one array to another array and then terminate with a null character. I'm sure this is simple but I'm still learning pointers :P
This is what I have right now:
void strncpy(char * t, const char * s, const unsigned int * n)
{
unsigned int i = 0;
for(i = 0; i < *n and *s; i++)
*t = *s;
*t = '\0';
}
Im calling it in main via:
char array_one[5] = "quiz";
char array_two[5] = "test";
unsigned int x = 2;
strncpy(array_one,array_two,x);
You've failed to increment the pointers, so you're always overwriting the same address. There's also no need to pass n via a pointer:
#include <cstddef>
void my_strncpy(char *t, const char *s, std::size_t n) {
while (n && *s) {
*t++ = *s++;
--n;
}
*t = '\0';
}
NB: note use of size_t to duplicate the standard parameter signature
of the standard strncpy function, although the standard version also returns the original value of t rather than void.
#include <iostream>
// changing the function signature to take an int instead of
// pointer to int - cleaner
void my_strncpy(char * t, const char * s, const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n; i++)
{
*t++ = *s++; // copy and increment
}
*t = '\0'; // fixing - added terminating char
}
int main(void)
{
char a[] = "string1";
char b[] = "string2";
my_strncpy(a,b,7); // replace 7 with appropriate size
std::cout << a << std::endl;
}
You need to copy over each character from one string to another and then increment the pointers - you were missing that in your implementation.
I also assume that you will not overshoot the array you are copying from.
I have a program where I have a function that sorts elements of an array of structures by their key field. However, when I invoke the function Insertion(a[],7) - I pass the array and its size, the compiler gives an error expected primary expression before ']' token. I would like to ask what am I doing wrong?
#include <iostream>
using namespace std;
struct CElem
{
int key;
};
CElem a[7];
void Insertion(CElem m[],int n)
{
CElem x;
int i;
int j;
for (i = 0; i < n; i++)
{
x = m[i];
j = i-1;
while (j >= 0 && x.key < m[j].key)
m[j+1] = m[j--];
m[j+1] = x;
}
}
int main()
{
a[0].key=32;
a[1].key=45;
a[2].key=128;
a[3].key=4;
a[4].key=-9;
a[5].key=77;
a[6].key=-7;
Insertion(a[],7);
return 0;
}
you only need to pass the pointer to the start of the array:
Insertion(a, 7);
Your parameter m of the method Insertion is of type CElem*. The variable a is of type CElem* too so you are supposed to give the method just a, like Insertion(a,7);.
I'm trying to pass an array into my function calls for build_max_heap and max_heapify so I can modify the array after each call, but I receive an error saying "candidate function not viable: no known conversion from 'int [9]' to 'int *&'for 1st argument."
#include <iostream>
#include <string>
using namespace std;
void build_max_heap(int*& array, int size);
void max_heapify(int*& array, int size, int index);
void build_max_heap(int*& array, int size)
{
for(int i = size/2; i>=0; i--)
{
max_heapify(array, i);
}
}
void max_heapify(int*& array, int size, int index)
{
int leftChild = 2*index+1;
int rightChild = 2*index+2;
int largest;
int heap_size = size;
if( leftChild <= heap_size && array[leftChild] > array[index])
largest = leftChild;
else
largest = index;
if(rightChild <= heap_size && array[rightChild] > array[largest])
largest = rightChild;
if(largest != index) {
int tempArray = array[index];
array[index] = array[largest];
array[largest] = tempArray;
max_heapify(array, heap_size, largest);
}
}
int main()
{
int array[]={5,3,17,10,84,19,6,22,9};
int size = sizeof(array)/sizeof(array[0]);
build_max_heap(array, size);
return 0;
}
int array[]={5,3,17,10,84,19,6,22,9};
While array can be decayed to a pointer int* to be passed as a function argument, it the pointer cannot be passed as a "non-const reference" int*&, because it is immutable (it is a constant address). You could have passed it as a const reference like this:
void max_heapify(int* const& array, int size, int index)
// ^^^^^^
However, this doesn't make much sense, you can simply pass the pointer by value (a copy of the address of the array), which results in the same: the variable at the caller wont be changed. The usual use case of const& parameters is to pass objects that are expensive to copy, such as std::string. This does not apply to pointers; making a copy of a pointer is as cheap as copying any basic variable.
You should change your functions to take the pointer by value:
void build_max_heap(int* array, int size)
void max_heapify(int* array, int size, int index)
also, correct the call to max_heapify inside build_max_heap, give it the correct number of arguments:
void build_max_heap(int* array, int size)
{
for(int i = size/2; i>=0; i--)
{
max_heapify(array, size, i); // <-- 3 arguments
}
}