How do sort operator works? - c++

(Here a is an array, asize is the size of array.)
My question is that can someone explain why sort requires 'a' and 'a + asize' in it and what it does with it?

a is an array. In various contexts, when an array is referring to by just its name, it will decay into a pointer to its 1st element.
Adding asize to such a pointer will perform pointer arithmetic to advance the pointer by asize number of elements.
std::sort() takes 2 iterators as input, denoting a range of values [start, end). Meaning it will loop through and sort the values including start up to, but not including, end.
Pointers to elements in an array are valid iterators. So, a statement like sort(a, a + asize) is the same as sort(&a[0], &a[asize]).

Credit: Branko Dimitrijevic
So the a is a pointer that points towards the beginning of the array and a+asize would be the pointer to the "imaginary" that exists immediately after the last real element of array.

Related

Why do we write arr + n in sort function?

sort (arr, arr + n)
Why do we write arr + n in sort function in (function in algorithm library) C++. What does it mean arr + n?
std::sort accepts iterators to beginning and end of some range (end points to first element beyond range).
A pointer can be an iterator
In C an array of type sometype[n] decays to a pointer of type: sometype*. So arr is treated as a pointer and arr + n advances this pointer by n elements (so it point to first element beyond array).
Now alternative ways to write this code to make it more clear and less bug prone:
std::sort(std::begin(arr), std::end(arr));
// or using C++20 ranges:
std::ranges::sort(arr);
Given the declaration of type arr[], the expression arr + n is evaluated as the address of the nth element in arr.
In other words (hoping that it helps clarifying), arr + n is equivalent to &arr[n].
std::sort takes a pair of iterators and them uses std::swap to sort the elements in that range.
The iterators must provide implementations for operator* and operator++. These requirements are defined as "named requirements" here.
If you thing about it, any pointer fulfills these criteria.
In other words, you can think of iterators as a generalization of pointers. By passing a pointer to the first &arr[0] and a pointer to one past the last element &arr[n] you are providing the begin and end iterators. arr and arr + n are fancy abbreviations for &arr[0] and &arr[n].

How to get the begin and end of an array that was created by new

int[] a = {1,2,3};
int* b = new int[3]{4,5,6};
I want to get the begin and end of b. std::begin()works in abut not in b. Is there an suitable way to get the two positions of b?
If you see a reference to std::begin and std::end you will see that beginning and end iterators are in way pointers to the first and one-beyond-last elements of the container. For arrays this is doubly-true because then you can use actual pointers for the iterators.
For an array like a the std::begin function returns a pointer to the first element, and the std::end function returns a pointer to one beyond the last element.
Now when you know that information it's easy to figure out what "begin" and "end" iterators for a pointer is, because it's exactly the same as for an array. I.e. pointers to the first and one-beyond-last elements.
In the case of your example, the "begin iterator" is simply b (because it points to the first element), and the "end iterator" is b + 3 which is a pointer to one beyond the last element.

Check Arrays for same entries

I have two Arrays of doubles. One Array will be sorted and after this I want to check if every Element of the original Array is still in the sorted Array. I used the find() function of C++ but this pointer only points to the first Element if found, e.g. if you have as original Array {1, 1 ,1 ,1}, the sorted one is {1, 1, 1, 1} but find() only points to the first Element.
Do I really need to loop through the original Array and count the number of times the Elements occure and then loop through the sorted Array and do the same?
Since you just want to check if your array was sorted correctly, you can just sort the other array with std::sort which works correctly for sure and then compare the results:
your_sort(first_array);
std::sort(second_array.begin(),second_array.end());
bool sort_worked = std::equal(first_array.begin(),first_array.end(),
second_array.begin());
Just in case you did not know:
Every standard library-container has the begin() and end() member functions.
You should always use them, use std::vector as your default data structure and another standard container iff you have a good reason to do so. Do not use C-style arrays.
The find() function returns a pointer to the first occurence of the
desired element within a range.
std::find(first, last, value_to_be_searched)
if the element was not found it returns 'last'. You can loop through your
first array and just check that for each element the find function
returns something different from 'last' when called on your second array.

How can I sort an array passed as a parameter?

I have to write a method within already-written code that passes me an array directly. However once inside my method that array has become a pointer to the first object in the array. So now I have done some calculations and want to sort the array. But since it's now not considered an array, I can't perform the sort() function.
What's the best way to sort an array when I only have the pointer to work with?
You either need to know the number of elements in the array, passed as a separate parameter or have a pointer to one past the last element.
void my_sort(int* p, unsigned n) {
std::sort(p, p+n);
}
or
void my_sort2(int* p, int* p_end) {
std::sort(p, p_end);
}
and you would call them
int a[] = { 3, 1, 2 };
my_sort(a, sizeof a / sizeof a[0]); // or 3...
my_sort2(a, &a[2] + 1); // one past the last element! i.e. a+3
In c there is essentially no difference between an "array" and a "pointer to the first object in the array". Arrays are referred to using their base pointer, that is, pointer to first object.
Technically precise explanation at Array base pointer and its address are same. Why?
So, just sort the array as you would anywhere else. Got an example sort or sample code in mind or is that sufficient?
Sort it exactly as you would sort it before you passed it in. If your sort() function requires a length, then pass the length as an additional parameter.
The best would be if you could start using std::array from C++11 on:
http://en.cppreference.com/w/cpp/container/array
This way, you would also have the size known and accessible by the corresponding size method. You could also consider other std container types rather than raw array. In general, it is better to avoid raw arrays as much as possible.
Failing that, you would need to know the size of the array either through function parameter, or other means like class member variable if it is happening inside a class, and so on.
Then, you could use different type of sorting algorithms based on your complexity desire; let it be quick sort, bubble sort, heap sort, stable sort, etc... it depends on what kind of data, the array represents, etc.
One sorting algorithm is to use std::sort. Therefore, you would be writing something like this:
std::sort (mystdarray.begin(), mystdarray.end());
or
std::sort (myrawarray, myrawarray+size);

Can I move through an array by incrementing a pointer? Qt

Let's say I have an array of QStrings and a QString pointer. I want to use the pointer to iterate through the entire array; could I do this?
QString * strPointer;
QString data[100];
strPointer = & data[0]; //address to first element
strPointer ++; //address to second element
Would this be valid or am I doing something wrong?
You're on the right lines. Here's one way
QString data[100];
for (QString* strPointer = &data[0]; strPointer != &data[100]; ++strPointer)
{
...
}
Yes, this is fine so long as the type of the pointer matches what's actually being pointed to in the array. By incrementing a pointer you are performing pointer arithmetic.
It may be interesting to note that because iterators in the Standard Library are written to look & feel like pointers in many ways, and all the Standard Library algorithms take iterators specified as template parameters, it is legal and well-defined to use these algorithms with raw pointers as well. For example, this is perfectly legitimate, even with your pointers:
const size_t num_data = sizeof(data)/sizeof(data[0]);
std::copy( &data[0], &data[num_data], ostream_iterator<QString>(cout,"\n") );
...assuming of course you have implemented operator<< for a QString object.
Now, all this being said, take a look at this:
QString data[100];
The 100 here is what's called a Magic Number. The use of Magic Numbers is widely considered to be an anti-pattern, or a bad practice. Ask yourself a couple questions:
How do you know that 100 elements will be enough?
If you don't need 100 elements, are you being wasteful?
If you need more than 100 elements, will your program crash?
It's best to avoid using magic numbers wherever you can. Your choice of 100 here is arbitrary. It would be better to use a collection type that grows and shrinks as you add and remove objects. std::vector is a good place to start:
std::vector<QString> data;
Now you can add items:
data.push_back( ... );
...remove them, and iterate easily, using iterators:
std::copy( data.begin(), data.end(), ostream_iterator<QString>(cout,"\n") );
Yes, it is. Remember about checking index - operator++ can go "too far" - beyond the array.
Yes, incrementing a pointer to an element of an array will produce a pointer to the next element or to a position one past the end of the array.
When an expression that has integral type is added to or subtracted
from a pointer, the result has the type of the pointer operand. If the
pointer operand points to an element of an array object, and the array
is large enough, the result points to an element offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integral expression.
In other words, ifthe expression P points to the i-th element of an
array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
(where N has the value n) point to, respectively, the i + n-th and i −
n-th elements of the array object, provided they exist. Moreover, if
the expression P points to the last element of an array object, the
expression (P)+1 points one past the last element of the array object,
and if the expression Q points one past the last element of an array
object, the expression (Q)-1 points to the last element of the array
object. If both the pointer operand and the result point to elements
of the same array object, or one past the last element of the array
object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. — [expr.add] 5.7 /5