I am still getting lldb error, because i am probably accessing memory, that i shouldn't.
It looks like i am doing something wrong when manipulating with parameters in io_seg_sort, because before calling qsort, it is still ok.
#define IO_SEG_IMAX (IO_SEG - 1)
static int io_seg_sort (const void * seg1, const void * seg2) {
int * _seg1 = (int *)seg1;
int * _seg2 = (int *)seg2;
cout << _seg1[1] <<endl; // this gives some random values and not what i am expecting
if (_seg1[1] > _seg2[1]) {
return 1;
}
else if (_seg1[1] < _seg2[1]) {
return -1;
}
else {
return 0;
}
}
int **temp = new int *[IO_SEG];
for (int i = 0; i <= IO_SEG_IMAX; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
qsort(temp, IO_SEG, sizeof(int *) , io_seg_sort);
EDIT1: the problem is i am getting some random values in io_seg_sort when calling cout instead of what i am expecting. inputs[i] is class member int inputs[IO_SEG][2];
You're putting IO_SEG_MAX + 1 items into an array that's IO_SEG long.
for (int i = 0; i <= IO_SEG_IMAX; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
That should be:
for (int i = 0; i < IO_SEG; i++) {
temp[i] = new int[2];
memcpy(temp[i], inputs[i], sizeof(int) * 2);
}
But if you really intend to do this in C++, you should look into std::vector and std::sort.
The primary reason your code prints garbage is that you have mismatched levels of indirection inside the comparison function. Your temp array that you pass to qsort consists of pointers to two-element arrays. That means that inside the comparison function you actually receive pointers to pointers to int. I.e. this is already incorrect
static int io_seg_sort (const void * seg1, const void * seg2) {
int * _seg1 = (int *)seg1;
int * _seg2 = (int *)seg2;
cout << _seg1[1] <<endl;
You have to do something like
static int io_seg_sort (const void * seg1, const void * seg2) {
const int * _seg1 = *(const int *const *) seg1;
const int * _seg2 = *(const int *const *) seg2;
to get access to your arrays through _seg1 and _seg2 as you do it in the body of io_seg_sort (I also added some const qualifiers, although they are not required for the code to work.)
Related
Is there a way to tell the compiler that I've allocated a memory of size N * M and I wanna treat this pointer as N * M array? In other words, is there a way to write something like this?:
int arr[N][M] = (int[N][M])malloc(N * M * sizeof(int));
arr[x][y] = 123;
I know that the compiler doesn't know the dimensions of the array, all it knows is that that's a pointer. so my question is: can I somehow tell the compiler that this pointer returned by malloc is an array pointer and it's dimensions are N * M? I can use an array to pointers, pointer to arrays or pointer to pointers, but in all cases I'll have to lookup 2 addresses. I want to have a contiguous memory on the heap and treat it as a multidimensional array. just like how I would write:
int arr[N][M];
Is there any way to achieve that?
In a C++ program you should use the operator new.
As for malloc then in C++ M shall be a constant expression if you want to allocate a two-dimensional array.
You can write for example
int ( *arr )[M] = ( int ( * )[M] )malloc( N * M * sizeof(int) );
or
int ( *arr )[M] = ( int ( * )[M] )malloc( sizeof( int[N][M] ) );
If to use the operator new then the allocation can look like
int ( *arr )[M] = new int[N][M];
If M is not a compile-time constant then you can use the standard container std::vector as it is shown in the demonstrative program below
#include <iostream>
#include <vector>
int main()
{
size_t n = 10, m = 10;
std::vector<std::vector<int>> v( n, { m } );
return 0;
}
What you want is a "matrix" class like
template <typename T>
class matrix
{
size_t len;
size_t width;
std::vector<T> data;
public:
matrix(size_t len, size_t width) : len(len), width(width), data(len*width) {}
T& operator()(size_t row, size_t col) { return data[width * row + col]; }
const T& operator()(size_t row, size_t col) const { return data[width * row + col]; }
size_t size() const { return len * width; }
};
int main(int argc, char const *argv[])
{
matrix<int> m(5, 7);
m(3, 3) = 42;
std::cout << m(3, 3);
}
This keeps all of the data in a single contiguous buffer, and doesn't have any undefined behavior unlike all the other examples that use malloc. It's also RAII, and you don't have to write any copy or move constructors since all of the members "do the right thing" with the compiler provided defaults. You can make this class more complicated, provide a proxy object so you can overload operator[] and be able to do m[][], but at it's base this is what you want.
If you what to avoid use of stack and you need large single block of data to keep two dimensional array of constant size (know at compile time) the this is the best cleanest way to do it:
std::vector<std::array<int, M>> arr(N);
arr[x][y] = 3;
Now if you need M is a value known at run-time, it would be best to use boost::multi_array
I do not see a reason to use malloc.
You can do exactly what you want with a helper function. This let's you specify the array size at runtime, and it uses malloc as requested (although typically you should be using new):
#include <iostream>
#include <string>
#include <memory>
template <class T>
T** Get2DMalloc(size_t m, size_t n) {
T** ret = (T**)malloc(sizeof(T*) * m);
for (size_t i = 0; i < m; ++i) {
ret[i] = (T*)malloc(sizeof(T) * n);
}
return ret;
}
template <class T>
void Free2D(T** arr, size_t m, size_t n) {
for (int i = 0; i < m; ++i) {
free(arr[i]);
}
free(arr);
}
int main() {
int m = 3;
int n = 3;
int** a = Get2DMalloc<int>(3, 3);
for (int x = 0; x < m; ++x) {
for (int y = 0; y < n; ++y) {
a[x][y] = x * m + y;
}
}
for (int i = 0; i < m * n; ++i) {
std::cout << a[i / m][i % n] << std::endl;
}
Free2D<int>(a, m, n);
system("pause");
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I got the below snippet from Algorithms in a nut shell
void sortPointers (void **ar, int n,
int (*cmp)(const void *, const void *)) {
int j;
for (j = 1; j < n; j++) {
int i = j-1;
void *value = ar[j];
while (i >= 0 && cmp (ar[i], value) > 0) {
ar[i+1] = ar[i];
i--;
}
ar[i+1] = value;
}
}
https://www.amazon.com/Algorithms-Nutshell-OReilly-George-Heineman/dp/059651624X
They do not provide the main() implementation of
sortPointers
so i have some problems figuring out what does **ar do
when i attempted to do a test code on
**arrPtr = x
it returns the error that you cannot cast void ** on a int *.
this surprises me as the book clearly says you feed an array into the function.
int main()
{
var x[3] = { 2 , 4 , 3};
void **arrPtr = x[0];
return 0;
}
a side question as well.
void *value = ar[j];
is this a unneeded step? the CMP function was able to take ar[i] as a argument, shouldnt it be able to take ar[j] as is?
In C we have the function qsort which is a generic function to sort arrays. It can sort all kind of arrays (e.g. arrays of int, arrays of double and even arrays of custom structs). All it requires is that the user provide a "compare" function for comparing two elements.
The sortPointers seems to be pretty much the same except it does not sort arrays of elements but instead sorts an array of pointers to elements.
As far a I can see the idea is to use it like:
#include <stdio.h>
#include <stdlib.h>
int cmp(const void * a, const void * b)
{
int* pa = (int*)a;
int* pb = (int*)b;
if (*pa > *pb) return 1;
if (*pa < *pb) return -1;
return 0;
}
void sortPointers (void **ar, int n,
int (*cmp)(const void *, const void *))
{
int j;
for (j = 1; j < n; j++) {
int i = j-1;
void *value = ar[j];
while (i >= 0 && cmp (ar[i], value) > 0) {
ar[i+1] = ar[i];
i--;
}
ar[i+1] = value;
}
}
void pp(int **ar, int n)
{
for(int i=0; i<n; ++i)
printf("Address %p holds the value %p and points to %d, i.e. arr[%d] points to %d\n", (void*)(&ar[i]), (void*)ar[i], *ar[i], i, *ar[i]);
}
#define ELEM 3
int main(void)
{
int* arr[3];
for(int i=0; i<ELEM; ++i) arr[i] = malloc(sizeof(int));
*arr[0] = 5;
*arr[1] = 8;
*arr[2] = 2;
pp(arr, ELEM);
sortPointers((void**)arr, ELEM, cmp);
printf("------------------------\n");
pp(arr, ELEM);
for(int i=0; i<ELEM; ++i) free(arr[i]);
return 0;
}
Output:
Address 0x7fff9a7d0270 holds the value 0xeeb010 and points to 5, i.e. arr[0] points to 5
Address 0x7fff9a7d0278 holds the value 0xeeb030 and points to 8, i.e. arr[1] points to 8
Address 0x7fff9a7d0280 holds the value 0xeeb050 and points to 2, i.e. arr[2] points to 2
------------------------
Address 0x7fff9a7d0270 holds the value 0xeeb050 and points to 2, i.e. arr[0] points to 2
Address 0x7fff9a7d0278 holds the value 0xeeb010 and points to 5, i.e. arr[1] points to 5
Address 0x7fff9a7d0280 holds the value 0xeeb030 and points to 8, i.e. arr[2] points to 8
However, the whole function seems to be a waste of time. The standard qsort can do this for you so why write a special function? As written above qsort can sort all kind of arrays so it can also sort an array of pointers. The compare function just needs to be a bit different. Simply use qsort like:
// Compare function
int cmp_qsort(const void * a, const void * b)
{
int** pa = (int**)a;
int** pb = (int**)b;
if (**pa > **pb) return 1;
if (**pa < **pb) return -1;
return 0;
}
// Call from main like:
qsort(arr, ELEM, sizeof(int*), cmp_qsort);
The output will be the same (except for the address that change every time you run it) and you don't need a custom sort function like sortPointers.
I'm having trouble trying to come up with the pointer version of this function:
void strncpy(char t[], const char s[], const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n and s[i]; i++)
t[i]=s[i];
t[i] = '\0'
}
This function is supposed to copy the first "n" characters of one array to another array and then terminate with a null character. I'm sure this is simple but I'm still learning pointers :P
This is what I have right now:
void strncpy(char * t, const char * s, const unsigned int * n)
{
unsigned int i = 0;
for(i = 0; i < *n and *s; i++)
*t = *s;
*t = '\0';
}
Im calling it in main via:
char array_one[5] = "quiz";
char array_two[5] = "test";
unsigned int x = 2;
strncpy(array_one,array_two,x);
You've failed to increment the pointers, so you're always overwriting the same address. There's also no need to pass n via a pointer:
#include <cstddef>
void my_strncpy(char *t, const char *s, std::size_t n) {
while (n && *s) {
*t++ = *s++;
--n;
}
*t = '\0';
}
NB: note use of size_t to duplicate the standard parameter signature
of the standard strncpy function, although the standard version also returns the original value of t rather than void.
#include <iostream>
// changing the function signature to take an int instead of
// pointer to int - cleaner
void my_strncpy(char * t, const char * s, const unsigned int n)
{
unsigned int i = 0;
for(i = 0; i < n; i++)
{
*t++ = *s++; // copy and increment
}
*t = '\0'; // fixing - added terminating char
}
int main(void)
{
char a[] = "string1";
char b[] = "string2";
my_strncpy(a,b,7); // replace 7 with appropriate size
std::cout << a << std::endl;
}
You need to copy over each character from one string to another and then increment the pointers - you were missing that in your implementation.
I also assume that you will not overshoot the array you are copying from.
I got a compiler error:
main.cpp|59|error: invalid conversion from 'int' to 'int*' [-fpermissive]|
The offending line is
int *pComienzo = vector, *pFinal = vector[nElementos-1];
Why there is an error? Can someone help me?
Below is my code:
#include <iostream>
#include <ctype.h>
using namespace std;
const unsigned short int MAX_VAL = 10;
int LongitudCadena(char*);
int BuscarCaracter(char *cadena, char caracter);
void Ordenar(int *vector, int nElementos, bool ascendente);
int main()
{
char *cadena = "asdasd";
cout << LongitudCadena(cadena) << endl;
cout << BuscarCaracter(cadena, 'a') << endl;
int iArray[] = {5,4,3,2,1};
Ordenar(iArray, 5, 1);
cout << iArray << endl;
return 0;
}
int LongitudCadena(char *cadena)
{
char *c = cadena;
for(int i = 0; i < MAX_VAL; i++)
{
if (c[i] == 0) break;
cadena++;
}
return cadena - c;
}
int BuscarCaracter(char * cadena, char caracter)
{
char *pCadena = cadena;
for (int i = 0; i < MAX_VAL; i++)
{
pCadena++;
if (toupper(cadena[i]) == toupper(caracter))
return pCadena- cadena;
}
return -1;
}
void Ordenar(int *vector, int nElementos, bool ascendente)
{
int *pComienzo = vector, *pFinal = vector[nElementos-1];
if (ascendente)
{
for (int i = 0; i < nElementos; i++)
{
for (; pComienzo < pFinal; pComienzo++, pFinal--)
{
if (*pComienzo > *pFinal)
{
*pComienzo += *pFinal;
*pFinal -= *pComienzo;
*pComienzo -= *pFinal;
}
}
}
}
}
I'm learning...
Your error is in this line:
int *pComienzo = vector, *pFinal = vector[nElementos-1];
The reason for this is that vector is an int*, but vector[nElementos - 1] is a regular int. Thus the declaration
int *pFinal = vector[nElementos - 1];
is trying to assign the integer value at the last index of vector to the pointer pFinal, hence the compiler error.
To fix this, you may want to do either
int *pFinal = &vector[nElementos - 1];
which makes pFinal point to the last element of vector, or
int *pFinal = vector + (nElementos - 1);
which accomplishes the same thing using pointer arithmetic.
That said, since you're working in C++, why not use the provided std::vector type and avoid working with pointers altogether?
Hope this helps!
vector is a pointer, but subscripting it as vector[nElementos-1] dereferences it to simply an int. What it looks like you want is instead
int *pComienzo = vector, *pFinal = &(vector[nElementos-1]);
An array access/subscript (i.e., a[i] where a is an array/pointer and i is an integer) is an expression with the type being the thing you have in the array.
Simply use the address-of operator & to store the address in the pointer:
int *pComienzo = vector, *pFinal = &vector[nElementos-1];
You forgot &. vector[nElementos-1] is the value, while you need an address for pFinal.
Either *pFinal = &(vector[nElementos-1]) or *pFinal = vector + nElementos-1.
I'm trying to make a pointer point to a 2D array of pointers. What is the syntax and how would I access elements?
By the letter of the law, here's how to do it:
// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
array2d[i] = new (int*)[cols];
}
// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array2d[i][j] = NULL;
}
}
Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.
However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.
It depends. It can be as simple as:
int main()
{
int* data[10][20]; // Fixed size known at compile time
data[2][3] = new int(4);
}
If you want dynamic sizes at runtime you need to do some work.
But Boost has you covered:
int main()
{
int x;
int y;
getWidthAndHeight(x,y);
// declare a 2D array of int*
boost::multi_array<int*,2> data(boost::extents[x][y]);
data[2][3] = new int(6);
}
If you are fine with jagged arrays that can grow dynamically:
int main()
{
std::vector<std::vector<int*> > data;
data.push_back(std::vector<int*>(10,NULL));
data[0][3] = new int(7);
}
Note: In all the above. I assume that the array does not own the pointer. Thus it has not been doing any management on the pointers it contains (though for brevity I have been using new int() in the examples). To do memory management correctly you need to do some more work.
int *pointerArray[X][Y];
int **ptrToPointerArray = pointerArray;
That's how you make a true (contiguous in memory) multidimensional array.
But realize that once you cast a multidimensional array to a pointer like that, you lose the ability to index it automatically. You would have to do the multidimensional part of the indexing manually:
int *pointerArray[8][6]; // declare array of pointers
int **ptrToPointerArray = &pointerArray[0][0]; // make a pointer to the array
int *foo = pointerArray[3][1]; // access one element in the array
int *bar = *(ptrToPointerArray + 3*8 + 1); // manually perform row-major indexing for 2d array
foo == bar; // true
int *baz = ptrToPointerArray[3][1]; // syntax error
double** array = new double*[rowCnt];
for (int row = 0; row < rowCnt; ++row)
array[row] = new double[colCnt];
for (int row = 0; row < rowCnt; ++row)
for (int col = 0; col < colCnt; ++col)
array[row][col] = 0;
You could try Boost::MultiArray.
Check out this page for details.
:)
I had these once in a piece of code I wrote.
I was the laughing stock of the team when the first bugs leaked out. On top of that we use Hungarian notation, leading to a name like papChannel - a pointer to an array of pointers...
It's not nice. It's nicer to use typedefs to define a 'row of columns' or vice versa. Makes indexing more clear, too.
typedef int Cell;
typedef Cell Row[30];
typedef Row Table[20];
Table * pTable = new Table;
for( Row* pRow = *pTable; pRow != *pTable+_countof(*pTable); ++pRow ) {
for( Cell* pCell = *pRow; pCell != *pRow + _countof(*pRow); ++pCell ) {
... do something with cells.
}
}
You can define a vector of vectors:
typedef my_type *my_pointer;
typedef vector<vector<my_pointer> > my_pointer2D;
Than create a class derived from my_pointer2D, like:
class PointersField: public my_pointer2D
{
PointsField(int n, int m)
{
// Resize vectors....
}
}
PointsField pf(10,10); // Will create a 10x10 matrix of my_pointer
I prefer to use the () operator. There are lots of reasons for this (C++ FAQs 13.10). Change the internal representation to a std::vector if you like:
template <class T, int WIDTH, int HIEGHT>
class Array2d
{
public:
const T& operator ()(size_t col, size_t row) const
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
T& operator ()(size_t col, size_t row)
{
// Assert col < WIDTH and row < HIEGHT
return m_data [( row * WIDTH + col)];
}
private:
T m_data[WIDTH * HIEGHT];
};
You can use it like this:
Array2d< Object*, 10, 10 > myObjectArray;
myObjectArray(5,6) = new Object();
See my code. It works on my FC9 x86_64 system:
#include <stdio.h>
template<typename t>
struct array_2d {
struct array_1d {
t *array;
array_1d(void) { array = 0; }
~array_1d()
{
if (array) {
delete[] array;
array = 0;
}
}
t &operator[](size_t index) { return array[index]; }
} *array;
array_2d(void) { array = 0; }
array_2d(array_2d<t> *a) { array = a->array; a->array = 0; }
void init(size_t a, size_t b)
{
array = new array_1d[a];
for (size_t i = 0; i < a; i++) {
array[i].array = new t[b];
}
}
~array_2d()
{
if (array) {
delete[] array;
array = 0;
}
}
array_1d &operator[](size_t index) { return array[index]; }
};
int main(int argc, char **argv)
{
array_2d<int> arr = new array_2d<int>;
arr.init(16, 8);
arr[8][2] = 18;
printf("%d\n",
arr[8][2]
);
return 0;
}
Effo UPD: a response to "Isn't that an array of pointers to arrays?", adding the example of array of pointers, very simple:
int main(int argc, char **argv)
{
array_2d<int*> parr = new array_2d<int*>;
int i = 10;
parr.init(16, 8);
parr[10][5] = &i;
printf("%p %d\n",
parr[10][5],
parr[10][5][0]
);
return 0;
}
Did I still misunderstand your question?
And you could even
typedef array_2d<int*> cell_type;
typedef array_2d<cell_type*> array_type;
int main(int argc, char **argv)
{
array_type parr = new array_type;
parr.init(16, 8);
parr[10][5] = new cell_type;
cell_type *cell = parr[10][5];
cell->init(8, 16);
int i = 10;
(*cell)[2][2] = &i;
printf("%p %d\n",
(*cell)[2][2],
(*cell)[2][2][0]
);
delete cell;
return 0;
}
It also works on my FC9 x86_64 system.