I am trying to sort a pointer array of characters using qsort and keep getting a segmentation fault when I compile. I will post the code for my qsort call and the compare function and any help would be greatly appreciated.
//count declaration
size_t count = (sizeof (strPtrsQsort)/sizeof (*strPtrsQsort));
//function call
qsort ((char *)ptr, size, sizeof(char), compare);
//compare function
int compare (const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp (*ia, *ib);
}
Judging by your qsort call, you are sorting an array of char elements: the base pointer type is passed to qsort as char * value and the element size is sizeof(char). However, your comparison function is written for an array of pointers to char. That's completely incorrect and inconsistent. That is what is causing the crash.
In the accompanying text you state that you are "trying to sort a pointer array of characters". Why in that case are you specifying the element size as sizeof(char) and not as, say, sizeof (char *)?
Note that even when you're required to work with C-style raw arrays you can still use C++ STL algorithms, since pointers are in fact RandomAccessIterators. For example, this works:
#include <algorithm>
#include <iostream>
#include <cstring>
static
bool compare(const char *a, const char *b)
{
return std::strcmp(a, b) < 0;
}
int main()
{
const char *stringarray[] = {
"zyxulsusd",
"abcdef",
"asdf"
};
std::sort(stringarray, stringarray + 3, compare);
// -----------^
// Just like a normal iterator the end iterator points
// to an imaginary element behind the data.
for(int i = 0; i < 3; i++) {
std::cout << stringarray[i] << std::endl;
}
return 0;
}
The primary advantage of this approach is type safety and it avoids thus most pitfalls common with C-style functions like qsort.
Related
I am writing a simple function that returns the largest integer in an array. The problem I am having is finding the number of elements in the array.
Here is the function header:
int largest(int *list, int highest_index)
How can I get the number of integers in the array 'list'.
I have tried the following methods:
int i = sizeof list/sizeof(int); //returns incorrect value
int i = list.size(); // does not compile
Any help will be greatly appreciated!
C++ is based on C and inherits many features from it. In relation to this question, it inherits something called "array/pointer equivalence" which is a rule that allows an array to decay to a pointer, especially when being passed as a function argument. It doesn't mean that an array is a pointer, it just means that it can decay to one.
void func(int* ptr);
int array[5];
int* ptr = array; // valid, equivalent to 'ptr = &array[0]'
func(array); // equivalent to func(&array[0]);
This last part is the most relevant to your question. You are not passing the array, you are passing the address of the 0th element.
In order for your function to know how big the incoming array is, you will need to send that information as an argument.
static const size_t ArraySize = 5;
int array[ArraySize];
func(array, ArraySize);
Because the pointer contains no size information, you can't use sizeof.
void func(int* array) {
std::cout << sizeof(array) << "\n";
}
This will output the size of "int*" - which is 4 or 8 bytes depending on 32 vs 64 bits.
Instead you need to accept the size parameters
void func(int* array, size_t arraySize);
static const size_t ArraySize = 5;
int array[ArraySize];
func(array, ArraySize);
Even if you try to pass a fixed-sized array, it turns out this is syntactic sugar:
void func(int array[5]);
http://ideone.com/gaSl6J
Remember how I said that an array is NOT a pointer, just equivalent?
int array[5];
int* ptr = array;
std::cout << "array size " << sizeof(array) << std::endl;
std::cout << "ptr size " << sizeof(ptr) << str::endl;
array size will be 5 * sizeof(int) = 20
ptr size will be sizeof(int *) which will be either 4 or 8 bytes.
sizeof returns the size of the type being supplied, if you supply an object then it deduces the type and returns the size of that
If you want to know how many elements of an array are in the array, when you have the array and not a pointer, you can write
sizeof(array) / sizeof(array[0])
or
sizeof(array) / sizeof(*array)
There's no way to do that. This is one good reason (among many) to use vectors instead of arrays. But if you must use an array then you must pass the size of the array as a parameter to your function
int largest(int *list, int list_size, int highest_index)
Arrays in C++ are quite poor, the sooner you learn to use vectors the easier you will find things.
Pointers do not have information about the number of elements they refer to. If you are speaking about the first argument of the function call then if list is an array you can indeed use the syntax
sizeof( list ) / sizeof( int )
I would like to append that there are three approaches. The first one is to use arrays passed by reference. The second one is to use pointer to the first element and the number of elements. And the third one is to use two pointers - the start pointer and the last pointer as standard algorithms usually are defined. Character arrays have an additional possibility to process them.
The simple answer is you cannot. You need to store it in a variable. The great advantage with C++ is it has STL and you can use vector. size() method gives the size of the vector at that instant.
#include<iostream>
#include<vector>
using namespace std;
int main () {
vector<int> v;
for(int i = 0; i < 10; i++) {
v.push_back(i);
}
cout << v.size() << endl;
for(int i = 0; i < 10; i++) {
v.push_back(i);
}
cout << v.size() << endl;
return 0;
}
output:
10
20
Not tested. But, should work. ;)
You need to remember in a variable array size, there is no possibility to retrieve array size from pointer.
const int SIZE = 10;
int list[SIZE];
// or
int* list = new int[SIZE]; // do not forget to delete[]
My answer uses a char array instead of an integer array but I do hope it helps.
You can use a counter until you reach the end of the array. Char arrays always end with a '\0' and you can use that to check the end of the array is reached.
char array[] = "hello world";
char *arrPtr = array;
char endOfString = '\0';
int stringLength = 0;
while (arrPtr[stringLength] != endOfString) {
stringLength++;
}
stringLength++;
cout << stringLength << endl;
Now you have the length of the char array.
I tried the counting the number of integers in array using this method. Apparently, '\0' doesn't apply here obviously but the -1 index of the array is 0. So assuming that there is no 0, in the array that you are using. You can replace the '\0' with 0 in the code and change the code to use int pointers and arrays.
I am writing a simple function that returns the largest integer in an array. The problem I am having is finding the number of elements in the array.
Here is the function header:
int largest(int *list, int highest_index)
How can I get the number of integers in the array 'list'.
I have tried the following methods:
int i = sizeof list/sizeof(int); //returns incorrect value
int i = list.size(); // does not compile
Any help will be greatly appreciated!
C++ is based on C and inherits many features from it. In relation to this question, it inherits something called "array/pointer equivalence" which is a rule that allows an array to decay to a pointer, especially when being passed as a function argument. It doesn't mean that an array is a pointer, it just means that it can decay to one.
void func(int* ptr);
int array[5];
int* ptr = array; // valid, equivalent to 'ptr = &array[0]'
func(array); // equivalent to func(&array[0]);
This last part is the most relevant to your question. You are not passing the array, you are passing the address of the 0th element.
In order for your function to know how big the incoming array is, you will need to send that information as an argument.
static const size_t ArraySize = 5;
int array[ArraySize];
func(array, ArraySize);
Because the pointer contains no size information, you can't use sizeof.
void func(int* array) {
std::cout << sizeof(array) << "\n";
}
This will output the size of "int*" - which is 4 or 8 bytes depending on 32 vs 64 bits.
Instead you need to accept the size parameters
void func(int* array, size_t arraySize);
static const size_t ArraySize = 5;
int array[ArraySize];
func(array, ArraySize);
Even if you try to pass a fixed-sized array, it turns out this is syntactic sugar:
void func(int array[5]);
http://ideone.com/gaSl6J
Remember how I said that an array is NOT a pointer, just equivalent?
int array[5];
int* ptr = array;
std::cout << "array size " << sizeof(array) << std::endl;
std::cout << "ptr size " << sizeof(ptr) << str::endl;
array size will be 5 * sizeof(int) = 20
ptr size will be sizeof(int *) which will be either 4 or 8 bytes.
sizeof returns the size of the type being supplied, if you supply an object then it deduces the type and returns the size of that
If you want to know how many elements of an array are in the array, when you have the array and not a pointer, you can write
sizeof(array) / sizeof(array[0])
or
sizeof(array) / sizeof(*array)
There's no way to do that. This is one good reason (among many) to use vectors instead of arrays. But if you must use an array then you must pass the size of the array as a parameter to your function
int largest(int *list, int list_size, int highest_index)
Arrays in C++ are quite poor, the sooner you learn to use vectors the easier you will find things.
Pointers do not have information about the number of elements they refer to. If you are speaking about the first argument of the function call then if list is an array you can indeed use the syntax
sizeof( list ) / sizeof( int )
I would like to append that there are three approaches. The first one is to use arrays passed by reference. The second one is to use pointer to the first element and the number of elements. And the third one is to use two pointers - the start pointer and the last pointer as standard algorithms usually are defined. Character arrays have an additional possibility to process them.
The simple answer is you cannot. You need to store it in a variable. The great advantage with C++ is it has STL and you can use vector. size() method gives the size of the vector at that instant.
#include<iostream>
#include<vector>
using namespace std;
int main () {
vector<int> v;
for(int i = 0; i < 10; i++) {
v.push_back(i);
}
cout << v.size() << endl;
for(int i = 0; i < 10; i++) {
v.push_back(i);
}
cout << v.size() << endl;
return 0;
}
output:
10
20
Not tested. But, should work. ;)
You need to remember in a variable array size, there is no possibility to retrieve array size from pointer.
const int SIZE = 10;
int list[SIZE];
// or
int* list = new int[SIZE]; // do not forget to delete[]
My answer uses a char array instead of an integer array but I do hope it helps.
You can use a counter until you reach the end of the array. Char arrays always end with a '\0' and you can use that to check the end of the array is reached.
char array[] = "hello world";
char *arrPtr = array;
char endOfString = '\0';
int stringLength = 0;
while (arrPtr[stringLength] != endOfString) {
stringLength++;
}
stringLength++;
cout << stringLength << endl;
Now you have the length of the char array.
I tried the counting the number of integers in array using this method. Apparently, '\0' doesn't apply here obviously but the -1 index of the array is 0. So assuming that there is no 0, in the array that you are using. You can replace the '\0' with 0 in the code and change the code to use int pointers and arrays.
I'm trying to loop through a constant array of integers using pointers. My code is as follows:
void printArrayPointer(const int arr[], int n){
for (int *i = arr; i < arr + n; i++) {
cout << *i << ' ';
}
}
This gives me an error telling me that there is an invalid conversion from const int* to int*. I know how to do this using traversal by index (as in using the index of the elements in the array) but I'm trying to use pointers for this code.
As the compiler already told you, there is an error in the line:
for (int *i = arr;...
arr is const int[], i is int *. If the compiler allows i to be initialized with a const int * then the subsequent code can change the const values stored in a using i, because i is a pointer to non-const data. That's the reason the code doesn't compile and the compiler tells you in the error message.
You have to declare i as const int *i and it will work.
void printArrayPointer(const int arr[], int n){
for (const int *i = arr; i < arr + n; i++) {
cout << *i << ' ';
}
}
As axiac said, you must write for (const int* i ... because arr is a const int*.
The reason that you can still increment i is that const int* means that what is at i cannot be changed, by you can still change what i points to. So you cannot change the values in the array, but you can change the const pointer that iterates through them.
To make it so that you can't change what a pointer points to, you would have to declare it like this: int* const i. Then you could change what is at i but not what i points to. You could also make it so that neither could be changed, which could be written as const int* const i.
When print_array is called, the size of the int array[] parameter (count) isn't what was expected. It seems sizeof is not returning the size of the entire array which would be 5*sizeof(int) = 20.
namespace Util
{
void print_array(int array[])
{
size_t count = (sizeof array)/(sizeof array[0]);
cout << count;
// int count = sizeof(array)/sizeof(array[0]);
// for (int i = 0; i <= count; i++) cout << array[i];
}
}
int array_test[5]={2,1,5,4,3};
Util::print_array(array_test);
int array[] here becomes int* array, and sizeof(array) returns the same thing sizeof(int*). You need to pass an array by reference to avoid that.
template <size_t N>
void print_array(int (&array)[N]) {
std::cout << N;
}
int array[] = { 2, 1, 5, 4, 3 };
print_array(array);
Read this: it says the way to fix this, but for a quick description:
When a function has a specific-size array parameter, why is it replaced with a pointer?
Using sizeof(array) will work in the scope that the array is statically defined in. When you pass it into a function though the type gets converted into a pointer to the array element type. In your case, when you're in print_array it is an int*. So, your sizeof in in the function will be the size of a pointer on your system (likely 32 or 64 bits).
You can get around this with some fancy syntax like so (from the link above):
If you want that the array type is preserved, you should pass in a
reference to the array:
void foo ( int(&array)[5] );
but I'd say just pass the size in as well as another parameter, its more readable.
As this array is implemented as a thin overlay on pointers, the variable you have is just a pointer, so sizeof will return the size of your pointer.
The only way to know the length of an array is to place a terminating object, as the null character in C strings.
There is no other way to determine the size of an array if you only have a pointer to it.
Here's a trick: you can take a reference to an array of fixed size. You can use this to template-deduce the size.
#include <iostream>
char a [22];
char b [33];
void foo (char *, size_t size)
{
std :: cout << size << "\n";
}
template <size_t N>
void foo (char (&x) [N])
{
foo (x, N);
}
int main () {
foo (a);
foo (b);
}
This prints 22\n33\n
void print_array( int array[] ) is synonymous with void print_array( int *array ). No size information is passed when the function call is made, so sizeof doesn't work here.
For an algorithm like this, I like to use iterators, then you can do what you want... e.g.
template <typename Iterator>
void print(Interator begin, Iterator end)
{
std::cout << "size: " << std::distance(begin, end) << std::endl;
std::copy(begin, end, std::ostream_iterator<std::iterator_traits<Iterator>::value_type>(std::cout, ", "));
}
to call
print(a, a + 5); // can calculate end using the sizeof() stuff...
just an addition to all the answers already posted:
if you want to use an array which is more comfortable (like an ArrayList in java for instance) then just use the stl-vector container which is also able to return its size
All the following declarations are exactly same:
void print_array(int array[]);
void print_array(int array[10]);
void print_array(int array[200]);
void print_array(int array[1000]);
void print_array(int *array);
That means, sizeof(array) would return the value of sizeof(int*), in all above cases, even in those where you use integers (they're ignored by the compiler, in fact).
However, all the following are different from each other, and co-exist in a program, at the same time:
void print_array(int (&array)[10]);
void print_array(int (&array)[200]);
void print_array(int (&array)[1000]);
int a[10], b[200], c[1000], d[999];
print_array(a); //ok - calls the first function
print_array(b); //ok - calls the second function
print_array(c); //ok - calls the third function
print_array(d); //error - no function accepts int array of size 999
I have a single buffer, and several pointers into it. I want to sort the pointers based upon the bytes in the buffer they point at.
qsort() and stl::sort() can be given custom comparision functions. For example, if the buffer was zero-terminated I could use strcmp:
int my_strcmp(const void* a,const void* b) {
const char* const one = *(const char**)a,
const two = *(const char**)b;
return ::strcmp(one,two);
}
however, if the buffer is not zero-terminated, I have to use memcmp() which requires a length parameter.
Is there a tidy, efficient way to get the length of the buffer into my comparision function without a global variable?
With std::sort, you can use a Functor like this:
struct CompString {
CompString(int len) : m_Len(len) {}
bool operator<(const char *a, const char *b) const {
return std::memcmp(a, b, m_Len);
}
private:
int m_Len;
};
Then you can do this:
std::sort(begin(), end(), CompString(4)); // all strings are 4 chars long
EDIT: from the comment suggestions (i guess both strings are in a common buffer?):
struct CompString {
CompString (const unsigned char* e) : end(e) {}
bool operator()(const unsigned char *a, const unsigned char *b) const {
return std::memcmp(a, b, std::min(end - a, end - b)) < 0;
}
private:
const unsigned char* const end;
};
With the C function qsort(), no, there is no way to pass the length to your comparison function without using a global variable, which means it can't be done in a thread-safe manner. Some systems have a qsort_r() function (r stands for reentrant) which allows you to pass an extra context parameter, which then gets passed on to your comparison function:
int my_comparison_func(void *context, const void *a, const void *b)
{
return memcmp(*(const void **)a, *(const void **)b, (size_t)context);
}
qsort_r(data, n, sizeof(void*), (void*)number_of_bytes_to_compare, &my_comparison_func);
Is there a reason you can't null-terminate your buffers?
If not, since you're using C++ you can write your own function object:
struct MyStrCmp {
MyStrCmp (int n): length(n) { }
inline bool operator< (char *lhs, char *rhs) {
return ::strcmp (lhs, rhs, length);
}
int length;
};
// ...
std::sort (myList.begin (), myList.end (), MyStrCmp (STR_LENGTH));
Can you pack your buffer pointer + length into a structure and pass a pointer of that structure as void *?
You could use a hack like:
int buffcmp(const void *b1, const void *b2)
{
static int bsize=-1;
if(b2==NULL) {bsize=*(int*)(b1); return 0;}
return memcmp(b1, b2, idsize);
}
which you would first call as buffcmp(&bsize, NULL) and then pass it as the comparison function to qsort.
You could of course make the comparison behave more naturally in the case of buffcmp(NULL, NULL) etc by adding more if statements.
You could functors (give the length to the functor's constructor) or Boost.Lambda (use the length in-place).
I'm not clear on what you're asking. But I'll try, assuming that
You have a single buffer
You have an array of pointers of some kind which has been processed in some way so that some or all of its contents point into the buffer
That is code equivalent to:
char *buf = (char*)malloc(sizeof(char)*bufsize);
for (int i=0; i<bufsize; ++i){
buf[i] = some_cleverly_chosen_value(i);
}
char *ary[arraysize] = {0};
for(int i=0; i<arraysize; ++i){
ary[i] = buf + some_clever_function(i);
}
/* ...do the sort here */
Now if you control the allocation of the buffer, you could substitute
char *buf = (char*)malloc(sizeof(char)*(bufsize+1));
buf[bufsize]='\0';
and go ahead using strcmp. This may be possible even if you don't control the filling of the buffer.
If you have to live with a buffer handed you by someone else you can
Use some global storage (which you asked to avoid and good thinking).
Hand the sort function something more complicated than a raw pointer (the address of a struct or class that supports the extra data). For this you need to control the deffinition of ary in the above code.
Use a sort function which supports an extra input. Either sort_r as suggested by Adam, or a home-rolled solution (which I do recommend as an exercise for the student, and don't recommend in real life). In either case the extra data is probably a pointer to the end of the buffer.
memcmp should stop on the first byte that is unequal, so the length should be large, i.e. to-the-end-of-the-buffer. Then the only way it can return zero is if it does go to the end of the buffer.
(BTW, I lean toward merge sort myself. It's stable and well-behaved.)