I'm a student & i looked up this function in a book. It works as it should but i don't quite understand the inner workings of the sortFunction() which is passed to the qsort() function. If some one could explain it in detail, please do. Thanks in advance.
#include<iostream>
#include<stdlib.h>
using namespace std;
//form of sort function required by qsort()
int sortFunction(const void *intOne,const void *intTwo);
const int tableSize = 10;
int main()
{
int i, table[tableSize];
//fill the table with values
for(i = 0; i < tableSize; i++)
{
cout << "Enter value " << (i + 1) << " : ";
cin >> table[i];
}
cout << "\n";
//sort values
qsort((void*)table, tableSize, sizeof(table[0]), sortFunction);
//print the results
for(i = 0; i < tableSize; i++)
{
cout << "Value " << (i + 1) << " : " << table[i] << endl;
}
cout << "\nDone\n";
return 0;
}
int sortFunction(const void *a, const void *b)
{
int intOne = *((int*)a);
int intTwo = *((int*)b);
if (intOne < intTwo)
{
return -1;
}
if (intOne == intTwo)
{
return 0;
}
return 1;
}
If you look at the actual call to qsort...
qsort((void*)table, tableSize, sizeof table[0], sortFunction);
...you'll see it provides:
a void* address and the size (in bytes) of the entire data array to be sorted, then
the size of one data element in that array, then
a pointer to the comparison function "sortFunction".
There's no argument passed that allows qsort to know what the type of the element is - i.e. how the individual bits in any single data element are used to represent some data value - so there's no way qsort can meaningfully compare two such elements. When you supply...
int sortFunction(const void *a, const void *b)
{
int intOne = *((int*)a);
int intTwo = *((int*)b);
...and qsort calls it, you're getting two pointers - they're to memory addresses but when qsort calls sortFunction those void pointers still tell you nothing about the data element type, as qsort has no insight itself to pass along. The last two lines of code above are where you - the programmer coordinating the qsort call - reapply the knowledge you've had all along about what the data element type is: in this case, they're ints, so you cast each void* to an int* (using (int*)a), then dereference that int* to get the int at memory address a. Similarly for b. In doing so, you've recovered the two numbers that were there as numbers. Then, the job of sortFunction is to indicate how they should be ordered when sorting finishes. To indicate that a should be first, sortFunction can return any negative value (e.g. -1); if they're equivalent, return 0;, and if b should be first, return any positive value (e.g. 1). qsort() receives that information and uses it to work out how to shuffle the data elements around as it sorts.
FWIW, C lets you express that a bit more succinctly as...
return intOne < intTwo ? -1 :
intOne == intTwo ? 0 :
1;
...or (faster, but relying on boolean comparison results being 0 and 1, which may confuse some programmers reading your code)...
return (intOne > intTwo) - (intOne < intTwo);
...or, if you're sure the following can never be mathematically less than INT_MIN (such values wrap around to a big positive number inappropriately)...
return intOne - intTwo;
sortFunction isn't actually doing the sorting, it is being used as a comparison function to determine whether one element should precede another in the sorted list.
What you called 'sortFunction' is normally called a comparator. It basically tells the generic sort code in qsort() whether two elements in the array being sorted compare equal (0), or whether the first argument sorts before the second (<0) or the first argument sorts after the second (>0).
With that information, plus the size of each row, plus the number of rows in the array and the start of the array, the qsort() function can order the data correctly.
As you can see in documentation, qsort function takes a comparator as it's last parameter. This function is used to actually compare parameters (tell which one should go first in a sorted array).
Related
I am trying out some codes that is based on finding all possible combinations that add up to a integer's value that is declared in the main function. However, the problem is when I call the function "findCombinations(n);", it gives an error at "int arr[n];". That is the only line which has an error which is stopping me from running the program. If you know of a solution, do let me know.
#include <iostream>
using namespace std;
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0) ? 1 : arr[index - 1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
int main()
{
int n = 10;
findCombinations(n);
return 0;
}
C-style array dimensions must be known at compile-time in Standard C++.
You can make n be a compile-time function parameter like this:
template<int n>
void findCombinations()
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
int main()
{
const int n = 10;
findCombinations<n>();
return 0;
}
From http://www.cplusplus.com/doc/tutorial/arrays/:
NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
While some compilers will allow it, you should avoid dynamic size arrays.
Here are a few options:
If the size of the array will always be 10, initiate it to hard-coded const 10.
Use std::shared_ptr to an array pointer:
std::shared_ptr pArray;
pArray=std::make_shared(n)
Use std::vector to dynamically allocate the size. (IMHO this is the preferred option).
use c-style pointers (IMHO should only be used as last resort)
Template class (wasteful, as it created and compiles many instances of the same function)
Type of variable arr must be known at compile time. If you need storage of variable size, you have to allocate it.
Possible alternative (one of many)
#include <vector>
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
std::vector<int> arr(n); // allocate n elements
//find all combinations
findCombinationsUtil( &*arr.begin(), 0, n, n);
}
if compiler at least partially complies to C++11 e.g. it's late gcc 4.6 or higher or VS2010 and higher, then there is method data() that returns pointer to internal storage. But better to rewrite, templatize or overload findCombinationsUtil to use a container or iterator
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<>!
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.
I am trying to loop through the array and get the elements inside in C++. Here is my code:
int result;
int index_array [] = {11,12,13,14,15,16,17,18,19,20};
for (int count =0; count < index_array.length() ; count++){
if(count%2 == 0){
cout << "Elements at the even index are " << index_array[count] << endl;
}
}
If I change the for loop to:
for (int count =0; count < 10 ; count++){
There is no error because my array only consists of 10 items. But if I used the .length() method, there is an error which is expression must have a class type. I have no idea what is it, as in if it is in Eclipse, there contains a more detailed error description. What might be wrong?
Updated answer
for (int count =0; count < sizeof(index_array)/sizeof(index_array [0]) ; count++){
if((count+1)%2 == 0){
cout << "Elements at the even index are " << index_array[count] << endl;
}
}
You can't call length() on int index_array[], it is a primitive array, not an object.
You could call size(), if you have, for example vector<int> index_array.
There is not .length for a plain array in C++.
Instead use std::vector and you can use method size() :
std::vector<int> index_array {11,12,13,14,15,16,17,18,19,20};
for (int count =0; count < index_array.size() ; count++){
if(count%2 == 0){
cout << "Elements at the even index are " << index_array[count] << endl;
}
}
Also in your case, you can calculate the length of the array:
int length = sizeof(index_array)/sizeof(index_array[0]);
int index_array [] = {11,12,13,14,15,16,17,18,19,20};
This is not an object that you can invoke some length() method on. Instead, it's a regular array, just like in C.
You can do one of two things.
The first is to use one of the C++ collection classes such as std::vector (adjustable size) or std::array (constant size) with their size() methods:
// C++11 syntax
std::vector<int> index_array {11,12,13,14,15,16,17,18,19,20};
// Pre C++11 syntax
int ia_src[] = {11,12,13,14,15,16,17,18,19,20};
vector<int> index_array (ia_src, ia_src + sizeof (ia_src) / sizeof (*ia_src));
std::array<int,10> index_array = {11,12,13,14,15,16,17,18,19,20};
The second is to simply treat the array as an array, in which case the length of that array can be found with the expression:
sizeof (index_array) / sizeof (*index_array)
Just be aware that this only works for arrays. If you pass that array to a function, it will decay to a pointer to the first element and sizeof will no longer work as you expect. You need to get the size while it's still an array and pass that along with it.
Arrays in c++ are not object (classes) so they don't have neither methods nor attributes.
May be you can use the Array class instead and get the size like std::array::size()
I'm trying to find and fix what is wrong with this code. It's a binary search implemented by recursion. I dont know why it's returning stack overflow and crashing.
bool find( const int x, const int* pBegin, const int* pEnd)
{
int medel = (*pBegin +(( *pEnd-1) - *pBegin)/2) ;
if(x == medel)
return true ;
else if( x > medel)
{
int begin = (medel +1);
return find (x, &begin, pEnd);
}
else if( x< medel)
{
int last = (medel-1);
return find(x,pBegin, &last);
}
}
void main()
{
int arr[10];
for (int i=0;i<10;++i)
arr[i] = i;
bool hittat = find(7, &arr[0], &arr[9]);
cout << "hittat = " << hittat << endl;
system("pause");
}
When I debug the code, I see that when the function "find" is called it takes weird arguments, like in this pic.
It should take 0 and 9, not these huge numbers :/
Is there anything wrong with my pointers?
You should compute the average of the pointers and check what it's the value of the element hallway between them. Instead you compute the average of the values pointed by them which is significantly different.
You're using medel (I'm assuming that should be middle) as a pointer to an int in some places, but as an int in others.
Try declaring it like this:
const int* middle = pBegin + (pEnd - pBegin + 1) / 2;
Then, when you want to access what is stored there, use *medel.
Also, you'll need a second terminating condition (for when it won't be found). Something like:
if (((middle == pEnd) && (x > *middle)) ||
((middle == pBegin) && (x < *middle))) {
// Terminating condition
return false;
}
You are mixing pointer on int and int with your medel, just set it to be a pointer and access his data with *medel
The problem shown in your picture looks like it was taken from your original code as seen in a prior question. There you had pEnd pointing past the end of an array, so that dereferencing it was not allowed (and yields weird values).
That should not occur with the code as posted.
Your current code only uses pointers to valid integers. But most of those don't point into your array, so what you do is not a search in your array. The program simply does calculations with integers. Only the values of the first and last element of your array are ever used.
The program is confusing, because you pass around the integer values as pointers to their storage. While you start with pointers into your array, you then mix in pointers to automatic variables (beginand end), where you have stored a calculated value. (You never use pointers to array elements other than the first and last.