How to navigate around a linked list? - c

So let's say I have 3 nodes in my linked lists, each with a first name in it. The list is supposed to be ordered alphabetically. I need to navigate with pointers
I have a .h interface and a .c file implementation, so you can assume anything prototyped int he List.c file is not in the header file.
Let me explain what's going on logically, to make my code a bit easier to understand. ListP is a pointer to struct List that has simple attributes like logical size, physical size and a pointer to the head of the linked list. The character strings are typedefd as ListItemP for easy reconstruction to an integer linked list etc if need be.
List.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "List.h"
typedef struct Entry *EntryP;
EntryP newEntry(ListItemP thisItem);
struct List
{
int sizeL;
int sizeP;
ListItemP head;
};
struct Entry
{
ListItemP content;
struct Entry *next;
};
ListP newList()
{
ListP thisList = (ListP) malloc(sizeof(ListP));
thisList->head = 0x00;
thisList->sizeL = 0;
thisList->sizeP = 0;
return thisList;
}
void insertItemList(ListP thisList, ListItemP thisItem)
{
EntryP thisEntry = newEntry(thisItem);
thisEntry->content = thisItem;
// Make a conditional for the first condition (no items in list)
if ((thisList->head == 0x00) || (strcmp(thisItem, thisList->head) < 0)) {
thisList->head = thisEntry->content;
thisEntry->next = 0x00;
}
// The other conditional are what I don't understand, how to put go through
navigate through the list via pointers and such.
thisList->sizeL++;
thisList->sizeP++;
}
void displayList(ListP thisList)
{
printf("First Item: %s\n",thisList->head);
}
/*
* Not in the interface
*/
EntryP newEntry(ListItemP thisItem)
{
EntryP thisEntry = (EntryP) malloc(sizeof(EntryP));
thisEntry->content = thisItem;
thisEntry->next = NULL;
return thisEntry;
}
I would post my main.c (or tester.c or whatever you want to call it) but I don't really think its going to help at all, all the linked list navigation is going to occur in the List.c file.
So my question is this, assuming I have 3 or 4 or however many nodes, how can I navigate around them so I can do things like string compares and yadda yadda in order to place new strings in the linked list in alphabetical order.
Thank you!

Related

How do I send the linked list as a function argument

<DBDLinkedList.h>
...
typedef struct _dbDLinkedList
{
Node * head;
Node * tail;
Node * cur;
int numOfData;
} DBDLinkedList;
typedef DBDLinkedList List;
...
<mysourcecode.c>
int main(void)
{
...
List list;
int data;
ListInit(&list);
for(i=0; i<ID_LEN; i++)
LInsert(&list, new_id[i]);
solution(list, data);
...
}
int solution(List list, int data)
{
...
if(LFirst(&list, &data))
{
int i=1;
if(data==46)
LRemove(&list);
i++;
while(LNext(&list, &data))
{
if(i==numOfData)
if(data==46)
LRemove(&list);
i++;
}
}
...
}
I used dummy node doubly linked list.
When I complied this project, error occurred :
‘numOfData’ undeclared (first use in this function).
I'm not used to using Linked list.
How do I send the linked list as a function argument(for solution())?
from what I could see, the problem might not be in sending the linked list as a function argument. In "if(i==numOfData)", you are trying to access the numOfData, which is a part of a 'List' structure, so you need to access it through 'List' variable.... Perhaps replacing that line of code with something like "if(i == list.numOfData)" will do the trick
numOfData is not a variable. You most probably intended to access the current node's numOfData member.
But you really don't need to access that member directly. It seems likely (without seeing the code) that LNext will put that value in your data variable -- it is the reason why you pass &data as argument to LNext.
This brings us to another issue in your code. You call solution with data, but you never gave data a value. If the intention is to remove the node with value 46, then the main program should call solution as follows:
solution(list, 46);
And solution should be implemented as follows:
int solution(List list, int dataToRemove) {
if (!LFirst(&list, &data)) {
return 0; // to indicate that value to delete was not found
}
while (data != dataToRemove) {
if (!LNext(&list, &data)) {
return 0; // to indicate that value to delete was not found
}
}
LRemove(&list);
return 1; // to indicate success
}

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;
}

Winapi get Interlocked Singly Linked List Item, without Popping it

I use a WinApi native Single linked list, i have a code example like so, that creates singly linked list, and nsert some data there:
#include <Windows.h>
#include <stdio.h>
typedef struct Info
{
SLIST_ENTRY ItemEntry;
DWORD dwUserId;
} INFO,*PINFO;
int main()
{
PINFO pInfo1 = __aligned_malloc(sizeof(INFO));
pInfo1.dwUserId = 1;
PINFO pInfo2 = __aligned_malloc(sizeof(INFO));
pInfo2.dwUserId = 2;
PSLIST_HEADER pListHead = __aligned_malloc(sizeof(pListHead));
InitializeSListHead(pListHead);
InterlockedPushEntrySList(pListHead, &(pInfo1->ItemEntry));
InterlockedPushEntrySList(pListHead, &(pInfo2->ItemEntry));
PINFO pInfoFirst = InterlockedPopEntrySList(pListHead); // gets pInfo2 into pInfoFirst, and removes it from list
DebugBreak();
ExitProcess(0);
}
The thing is, that i don't need to pop the item, of course i can just insert it back, but that's really no needed overhead. I tried to access it like that:
PINFO pInfoFirst = (PINFO)&pListHead->Next;
But i get weird stuff in pInfoFirst. How can i do it?

Binary Tree of Strings returning wrong order

I am fairly new to C and have been learning from K&R's book The C Programming Language.
After doing the exercises on Binary trees I wanted to make a header for binary trees for
char*, long and double.
There is a function in the following code that has been giving me grief - it should fill an array of character pointers with the values stored in the tree in lexicographical order however it has a bug somewhere. Here's the code for the String Tree Header btree.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************** TYPES **************/
typedef struct ctree
{
char *name;
ctree *left;
ctree *right;
};
/************** Globals **************/
static int c_inc = 0;
/************** Function Prototypes **************/
ctree *add_to_c_tree (ctree *cnode, char *name);
void print_c_tree (ctree *cnode);
ctree *c_tree_alloc (void);
void c_tree_free (ctree *cnode);
void return_c_tree (ctree *cnode, char **array);
/************** Function Definitions **************/
/* add_to_c_tree() : Adds a new node to a *character binary tree */
ctree *add_to_c_tree (ctree *cnode, char *name){
/* If the node is null, allocate memory for it,
* copy the name and set the internal nodes to null*/
if(cnode == NULL){
cnode = c_tree_alloc();
cnode->name = strdup(name);
cnode->left = cnode->right = NULL;
}
/* If initialised then add to the left node if it is lexographically
* less that the node above it else add it to the right node */
else{
if(strcmp(name, cnode->name) < 0)
cnode->left = add_to_c_tree(cnode->left,name);
else if(strcmp(name, cnode->name) > 0)
cnode->right = add_to_c_tree(cnode->right,name);
}
return cnode;
}
/* print_c_tree() : Print out binary tree */
void print_c_tree(ctree *cnode){
if (cnode != NULL) {
print_c_tree(cnode->left);
printf("%s\n",cnode->name);
print_c_tree(cnode->right);
}
}
/* return_c_tree() : return array of strings containing all values in binary tree */
void return_c_tree (ctree *cnode, char **array){
if (cnode != NULL) {
return_c_tree (cnode->left,array+c_inc);
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
// printf("arr+%d:%s\n", c_inc-1,*(array+(c_inc-1)));
return_c_tree (cnode->right,array+c_inc);
c_tree_free(cnode->right);
}
}
/* c_tree_alloc() : Allocates space for a tree node */
ctree *c_tree_alloc(void){
return (ctree *) malloc(sizeof(ctree));
}
/* c_tree_free() : Free's Memory */
void c_tree_free (ctree *cnode){
free(cnode);
}
Which I have been testing with bt.c:
#include "btree.h"
int main(void){
ctree *node = NULL; char *arr[100];
node = add_to_c_tree(node, "foo");
node = add_to_c_tree(node, "yoo");
node = add_to_c_tree(node, "doo");
node = add_to_c_tree(node, "woo");
node = add_to_c_tree(node, "aoo");
node = add_to_c_tree(node, "boo");
node = add_to_c_tree(node, "coo");
print_c_tree(node);
return_c_tree(node,arr);
for (int i = 0; i < 7; ++i)
{
printf("%d:%s ..\n",i, arr[i]);
}
return 0;
}
The reason for this question is that I have been having issues with the return_c_tree() function, which is meant to mimic the behaviour of K&R's print_c_tree() function except instead of recursively calling itself until a NULL ptr and printing out the name of the nodes in lexicographical order it is meant to add their names to an array of character ptrs and free the nodes memory.
However the output I get when run as above is:
aoo
boo
coo
doo
foo
woo
yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which shows that the print function works fine but the return function obviously isn't.
The confusing thing is that if the call to printf() in return_c_tree() is uncommented this is the result:
aoo
boo
coo
doo
foo
woo
yoo
arr+0:aoo
arr+1:boo
arr+2:coo
arr+3:doo
arr+4:foo
arr+5:woo
arr+6:yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which implies that it actually does add the strings in the right order.
Also I have tried it without the c_inc variable -> ie just incrementing array
before passing it to the right node which the produces the same results from the printf
in return_c_tree() but different from main:
arr+-1:aoo
arr+-1:boo
arr+-1:coo
arr+-1:doo
arr+-1:foo
arr+-1:woo
arr+-1:yoo
0:foo ..
1:yoo ..
2:coo ..
3:(null) ..
4:(null) ..
5:(null) ..
6:(null) ..
I'm rather confused, so If anyone can help I would appreciate it greatly. I'm sure I'm just incrementing it in the wrong place but I can't work out where.
I thought I had finally understood pointers but apparently not.
Best
P
Your problem is how you handle your pointer to array when you recursively call. This will fix your return_c_tree function:
void return_c_tree (ctree *cnode, char **array)
{
if (cnode != NULL) {
return_c_tree (cnode->left,array); // <--- CHANGED 2ND PARAM
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
return_c_tree (cnode->right,array); // <--- AGAIN, CHANGED 2ND PARAM
c_tree_free(cnode->right);
}
}
You're using a global variable c_inc to keep track of the current index into the array. However, when you recursively called return_c_tree, you passed in array+c_inc, but you did not offset c_inc to account for this. Basically, you double-counted c_inc each time.
While this solves your particular problem, there are some other problems with your code.
In general, using global variables is asking for trouble. There's no need to do it here. Pass c_inc as a parameter to return_c_tree.
Also, mixing global variables with recursion is especially prone to problems. You really want recursive routines to keep their state on the stack.
As a commenter pointed out, all of your code in btree.h should really be in btree.c. The point of header files is to define an interface, not for code.
(This is more stylistic) Your return_c_tree function is really two distinct functions: copy the elements of the tree (in order) into the array, and free the memory used by the tree. These two operations are conceptually distinct: there are times that you'll want to do one and not both. There can be compelling performance (or other) reasons to mix the two, but wait until you have some hard evidence.

Resources