I'm trying to use qsort to sort a 2D array in C. The sort works, but I get the warning:
warning: initialization discards 'const' qualifier from pointer target type [enabled by default]
How can I modify my compare function to eliminate the warning (given that qsort requires the parameters const void *pa, const void *pb ?
int cmp (const void *pa, const void *pb ) {
const int (*a)[2] = pa; // warning here
const int (*b)[2] = pb; // warning here
if ( (*a)[1] < (*b)[1] ) return 1;
if ( (*a)[1] > (*b)[1] ) return -1;
return 0;
}
I've read this post on Stack Overflow, but I'm still not sure how I should alter the compare function.
I have an array that looks like this:
int letterCount[26][2] = {{0, 0},{1, 0},{2, 0},{3, 0},{4, 0},{5, 0},{6, 0},{7, 0},{8, 0},{9, 0},{10, 0},{11, 0},{12, 0},{13, 0},{14, 0},{15, 0},{16, 0},{17, 0},{18, 0},{19, 0},{20, 0},{21, 0},{22, 0},{23, 0},{24, 0},{25, 0}};
Except in the second column, instead of zeroes, those are filled with other numbers. I'm trying to sort this 2d array by the second column, after 0s are filled in.
You could toy with the decls, but in the end I think this will suffice for the comparator you're using:
int cmp (const void *pa, const void *pb )
{
const int *a = pa;
const int *b = pb;
if (a[1] < b[1])
return -1;
return (b[1] < a[1]);
}
Your data "items" are nothing more than int[] offsets in a 2D array. Were this a pointer array rather than a genuine 2D array, this would be considerably different. Grijesh was very close to this, only missing the [1] offsets (and the simple math), and if he undeletes his answers to fix it I'll just drop this.
what is this supposed to do (*a)[2] ?
it appears that you're dereferencing a pointer to an array in a declaration.
here for a lack of better things to do I wrote my own version , I hope it'll help you :
#include <time.h>
#include <stdio.h>
void Qsort(int matrix[][2] , int lenght)
{
if(!lenght)
return;
int temp = 0 , pivot , b = 0 , e = lenght - 1 , test = 0;
const int MIN =0 , MAX = e;
srand(time(NULL));
test = (rand() % (MAX - MIN + 1)) + MIN;
pivot = matrix[test][1];
while(b < e)
{
while(matrix[b][1] < pivot)
b++;
while(matrix[e][1] > pivot)
e--;
temp = matrix[b][1];
matrix[b][1] = matrix[e][1];
matrix[e][1] = temp;
}
Qsort(matrix , b);
Qsort(&(matrix)[b + 1] , lenght - 1 - b);
}
Related
I am learning C, and I came across this problem I can't figure it out. Write a function that computes the element of an integer array a plus 6 modulus 10 and store the result in array b. For example, if 5 is the second element of array a, then the second element of array b should be (5+6)%10, which is 1. The function has the following prototype, n is the length of the arrays, a and b are the integer arrays.
I did:
void arithmetic (int *a, int n, int *b)
{
int *arr1; arr1=a; int *arr2; arr2=b;
int i;
for(i = 0; i < n; i++) {
*arr1 = *(((a + i) + 6) % 10);
*arr2 = *arr1;
}
}//don't know if the function is correct.
A couple things:
No need to update the actual content of the first array (which fixes the error pointed out about your code always storing the result in the first element of a)
Use some parens to make sure you get the right order of operations.
void newArr(int *a, int n, int *b) {
int *arr1; arr1 = a; int *arr2; arr2 = b;
for (int i = 0; i < n; i++) {
*(arr2 + i) = (*(arr1 + i) + 6) % 10;
}
}
Think about your title "...using Pointer arithemtic". You need to add the loop counter to the array pointer for both arr1 and arr2 so that it steps through each element of each array: *(arr2 + i) and *(arr1 + i).
This is also a good place to reinforce the fact that the pointers are passed by value and that the function receives copy of each pointer which it is free to iterate with to affect the copy without effecting the pointers in the caller. So it would also be perfectly valid to do:
void arithmetic (int *a, int *b, size_t n)
{
if (!a || !b)
return;
for(size_t i = 0; i < n; i++, a++, b++)
*b = (*a + 6) % 10;
}
(good job Pablo with the use of size_t for the length (or number of elements) parameter)
No, your function is not correct.
*arr1 = *((a+i)+6)%10);
You are only writing the values in the first element of the array.
arr1 points to a which already has the values. You want to do the
calculation with a value stored in a and then save it to b, so don't modify
a.
*((a+i+6)%10) is completely wrong. a+i+6 is the same as &a[i+6]. The %10
applies to the value &a[i+6] (which is the address of the i+6th element), and returns a value between 0 and 9 (let's call
it x). When do *(x) you are interpreting the x as a pointer and it
dereferences (=access the value through the pointer) it, but this is not a valid
address at all. You will also eventually access a out of bounds.
*arr2 = *arr1; here you also only storing the values in the first element of arr2.
You function has no name.
int *arr1; arr1=a; this is unnecessary, you can access a directly, no
need to create a copy of the pointer.
The +6 % 10 rule applies to the values stored in the array, not the indices.
The correct function should look like this:
void compute(int *a, int *b, size_t len)
{
if(a == NULL || b == NULL)
return;
for(size_t i = 0; i < len; ++i)
b[i] = (a[i] + 6) % 10;
}
And if your assignment says you should do it with pointer arithmetic instead of
using array indexing:
void compute(int *a, int *b, size_t len)
{
if(a == NULL || b == NULL)
return;
for(size_t i = 0; i < len; ++i)
*(b+i) = (*(a + i) + 6) % 10;
}
Just started learning C programming and decided to take a class in algorithmic Toolbox on Coursera. One of the challenges is writing a code using fractional knapsack, maximizing the value of loot and a pseudo code was given to help in coding the solution. Below are the pseudo code and the code I wrote for the pseudo code.
#include<stdio.h>
int min(int a, int b)
{
if (a < b)
return a;
else
return b;
}
int knapsack(int value[], int weight[])
{
int capacity = 100;
int val = 0;
int array[] = { 0 };
for (int i = 1; i < capacity; i++)
{
if (capacity == 0)
{
return val;
}
for (int i = 1; i < capacity; i++)
{
if (weight[i] > 0 && (value[i] / weight[i]))
{
int a = min(weight[i], capacity);
val = val + a * (value[i] / weight[i]);
weight[i] = weight[i] - a;
array[i] = array[i] + a;
capacity = capacity - a;
}
}
}
return val;
}
int main()
{
int value[100];
int weight[100];
scanf("%d", &value[100]);
scanf("%d", &weight[100]);
printf("%d", knapsack(value[100], weight[100]));
return 0;
}
pseudo code
Knapsack(W, w1,v1,......wn,vn)
A <-- [0,0,], V <-- 0;
repeat n times:
if W = 0:
return (V,A)
select i with Wi > 0 and max vi/wi
a <-- min(wi, W)
V <-- V + a(vi/wi)
wi <-- wi - a, A[i] <-- A[i] + a, W <-- W - a
return (V, A)
I am getting errors when I compile such as "passing argument 1 of 'knapsack' makes pointer from integer without a cast [-Wint-conversion]"
printf("%d", knapsack(value[100],weight[100]));
"expected int * but argument is of type 'int'"
int knapsack(int value[], int weight[])
I also want to know if it is a good practice to declare int value[], int weight[] in the function int knapsack argument and also more explanation in using arrays and pointers in situations like this.
int knapsack(int value[], int weight[])
The above statement gives the compiler the information about HOW the function should be called (type of arguments) and WHAT the function will return.
It says the function knapsack will return an integer value (the 1st int).
Its name is knapsack (case-sensitive).
It expects two arguments: an integer array (named value) and an integer array (named weight).
Points 1, 2 and 3 together make up the signature of a function.
To call the function you have to pass 2 integer arrays as its arguments.
The mistake : value[100] corresponds to an INTEGER ENTRY in the array and not the array itself.
To pass the array you should pass the array name as its argument, which your function expects.
Call the function like this: knapsack(value, weight)
value corresponds the array value and weight corresponds to the array weight
Also, passing value[100] corresponds to some garbage value that is not within the array bounds as you can only access elements ranging from value[0] to value[99] (0-based indexing).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
We use to indicate a pointer with the symbol *. Iterating the procedure, we obtain a "double" pointer **, a "triple" pointer *** and, more generally, a "d-dimensional" pointer (for each d positive natural number).
Problem: given such a d as an input, define S to be a d-dimensional pointer.
Because I started studying dynamic structures only some days ago, I am unfortunately a bit in trouble with this problem.
Does anyone have a suggestion/hint?
Thank you in advance, and my apologies for my probably too basic question.
Ps: I used the word "pointer" without specify its type only for sake of brevity.
This problem has a solution in C as long as two conditions are met:
The value of d is known at compile time, and
d has a pre-defined limit, e.g. 10
You can solve this problem by defining a series of macros and "pasting" the value of d as a token:
#define D_PTR(d,T) D_PTR##d(T)
#define D_PTR0(T) T
#define D_PTR1(T) T*
#define D_PTR2(T) T**
#define D_PTR3(T) T***
...
#define D_PTR10(T) T**********
Now you can declare d-dimension pointers like this:
D_PTR(5,int) ptr5 = NULL;
Demo.
There are three distinct ways to solve this:
Your d is a compile-time constant. For this case, dasblinkenlight has already given the solution.
The hacky-C solution: Just use a cast to get back to the pointer type:
double* dereferenceDLevels(double* pointer, int d) {
for(; d--; ) pointer = *(double**)pointer;
return pointer;
}
I do not recommend this approach, though. It's just too dirty.
You implement your d-level pointers as user defined types:
typedef struct nLevelPointer {
int n;
union {
nLevelPointer* pointer;
double value;
};
} nLevelPointer;
double nLevelPointer_dereference(nLevelPointer* me) {
for(int i = me->n; i--; ) me = me->pointer;
return me->value;
}
I consider this approach the cleanest and most flexible one. However, it has the trade-off of requiring a significant amount of boilerplate code to make it fly.
Basically the number of * represents the number of indirections to reach the variable. So you have to create d indirections. I assume this has no practical application - that's an answer to a recreative problem.
An indirection in C is an address, a pointer. Creating d indirections means the creation of d addresses to reach a variable data (the space allocated to the variable of type T).
p(d) -> p(d-1) -> ... -> p(1) -> variable
To create dynamically such a structure, you could do it via malloc (replace T with any known type), and - since you may not specify the number of * dynamically to a pointer - requires some C hacking.
So, again, this is not something recommended and is a particularly bad design, especially for inexperienced C developers. Purpose is to show it could be done dynamically, whatever the value of d.
Say T is a double
int d = ...; // from input (d >= 1)
double variable;
double **S = malloc(sizeof(double *) * d); // array of pointers to pointer
S[d-1] = &variable; // last address points to target
int i;
for(i=d-2 ; i>=0 ; i--) S[i] = (double *)&S[i+1]; // previous address
// points to next location
There is no way to represent an arbitrary number of indirections in C, so S is only a ** to satisfy the compiler requirements, and is cast when necessary.
Let's try with d set to 4 and applying the algorithm above (say T is a double), having
double variable is at address 0100 (decimal), value 3.14
S address given by malloc at 1000
a pointer size being 4
a double size being 8
variable
v
[8 bytes double value 3.14]
^
0100
S
v
[1004][1008][1012][0100]
^ ^
1000 1012
Now the structure is in place, how to use/test it? You could create a function that returns the type T (double here), take the S value and d, operate the d indirections and return the variable
double getvariable(double **S, int d) {
while (--d > 0) S = (double **)*S; // d-1 iterations
return *(double *)*S;
}
trying it
printf("%lf\n", getvariable(S, d)); // 3.14
to test the above structure without a function, for d == 4, you could create
double ****p = (double ****)*S;
printf("%lf\n", ****p); // 3.14
Problem: given such a d as an input, define S to be a d-dimensional
pointer.
It's possible in C to functionally represent an N dimensional array at run time, if not a pointer with an arbitrary number of levels of indirection. This could be a start (uncompiled, and this utterly ignores any possible alignment issues):
void *allocateArray( unsigned int N, size_t elemSize, unsigned int *dimensions )
{
if ( N == 1U )
{
return( malloc( elemSize * dimensions[ 0 ] ) )
}
void *array = malloc( sizeof( void * ) * dimensions[ 0 ] );
for ( unsigned ii = 0; ii < dimensions[ 0 ]; ii++ )
{
array[ ii ] = allocateArray( N - 1, elemSize, &( dimensions[ 1 ] ) );
}
return( array );
}
Note, that is not a very efficient way of allocating an N-dimensional array.
You could call it like this:
unsigned dims[] = { 5,7,8,9 };
unsigned d = sizeof( dims ) / sizeof( dims[ 0 ] );
size_t elemSize = sizeof( double );
void *array = allocateArray( d, elemSize, dims );
A varargs solution is probably possible, too.
Dereferencing the array would require something similar. This returns the address of the element dereferenced:
void *dereferenceArray( void *array, unsigned int N,
size_t elemSize, unsigned int *element )
{
if ( N == 1U )
{
char *tmp = array;
return( tmp + ( elemSize * element[ 0 ] ) );
}
else
{
void **tmp = array;
return( dereferenceArray( tmp[ element[ 0 ] ],
N - 1, elemSize, &( element[ 1 ] ) ) );
}
}
It'd be much easier in C++ as you could provide a [] operator to your array object and nest them to build N-dimensional arrays.
You could create the runtime equivalent of a d-indirection pointer by chaining as many void ** pointers as you need. A sparse array could then be built this way:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
printf("Call this passing d (dimensions), n (elements for each dim), u (used elements) as parameters\n");
return 0;
}
int d = atoi(argv[1]);
assert(d > 0);
int n = atoi(argv[2]);
assert(n > 0);
int u = atoi(argv[3]);
assert(u < n * d);
// Creating
void *root = malloc(sizeof(void *) * n);
memset(root, 0, sizeof(void *) * n);
srand(time(NULL));
int i, p, c;
void **cursor;
for (int c = 0; c < u; ++c)
{
cursor = root;
for (i = 0; i < d; ++i)
{
p = rand() % n;
if (cursor[p] == NULL)
{
cursor[p] = malloc(sizeof(void *) * n);
memset(cursor[p], 0, sizeof(void *) * n);
}
cursor = cursor[p];
}
p = rand() % n;
if (cursor[p] == NULL)
cursor[p] = "Hello";
else
--c;
}
// Traversing
struct SE
{
void * *s;
int p;
};
struct SE *stack = malloc(sizeof(struct SE) * (d + 1));
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
}
else if (cursor[p] != NULL)
{
if (i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
else
{
printf("root");
for (c = 0; c < i; ++c)
printf("[%d]->", stack[c].p);
printf("[%d]=\"%s\"\n", p, cursor[p]);
}
}
}
// Tearing down
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
free(cursor[p]);
}
else if (cursor[p] != NULL && i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
}
free(root);
free(stack);
return 0;
}
I have a array of structs. lets call it structsarray
And i have a array of ints where the ints are index's of the stuct. Lets call it indexarray
I would like to sort indexarray but i want to compare the sorting with an int in structsarray
Any way that can be done with that setup?
You have a comparison function such as this:
int my_compare(const void *a, const void *b)
{
int index1 = *((const int *) a);
int indexb = *((const int *) b);
return structsarray[index1].field - structsarray[index2].field;
}
The arguments are pointer to the values in the array you are sorting. I cast the constant void pointer to a constant int pointer, and then dereference that pointer to get the actual value.
You can make use of qsort by implementing own comparison function. Here it is explained: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
Information provided is very limited.
May be you can do as follows:
Algorithm example:
bubble sort:
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (index[d] > index[d+1]) /* For decreasing order use < */
{
/* Sort index */
swap = index[d];
index[d] = index[d+1];
index[d+1] = swap;
/* Sort struct using above index */
swap = struct[d];
struct[d] = struct[d+1];
struct[d+1] = swap;
}
}
}
I need to order a array of data structure that contains information relating to a node origin, destination and weight. the problem is not ordered properly, because if two values are equal to array.originNode simply takes the first value you get and not as it should be ordered.
This is how my code does order the structure
0 1 30
1 3 22
2 3 20
3 5 20
3 4 15
Process returned 0 (0x0) execution time : 0.015 s
Here's how it should order
0 1 30
1 3 22
2 3 20
3 4 15
3 5 20
I think the problem is the function that I am passing as parameter to qsort, which is not making the correct comparison. How do I change my comparison function to my code sorts the array of struct properly?
this is my full code
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
typedef struct dataNodes{
int originNode;
int destinationNode;
int weight;
struct dataNodes *next;
} ARRAYS;
int function (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main() {
ARRAYS array[6];
int n = 5, i;
array [0].originNode = 3;
array [1].originNode = 3;
array[2].originNode = 1;
array[3].originNode = 0;
array[4].originNode = 2;
array [0].destinationNode = 4 ;
array [1].destinationNode = 5;
array[2].destinationNode = 3;
array[3].destinationNode = 1;
array[4].destinationNode = 3;
array [0].weight = 15;
array [1].weight = 20;
array[2].weight = 22;
array[3].weight = 30;
array[4].weight = 20;
qsort(array,n,sizeof(array[0]),function);
for(i=0; i<n; i++)
{
printf("%d %d %d\n",array[i].originNode,array[i].destinationNode,
array[i].weight);
}
return 0;
}
You need to change your compare function to compare ARRAY records properly. First compare originNode, and if they're the same compare destinationNode.
int function (const void * a, const void * b)
{
const ARRAYS *ap = a;
const ARRAYS *bp = b;
if( ap->originNode < bp->originNode )
return -1;
else if( ap->originNode > bp->originNode )
return 1;
else if( ap->destinationNode < bp->destinationNode )
return -1;
else if( ap->destinationNode > bp->destinationNode )
return 1;
else
return 0;
}
You are sorting an array of (uh...) ARRAYS. So your sort function that you pass in should be comparing ARRAYS objects. Your code treats it as int's.
To do secondary sorting, you need to compare the corresponding secondary fields in the case that the primary fields are equal. Do the same for any more fields you want to compare.
So in your case, this sort function could work for you:
int sort_ARRAYS (const void * a, const void * b)
{
/* the arguments are pointers to ARRAYS objects */
const ARRAYS *x = a;
const ARRAYS *y = b;
int cmp;
/* primary */
cmp = x->originNode - y->originNode;
if (cmp != 0) return cmp;
/* secondary */
cmp = x->destinationNode - y->destinationNode;
if (cmp != 0) return cmp;
/* tertiary */
return x->weight - y->weight;
}
From the fine manual:
void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *));
[...]
The compar argument is a pointer to the comparison function, which is called with two arguments that point to the elements being compared.
So your comparison function will receive two ARRAY * arguments disguised as const void * and your function just needs to cast them appropriately:
int
function(const void * a, const void * b) {
ARRAYS *aa = (ARRAYS *)a;
ARRAYS *bb = (ARRAYS *)b;
return aa->originNode - bb->originNode;
}
If you want a secondary sort key, then check if aa->originNode == bb->originNode and compare the secondary key if that's true; similarly for the tertiary key if needed.
Your current code is working by accident. This:
return ( *(int*)a - *(int*)b );
is actually comparing the first elements of the ARRAYS* arguments and it works because (a) there's no padding at the beginning of your structure and (b) originNode is at the beginning and it actually is an int.