Why are my qsort results incorrect? - c

When I run add cards using add_card, on the 7th card it is supposed to sort all of the cards. But when I run this I get a semi-ordered result.
>> require 'ext/straight_count' #=> true >> s = EV::StraightCount.new; s.add_card(5,0); s.add_card(8,1); s.add_card(12,2); s.add_card(14,3); s.add_card(12,4); s.add_card(3,5); s.add_card(5,6)
card: 12
card: 5
card: 12
card: 14
card: 8
card: 5
card: 3
I don't think there is a problem with NUM2INT, because when I print the array back unordered, it comes out as expected.
straight.h
int *pCards, *pSortedCards;
int cCards[NUM_CARDS], cSortedCards[NUM_CARDS];
straight.c
void Init_straight()
{
pCards = &cCards[0];
}
static VALUE
add_card(VALUE self, int rCardValue, int rCardIndex)
{
*(pCards + NUM2INT(rCardIndex)) = NUM2INT(rCardValue);
if (NUM2INT(rCardIndex) == 6)
check_for_straight();
return Qnil;
}
check_for_straight()
{
sort_by_value(pCards);
}
card_sort.c
int compare_card_values (const void *a, const void *b)
{
const double *da = (const double *) a;
const double *db = (const double *) b;
return (*da > *db) - (*da < *db);
}
void sort_by_value(int *pCards)
{
qsort(pCards, NUM_CARDS, sizeof(pCards[0]), compare_card_values);
}

You're casting the card values to double in compare_card_values even though the array contains int. Try this instead:
int compare_card_values (const void *a, const void *b)
{
const int *da = (const int *) a;
const int *db = (const int *) b;
return (*da > *db) - (*da < *db);
}

Related

Pointers to a struct inside a struct

I have two structures (one_d and two_d).
I have a function that will take struct two_d *smg as input. In main(), I am trying to create such smg so it will return value c increased.
My problem is that, while creating an array of struct two_d smg[2], I am not sure how to put inside information about its values, as it is a pointer to a different struct.
So how do you use pointer to a struct inside a struct? I would like to create struct two_d smg[2] but i dont now how to deal with struct one_d *a field in it
#include <stdio.h>
enum sid
{
DRB,
DRA,
};
struct one_d
{
unsigned int r;
unsigned int *p;
};
struct two_d
{
struct one_d *a;
enum sid z;
};
unsigned int getSmg(struct two_d *smg)
{
unsigned int c = 0;
const struct two_d *sd = NULL;
const struct one_d *ed = NULL;
for (sd = smg; sd->a != NULL; ++sd)
{
for (ed = sd->a; ed->p != NULL; ++ed)
{
if (DRA == sd->z)
{
/*P Increment the clear-state buffer size */
c += 1 + ed->r;
}
}
}
return c;
}
int main(void)
{
unsigned int rVal = 0;
struct two_d smg[2]={
//
// [0].a ={1,0},
// [0].z =DRA,
// [1].a={1,0},
// [1].z =DRA,
};
rVal = getSmg(smg);
printf("Return value is a %d\n", rVal);
printf("Return value is a l");
return( 0 );
}
Well, at least this compiles... I'm not game to run it, though...
For what it's worth...
enum sid { DRB, DRA, DRAwhoCares };
typedef struct {
unsigned int r;
unsigned int *p;
} oneD_t;
typedef struct {
oneD_t *a;
enum sid z;
} twoD_t;
unsigned int getSmg( twoD_t *smg ) {
unsigned int c = 0;
for( twoD_t *sd = smg; sd->a != NULL; +sd++ ) {
for( oneD_t *ed = sd->a; ed->p != NULL; ed++ ) {
if( DRA == sd->z ) {
/*P Increment the clear-state buffer size */
c += 1 + ed->r;
}
}
}
return c;
}
int main( void ) {
oneD_t foo[] = { { 1, NULL }, /* ... */ };
oneD_t bar[] = { { 1, NULL }, /* ... */ };
twoD_t smg[]={
{ foo, DRA, },
{ bar, DRA, },
{ NULL, DRAwhoCares, },
};
unsigned int rVal = getSmg( smg );
printf( "Return value: %u\n", rVal );
return 0; // return is not a function call... No parenthesis...
}

C minimum/maximum function

Is there a standard function in C99 to get minimum/maximum element in a given array using a given compare function. Similar to that:
void* get_min(void* start,size_t size,size_t elementSize,int (*compare)(const void *, const void*))
So it seems there is not such standard function, so here is my solution:
For minimum:
void* get_min(void* start,size_t size,size_t elementSize,int (*compare)(const void *, const void*))
{
char* minObject = start;
for(int i = elementSize;i<size*elementSize;i+=elementSize){
char* object = start+i;
if(compare(object,minObject)<0){
minObject = object;
}
}
return minObject;
}
and for maximum:
void* get_max(void* start,size_t size,size_t elementSize,int (*compare)(const void *, const void*))
{
char* maxObject = start;
for(int i = elementSize;i<elementSize*size;i+=elementSize){
char* object = start+i;
if(compare(object,maxObject)>0){
maxObject = object;
}
}
return maxObject;
}

Using qsort() with Structs

I just started learning C and I'm still new to it.
In this program I'm working with an array of structs. The structs are:
typedef struct {
int day;
int month;
int year;
} Date;
typedef struct {
int serial_num;
char full_name[15];
Date *pDate;
} Person;
The array is Person *people.
Now I have two arrays of people and birth dates of those people (same indexes):
const char* names[MAX] = { "Sasson_Sassoni", "Pooh", "James_Bond", "Elvis_is_Alive", "Shilgiya", "Cleopatra", "Sissoo_VeSimmhoo" };
const int dates[MAX][COLS] = {
{ 10, 1, 1988 },
{ 12, 12, 1948 },
{ 4, 12, 1970 },
{ 11, 11, 1890 },
{ 11, 11, 1948 },
{ 1, 10, 1213 },
{ 12, 11, 1948 }
};
By using switch case, every time the user types 1 a person from the lists (Name and birthday) is added to the list people. Then if the user types 3, the list people should be sorted by date (oldest to youngest). So I wrote the following two functions:
void sortList(Person **people, int index) {
qsort(*people, index, sizeof(Person), intcmp);
}
int intcmp(const void *a, const void *b) {
Person *one = (Person *)a;
Person *two = (Person *)b;
int year1 = one->pDate->year;
int year2 = two->pDate->year;
int month1 = one->pDate->month;
int month2 = two->pDate->month;
int day1 = one->pDate->day;
int day2 = two->pDate->day;
if (year1 > year2)
return -1;
else if (year2 > year1)
return 1;
if (month1 > month2)
return -1;
else if (month2 > month1)
return 1;
if (day1 > day2)
return -1;
else if (day2 > day1)
return 1;
return 0;
}
But every time I get an error saying:
Exception thrown: read access violation.
one->pDate was nullptr.
Any help?
Thanks!
EDIT:
Further explanation: In order to insert the people to the array one by one, I made a variable called index and every time a person is added the index grows by one. So When calling the function qsort(), index is the number of people in the array. Also MAX=7, COLS=3, LEN=10. The function that adds people to the array is:
void addToList(Person **people, int *index, const char *names[MAX], const int dates[][COLS]) {
people[*index] = (Person *)malloc(sizeof(Person));
people[*index]->serial_num = *index + 1;
strcpy(people[*index]->full_name, names[*index]);
Date *temp = (Date *)malloc(sizeof(Date));
temp->day = dates[*index][0];
temp->month = dates[*index][1];
temp->year = dates[*index][2];
people[*index]->pDate = temp;
printf("%d %s %d/%d/%d \n", people[*index]->serial_num, people[*index]->full_name, people[*index]->pDate->day, people[*index]->pDate->month, people[*index]->pDate->year);
*index = *index + 1;
}
Your mcve is not complete but I think it's because you confuse pointer and struct:
void sortList(Person **people, int index) {
qsort(people, index, sizeof(Person *), intcmp);
// or qsort(people, index, sizeof *people, intcmp);
}
int intcmp(const void *a, const void *b) {
const Person *one = *(const Person **)a;
const Person *two = *(const Person **)b;

Othello Minimax Algorithm not working

I am trying to make a minimax algorithm, but my function does not return the correct position. It returns the deepest node. I would like it to return the best possible move. Here is my code:
pos minimax(game* g, strategy_config sc)
{
int points = 0;
sc.minimax_config.heuristic(g, sc.minimax_config.hc);
pos p, p2;
int search_depth = sc.minimax_config.ply;
for (p.r = 0; p.r < g->b->nrows; p.r++)
{
for (p.c = 0; p.c < g->b->ncols; p.c++)
{
game* copy = g;
apply_move(copy, p);
if (sc.minimax_config.heuristic(copy, sc.minimax_config.hc)
> points && sc.minimax_config.ply > 0)
{
if (sc.minimax_config.ply == search_depth)
{
p2 = p;
}
sc.minimax_config.ply = sc.minimax_config.ply - 1;
minimax(copy, sc);
}
}
}
return p2;
}
And here are the relevant structs:
struct edge_corner_weight {
unsigned int edge_weight;
unsigned int corner_weight;
};
union heuristic_config {
unsigned int edge_weight;
struct edge_corner_weight edge_corner_weight;
};
typedef union heuristic_config heuristic_config;
struct minimax_config {
int (*heuristic)(game*, heuristic_config);
heuristic_config hc;
unsigned int ply;
};
typedef struct minimax_config minimax_config;
union strategy_config {
minimax_config minimax_config;
};

Bug in valgrind? or my mistake?

So I wrote a toy program for fun, and at the I moment I finished debugging thinking I finally got everything right, the last check with valgrind gave me 2 errors for not freeing 2 blocks of memory. But the error message really does not make sense to me.
==7419== 80 bytes in 1 blocks are definitely lost in loss record 1 of 2
==7419== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7419== by 0x400C77: mj_Malloc (mj.c:19)
==7419== by 0x401761: main (choco.c:93)
==7419==
==7419== 80 bytes in 1 blocks are definitely lost in loss record 2 of 2
==7419== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7419== by 0x400C77: mj_Malloc (mj.c:19)
==7419== by 0x401776: main (choco.c:94)
==7419==
==7419== LEAK SUMMARY:
==7419== definitely lost: 160 bytes in 2 blocks
Line 94 and 93 in main is
mj_Thread *chocolateMakers = mj_Malloc(nMakers * sizeof *chocolateMakers);
mj_Thread *chocolateEaters = mj_Malloc(nEaters * sizeof *chocolateEaters);
which is freed by
mj_Free(chocolateEaters);
mj_Free(chocolateMakers);
mj_Malloc and mj_Free are simple wrappers for error checking. (mj_Free for consistency)
void *mj_Malloc(size_t size) {
void *p = malloc(size);
if (p == NULL) {
mj_Error("heap allocation failed");
}
return p;
}
void mj_Free(void *p) {
free(p);
}
You can see the whole code below if you want.
choco.c
#include "../mj.c"
typedef struct {
int n;
mj_BlockingQueue orderQueue;
mj_BlockingQueue deliveryQueue;
} *ChocolateArgument;
ChocolateArgument ChocolateArgumentCreate(int n, mj_BlockingQueue orderQueue, mj_BlockingQueue deliveryQueue) {
ChocolateArgument this = mj_Malloc(sizeof *this);
this->n = n;
this->orderQueue = orderQueue;
this->deliveryQueue = deliveryQueue;
return this;
}
int MakeChocolates(void *data) {
ChocolateArgument argument = (ChocolateArgument)data;
while (true) {
if (mj_BlockingQueueOut(argument->orderQueue) != NULL) {
printf("chocolate maker %i going home\n", argument->n);
break;
}
int milli = mj_RandomInt(1, 1000);
mj_Sleep(milli);
printf("new chocolate (maker %i, %.3f seconds)\n", argument->n, (double)milli / 1000.0);
int *pMakerNumber = mj_Malloc(sizeof *pMakerNumber);
*pMakerNumber = argument->n;
mj_BlockingQueueIn(argument->deliveryQueue, pMakerNumber);
}
mj_Free(data);
return EXIT_SUCCESS;
}
void HireChocolateMakers(mj_Thread **pMakers, int nMakers, mj_BlockingQueue orderQueue, mj_BlockingQueue deliveryQueue) {
*pMakers = mj_Malloc(nMakers * sizeof **pMakers);
for (int i = 0; i < nMakers; i += 1) {
ChocolateArgument argument = ChocolateArgumentCreate(i + 1, orderQueue, deliveryQueue);
(*pMakers)[i] = mj_ThreadCreate(MakeChocolates, argument);
}
printf("%i chocolate makers hired\n", nMakers);
}
int EatChocolates(void *data) {
ChocolateArgument argument = (ChocolateArgument)data;
int nOrders = mj_RandomInt(1, 10);
for (int i = 0; i < nOrders; i += 1) {
mj_BlockingQueueIn(argument->orderQueue, NULL);
}
printf("chocolate eater %i ordered %i chocolates\n", argument->n, nOrders);
for (int i = 1; i <= nOrders; i += 1) {
int *pMakerNumber = mj_BlockingQueueOut(argument->deliveryQueue);
printf("maker %i -> eater %i (%i / %i)\n", *pMakerNumber, argument->n, i, nOrders);
free(pMakerNumber);
}
printf("chocolate eater %i is satisfied\n", argument->n);
mj_Free(data);
return EXIT_SUCCESS;
}
void OrderChocolates(mj_Thread **pEaters, int nEaters, mj_BlockingQueue orderQueue, mj_BlockingQueue deliveryQueue) {
*pEaters = mj_Malloc(nEaters * sizeof **pEaters);
for (int i = 0; i < nEaters; i += 1) {
ChocolateArgument argument = ChocolateArgumentCreate(i + 1, orderQueue, deliveryQueue);
(*pEaters)[i] = mj_ThreadCreate(EatChocolates, argument);
}
}
void GoHome(mj_Thread *eaters, int nEaters, mj_Thread *makers, int nMakers, mj_BlockingQueue orderQueue) {
for (int i = 0; i < nEaters; i += 1) {
mj_ThreadWait(eaters[i]);
mj_ThreadDelete(eaters[i]);
}
printf("all chocolate eaters are satisfied\n");
for (int i = 0; i < nMakers; i += 1) {
mj_BlockingQueueIn(orderQueue, NULL + 1);
}
for (int i = 0; i < nMakers; i += 1) {
mj_ThreadWait(makers[i]);
mj_ThreadDelete(makers[i]);
}
}
int main(int argc, char **argv) {
if (argc != 3) {
mj_Error("not enough arguments");
}
int nMakers = atoi(argv[1]);
int nEaters = atoi(argv[2]);
mj_RandomSeed();
mj_BlockingQueue orderQueue = mj_BlockingQueueCreate();
mj_BlockingQueue deliveryQueue = mj_BlockingQueueCreate();
mj_Thread *chocolateMakers = mj_Malloc(nMakers * sizeof *chocolateMakers);
mj_Thread *chocolateEaters = mj_Malloc(nEaters * sizeof *chocolateEaters);
HireChocolateMakers(&chocolateMakers, nMakers, orderQueue, deliveryQueue);
OrderChocolates(&chocolateEaters, nEaters, orderQueue, deliveryQueue);
GoHome(chocolateEaters, nEaters, chocolateMakers, nMakers, orderQueue);
mj_BlockingQueueDelete(orderQueue);
mj_BlockingQueueDelete(deliveryQueue);
mj_Free(chocolateEaters);
mj_Free(chocolateMakers);
return 0;
}
mj.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
void mj_Error(char *errorMessage) {
fprintf(stderr, "%s\n", errorMessage);
exit(EXIT_FAILURE);
}
void *mj_Malloc(size_t size) {
void *p = malloc(size);
if (p == NULL) {
mj_Error("heap allocation failed");
}
return p;
}
void mj_Free(void *p) {
free(p);
}
typedef struct mj_QueueElement {
void *data;
struct mj_QueueElement *next;
} *mj_QueueElement;
mj_QueueElement mj_QueueElementCreate(void) {
mj_QueueElement this = mj_Malloc(sizeof *this);
return this;
}
void mj_QueueElementDelete(mj_QueueElement this) {
mj_Free(this);
}
typedef struct {
mj_QueueElement first;
mj_QueueElement last;
} *mj_Queue;
mj_Queue mj_QueueCreate(void) {
mj_Queue this = mj_Malloc(sizeof *this);
this->first = mj_QueueElementCreate();
this->last = this->first;
return this;
}
void mj_QueueDelete(mj_Queue this) {
mj_QueueElementDelete(this->first);
mj_Free(this);
}
void mj_QueueIn(mj_Queue this, void *data) {
this->last->data = data;
this->last->next = mj_QueueElementCreate();
this->last = this->last->next;
}
void *mj_QueueOut(mj_Queue this) {
mj_QueueElement temp = this->first;
void *data = temp->data;
this->first = this->first->next;
mj_QueueElementDelete(temp);
return data;
}
typedef pthread_mutex_t *mj_Mutex;
mj_Mutex mj_MutexCreate(void) {
mj_Mutex this = mj_Malloc(sizeof *this);
pthread_mutex_init(this, NULL);
return this;
}
void mj_MutexDelete(mj_Mutex this) {
pthread_mutex_destroy(this);
mj_Free(this);
}
void mj_MutexLock(mj_Mutex this) {
pthread_mutex_lock(this);
}
void mj_MutexUnlock(mj_Mutex this) {
pthread_mutex_unlock(this);
}
typedef sem_t *mj_Semaphore;
mj_Semaphore mj_SemaphoreCreate(int n) {
mj_Semaphore this = mj_Malloc(sizeof *this);
sem_init(this, 0, n);
return this;
}
void mj_SemaphoreDelete(mj_Semaphore this) {
sem_destroy(this);
mj_Free(this);
}
void mj_SemaphoreUp(mj_Semaphore this) {
sem_post(this);
}
void mj_SemaphoreDown(mj_Semaphore this) {
sem_wait(this);
}
typedef struct {
mj_Queue queue;
mj_Mutex inLock;
mj_Mutex outLock;
mj_Semaphore emptyBlocker;
} *mj_BlockingQueue;
mj_BlockingQueue mj_BlockingQueueCreate(void) {
mj_BlockingQueue this = mj_Malloc(sizeof *this);
this->queue = mj_QueueCreate();
this->inLock = mj_MutexCreate();
this->outLock = mj_MutexCreate();
this->emptyBlocker = mj_SemaphoreCreate(0);
return this;
}
void mj_BlockingQueueDelete(mj_BlockingQueue this) {
mj_QueueDelete(this->queue);
mj_MutexDelete(this->inLock);
mj_MutexDelete(this->outLock);
mj_SemaphoreDelete(this->emptyBlocker);
mj_Free(this);
}
void mj_BlockingQueueIn(mj_BlockingQueue this, void *data) {
mj_MutexLock(this->inLock);
mj_QueueIn(this->queue, data);
mj_SemaphoreUp(this->emptyBlocker);
mj_MutexUnlock(this->inLock);
}
void *mj_BlockingQueueOut(mj_BlockingQueue this) {
mj_MutexLock(this->outLock);
mj_SemaphoreDown(this->emptyBlocker);
void *data = mj_QueueOut(this->queue);
mj_MutexUnlock(this->outLock);
return data;
}
typedef pthread_t *mj_Thread;
typedef struct {
int (*function)(void *);
void *argument;
} *mj_ThreadInfo;
mj_ThreadInfo mj_ThreadInfoCreate(int (*function)(void *), void *argument) {
mj_ThreadInfo this = mj_Malloc(sizeof *this);
this->function = function;
this->argument = argument;
return this;
}
void *mj_ThreadFunction(void *data) {
mj_ThreadInfo info = (mj_ThreadInfo)data;
info->function(info->argument);
mj_Free(data);
return NULL;
}
mj_Thread mj_ThreadCreate(int (*function)(void *), void *argument) {
mj_Thread this = mj_Malloc(sizeof *this);
mj_ThreadInfo info = mj_ThreadInfoCreate(function, argument);
if (pthread_create(this, NULL, mj_ThreadFunction, info) != 0) {
mj_Error("failed to create thread");
}
return this;
}
void mj_ThreadDelete(mj_Thread this) {
mj_Free(this);
}
void mj_ThreadWait(mj_Thread this) {
pthread_join(*this, NULL);
}
void mj_Sleep(int milli) {
struct timespec time;
time.tv_sec = milli / 1000;
time.tv_nsec = (milli % 1000) * 1000000;
nanosleep(&time, NULL);
}
uint64_t mj_RandomInt_s;
uint64_t mj_RandomInt_s2;
void mj_RandomSeed(void) {
srand((unsigned)time(NULL));
mj_RandomInt_s = rand() * rand();
mj_RandomInt_s2 = rand() * rand() * rand();
}
int mj_RandomInt(int from, int to) {
if (from > to) {
mj_Error("invalid arguments");
}
uint64_t x = mj_RandomInt_s;
uint64_t y = mj_RandomInt_s2;
mj_RandomInt_s = y;
x ^= x << 23;
x ^= x >> 17;
x ^= y ^ (y >> 26);
mj_RandomInt_s2 = x;
return (int)((x + y) % (uint64_t)(to - from + 1)) + from;
}
You're allocating chocolateMakers twice (line 93 first and line 36 then) and chocolateEaters twice too (line 94 first and line 62 then). In both cases, you're overwriting the pointer resulting of the first allocation with the one resulting of the second allocation. When you free the allocated memory, you're doing it only once, with the pointers of the second allocations. The pointers of the first allocation are lost, the memory allocated is never freed.

Resources