C: Make generic iteration function? - c

I have an struct which defines an array of structs, each of which contain a couple more arrays. These inner arrays define my 'datasets'.
In numerous places, I wish to iterate over all the datasets. To avoid 3 nested loops, I loop over the total number of datasets and have a few if statements to keep track of which array I need to access. It looks like this:
int datasetCount = 0;
int defendedDatasetCount = 0;
int i;
Dataset *ds;
for (i = 0 ; i < totalDatasets ; i++)
{
// If we have passed the number of datasets in this group, move to the next group
if (datasetCount == (dg->nDatasets + dg->nDefDatasets))
{
dg++;
datasetCount = 0;
defendedDatasetCount = 0;
}
// If we have gone through all the (undefended) datasets, read from thte defended datasets
if (datasetCount >= dg->nDatasets)
{
ds = &(dg->defDatasets[defendedDatasetCount]);
defendedDatasetCount++;
}
else
{
ds = &(dg->datasets[datasetCount]);
}
where dg is the pointer to a struct which is simply an array of structs and a size counter.
I find myself repeating this boilerplate code for iterating through the datasets in a few functions which do different things.
I'm struggling to be able to come up with something like this:
while (give_me_next_dataset(dg) == TRUE)
{
...
}
is it possible?

It's possible, but the proposed API isn't very nice. You're going to have to put iteration state somewhere, and you're not leaving any room for that.
I would propose something like:
struct DgIter {
struct Dg *dg;
size_t index;
size_t dataSet;
};
Then you can have functions like:
struct DgIter iter_start(struct Dg *dg)
{
const struct DgIter iter = { dg, 0, 0 };
return iter;
}
void * iter_next_dataset(struct DgIter *iter)
{
// check if there is a current dataset, else return NULL
// update fields in iter as necessary
}

Related

How to make struct point to previous array value

My schedule->start.hour points to the currect element of array. How to make it point to the previous element of array?
struct Time {
int hour;
} start, end;
struct Class {
struct Time start, end;
} schedule[100];
I need to use this inside a function which sets start of current to be equal to end of previous.
void add_class(struct Class shedule[]){
schedule->start.hour=schedule*(--).end.hour;
};
It seems you need something like the following
void add_class( struct Class shedule[], size_t n )
{
for ( size_t i = 1; i < n; i++ )
{
shedule[i].start.hour = shedule[i-1].end.hour;
}
//...
}
and the function is called like
add_class( shedule, sizeof( shedule ) / sizeof( *shedule ) );
or like
add_class( shedule, 100 );
Its not really clear what you are after and the code you show is wrong. There are no pointers there at all.
If you want to access different instances of Class in the schedule array you need
schedule[0].start.hour;
schedule[1].start.hour;
....
to loop over them all
for(int i = 0; i < 100; i++){
printf("start=%d, end = %d\n",schedule[i].start.hour, scehdule[i].end.hour);
}
if you have a pointer to a Class instance
void add_class(struct Class shedule[]){
...
};
You can access the prior entry in the array like this
void add_class(struct Class schedule[]){
struct Class *prior = schedule - 1;
schedule->start.hour=prior->end.hour;
};
But , and this is a huge but, this will be very bad if this is the first element in the array.
I would still do it by passing indexes tho.

How to order structure instances based on the value of a member

I'm trying to make an algorithm for cars passing through an intersection. I'm currently having problems on deciding which car is supposed to cross depending on other cars's priority.
Here's an example code of what I'm doing
int main(void)
{
struct Cars{
int priority;
};
struct Cars c1;
struct Cars c2;
struct Cars c3;
struct Cars c4;
c1.priority=2;
c2.priority=1;
c3.priority=3;
c4.priority=0;
int Priorities[4] = {c1.priority,c2.priority,c3.priority,c4.priority};
int Order[4];
}
What I am trying to do is trying to figure how to fill the Order array with the id of the car that is next to pass.
As in this example I want the Order array to be [4,2,1,3]. 0 being highest priority, 3 lowest
Although you could help me even more if you can help me figure out WHICH CAR has
which priority so I could write some if's like:
if(the car with priority 0 has passed AND the car with priority 1 has passed)
{
car with priority 2 can pass
}
You might be better first with a 'passed' variable as part of Cars and actually maybe rename Cars to Car as it represents just one car. It might help you visualize the problem better.
struct Car{
int priority;
int passed; // lets set this to 1 if passed
};
And an intersection structure
struct Intersection
{
struct Car cars[4]; // let's give an intersection 4 cars
}
Set up the intersection structure with some cars, initializing their 'passed' variable to 0 meaning 'not passed'.
struct Intersection intersection;
// set the car priority
intersection.cars[0].priority = 2;
intersection.cars[1].priority = 1;
intersection.cars[2].priority = 3;
intersection.cars[3].priority = 0;
intersection.cars[0].passed = 0;
intersection.cars[1].passed = 0;
intersection.cars[2].passed = 0; /** Could do a loop here to initialize instead! */
intersection.cars[3].passed = 0;
You can use a loop, looping until all cars have passed
An example program (not terribly efficient) as I'm taking into account the possibility you are new to C and have probably not yet learned the likes of linked lists or pointers etc.
#include <stdio.h>
int main()
{
struct Car{
int priority;
int passed;
};
// four cars per intersection
struct Intersection{
struct Car cars[4];
};
struct Intersection intersection;
// set the car priority
intersection.cars[0].priority = 2;
intersection.cars[1].priority = 1;
intersection.cars[2].priority = 3;
intersection.cars[3].priority = 0;
intersection.cars[0].passed = 0;
intersection.cars[1].passed = 0;
intersection.cars[2].passed = 0;
intersection.cars[3].passed = 0;
// keep looping until all cars passed
while (!intersection.cars[0].passed ||
!intersection.cars[1].passed || /* <--- this could be improved !! */
!intersection.cars[2].passed ||
intersection.cars[3].passed)
{
int best_priority = -1;
int best_car_index = -1;
// look for next car that can pass
for (int i = 0; i < 4; i++)
{
// this car hasn't passed yet -- check priority
if (!intersection.cars[i].passed)
{
// if not found a car yet to pass or this car is better, then choose this one so far...
if ((best_priority == -1) || (intersection.cars[i].priority < best_priority))
{
best_car_index = i;
best_priority = intersection.cars[i].priority;
}
}
}
if (best_car_index == -1)
break; // nothing found
else
{
// set the car with best priority to 'passed'
intersection.cars[best_car_index].passed = 1;
printf("Car ID %d with priority %d just passed the intersection!\r\n", best_car_index, best_priority);
}
}
return 0;
}
Program output
Car ID 3 with priority 0 just passed the intersection!
Car ID 1 with priority 1 just passed the intersection!
Car ID 0 with priority 2 just passed the intersection!
Car ID 2 with priority 3 just passed the intersection!
The program probably doesn't do what you want but hopefully you'll be able to manipulate it the way you want.
(You could fill a new list instead of printing the data)

ColdFusion, BigDecimal cannot be used as an array

I am trying to perform a few simple tasks with an array of structures that I have and feel like I'm almost done with my solution but am having some last minute trouble. I am trying to accomplish the following tasks:
Create a struct with the following values; id, name, int arr[].
I am using a FOR loop to iterate over an array of values like ID, name, sub id.
For each item in my list, I am trying to make the decision if I've seen the struct before and if its in my agencies Array.
If its not there, add the current struct to an array. If its already present in the array then add the current sub id to the int arr[] entry of the struct.
When I run my code below I keep getting the error, "BigDecimal cannot be used as an array" and I don't understand what's happening. I am new to CFSCRIPT so perhaps I'm either not getting the arr[] values out of the struct or not defining my struct correct so the third value is of Array type.
remote array function getCurrAgenciesList(String Acct_Id) returnformat="JSON"
{
include "qry_getCurrentAssignedRepoAgenciesAll.cfm";
//define arr to hold values...
var agenciesArr = [];
var recordLength = getCurrentAssignedRepoAgencies.RecordCount;
for(agency in getCurrentAssignedRepoAgencies)
{
currentStruct = {id=agency.repoID, name=agency.repoName, relatedColl=agency.collatSub};
var structArrIndex = arrayOfStructsFind(agenciesArr, "id", agency.repoID);
if(structArrIndex eq 0)
{
//add new struct to agenciesArr
ArrayAppend(agenciesArr,currentStruct,"true");
}
else
{
//find current struct in array using index from before...
var collFromStr = agenciesArr[structArrIndex]['relatedColl'];
//add current collatsub to array, append.
var updatedStruct = ArrayAppend(collFromStr,agency.collatSub);
//reassign updated arr[] struct value back in array.
agenciesArr[structArrIndex]['relatedColl'] = collFromStr;
}
}
//return...
return agenciesArr;
}
function arrayOfStructsFind(Array, SearchKey, Value)
{
var result = 0;
var i = 1;
var key = "";
for (i=1;i lte arrayLen(array);i=i+1)
{
for (key in array[i])
{
if(array[i][key]==Value and key == SearchKey)
{
result = i;
return result;
}
}
}
return result;
}
Any help would be greatly appreciated, as I feel I'm stuck on this one last thing or there's something I am missing. Any feedback is welcome.
UPDATE the error happens at line 27,
var updatedStruct = ArrayAppend(collFromStr,agency.collatsub);
UPDATE 3:39PM
I believe the issue is not related to the above line but this line:
var collFromStr = agenciesArr[structArrOmdex]['relatedColl'];
I am asking for an array to be returned from the struct from key, relatedColl. I am thinking only an integer is return so when the next Array Append operation is performed the code explodes. So, how does one create an array inside a struct in Cold Fusion\CFSCRIPT????
I have solved my problem by making the following changes:
Re-defined the struct definition to have an array type as the third element.
After doing this it looks like the search needed to be modified so I switched the ordering of my key, value if statement.
I also gathered a great amount of information from this link. It is wonderful.
Final Code:
remote array function getCurrAgenciesList(String Acct_Id) returnformat="JSON"
{
include "qry_getCurrentAssignedRepoAgenciesAll.cfm";
//define arr to hold values...
var agenciesArr = [];
var recordLength = getCurrentAssignedRepoAgencies.RecordCount;
for(agency in getCurrentAssignedRepoAgencies)
{
arr = [agency.collatSub];
currentStruct = {id=agency.repoID, name=agency.repoName, relatedColl=arr};
var structArrIndex = arrayOfStructsFind(agenciesArr, "id", agency.repoID);
if(structArrIndex eq 0)
{
//add new struct to agenciesArr
ArrayAppend(agenciesArr,currentStruct,"true");
}
else
{
//find current struct in array using index from before...
var collFromStr = agenciesArr[structArrIndex]['relatedColl'];
//add current collatsub to array, append.
ArrayAppend(collFromStr,agency.collatSub,"true");
//reassign updated arr[] struct value back in array.
agenciesArr[structArrIndex]['relatedColl'] = collFromStr;
}
}
//return...
return agenciesArr;
}
function arrayOfStructsFind(Array, SearchKey, Value)
{
var result = 0;
var i = 1;
var key = "";
for (i=1;i lte arrayLen(array);i=i+1)
{
for (key in array[i])
{
if(key == SearchKey and array[i][key]==Value)
{
result = i;
return result;
}
}
}
return result;
}

Exit code 11 on extractMin() in PriorityQueue in C'99

I'm new in C programming. I'm developing a priority queue in C'99 with the heap data structure.
I'm using heapifyDown() in combination with swapValues() to sort the heap array for extracting the first element (min-heap) pqueue_extractMin() function. My structure looks like this:
typedef struct ProrityQueue_s PriorityQueue;
typedef struct PriorityQueue_Entry_s *PriorityQueue_Entry;
struct ProrityQueue_s {
int size, last;
char error;
PriorityQueue_Entry *entries;
};
struct PriorityQueue_Entry_s {
char *value;
float priority;
};
For information – Full code for information on gist: https://gist.github.com/it4need/ddf9014bfda9fe6a64bb01a7417422bc
Questions:
Insertion into the Priority queue ("minheap") looks good. Everything is fine. But when I'm extract more than one element at once, I will get this error: "Process finished with exit code 11".
Is this line allowed to copy the whole contents of the last element to the first of the heap? priorityqueue->entries[0] = priorityqueue->entries[priorityqueue->last];
swapValues(priorityqueue, currentPositionIndex, smallestChild); Can I swap values of whole Structure elements? -> implementation (bottom).
HeapifyDown():
void heapifyDown(PriorityQueue *priorityqueue)
{
int currentPositionIndex = 0;
while(currentPositionIndex < priorityqueue->last)
{
int smallestChild = currentPositionIndex;
int leftChildIndex = (2 * currentPositionIndex) + 1;
int rightChildIndex = (2 * currentPositionIndex) + 2;
smallestChild = (priorityqueue->entries[leftChildIndex]->priority < priorityqueue->entries[smallestChild]->priority && priorityqueue->last > leftChildIndex)
? leftChildIndex : smallestChild;
smallestChild = (priorityqueue->entries[rightChildIndex]->priority < priorityqueue->entries[smallestChild]->priority && priorityqueue->last > rightChildIndex)
? rightChildIndex : smallestChild;
if(smallestChild == currentPositionIndex)
{
break;
}
swapValues(priorityqueue, currentPositionIndex, smallestChild); // #todo: Why does this line break the function on two function calls by negative values
currentPositionIndex = smallestChild;
}
}
SwapValues():
void swapValues(PriorityQueue *priorityqueue, int firstIndex, int secondIndex)
{
// #todo: Does this work properly?
PriorityQueue_Entry tmp_entry = priorityqueue->entries[firstIndex];
priorityqueue->entries[firstIndex] = priorityqueue->entries[secondIndex];
priorityqueue->entries[secondIndex] = tmp_entry;
}
extractMin():
char *pqueue_extractMin(PriorityQueue *priorityqueue)
{
if(isEmpty(priorityqueue))
{
priorityqueue->error = ERROR_PRIORITY_QUEUE_EMPTY;
}
priorityqueue->last--;
char *tmp = priorityqueue->entries[0]->value;
priorityqueue->entries[0] = priorityqueue->entries[priorityqueue->last]; // #todo: Is this allowed?
heapifyDown(priorityqueue); // #todo: Why does this line break the extractMin() function on two function calls -> check swapValues() in heapifyDown()
return tmp;
}
Full code for information on gist: https://gist.github.com/it4need/ddf9014bfda9fe6a64bb01a7417422bc

C: how sort and subsort values in a structure

After hours of thinking and tinkering I almost gave up but decided to turn to the community for their help. I'm new to C and I just learned bubble sort. For example the following code sorts by name, what I would like to implement is a sub sort where it also sorts by person ID, how would I do that or change the following code to do just that? (This is structure problem).
struct human {
char name;
char id;
}
function sorting(struct human person)
{
struct human temp
int i, unsorted;
do{
unsorted = 0;
for(i = o; i<count-1; i++)
{
if(strcmp(person[i].name, person.name) > 0)
{
temp = person[i];
person[i] = person[i+1];
person[i+1] = temp;
unsorted = 1;
}
}while(unsorted);
}
First, it would help to break out your comparison function into its own function:
int compare_people(struct human *person1, struct human *person2)
{
return strcmp(person1->name, person2->name);
}
Then, you can more easily change the logic to compare ID if the name is equal:
int compare_people(struct human *person1, struct human *person2)
{
int d = strcmp(person1->name, person2->name);
if (d == 0) {
return person2->id - person1->id;
} else {
return d;
}
}

Resources