Sorting an array by reference - c++

I made a simple routine to sort an array witch accepts as a parameter an array of ints the problem is that when i compare the values array[i] shows the correct value in the debugger but array[i + 1] shows a bogus value ... i guess is a pointer issue but i can't figure it out what i am doing wrong.
Here is the code :
typedef int vector[10];
void task1(vector * param)
{
bool ordered = false;
while (!(ordered))
{
int tmp = 0;
ordered = true;
for (int i = 0; i < 9 ; i++)
{
if (*param[i] > *param[i+1])
{
tmp = *param[i];
*param[i] = *param[i + 1];
*param[i + 1] = tmp;
ordered = false;
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
vector tavi = {10,88,77,192,7,27,82,1,882,13};
task1(&tavi);
for (int i = 0 ; i < 10 ; i ++)
printf("%d ",tavi[i]);
_getch();
return 0;
}

The subscript-operator ([]) has a higher precedence than the derefence-operator (*), so *param[i] is actually *(param[i]). This means, you first go to the i-th element of param, and then dereference it - that is not what you want (param is not a pointer into an array). You want to dereference param and then go to the i-th element - this would be (*param)[i].

First of all: Why would you write the sorting yourself (not to mention that bubblesort is not exactly fast).
So why not simply use
std::sort(tavi, tavi + 10, std::less<int>());
Of course if you have C++11 or boost its also a good idea to forget about c style arrays and use std::array or boost::array instead:
std::array<int, 10> tavi = {10,88,77,192,7,27,82,1,882,13};
std::sort(tavi.begin(), tavi.end(), std::less<int>());
for (int i = 0 ; i < tavi.size(); i ++)
std::cout<<tavi[i]<<" ";
If however you really want to do it like that, *param[i] is the same as *(param[i]), while you want to use (*param)[i].

vector is type int[10]. Therefore, vector* is type int(*)[10]. That is, a pointer to an array of 10 ints. So the distance between param[i] and param[i+1] is sizeof(int) * 10
When you do this:
if (*param[i] > *param[i+1])
You are comparing one array of 10 ints to the next array of 10 ints. I wish this would simply not compile, unfortunately, what happens is that the arrays are implicitly converted to pointers to their first element. Since i < i+1, the above comparison will never be true.

Related

How to convert vector<vector<int>>to int**?

vectoris easy to obtain int* through vector::data(), so how to convert vector<vector>to int**?
int main(int argc, char *argv[])
{
std::vector<std::vector<int>> temp {{1,2,3},{4,5,6}};
int **t;
t = reinterpret_cast<int **>(std::data(temp));
for (int i = 0; i < 2; ++i)
{
for (int j = 0; j < 3; ++j)
{
std::cout << t[i][j] << " ";
}
}
}
// out : 1 2 3 0 0 0
It's obviously wrong.
There is a simple "trick" to create the pointer that you need, as a temporary workaround while the code is being refactored to handle standard containers (which is what I really recommend that you should do).
The vectors data function returns a pointer to its first element. So if we have a std::vector<int> object, then its data function will return an int*. That puts us about halfway to the final solution.
The second half comes by having a std::vector<int*>, and using its data function to return an int**.
Putting this together, we create a std::vector<int*> with the same size as the original std::vector<...> object, and then initialize all elements to point to the sub-vectors:
std::vector<std::vector<int>> temp;
// ...
// Create the vector of pointers
std::vector<int*> pointer_vector(temp.size());
// Copy the pointers from the sub-vectors
for (size_t i = 0; i < temp.size(); ++i)
{
pointer_vector[i] = temp[i].data();
}
After the above loop, then you can use pointer_vector.data() to get the int** pointer you need.
Until you have refactored the code, you could put this in an overloaded function that does the conversion and calls the actual function:
// The original function
void some_function(int**);
// Creates a vector of pointers, and use it for the
// call of `some_function(int**)`
void some_function(std::vector<std::vector<int>> const& actual_vector);

How to sort one array and get corresponding second array in C++? [duplicate]

This question already has answers here:
sort one array and other array following?
(3 answers)
Closed 7 years ago.
I have two arrays in same size. And want to sort one of the array normally and then sort the next array elements accordingly.
Let's say we have two arrays
e[] = {4,2,3,7,6,8}
s[] = {2,0,4,3,7,9}
First I want to sort array e normally, Then change the element positions of s array according to the changed element positions of e.
This should be the final result
e[] = {2,3,4,6,7,8}
s[] = {0,4,2,7,3,9}
How should I do this? Should I use a class object with these two as private members and then proceed? If so, how to do that?
Create a single array (or vector) of std::pair objects, where first is from the first array and second from the second. Then just use std::sort with a custom comparator function that uses only second from the pair for comparison. Iterate over the sorted array (or vector) and split up into the original arrays.
Note: If the values in each array are tightly coupled then consider putting them in a structure or class instead of using two (or more) distinct arrays.
What I think is use std::map
Assign array e element as the key
And corresponding array s element as the value.
Then sort the may by key
Go trough the map and get the values one by one
If you do this in a class, you can create an array of indices and sort the indices according to the values in e[]. If not doing this within a class, and for a more general approach, create an array of pointers to e[], then sort the pointers according to e[]. Then reorder e[] and s[] according to the pointers, converting the the sorted pointers to an index by using array_of_pointers[i] - &e[0] (or just array_of_pointers[i]-e). You could write your own sort, or use qsort, std::sort, or std::stable sort to sort the array of pointers, with a compare function that compares using dereferenced pointers (compares the values pointed to). Example C code using qsort and reorder in place logic with O(n) time complexity:
int compare(const void *pp0, const void *pp1)
{
int i0 = **(int **)pp0;
int i1 = **(int **)pp1;
if(i0 > i1)return -1;
if(i0 < i1)return 1;
return 0;
}
int main()
{
int e[...];
int s[...];
int *pe[...];
size_t i, j, k;
int te, ts;
/* ... */
/* create array of pointers to e[] */
for(i = 0; i < sizeof(e)/sizeof(e[0]); i++)
pe[i] = &e[i];
/* sort array of pointers */
qsort(pe, sizeof(e)/sizeof(e[0]), sizeof(pe[0]), compare);
/* reorder e[] and s[] according to the array of pointers */
for(i = 0; i < sizeof(e)/sizeof(e[0]); i++){
if(i != pe[i]-e){
te = e[i];
ts = s[i];
k = i;
while(i != (j = pe[k]-e)){
e[k] = e[j];
s[k] = s[j];
pe[k] = &e[k];
k = j;
}
e[k] = te;
s[k] = ts;
pe[k] = &e[k];
}
}
/* ... */
return 0;
}
If you don't want to use other Data structures and stick with the two different integer arrays..
Following code snippet will help you
int _tmain(int argc, _TCHAR* argv[])
{
int e[] = {4,2,3,7,6,8} ;
int s[] = {2,0,4,3,7,9} ;
int temp ;
int Array_Size = 6 ; // don't use hard coded value here, rather calculate from array size
for(int i = 0 ; i < Array_Size ; i++)
{
for(int j = i+1 ; j < Array_Size ; j++)
{
if(e[i] > e[j])
{
// Swap elements in first array
temp = e[j] ;
e[j] = e[i] ;
e[i] = temp ;
// As you want both arrays in sync
// Swap elements in second array here itself
temp = s[j] ;
s[j] = s[i] ;
s[i] = temp ;
}
}
}
return 0;
}
It is quite simple when we use structure.Your basic task is to sort two arrays. I want to suggest one method regarding it. Use a structure having two variables x and y which are used here for two arrays. Make two array of objects of this structure.
struct Point
{
int x,y;
};
struct Point arr[n];
After providing entries to the array of structure objects, make use of STL function
sort(arr,arr+n,myfun);
where myfun is function to sort according to ur need and it is defined as
bool myfun(struct Point a,struct Point b)
{
if(a.x<b.x)
return true;
else
return false;
}
And here is the complete program in c++
#include <bits/stdc++.h>
using namespace std;
struct Point{
int x,y;
};
bool myfun(struct Point a,struct Point b)
{
if(a.x<b.x)
return true;
else
return false;
}
int main()
{
int n; //n is the number of elements of array
cin>>n;
struct Point arr[n];
//Enter first array
for(int i=0;i<n;i++)
cin>>arr[i].x;
//Enter second array
for(int i=0;i<n;i++)
cin>>arr[i].y;
//sorting with the help of myfun
sort(arr,arr+n,myfun);
//now print the arrays
for(int i=0;i<n;i++)
cout<<arr[i].x<<" ";
cout<<"\n";
for(int i=0;i<n;i++)
cout<<arr[i].y<<" ";
return 0;
}
void bubbleSort(int e[], int s[], int n) {
bool swapped = true;
int j = 0;
int tmp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < n - j; i++) {
if (e[i] > e[i + 1]) {
tmp = e[i];
e[i] = e[i + 1];
e[i + 1] = tmp;
tmp = s[i];
s[i] = s[i + 1];
s[i + 1] = tmp;
swapped = true;
}
}
}
}

Function behaves badly when passing dynamically allocated pointer

I have this function
void shuffle_array(int* array, const int size){
/* given an array of size size, this is going to randomly
* attribute a number from 0 to size-1 to each of the
* array's elements; the numbers don't repeat */
int i, j, r;
bool in_list;
for(i = 0; i < size; i++){
in_list = 0;
r = mt_lrand() % size; // my RNG function
for(j = 0; j < size; j++)
if(array[j] == r){
in_list = 1;
break;
}
if(!in_list)
array[i] = r;
else
i--;
}
}
When I call this function from
int array[FIXED_SIZE];
shuffle_array(array, FIXED_SIZE);
everything goes all right and I can check the shuffling was according to expected, in a reasonable amount of time -- after all, it's not that big of an array (< 1000 elements).
However, when I call the function from
int *array = new int[dynamic_size];
shuffle_array(array, dynamic_size);
[...]
delete array;
the function loops forever for no apparent reason. I have checked it with debugging tools, and I can't say tell where the failure would be (in part due to my algorithm's reliance on random numbers).
The thing is, it doesn't work... I have tried passing the array as int*& array, I have tried using std::vector<int>&, I have tried to use random_shuffle (but the result for the big project didn't please me).
Why does this behavior happen, and what can I do to solve it?
Your issue is that array is uninitialized in your first example. If you are using Visual Studio debug mode, Each entry in array will be set to all 0xCC (for "created"). This is masking your actual problem (see below).
When you use new int[dynamic_size] the array is initialized to zeros. This then causes your actual bug.
Your actual bug is that you are trying to add a new item only when your array doesn't already contain that item and you are looking through the entire array each time, however if your last element of your array is a valid value already (like 0), your loop will never terminate as it always finds 0 in the array and has already used up all of the other numbers.
To fix this, change your algorithm to only look at the values that you have put in to the array (i.e. up to i).
Change
for(j = 0; j < size; j++)
to
for(j = 0; j < i; j++)
I am going to guess that the problem lies with the way the array is initialized and the line:
r = mt_lrand() % size; // my RNG function
If the dynamically allocated array has been initialized to 0 for some reason, your code will always get stack when filling up the last number of the array.
I can think of the following two ways to overcome that:
You make sure that you initialize array with numbers greater than or equal to size.
int *array = new int[dynamic_size];
for ( int i = 0; i < dynnamic_size; ++i )
array[i] = size;
shuffle_array(array, dynamic_size);
You can allows the random numbers to be between 1 and size instead of between 0 and size-1 in the loop. As a second step, you can subtract 1 from each element of the array.
void shuffle_array(int* array, const int size){
int i, j, r;
bool in_list;
for(i = 0; i < size; i++){
in_list = 0;
// Make r to be betwen 1 and size
r = rand() % size + 1;
for(j = 0; j < size; j++)
if(array[j] == r){
in_list = 1;
break;
}
if(!in_list)
{
array[i] = r;
}
else
i--;
}
// Now decrement the elements of array by 1.
for(i = 0; i < size; i++){
--array[i];
// Debugging output
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
}
You are mixing C code with C++ memory allocation routines of new and delete. Instead stick to pure C and use malloc/free directly.
int *array = malloc(dynamic_size * sizeof(int));
shuffle_array(array, dynamic_size);
[...]
free(array);
On a side note, if you are allocating an array using the new[] operator in C++, use the equivalent delete[] operator to properly free up the memory. Read more here - http://www.cplusplus.com/reference/new/operator%20new[]/

c style string and dynamic allocation in c++

I must implement a bunch of methods that allocates, modify and free a 2D array of c-style string. I cannot use string nor vectors nor any stl container.
getNewMat :
char*** getNewMat(int w, int h){
char*** newMat = new char**[h];
for(int i = 0 ; i < h ; i++){
newMat[i] = new char*[w];
for(int j = 0 ; j < w ; j++)
newMat[i][j] = NULL;
}
return newMat;
}
fillMat
void fillMat(char***mat, int x, int y, char* newEl){
mat[y][x] = newEl; //this will produce a segfault (even with good index)
}
showMat :
void showMat(char*** mat, int w, int h){
for(int i = 0 ; i < h ; i++){
for(int j = 0 ; j < w ; j++)
cout << mat[i][j];
}
cout << endl;
}
so, can anyone please tell me what's wrong with this?
In your fillMat method you do this:
mat[y][x] = newEl;
Where x and y are the dimensions of the two ranks of the array. That line will cause a segmentation fault because you're going outside the bounds of the array. mat is indexed from 0 to length - 1 and setting by x and y is going 1 outside the bounds of the array.
Maybe you meant to loop through and set them:
for (int i = 0; i < y; ++i)
{
for (int k = 0; k < x; ++k)
mat[i][k] = newEl;
}
Moreover, inside your showMat function you have this:
cout << showMat[i][j];
I think you meant for that to be mat:
cout << mat[i][j];
newMat[i][j] = NULL - it's a bad idea. In showMat you will try to dereference a NULL pointer - this is UB and may cause a segfault.
char* - it's not a string - it's just a pointer to char, that may points to memory location, where can be beginning of string. If you want to work with it like with a string, you should allocate memory for it too.
mat[y][x] = newEl - it's a bad idea too. As I already said, char* is not a string, so, you can't just use assignment operator to copy data from one C-string into another. You should use std::copy or std::strncpy.
Do not forget to free allocated memory after using.
You should implement your own string class - it's the better solution, I can see there. At least, because it simpler and easier to understand.
I must implement a bunch of methods that allocates, modify and free a
2D array of c-style string. ...snip... so, can anyone please tell me
what's wrong with this?
A "c-style string" isn't a type. It's a representation of data within a type. '\0'-terminated strings are typically stored within char arrays, but you could store one just as easily in a unsigned int array. For example:
unsigned int message[32] = { 0 };
strcpy((char *) message, "Hello, world!");
printf("%s\n", (char *) message);
I discourage programming like this, however micro-optimistic the benefits may seem. It's also possible to store a string in something that isn't an array. Consider that a char might be suitable for storing an empty string:
char x = '\0';
printf("%s\n", &x);
It's reasonable to assume that you meant "an array of array of array of char", when you said "2D array of c-style string". Let us carry on in that direction.
I don't know a lot about C++, but there's a list of property of arrays which you probably haven't thought about in your quest to mimic actual arrays. I'll summarise these using assertions:
#define x 7
#define y 13
#define z 1
char foo[x][y][z] = { 0 };
assert((char *) foo == foo[0]);
assert(sizeof foo == (char *) &foo[1] - (char *) &foo[0]);
assert(sizeof foo == x * y * z);
I'm not sure if you'll be able to solve your problem with any of these assertions passing in C++, but I'm open for any input from others as to hints as to how one might...
Arrays are contiguous. This means that newMat[x] + w and newMat[x+1], for values of x in 0 .. h-1. In your code, this isn't a reality, because you allocate newMat[x] and newMat[x+1] separately. Similarly, it is expected that newMay[0][y] == newMat[0][y+1] + n, where n is the maximum length of your strings. This can be a problem when using generic array sorting algorithms, because they might rely upon your arrays being contiguous.
The closest you might come to solving this problem seems to involve allocating only once per dimension, rather than h times for the first dimension and w for the second. This would look something like this:
char ***getNewMat(size_t w, size_t h, size_t n){
char ***newMat = new char **[h];
newMat[0] = new char *[h*w];
newMat[0][0] = new char[h*w*n];
for(size_t i = 0; i < h; i++){
newMat[i] = newMat[0] + i * w;
for (size_t j = 0; j < w; j++) {
newMat[i][j] = newMat[0][0] + i * w * n + j * n;
}
}
return newMat;
}
One side-effect of arrays being contiguous is that you can't assign C-style strings by merely changing the pointer within the array to point to a different location. The pointer is the result of a conversion from an array expression to a pointer expression which isn't an lvalue. As I said earlier, I don't know much about C++, but in C that means the following code can't compile:
char foo[x][y][z] = { 0 };
foo[a][b] = "hello";
However, the following code can compile:
char *foo[x][y] = { 0 };
foo[a][b] = "hello";
The former might constitute an array of C-style strings, but the latter can't because of the contiguity rule we've covered, and the fact that it starts off with most if it's elements pointing to NULL, a pointer which can't point to anything let alone strings. There might be some operator overloading magic you can perform to permit the former to compile. I'm also open for any hints in the right direction to provide an example for the OP, here.

How to declare array of pointers to the another array elements

I have an array.
char tab[200];
and then I want to create array which consists pointers to the previous array elements
char** t = new (char*)[LENGTH];
but i do get
C:\Users\Duke\Desktop\PJC3\main.cpp|37|error: array bound forbidden after parenthesized type-id|
How should I declare it DYNAMICALLY?
EDIT: Is that correct pointing to corresponding elements of the tab array?
char** t = new char*[dlugoscTab];
for(int i = 0; i < dlugoscTab; i++){
*(t + i*sizeof(char)) = (tab + i*sizeof(char));
}
To do it the way you're trying to, you need to just get rid of the parentheses:
char** t = new char*[LENGTH];
for (i = 0; i < LENGTH; i++) {
t[0] = &tab[i];
}
However, there doesn't seem to be much of a reason to use dynamic allocation here, so just use an array of char*:
char* t[LENGTH];
for (i = 0; i < LENGTH; i++) {
t[0] = &tab[i];
}
Or better yet, use a standard container like std::array or std::vector.
The assignment in your edit is incorrect:
*(t + i*sizeof(char)) = (tab + i*sizeof(char));
It will work in this case but only because sizeof(char) is 1. You should not be involving sizeof here. Adding 1 to a pointer does not move it 1 byte, but moves it to point to the next object of the type it is pointing at. You should be doing:
*(t + i) = (tab + i);
But as I've written in my examples above, this is exactly the much easier to understand:
t[i] = &tab[i];
char** t = new (char*)[LENGTH];
Should be:
char** t = new char*[LENGTH];
If you want every ith element in t to point to the ith element in tab, you can simply do this like so:
for(int i=0; i<LENGTH; i++ )
t[i] = & tab[i];
The correct syntax is:
char (*t)[LENGTH] = new char(*)[LENGTH];
But it doesn't make much sense to allocate it with new because that just allocates one pointer, not an array.