I have 4 sorted integer arrays, which i'm trying to merge into one huge sorted array.
I merge A and B together which gives me another int array called X
Then I merge C and D together which gives me another int array called Y
Finally i merge X and Y together to get Z, which is the final product.
The merge function is doing exactly the same each time, just storing the results into a different array which i want to pass in by reference.
I want to do something like this:
void mergeSort(int arr1[], int arr2, int &result[]){
...
}
But i get the error "Array of reference is not allowed". What is the best way to do this?
The syntax to pass an array by reference in C++ is
int (&result)[size]
note that you need to know the size at compile time. This is probably not what you want to do here and I would suggest to use vector<int>.
You can not write such a way the function because arrays even if they have elements of the same type but with different sizes are different types.
You need to write a template function
For example
template <size_t N1, size_t N2>
void mergeSort( int ( &arr1 )[N1], int ( &arr2 )[N2], int ( &result )[N1+N2])
{
...
}
Otherwise you need to pass to the function sizes of the arrays. For example
void mergeSort( int arr1[], size_t n1, int arr2[], size_t n2, int result[])
{
...
}
In this case it is assumed that the size of array result at least is not less than n1 + n2.
void mergeSort( int *arr1, int *arr2, int sizeOfArray, int *result[] )
{
...
}
I think the answers above give you what is likely a better solution than what you are doing. But if you absolutely insist on taking arrays (by reference and want to leave the size "unspecified"), do the following:
template <unsigned int SIZE> void mergeSort(int arr1[], int arr2, int (&result)[SIZE]){
}
Then you can pass any size arrays to it and the template argument deduction process will figure out the size at compile time.
Please note that this will not work with VLA's if your implementation supports VLA's.
Related
I have to define a function to delete an element in an array, here is the code
void delete_element(int a[], int n, int pos)
{
if (pos>=n)
pos=n-1;
else if (pos<0)
pos=0;
for (int i=pos-1;i<n-1;i++)
{
a[i]=a[i+1];
}
--n;
}
and here is an example:
int n;
printf("Enter the length of the array: ");
scanf("%d", &n);
int A[n]
for (int i=0;i<n;i++)
scanf("%d", &A[i]);
delete_element(A,n,2);
suppose that n=5 and A = {1,2,3,4,5}, after running the above code, it will print out {1,3,4,5,5}
When I use int n as parameter, the function deletes the element I want but the last element will appear twice in the array. I searched and then found out that by using int &n, the problem will be solved but I don't understand the reasons here. I would really appreciate if you could help me with this!
If you use void delete_element(int a[], int n, int pos), the arguments are copied to the function.
So if you decrease n by using --n;, it will only affect the "local" n, the copy.
If you use void delete_element(int a[], int& n, int pos), the parameter n is padded by referece. This means, there is no local copy used in the function but the variable n from the "outside world".
Therefore, --n; will now affect the variable which is given as a parameter to your function.
You could create the same behavior by passing a pointer to the variable. In that case, the address is copied, but instead of the copied address the memory location it points to, the original variable, will be modified.
This function doesn't delete an element in an array actually, because it just overlaps the data at pos with the next data, and the size is not changed.
It seems that n is array's size, so when you use int n, the size is passed as value, so outer n is not changed. And when you use int& n, the size is passed as reference, so n will be changed.
If you want to delete an element in array actually, you may refer to pop_back() or pop_front() function of vector.
I am trying to write a function that prints out the elements in an array. However when I work with the arrays that are passed, I don't know how to iterate over the array.
void
print_array(int* b)
{
int sizeof_b = sizeof(b) / sizeof(b[0]);
int i;
for (i = 0; i < sizeof_b; i++)
{
printf("%d", b[i]);
}
}
What is the best way to do iterate over the passed array?
You need to also pass the size of the array to the function.
When you pass in the array to your function, you are really passing in the address of the first element in that array. So the pointer is only pointing to the first element once inside your function.
Since memory in the array is continuous though, you can still use pointer arithmetic such as (b+1) to point to the second element or equivalently b[1]
void print_array(int* b, int num_elements)
{
for (int i = 0; i < num_elements; i++)
{
printf("%d", b[i]);
}
}
This trick only works with arrays not pointers:
sizeof(b) / sizeof(b[0])
... and arrays are not the same as pointers.
Why don't you use function templates for this (C++)?
template<class T, int N> void f(T (&r)[N]){
}
int main(){
int buf[10];
f(buf);
}
EDIT 2:
The qn now appears to have C tag and the C++ tag is removed.
For C, you have to pass the length (number of elements)of the array.
For C++, you can pass the length, BUT, if you have access to C++0x, BETTER is to use std::array. See here and here. It carries the length, and provides check for out-of-bound if you access elements using the at() member function.
In C99, you can require that an array an array has at least n elements thusly:
void print_array(int b[static n]);
6.7.5.3.7: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within the [ and ] of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.
In GCC you can pass the size of an array implicitly like this:
void print_array(int n, int b[n]);
You could try this...
#include <cstdio>
void
print_array(int b[], size_t N)
{
for (int i = 0; i < N; ++i)
printf("%d ", b[i]);
printf("\n");
}
template <size_t N>
inline void
print_array(int (&b)[N])
{
// could have loop here, but inline forwarding to
// single function eliminates code bloat...
print_array(b, N);
}
int main()
{
int a[] = { 1, 2 };
int b[] = { };
int c[] = { 1, 2, 3, 4, 5 };
print_array(a);
// print_array(b);
print_array(c);
}
...interestingly b doesn't work...
array_size.cc: In function `int main()':
array_size.cc:19: error: no matching function for call to `print_array(int[0u])'
JoshD points out in comments below the issue re 0 sized arrays (a GCC extension), and the size inference above.
In c++ you can also use a some type of list class implemented as an array with a size method or as a struct with a size member(in c or c++).
Use variable to pass the size of array.
int sizeof_b = sizeof(b) / sizeof(b[0]); does nothing but getting the pre-declared array size, which is known, and you could have passed it as an argument; for instance, void print_array(int*b, int size). size could be the user-defined size too.
int sizeof_b = sizeof(b) / sizeof(b[0]); will cause redundant iteration when the number of elements is less than the pre-declared array-size.
The question has already some good answers, for example the second one. However there is a lack of explanation so I would like to extend the sample and explain it:
Using template and template parameters and in this case None-Type Template parameters makes it possible to get the size of a fixed array with any type.
Assume you have such a function template:
template<typename T, int S>
int getSizeOfArray(T (&arr)[S]) {
return S;
}
The template is clearly for any type(here T) and a fixed integer(S).
The function as you see takes a reference to an array of S objects of type T, as you know in C++ you cannot pass arrays to functions by value but by reference so the function has to take a reference.
Now if u use it like this:
int i_arr[] = { 3, 8, 90, -1 };
std::cout << "number f elements in Array: " << getSizeOfArray(i_arr) << std::endl;
The compiler will implicitly instantiate the template function and detect the arguments, so the S here is 4 which is returned and printed to output.
I am trying to make some functions working on two dimensional arrays:
void display_matrix(int**, int, int);
void gen_matrix(int**, int, int);
int main()
{
srand(time(0));
int m=5, n=3;
int my_matrix[m][n];
gen_matrix(my_matrix, m, n);
display_matrix(my_matrix, m, n);
}
I don't know what's wrong, but I get the following error when I call the functions:
[Error] cannot convert 'int ()[(((sizetype)(((ssizetype)n) + -1)) + 1)]' to 'int*' for argument '1' to 'void gen_matrix(int**, int, int)'
I know I can use vector but I am trying to practise and remember the use of pointers and arrays.
Declaring a matrix in the form <type> <name>[<dim1>][<dim2>] defines a block of memory with an implicit stride of dim1. Internally elements are accessed by using multiples of dim1 to reach the correct row and offsetting from there by the second dimension.
the type <type> <name>** is a pointer to an array of pointers - very different. The structure consists of an array of pointers to rows of data. These have to be allocated and linked appropriately before calling the subroutine. There is also no requirement that they are contiguously allocated, and an indirect lookup needs to be done to each an element on each new row.
The advantage is that the rows can be different lengths suiting some algorithms that do not have rectangular structure.
Change the code the following way
const int n = 3;
void display_matrix( int ( * )[n], int );
void gen_matrix( int ( * )[n], int);
int main()
{
srand(time(0));
const int m = 5;
int my_matrix[m][n];
gen_matrix( my_matrix, m );
display_matrix(my_matrix, m );
}
Or you can keep your functions as defined but call them for example as
gen_matrix( reinterpret_cast<int **>( my_matrix ), m, n);
Here is my problem:
I have a struct:
struct point
{
int x;
int y;
};
and then I have an array:
for (int i = 0;i < n;i++)
{
arr[i].x=rand() % n + 1;
}
I defined the quicksort function as follows:
void quicksort(int *a, int left, int right);
and I want to sort the point by X coordinate, so I call the quicksort:
quicksort(arr.x, 0, n-1);
And this is the error message:
error: request for member 'x' in 'arr', which is of non-class type 'point [(((unsigned int)(((int)n) + -0x000000001)) + 1)]'
Sorry if the question is too stupid or badly formulated, the truth is I'm a newbie and I'm really willing to learn as much as possible and I'd be very thankful for your help!
If you always want to sort by x, then you can hard-code it into the sort function, and just pass a pointer to the array to sort:
void quicksort(point * arr, int left, int right) {
// test points with
// if (arr[i].x < arr[j].x) {/* i sorts before j */}
}
quicksort(arr, 0, n-1);
To specify a class member to sort by, you need a pointer-to-member, not a pointer; something like:
void quicksort(point * arr, int point::*member, int left, int right){
// test points with
// if (arr[i].*member < arr[j].*member) {/* i sorts before j */}
}
quicksort(arr, &point::x, 0, n-1);
More generically, you could follow the example of std::sort and accept any comparison functor:
template <typename RandIter, typename Compare>
void quicksort(RandIter begin, RandIter end, Compare compare) {
// test points with
// if (compare(*it1, *it2)) {/* *it1 sorts before *it2 */}
}
quicksort(arr, arr+n,
[](point const &lhs, point const &rhs) {return lhs.x < rhs.x;});
And of course, unless you're learning how to implement a sorting algorithm, just use std::sort.
quicksort(arr,0,n-1);
then within quicksort, try to compare the arr[i].x
There are a few problems with your code.
1. quicksort accepts int* but you try to pass int value x
2. You try to pass int but you actually call an undefined variable arr.x
What you need to do is either call in the form of &arr[i].x, but to accomplish what you want, you probably want to pass the entire struct as a pointer.
You need to pass arr as the parameter, as that is the array to be sorted. arr.x is meaningless. You are not passing the string "arr.x" as a parameter which can somehow be interpreted as meaning sort on the x field - when the compiler sees this, it is looking for an x element of arr, which doesn't exist, as the error message suggests - only the elements of arr (e.g. arr[0]) have x elements (accessed as arr[0].x).
Assuming this is for academic purposes (why else would you declare your own sorting algorithm instead of using one of the ones already implemented with a custom comparator?), you can do this a few ways:
Array
std::array<point, 10> myArray; // declares an array of size 10 for points
template<size_t N>
void quicksort(std::array<point, N>& arr, ...)
{
// implement sort operating on arr
}
Vector
std::vector<point> myVector; // declares a dynamic array/vector of points
void quicksort(std::vector<point>& arr, ...)
{
// implement sort operating on arr
}
If for some god-awful reason, you want to keep it in C:
Legacy
const size_t SIZE = 10;
point arr[SIZE]; // declare an array of 10 points
void quicksort(point* p, const size_t n, ...)
{
// implement sort operating on elements in p passing in SIZE for n
}
I'd rather defined the function as:
void quicksort(void *a,int left,int right, size_t size, int (*fp)(void*,void*));
size is the size of one element of array and fp is a compare function which returns true if the two arguments are equal. Now you can pass the call the function as:
quicksort(arr,0,n-1,sizeof(arr)/sizeof(arr[0]), compare);
where function compare is something like:
int compare(void* a, void* b) { return *((int*)a) >= *((int*)b); }
Rest of the implementation of function is trivial I think.
(almost) never try to fool the system by passing a pointer to a member when you really want to pass a pointer to an object. Do as Grijesh suggested. Passing a member can lead to horrible side effects. For example, quicksort is going to sort all the integers together, regardless of which of them are X's and which are Y's. In milder cases you may get wrong compare criteria, and often hard to debug effects such as incorrect pointer optimization. Just be honest with the compiler and pass the object pointer if you need to pass an object pointer. There are very very very few exceptions, mostly to do with low-level system programming where the "other side' of the function call won't be able to handle the object.
I have got a small problem with 1D array in c++. I have got a function line this:
void func(int (&array)[???])
{
// some math here;
"for" loop {
array[i] = something;
}
}
I call the functions somewhere in the code, and before I made math I'm not able to know dimension of the array. The array goes to the function as a reference!, because I need it in the main() function. How I can allocate array like this?, so array with ?? dimension goes to the function as reference then I have to put the dimension and write to it some values.
Since you're using C++, why not use a std::vector<> instead?
Other have mentioned that you should use std::vector in C++ and they are right.
But you can make your code work by making func a function template.
template <typename T, size_t N>
void func(T (&array)[N])
{
// some math here;
"for" loop {
array[i] = something;
}
}
Use a pointer, not a reference:
void func(int *a, int N);
Or, easier, use a vector:
void func(std::vector<int> &a);
Vectors can be allocated by simply saying
std::vector<int> a(10);
The number of elements can be retrieved using a.size().
If the array you pass to func is a stack array, and not a pointer, you can retain its size by using a function template:
template <class T, size_t N>
void func(T(&array)[N])
{
size_t array_length = N; // or just use N directly
}
int main()
{
int array[4];
func(array);
}
That said, as others have already pointed out, std::vector is probably the best solution here.
As well as vector which has been suggested you could possibly use valarray which is also part of STL and is intended specificially to handle mathematical collections.
What you have to realize, is that arrays are pointers. A definition like int array[5] will allocate space for 5 integers on the stack and array will be the address of the first value. Thus, to access the first value in the array, you can write
array[0] or *array (which is the same as *(array + 0))
In the same way to retrieve the address of the third element, you can write
&array[2] or array + 2
Since arrays are pointers, you don't have to worry about the runtime size of your array if you would like to pass it to a function, simply pass it as a pointer:
void func(int *array)
{
int size;
//compute size of the array
for (int i = 0; i < size; ++i)
{
//do whatever you want with array[i]
}
}