So I am having trouble using qsort to sort an array of structures.
I used this link as an example: http://support.microsoft.com/kb/73853
When I run the program it gives me blanks for the names that were originally in the structure and zeroes for all the values of gp.
typedef int (*compfn)(const void*, const void*);
struct record
{
char player[20];
int gp;
};
struct record entries[15];
int compare(struct record *, struct record *);
void show ()
{
int v;
qsort((void *)entries, 10, sizeof(struct record), (compfunc)compare);
struct record *p = entries;
for(v=0;v<counter;v++, p++)
{
printf("%s ..... %d \n", p->player , p->gp);
}
}
int compare(struct record * p1, struct record * p2)
{
if( p1->gp < p2->gp)
return -1;
else if (p1->gp > p2->gp)
return 1;
else
return 0;
}
Edit: Hey everyone thanks so much for all your help but, I have tried everything you guys have said and it still just turns everything value to zero
Your call can be simplified, no need to cast to void *:
qsort(entries, 10, sizeof entries[0], compare);
Note use of sizeof entries[0] to avoid pointless repetition of the array type.
There should be no cast of the comparison function either, since it should simply be defined to match the prototype:
static int compare(const void *a, const void *b)
{
const struct record *ra = a, *rb = b;
if( ra->gp < rb->gp)
return -1;
if (ra->gp > rb->gp)
return 1;
return 0;
}
By the way, just to be informational, here's a classic (?) way to tersify the 3-way testing that you sometimes see in places like these:
return (ra->gp < rb->gp) ? -1 : (ra->gp > rb->gp);
I do not argue for this way of expressing it, especially not if you're a beginner, but thought I'd include it since it's relevant and might be instructional to have seen.
Apart from the fact that the microsoft support pages are a real mess and not a good source for learning C, your code is missing an & here:
...
qsort((void *)entries, 10, sizeof(struct record), (compfunc)compare);
...
should be
...
qsort((void *)&entries, 10, sizeof(struct record), (compfunc)compare);
...
also, I think you meant to write
...
qsort((void *)&entries, 15, sizeof(struct record), (compfn)compare);
...
Related
I have an ArrayList struct and Department struct that go as follows:
typedef struct ArrayList {
void** elements;
int size;
int length;
} ArrayList;
typedef struct Department {
char* name;
ArrayList* courses;
} Department;
To print my list, I'm using these two methods:
void* get(ArrayList* arraylist, int i) {
if (i < 0 || i >= arraylist -> size) {
return (void*) NULL;
}
return arraylist -> elements[i];
}
void printAL(ArrayList* arraylist) {
for (int i = 0; i < arraylist -> size; i++) {
printf("%s\n", (char*) get(arraylist, i));
}
}
The issue I'm facing, however, is that when I add a Department to my ArrayList, the line 'return arraylist -> elements[i];' returns the address of that struct. I'm trying to get it to print the name of the struct using 'return arraylist -> elements[i] -> name' but I keep getting a warning that I'm dereferencing a void* pointer, followed by an error that says 'request for member ‘name’ in something not a structure'. This obviously means that 'arraylist -> elements[i]' isn't a struct but rather an address. How can I reference the name of the struct at that address then? I'm quite confused because of the double pointer in the ArrayList struct.
TIA!
You need different printing functions for each different type of data element that could be in the ArrayList. You need one function to print departments; you need a different function to print courses. You pass the function pointer to the printing function — printAL() — along with a pointer to other data (which in this case is probably just a FILE *, but could be a more general structure).
This is analogous to the qsort() function in standard C. It can sort any data type; you just need to pass it a different comparator function for different data types.
Like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct ArrayList
{
void **elements;
int size; /* Allocated size */
int length; /* Space in use */
} ArrayList;
typedef struct Department
{
char *name;
ArrayList *courses;
} Department;
static void *get(ArrayList *arraylist, int i)
{
if (i < 0 || i >= arraylist->size)
return NULL;
return arraylist->elements[i];
}
static void printAL(ArrayList *arraylist, void (*function)(const void *data, void *thunk), void *thunk)
{
for (int i = 0; i < arraylist->length; i++)
{
(*function)(get(arraylist, i), thunk);
}
}
static void put(ArrayList *al, void *data)
{
if (al->length >= al->size)
{
size_t new_size = (al->size + 2) * 2;
void *new_data = realloc(al->elements, new_size * sizeof(void *));
if (new_data == 0)
{
fprintf(stderr, "Failed to allocate %zu bytes memory\n", new_size * sizeof(void *));
exit(1);
}
al->elements = new_data;
al->size = new_size;
}
al->elements[al->length++] = data;
}
/*
typedef struct Course
{
const char *name;
const char *code;
// ...
} Course;
static void print_courseinfo(const void *data, void *thunk)
{
FILE *fp = thunk;
const Course *cp = data;
fprintf(fp, " - %s (%s)\n", cp->name, cp->code);
}
*/
static void print_deptname(const void *data, void *thunk)
{
FILE *fp = thunk;
const Department *dp = data;
fprintf(fp, "Name: %s\n", dp->name);
/*
if (dp->courses != 0)
printAL(dp->courses, print_courseinfo, thunk);
*/
}
int main(void)
{
ArrayList al = { 0, 0, 0 };
Department dl[] =
{
{ "Engineering", 0 },
{ "Physics", 0 },
{ "Mathematics", 0 },
{ "Chemistry", 0 },
{ "Biology", 0 },
{ "English", 0 },
{ "Computational Astronomy and Universe-Scale Data Modelling", 0 },
{ "Economics", 0 },
};
enum { DL_SIZE = sizeof(dl) / sizeof(dl[0]) };
for (size_t i = 0; i < DL_SIZE; i++)
put(&al, &dl[i]);
printAL(&al, print_deptname, stdout);
return 0;
}
Sample output:
Name: Engineering
Name: Physics
Name: Mathematics
Name: Chemistry
Name: Biology
Name: English
Name: Computational Astronomy and Universe-Scale Data Modelling
Name: Economics
You didn't document what the length and size members of the ArrayList represent. I've annotated what I've assumed, but I had to change the printAL() function to iterate over length elements instead of size elements, so I may have inverted the meaning you intended. It's easy to reverse them. I tend to use names like max_elements and num_elements for the job; it is more obvious what they're for, perhaps, since length and size are ambiguous or even equivalent in many contexts.
There's skeletal code in there to show how to handle the ArrayList of courses offered by each department. I couldn't be bothered to write code to initialize a separate ArrayList for each department, though it wouldn't be particularly hard to do.
I still prefer the pre-standard notation (*funcptr)(arg1, arg2) notation for invoking a function designated by a function pointer — it was necessary when I learned C, and I still find it clearer than the alternative. You're excused if you prefer funcptr(arg1, arg2) instead, though that can leave me wondering where funcptr is defined.
You can also find some code closely related to what you're doing in my SOQ (Stack Overflow Questions) repository on GitHub as files aomcopy.c, aomcopy.h, aommngd.c, aommngd.h, aomptr.c, aomptr.h, aoscopy.c, aoscopy.h, aosptr.c and aosptr.h in the src/libsoq sub-directory.
aomcopy.c, aomcopy.h: array of memory blocks, copied.
aommngd.c, aommngd.h: array of memory blocks, managed.
aomptr.c, aomptr.h: array of memory blocks, 'raw'.
aoscopy.c, aoscopy.h: array of strings, copied.
aosptr.c. aosptr.h: array of strings, 'raw'.
The 'raw' versions simply take the pointer passed and store it. The onus is on the user to ensure the data pointed at remains valid while the array lasts. The 'copied' versions allocate a simple copy of the data passed to it; it doesn't matter if the data passed is reused to store the next value. The 'managed' version calls user-defined functions to create copies of the data structures. This would be necessary if you have a complex structure (like a department) where you need a 'deep copy' of the data.
As already written at issue#2217, I want to design a function which return a list of oid in the first out param.
Should I:
Return the list of oids as a pointer to pointer?
int git_commit_tree_last_commit_id(git_oid **out, git_repository *repo, const git_commit *commit, char *path)
Or return the list of oids as a pointer to a custom struct?
int git_commit_tree_last_commit_id(git_oid_xx_struct *out, git_repository *repo, const git_commit *commit, char *path)
What is your advice?
The question is, how do you know how many OIDs are in the returned array, and who allocates the underlying memory.
For the first part there are several possibilities,
Return the number in a separate return parameter,
Use a sentinel value to terminate the list.
Return a new struct type, like git_strarray that contains the count and the
raw data.
For the second part, either
the caller can allocate the underlying memory
The function can allocate the memory
the new struct type can manage the memory.
Which path you go down depends upon what you want the code to look like, how much you expect it to be reused, how critical performance is etc.
To start with I'd go with the simplest, which IMO is function returns count and allocates memory.
That means my function would have to look like this:
int get_some_oids_in_an_array(OID** array, int * count, ... ) {
...
*count = number_of_oids;
*array = (OID*)malloc( sizeof(OID)*number_of_oids);
for(i=0; i<number_of_oids; ++i) {
*array[i]=...;
}
...
return 0;
}
/* Example of usage */
void use_get_oids() {
OID* oids;
int n_oids;
int ok = get_some_oids_in_an_array(&oids, &n_oids, ...);
for(i=0; i<n_oids; ++i ) {
... use oids[i] ...
}
free(oids);
}
Note: I'm returning an array of OID, rather than an array of OID*, either is a valid option, and which will work best for you will vary.
If it turned out I was using this kind of pattern often, then would consider switching to the struct route.
int get_some_oids( oidarray * oids, ... ) {
int i;
oidarray_ensure_size(number_of_oids);
for(i=0; i<number_of_oids; ++i) {
oidarray_set_value(i, ...);
}
return 0;
}
typedef struct oidarray {
size_t count;
OID* oids;
};
/* Example of usage */
void use_get_oids() {
oid_array oids = {0};
get_some_oids(&oids);
for(i=0; i<oids.count; ++i) {
... use oids.oids[i] ...
}
oidarray_release(&oids);
}
Good Morning All,
I'm trying to reduce a function that's very repetitive, but each "repetition" has two structs with struct A.element1 setting struct B.element1. At the moment I have myFunction() with about twelve different reqFunction() calls to set B to A. Basically what I have now is:
void myFunction( structB *B )
{
structA A;
if( reqGetFunction( GLOBAL_IN_1, ( void *)&A, SIZE ) != 0 )
{
A.element3 = -1;
printf( "element3 failed\n" );
}
B->element7 = A.element3; // A is gotten when regGetFunction() is called
.
.
.
if( reqGetFunction( GLOBAL_IN_12, ( void *)&A, SIZE ) != 0 )
{
A.element14 = -1;
printf( "element14 failed\n" );
}
B->element18 = A.element14;
}
reqGetFunction() can't be changed. I have a static global array for other functions that would loop through GLOBAL_IN, and I could make structA A a static global.
I want to have something like myFunctionSingle() that will do one block, and myFunctionAll() that will have a for loop to cycle through the GLOBAL_IN array as well as the elements of struct's A and B and input them to myFunctionSingle().
So I guess my real question is how could I cycle through the elements of the structs as I can with an array, because everything there (like the structs' setups and reqGetFunction) are set in stone. I've tried a few things and searched around, but am currently stumped. I'm honestly not sure if this is possible or even worth it. Thank you in advance for your input!
Your function calls differ by 1)GLOBAL_IN_XX values 2)A.elementxx that you modify. 3)B.elementxx that you modify
What you need to do is to create a struct containing a value for GLOBAL_IN_XX a pointers to A.element and B.element, whatever type they are, for example:
struct call_parms
{
int global_parm;
int* a_ptr;
int* b_ptr;
};
Then, you need to create an array of those and initialize it accordingly, for example:
struct call_parms callParmsArray[MAX_CALLS]= {{GLOBAL_IN_1,&A.element3,&(B->element5)}, ... };
Then, just iterate over array and call your reqGetFunction with the parameters specified in each array element,something along the lines of:
for(int i = 0; i<MAX_CALLS;i++)
{
reqGetFunction( callParmsArray[i].global_parm, callParmsArray[i].element_ptr, SIZE );
}
You may also want factor a pointer to B->element in the struct and deal with it accordingly, as it is also repetitive. This will likely involve creating a wrapper around reqGetFunction() which will also deal with B and such:
struct call_parms
{
int global_parm;
int* a_ptr;
int* b_ptr;
};
bool myReqFn(struct call_parms* parm)
{
bool res;
if( res = reqGetFunction( parm->global_parm, ( void *)&A, SIZE ) != 0 )
{
*(parm->a_ptr) = -1;
printf( "element %d failed\n",parm->global_parm );
}
*(parm->b_ptr) = *(parm->a_ptr);
return res;
}
for(int i = 0; i<MAX_CALLS;i++)
{
myReqFn( &callParmsArray[i]);
}
The rest is left as an exercise to the reader, as they say...
One way to cycle through a struct that I know of is to use pointer math. I'm not sure what kind of datatype your struct members are, but if you have a concurrent set of identical datatypes numbered from j to k, your code would look something like this:
(_datatype_)*a = &(A.elementj);
(_datatype_)*b = &(B.elementj);
int i;
for (i = j; i < k; i++)
{
*(b + ((_sizeofdatatype) * (i - j)) = *(a + ((_sizeofdatatype) * (i - j));
}
EDIT: This is also, of course, assuming that you want to duplicate each pair of corresponding elements in order, but you can probably tweak it around to get the desired effect.
EDIT: This also assumes you allocate your entire struct (including variables) at the same time, so be careful.
Does GLOBAL_IN_XXX mean GLOBAL_IN[XXX] etc? And does GLOBAL_IN_XXX always map to A.element(XXX+2)? And its always B.element(N+1) = A.elementN?
I'm also going to assume that you can't change A.element1, A.element2 into A.element[], otherwise the soution would be fairly simple wouldn't it?
The most portable solution is to know the offset of each element in A and B (in case there are data alignment gotchas in the stuctures... could occur if you don't have N consecutive ELEMENT_TYPES etc)
#include <stddef.h>
// NOTE: These arrays are clumbsy but avoid making assumptions about member alignment
// in strucs.
static size_t const A_Offsets[] = {
offsetof(struct A, element1),
offsetof(struct A, element2),
offsetof(struct A, element3),
...
...
offsetof(struct A, elementN) };
static size_t const B_Offsets[] = {
offsetof(struct B, element1),
offsetof(struct B, element2),
offsetof(struct B, element3),
...
...
offsetof(struct B, elementN) };
void myFunctionSingle( structB *B, unsigned int index )
{
structA A;
ELEMENT_TYPE *elAPtr = (ELEMENT_TYPE *)((char *)A + A_Offsets[index + 2]);
ELEMENT_TYPE *elBPtr = (ELEMENT_TYPE *)((char *)A + B_Offsets[index + 6]);
if( reqGetFunction( GLOBAL_IN[index], ( void *)&A, SIZE ) != 0 )
{
*elAPtr = -1;
printf( "element%u failed\n", index);
}
*elBPtr = *elAPtr; // A is gotten when regGetFunction() is called
}
void myFunction( structB *B )
{
unsigned int i = 1;
for(; i < MAX_INDEX; ++i)
myFunctionSingle(B, i);
}
EDIT: I'm not sure if the offsetof() stuff is necessary because if you structure has only ELEMENT_TYPE data in it they are probably packed tight, but I'm not sure... if they are packed tight, then you don't have any data alignment issues so you could use the solution presented in Boston Walker's answer.
I would like to save a struct into a db file (or .txt that doesn matter still!) but I ve got the following problem. I ve wanted to create structs inside structs like the following code.
typedef struct classes cl;
typedef struct attribute a;
struct classes{ \\where "a" is a type of struct
a hunter;
a channeler;
a warrior;
a rogue; };
struct human{ \\where "cl" is type of struct classes (
cl Borderlands;
cl Shienear;
cl Arafel;
cl Illian;
cl Tear;
cl Tarabon;
cl Andor;
cl TwoRivers;
cl Amandor;
cl Mayene;
cl Murandy;
};
The question is if i have a variable
struct human data
do i have to save all the branches of the tree(as i think that it is a tree that i have created), or by just saving the root, do I save the whole struct?
P.S. please excuse my way of writting, i am not that experienced in programming
You should make save method for every structure like this:
void save_h(human * h, FILE * stream)
{
save_cl(h->Borderlands,stream);
save_cl(h->Shienear,stream);
save_cl(h->Arafel,stream);
save_cl(h->Illian,stream);
save_cl(h->Tear,stream);
save_cl(h->Tarabon,stream);
...
}
void save_cl(classes * cl, FILE * stream)
{
save_a(cl->hunter,stream);
save_a(cl->channeler,stream);
save_a(cl->warrior,stream);
save_a(cl->rogueon,stream);
...
}
void save_a(attribute * a, FILE * stream)
{
...
}
If you have simple structs with no pointers, fixed size field types and are not planning to move this data onto other machines, you can just simply write entire structure to a binary file since it has linear representation in memory. And read it back the same way. Otherwise, read about marshaling and unmarshaling data. If you don't understand this concept none of the code is actually very helpful.
Here is how I would do it:
#define STRUCTFLAG 565719 // some random number
// NOTE: This is based on the idea that sizeof(int) == sizeof(int *).
// If this is wrong, then make the type of variables such that
// sizeof(typeof variable) = sizeof(int *).
struct basestruct {
int flag; // when initialized, this has the value of STRUCTFLAG, so that we know it's a struct
int size; // total size of the struct, in bytes. set when struct is created.
// all other variables in the struct are either pointers to other structs or of the primitive type of the size 'int *'.
}
struct mystruct {
int flag;
int size;
struct mystruct2 *variable1;
struct mystruct3 *variable2;
}
int isStruct(const void *structAddr)
{
int *casted = (int *) structAddr;
return casted[0] == STRUCTFLAG;
}
void saveStruct(FILE *file, const void *structaddr)
{
// make sure it's a struct
if (isStruct(structaddr))
{
int *casted = (int *) structaddr;
fprintf(file, "%i\n", casted[0]); // print flag
casted++; // skip 'flag';
fprintf(file, "%i\n", casted[0]); // print size
int numVariables = ((casted[0] / sizeof(int)) - 2);
casted++;
for (int i = 0; i < numVariables; i++)
{
if (isStruct(casted + i))
{
saveStruct(file, casted + i);
}
else
{
fprintf(file, "%i\n", casted[i]);
}
}
}
else
{
// report error
}
}
Good luck reading it back in though. You only asked how to save it!
I'm assuming that the good old qsort function in stdlib is not stable, because the man page doesn't say anything about it. This is the function I'm talking about:
#include <stdlib.h>
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
I assume that if I change my comparison function to also include the address of that which I'm comparing, it will be stable. Is that correct?
Eg:
int compareFoos( const void* pA, const void *pB ) {
Foo *pFooA = (Foo*) pA;
Foo *pFooB = (Foo*) pB;
if( pFooA->id < pFooB->id ) {
return -1;
} else if( pFooA->id > pFooB->id ) {
return 1;
} else if( pA < pB ) {
return -1;
} else if( pB > pA ) {
return 1;
} else {
return 0;
}
}
No, you cannot rely on that unfortunately. Let's assume you have the array (two fields in each record used for checking but only first field used for sorting):
B,1
B,2
A,3
A non-stable sort may compare B,1 with A,3 and swap them, giving:
A,3
B,2
B,1
If the next step were to compare B,2 with B,1, the keys would be the same and, since B,2 has an address less than B,1, no swap will take place. For a stable sort, you should have ended up with:
A,3
B,1
B,2
The only way to do it would be to attach the starting address of the pointer (not its current address) and sort using that as well as the other keys. That way, the original address becomes the minor part of the sort key so that B,1 will eventually end up before B,2 regardless of where the two B lines go during the sorting process.
The canonical solution is to make (i.e. allocate memory for and fill) an array of pointers to the elements of the original array, and qsort this new array, using an extra level of indirection and falling back to comparing pointer values when the things they point to are equal. This approach has the potential side benefit that you don't modify the original array at all - but if you want the original array to be sorted in the end, you'll have to permute it to match the order in the array of pointers after qsort returns.
This does not work because during the sort procedure, the ordering will change and two elements will not have consistent output. What I do to make good old-fashioned qsort stable is to add the initial index inside my struct and initialize that value before passing it to qsort.
typedef struct __bundle {
data_t some_data;
int sort_score;
size_t init_idx;
} bundle_t;
/*
.
.
.
.
*/
int bundle_cmp(void *ptr1, void *ptr2) {
bundle_t *b1, *b2;
b1 = (budnel_t *) ptr1;
b2 = (budnel_t *) ptr2;
if (b1->sort_score < b2->sort_score) {
return -1;
}
if (b1->sort_score > b2->sort_score) {
return 1;
}
if (b1->init_idx < b2->init_idx) {
return -1;
}
if (b1->init_idx > b2->init_idx) {
return 1;
}
return 0;
}
void sort_bundle_arr(bundle_t *b, size_t sz) {
size_t i;
for (i = 0; i < sz; i++) {
b[i]->init_idx = i;
}
qsort(b, sz, sizeof(bundle_t), bundle_cmp);
}