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;
}
}
}
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).
I can't figure out how to use qsort. I want to sort an array of strings. Like so:
John Adam
Adam -> John
Stacy Stacy
However, nothing I do seems to work. I've tried copying exactly what others have used (about 5 different qsort functions from various sources) and nothing has worked. I have one for int's that works (backwards but at least it works).
Here's the necessary code I have:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char name[80];
int age;
} RECORD;
RECORD record[25];
int main (int argc, char *argv[80]){ // Using command line to get my strings
int i = 2, j;
for(j = 0; j < (argc / 2); j++) //Converting and storing my ages
{
record[j].age = atoi(argv[i]);
i = i + 2;
}
int p, q = 1;
for(p = 0; p < (argc / 2); p++)
{
strcpy(record[p].name, argv[q]);
q = q + 2;
}
}
int compareByName(const void* a, const void* b) //The qsort that doesn't work at all
{
const char *ia = (const char *)a;
const char *ib = (const char *)b;
return strncmp(ia, ib, 25);
}
int compareByAge (const void * a, const void * b) //My other qsort that works backwards
{
RECORD *RECORDA = (RECORD *)a;
RECORD *RECORDB = (RECORD *)b;
return ( RECORDB->age - RECORDA->age );
}
void printRecords(RECORD r[], int num){
//printing stuff here
double size = sizeof r[0];
double count = sizeof(r)/size; //My qsort with size stuff, doesn't work
qsort(r, count, size, compareByName); // if I do it the same as the other
qsort (r, 25, sizeof(RECORD), compareByAge); //My other qsort that works backwards
//more printing stuff here
}
You don't have an array of strings, you have an array of RECORDs, and it sounds like you want to sort that array based on the strings in the name array of the records. So you want something like:
int compareByName(const void *a_, const void *b_) {
RECORD *a = a_, *b = b_;
return strcmp(a->name, b->name);
}
and then you sort with
qsort (r, 25, sizeof(RECORD), compareByName);
Okay, I see several issues here.
It's worth noting that sizeof is evaluated at compile time, so you can't use sizeof(r) to determine the size of a dynamically-sized array you were passed. I'm going to guess that's why num is passed in to printRecords.
As #Chris points out, you're sorting RECORD structures rather than character pointers, so the comparison function and the qsort call both need to take that into account.
You have the subtraction reversed in the age comparison - it needs to return a negative number if the left side is less than the right side, so use RECORDA->age - RECORDB->age.
First off (this is why your strings aren't sorting), double count = sizeof(r)/size; is wrong. sizeof(r) isn't doing what you expect it to. You'll need to pass the size of the array to printRecords() as described in this question:
How to get the length of array in C? is "sizeof" is one of the solution?
Second off,
int compareByAge (const void * a, const void * b) //My other qsort that works backwards is backwards because you're doing it backwards. Comparator functions always return A - B, not B - A.
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);
}
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.