Changes to Pointers not made permanent - c

struct Limit
{
float Price;
int size;
int Volume;
struct Limit *Parent;
struct Limit *ltChild;
struct Limit *rtChild;
struct list_head* Order;
};
typedef struct Limit Limit;
struct Order
{
double idNum;
bool BuySell;
int shares;
float limitPrice;
char* entryTime;
char* eventTime;
struct list_head ord_Queue;
};
typedef struct Order Order;
void AddOrder(Order* newOrder,Limit* Limit,HXmap* OrderMap)
{
list_add_tail(&newOrder->ord_Queue,Limit->Order);
HXmap_add(OrderMap,&newOrder->idNum,newOrder);
Limit->size++;
Limit->Volume +=newOrder->shares;
}
void ModifyOrder(float oLimit, int oShares,float nLimit,int nShares,HXmap* LimitMap,HXmap* OrderMap, oBook* OrderBook)
{
Limit* ParentLimit = (Limit*)HXmap_get(LimitMap,&oLimit);
if(ParentLimit==NULL)
{
printf("ERRONEOUS ORDER\n");
return;
}
struct list_head *pos;
pos = ParentLimit->Order->next;
Order* Ord= NULL;
while(pos!=ParentLimit->Order)
{
Ord = list_entry((pos),Order,ord_Queue);
if(Ord->shares==oShares)
break; //found the order
else pos = pos->next;
}
if(pos==ParentLimit->Order && Ord->shares!=oShares)
{
printf("ORDER NOT FOUND\n");
return;
}
if(oLimit==nLimit)
{
ParentLimit->Volume = (ParentLimit->Volume + nShares)-oShares;
Ord->shares = nShares;
}
else
{
//delete from list
Ord->ord_Queue.next->prev = Ord->ord_Queue.prev;
Ord->ord_Queue.prev->next = Ord->ord_Queue.next;
ParentLimit->size--;
HXmap_del(OrderMap,&Ord->idNum);
if(ParentLimit->Volume==Ord->shares)
{
if(Ord->BuySell==1)
OrderBook->buyTree = RemoveLimit(OrderBook->buyTree,ParentLimit,LimitMap);
else
OrderBook->sellTree = RemoveLimit(OrderBook->sellTree,ParentLimit,LimitMap);
}
else
ParentLimit->Volume-=Ord->shares;
Ord->limitPrice = nLimit;
Ord->shares = nShares;
INIT_LIST_HEAD(&Ord->ord_Queue);
ParentLimit = HXmap_get(LimitMap,&nLimit);
if(ParentLimit==NULL)
{
ParentLimit = Limit_init(nLimit);
if(Ord->BuySell==1)
OrderBook->buyTree= AddLimit(OrderBook->buyTree,ParentLimit,LimitMap);
else
OrderBook->sellTree = AddLimit(OrderBook->sellTree,ParentLimit,LimitMap);
}
AddOrder(Ord,ParentLimit,OrderMap);
}
}
Okay, its a longish code, but much of it is purely intuitive. [It uses list.h Kernel Linked List and its associate functions.More info about KLL can be found here ]The idea, is when a message to modify a preexisting order at a particular price(its a financial code) arrives, it removes the order from the previous "queue" of its old Price (ParentLimit in ModifyOrder() ) finds the address of new limit price structure by querying the map, if it doesnt exist, creates a new limit and add the order else it simply adds it.
Now, I enter same message of modifying orders in a particular limit price.
Configuration before passing the messages:
Limit Price : 181.25, two orders of 250 shares each.
When I pass, the first modify message, to modify the first order of 250 shares from 181.25 to 181.35(no previous limit exists so it will create a new limit and add it to the tree), the control eventually flows to AddOrder() hence, adding the orders. Definition of AddOrder() function is attached, though its very simplistic and calls list_add_tail() to add it to list.
After the first modification(and addition of order), the DDD gives me this situation:
Address of ParentLimit: 0x804f1d0
Address of ->Order: 804f710
Contents of ->next: 804dec4
Contents of ->prev: 804dec4
Address of Order->ord_Queue (just inserted): 0x804dec4
Contents of Order->ord_Queue->prev: 0x804f710
Contents of Order->ord_Queue->next: 0x804f710
This shows the addition of the order to the queue has taken place successfully.
When I pass the second message to modify another order at the same old price (181.25 to 181.35) and query the map to find me the address of the new Limit Price,
The situation is:
Address of ParentLimit: 0x804f1d0
Address of ->Order: 804f710
Contents of ->next: 804f710
Contents of ->prev: 804f710
Which means, that somehow the change made was not made permanent. I dont know why this is happeneing.

This is the behavior you expect, given your description of where you are querying. These lines will remove the order from your linked list before your query the map to get a ParentLimit for the new price:
Ord->ord_Queue.next->prev = Ord->ord_Queue.prev;
Ord->ord_Queue.prev->next = Ord->ord_Queue.next;
To clarify: Limit.Order is a pointer. It will follow your list head even when you move it to other lists. Thus, deleting from from your old list ends up following a pointer to your new list if you only have one order. You will either need to make it an embedded struct or keep a dummy head that is empty for both new and old lists.

Related

Problem constructing and appendNode function ifor a linked llist C

source code from tbaMUD
In file "handler.c", we have this "obj_to_room" function, which takes any object dropped in the room and adds it to a linked list. This creates a stack of objects, with the first object at the bottom (head) of the stack, the second object stacked on top the first, and so on. This is the default behavior for linked lists in C.
In file "act.informative.c" we have the "look_at_room" function. That calls the "list_obj_to_char" function. This uses a "for loop" to read the list/stack.
When using a "for loop" to read the list/stack/node, it does so from top (tail) to bottom (head). This, too is the default behavior in C. Therefore, objects dropped in the room are displayed with the most recently dropped object at the top of the list and the first object dropped at the bottom.
That's what causes this issue:
www.tbamud.com/forum/2-general/5530-has-anyone-else-noticed
My goal is to invert the order of objects in that linked list. There are a few hacks I might pull off, but that's just what they would be - hacks, not exactly proper and certainly not elegant. I think the best solution is coding a function using "appendNode" to add objects at the tail (top) of the list instead of its head (bottom).
Toward that end, I need to change this:
/* put an object in a room */
void obj_to_room(struct obj_data *object, room_rnum room)
{
if (!object || room == NOWHERE || room > top_of_world)
log("SYSERR: Illegal value(s) passed to obj_to_room. (Room #%d/%d, obj %p)",
room, top_of_world, (void *)object);
else {
object->next_content = world[room].contents;
world[room].contents = object;
IN_ROOM(object) = room;
object->carried_by = NULL;
if (ROOM_FLAGGED(room, ROOM_HOUSE))
SET_BIT_AR(ROOM_FLAGS(room), ROOM_HOUSE_CRASH);
}
}
to something like this:
/*put an object in a room */
void obj_to_room(struct obj_data *object, room_rnum room)
{
if (!object || room == NOWHERE || room > top_of_world)
{
log("SYSERR: Illegal value(s) passed to obj_to_room. (Room #%d/%d, obj %p)",
room, top_of_world, (void*) object);
}
else
{
/*function to add objects at the tail of the list instead of its head*/
/*everything hinges on this single line and I probably have it all kinds of wrong*/
/*struct node* appendNode(struct node** head, int key)*/
struct world[room].contents* appendNode(struct world[room].contents** object, room_rnum room)
{
/* special case for length 0*/
if (object == NULL)
{
*object = world[room].contents;
}
else
{
/* locate the last node */
while (object->next_content != NULL)
{
object = object->next_content;
}
object->next_content = world[room].contents;
world[room].contents = object;
IN_ROOM(object) = room;
object->carried_by = NULL;
if (ROOM_FLAGGED(room, ROOM_HOUSE))
SET_BIT_AR(ROOM_FLAGS(room), ROOM_HOUSE_CRASH);
}
}
}
}
Problem 1
Although I'm familiar with multiple programming languages, C is not one of them. When it comes to the idiosyncrasies and technical fine points of the language, I know nothing. That makes reading C code challenging and writing it even more so.
Problem2
I understand the format should be:
struct node* appendNode(struct node** head, int key)
I think the head and int key are correct, but I'm unable to identify the node in the original code. So I used my best guess.
It's not surprising that attempting to compile this code yields:
handler.c: In function ‘obj_to_room’:
handler.c:681:19: error: expected identifier or ‘(’ before ‘[’ token
681 | struct world[room].contents* appendNode(struct world[room].contents** object, room_rnum room)
| ^
make[1]: *** [<builtin>: handler.o] Error 1
Ok, I suspect there's all sorts of things wrong with that line, but I don't know how to fix it. I'm hoping that some brilliant coder will be kind enough to help out.
This does the trick.
/* put an object in a room */
void obj_to_room(struct obj_data* object, room_rnum room)
{
if (!object || room == NOWHERE || room > top_of_world) {
log("SYSERR: Illegal value(s) passed to obj_to_room. (Room #%d/%d, obj %p)", room, top_of_world, (void *)object);
}
else {
if (world[room].contents == NULL) { // here, we have an empty list.
world[room].contents = object; // Just add it.
}
else {
struct obj_data* i = world[room].contents; // define a temporary pointer
while (i->next_content != NULL) {
i = i->next_content; // find the first without a next_content
}
i->next_content = object; // add it at the end
}
object->next_content = NULL; // end of the linked list
IN_ROOM(object) = room;
object->carried_by = NULL;
if (ROOM_FLAGGED(room, ROOM_HOUSE)) {
SET_BIT_AR(ROOM_FLAGS(room), ROOM_HOUSE_CRASH);
}
}
}

How to get a node with specific value in a linked list?

I want to get a node with bno(branch number).
struct bank {
struct branch *branches; // to hold the branches of the bank
struct operation_type *optypes; // to hold the transaction types offered by the bank
};
struct branch *getProperBranch(struct bank *banka, int entity) {
while (banka->branches != NULL) {
if (banka->branches->bno == entity) {
return banka->branches;
}
banka->branches = banka->branches->nextb;
}
}
When I do this I can find it but bank->branches address is changed. I lose its original values. How can I do this without losing position?
I need to access bank->branches->customers and add new customer in a proper location.
Thanks in advance.
Use a temporary variable with the type of your node. Don't forget the return value in the event entity is not found.
struct branch *getProperBranch(struct bank *banka, int entity) {
for (struct branch *bp = banka->branches; bp; bp = bp->nextb)
if (bp->bno == entity)
return bp;
return NULL;
}

C Read from File into LinkedList

I have a text file that I need to read a populate a linked list. The file structure is like this.
Ant,Adam 10 5
Mander,Sally 4 3
King,May 6 6
King,Joe 9 6
Graph,Otto 2 5
Carr,Redd 1 3
The name is szName. The second int is iDepartTmUnits, and the last int is iTime;
I'm trying to read the input from stdin
It should insert EVT_ARRIVE and EVT_DEPART events into the simulation's eventList. Assuming you are using fgets and sscanf, please make certain you check the count returned from your sscanf.
// Event Constants
#define EVT_ARRIVE 1 // when a person arrives
#define EVT_DEPART 2 // when a person departs the simulation
We have these structures
typedef struct
{
char szName[16]; // Name
int iDepartTmUnits; // time units representing how long he/she stays around
} Person;
// Event typedef (aka Element)
typedef struct
{
int iEventType; // The type of event as an integer:
// EVT_ARRIVE - arrival event
// EVT_DEPART - departure event
int iTime; // The time the event will occur
Person person; // The person invokved in the event.
} Event;
// NodeLL typedef - these are the nodes in the linked list
typedef struct NodeLL
{
Event event;
struct NodeLL *pNext; // points to next node in the list
} NodeLL;
// typedefs for the ordered link list
typedef struct
{
NodeLL *pHead; // Points to the first node in the ordered list
} LinkedListImp;
typedef LinkedListImp *LinkedList;
// typedefs for the Simulation
typedef struct
{
int iClock; // clock time
LinkedList eventList; // A linked list of timed events
} SimulationImp;
typedef SimulationImp *Simulation;
Now where I am struggling is how to populate a linked list with this information.
Actually I'm struggling with a lot to grasp my head around this, so I'm sorry at the question being overly complex or overly simple.
First Thing I am struggling with
I'm declaring it as
void generateArival(Event eventM[])
I believe that is incorrect, because in my main, I wouldn't pass it the event, I believe I would pass it a Simulation implementation.
Second Thing I Am struggling with
Here is the code I have so far where I am too copy from the file into a linked list.
while(!feof(pFilePerson))
{
iLineCount++;
i++;
fgets(szInputBuffer, MAX_LINE_SIZE, pFilePerson);
iScanfCnt = sscanf(szInputBuffer,"%s %d %d\n",
event.person.szName,
event.iTime,
event.person.iDepartTmUnits,
);
}
Lastly
I am to input the EVT_ARRIVE and EVT_DEPART into the eventList.
I believe that to be something like this,
they are int 1 and 2 respectfully, so I would need something like iEvent = event.iEventType;
and input that into the sim->eventList
Any help is appreciated, I need a lot more time with this concept of linked lists, but this is breaking my head.
EDIT
I can print out the name but not the numbers
while(fgets(szInputBuffer, sizeof szInputBuffer, pFilePerson) != NULL)
{
// print the input buffer as is (it also has a linefeed)
//printf("Person # %d: %s\n", iLineCount, szInputBuffer);
sscanf(szInputBuffer,"%s",
event.person.szName);
sscanf(szInputBuffer, "%I64d",
&event.person.iDepartTmUnits);
//linkList.event.iTime);
printf("%-7s\n", event.person.szName);
printf("%d\n", event.person.iDepartTmUnits);
}

(C Programming) How do I use a data structure and function which are defined in another file?

Say, I have a file dataStructure.c and dataStructure.h. (My data structure is a hash map.) These files contain the implementation of the data structure and methods for adding new entries to the structure as well as retrieving entries.
Here's an example:
// dataStructure.h
struct node {
char *label;
int address;
struct node *next; // Points to the next node.
};
struct ourTable {
int size;
struct node **list; // List of all the (key, value) pairs.
};
// Then, here are methods to create table, add new entries and retrieving them.
struct ourTable createTable(int size);
void addEntry(struct ourTable *t, char *label, int address);
unsigned retrieveAddress(struct ourTable* table, char *label);
The function retrieveAddress basically just returns the address of that label. Since I am trying to implement a hash map, which is just a data structure of several (key, value) pairs. In my case, the key is label whereas value is address.
unsigned retrieveAddress( struct ourTable* table, char *label)
{
int bin = 0;
bin = hashFunction(table, label); // Hashing function
struct node *list = table->list[bin];
struct node *entryItem = list;
while(entryItem)
{
if (entryItem->label == label)
{
return entryItem->address; // Returns the address of that label.
}
entryItem = entryItem->next;
}
return NULL;
}
Then, I have another file, establishTable.c which just uses the methods implemented in dataStructure.h to create a table and then add new entries. This is what I wrote in that file:
// establishTable.c
#include "dataStructure.h"
struct ourTable establishTable()
{
struct ourTable table = createTable(1000); // Create a table with a maximum of 1000 entries.
addEntry(&table, "word", 1234);
}
And what I want to do is to pass the structure ourTable with the new entries I inserted in establishTable.c to the main file main.c. To illustrate what I am trying to accomplish:
// main.c
#include "dataStructure.h"
#include "establishTable.h"
int main()
{
// I'm not sure how to pass the data structure... Something like this:
struct ourTable table = establishTable();
// Get the retrieveLabel function from dataStructure.h and use it here.
printf("retrieved from the table at %u\n\n", retrieveAddress(&table,"word") );
}
I tried running the main.c. It doesn't show any errors but it just outputs
retrieved from the table at 0
which just tells me that the table I already established was not passed on at all. The output should be 1234.
So, how do I pass a data structure and the result of a function from another file to my main.c file? It works when I just do everything in establishTable.c but that is not my intention. I have tried the extern method as suggested in other threads, but nothing works.
You forgot the return statement
struct ourTable establishTable()
{
struct ourTable table = createTable(1000); // Create a table with a maximum of 1000 entries.
addEntry(&table, "word", 1234);
return table;
}

Last element value appears in first and last position when printing linked list

Happy New Year.
This question arises from a project to program a game called Laby-chiffres in C. To see the game look in the third batch of games on this link: http://www.rci-jeux.com/jeux/labychiffres/laby.swf .
Context:
I am using a linked list to store the path taken by a player through a grid of numbers. The player's aim is to find a path from the departure point to the arrival point, with a given length and given total of the numbers in the path. There is a switch statement for a menu and then one to accept the direction the player wants to move in. This works as I have code that shows that the 'passage' of the player to each number is recorded correctly
Problem:
When I try to print the path (which is a requirement of the assignment - and useful for the player to see) I print the path in the correct order, except that the last element, i.e. where the player most recently moved to, is shown at the start and the end of the list.
Example: Player makes moves through positions with values as follows. Starting with the departure point value 5 -> 8 -> 4-> 1. What is printed at each stage is:
5->
8->8->
4->8->4->
1->8->4->1->
What I have tried
I have looked at several other linked list questions, but none I have seen have the same issue that I have.
I have tried changing lots of things, but to be honest now more experimentally than anything. For example, changing the empiler function to add elements at the wrong end prints the path in the wrong order (as expected) but still prints the most recently reached number twice, just both at the start of the path rather than one at the start and one at the end.
Relevant functions
The lecturer has said explicitly that the printing needs to reverse the order so these are the printing functions:
void affiche_chemin (PLATEAU jeu, PILE pile){
afficher_pile_inverse(&jeu , jeu.chemin.P_sommet);
printf("\n");
}
void afficher_pile_inverse(PLATEAU *P_jeu, ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse(P_jeu,P_cur->P_suivant);
printf("%d->",lire_valeur_a(P_jeu,&P_cur->valeur));
}
}
lire_valeur_a reads the value in the grid, which is part of the PLATEAU structure given below and read in from a text file. This appears to work so I am not including it to try to keep the question length down.
The function to add elements is :
ELEMENT* empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
P_elt_ajoute ->P_suivant = P_liste->P_sommet;
P_liste->P_sommet = P_elt_ajoute;
return P_elt_ajoute;
}
Given the lecturers comments about needing to reverse the order to print correctly I think I am adding elements at the right end of the list.
These functions initialise the path, and allocate a new ELEMENT, and are just given for reference as used in the next extract.
void initialiser_pile(PILE *P_pile){
P_pile->P_sommet = NULL;
}
ELEMENT *nouvel_element (POSITION nouvelle_valeur){
ELEMENT *P_elt;
P_elt =(ELEMENT*) malloc(sizeof(ELEMENT));
if(P_elt ) { /* NULL equivalent to false like 0 */
P_elt->valeur = nouvelle_valeur;
P_elt->P_suivant = NULL;
}
return P_elt;
}
This code sets up the path for the first time when the text file for the game is read, so it is the first time empiler is used to add an element to a path. (This extract is from a long function using fscanf multiple times to read the game text file, and seems to work correctly.)
ELEMENT *P_sommet = nouvel_element(PLAT->dep);
if (P_sommet == NULL){
printf("Erreur d'allocation\n");
return 0;
}
initialiser_pile(&PLAT->chemin);
empiler (&PLAT->chemin,P_sommet);
PLAT->longcur = 1;
PLAT->sumcur=PLAT->grille[PLAT->dep.indl][PLAT->dep.indc];
The following function is used for adding elements during the game.
int choix_indep_jeu_update(PLATEAU *jeu, POSITION *new_pos, int pas, int dir){
ELEMENT *new = nouvel_element(*new_pos);//1 Make new element
if (new == NULL) return 0;
empiler( &jeu->chemin, new );//should add new element
jeu->longcur++;
jeu->sumcur = jeu->sumcur + lire_valeur_a(jeu, new_pos);
affiche_grille(*jeu);
affiche_chemin(*jeu,jeu->chemin);
return 1;
}
Data Structures
typedef struct position_st{
int indl;//indice of ligne
int indc;//indice of colonne
}POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
}PILE;
typedef struct plat_st{
//########## GAME FILE INFORMATION
int nl; //number of lines in grid
int nc; //number of columns in grid
POSITION dep; //position du depart: dep.indl and dep.indc
POSITION arr; //position d'arrive: arr.indl and arr.indc
int longdem; //length demanded
int sumdem; //total demanded
int ** grille; //Playing grid
//#######INFO re GAME IN PROGRESS ########
int longcur; //longueur courant
int sumcur; //totale courant
PILE chemin; //The path
}PLATEAU;
I simplified your code and it seems to be working, assuming that you want empiler() to insert elements into the front of the list, so they end up in reverse order. I added afficher_pile_inverse1() so that the last value doesn't have a "->" after it. So the error is in creating the list or there's an issue with the grid function which you did not show.
#include <stdio.h>
#include <stdlib.h>
typedef int POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
}PILE;
void empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
P_elt_ajoute ->P_suivant = P_liste->P_sommet;
P_liste->P_sommet = P_elt_ajoute;
}
void afficher_pile_inverse1(ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse1(P_cur->P_suivant);
printf("%d->",P_cur->valeur);
}
}
void afficher_pile_inverse(ELEMENT *P_cur){
if(P_cur != NULL){
afficher_pile_inverse1(P_cur->P_suivant);
printf("%d",P_cur->valeur);
}
}
void affiche_chemin (PILE pile){
afficher_pile_inverse(pile.P_sommet);
printf("\n");
}
int main(void){
ELEMENT ae[4] = {{0,NULL},{1,NULL},{2,NULL},{3,NULL}};
PILE P_liste = {NULL};
size_t i;
for(i = 0; i < 4; i++)
empiler(&P_liste, &ae[i]);
affiche_chemin(P_liste);
return 0;
}

Resources