I have the following code, when I add nodes why does it reset all nodes to the most recent nodes data? Assuming everything else in the codes works correctly, parsing etc. can anyone identify a problem with the list. See output at the bottom.
typedef char* string;
typedef struct linked_list listType;
typedef struct linked_list* linked_list;
typedef struct node NodeType;
typedef struct node* Node;
typedef enum boolean{
true = 1,
false = 0
}boolean;
struct node{
Node next;//next node in the list
string *transData;//listAdd--->string data[]
};
struct linked_list{
Node head;//first node in the list
int size;//size of list, number of nodes in list
};
boolean add(linked_list list, string *data)
{
boolean retval = false;//default retval is false
Node nod;//node to add
nod = (Node)malloc(sizeof(NodeType));
nod->transData = data;
nod->next = NULL;
//list size is 0
if(list->head == NULL)
{
list->head = nod;
printf("First Node added: '%s'\n", nod->transData[0]);fflush(stdout);
retval = true;
}
//nodes already in list
else
{
printf("List with nodes already\n");
fflush(stdout);
Node node = list->head;
//iterating through nodes
while(node->next != NULL)
{
node = node->next;
}//while
node->next = nod;
printf("Node added: '%s'\n", nod->transData[0]); fflush(stdout);
retval = true;
}
list->size+=1;
return retval;//success
}
/**
* Returns the size of the list.
*/
int listSize(linked_list list)
{
return list->size;
}
/**
*Can only print with 2 or more elements
*/
void printList(linked_list list)
{
int i=0;
Node nod = list->head;
int length = listSize(list);
printf("ListSize:%d\n",listSize(list));
fflush(stdout);
while(nod->next != NULL)
{
printf("Node %d's data: %s\n", i, nod->transData[0]);
fflush(stdout);
nod = nod->next;
i++;
}
}//printlist
Output:
trans 5 5
Argument 1: trans
Argument 2: 5
Argument 3: 5
Last spot(4) is: (null)
name of command: trans
ID 1
First Node added: 'trans'
ListSize:1
>>check 4
Argument 1: check
Argument 2: 4
Last spot(3) is: (null)
name of command: check
ID 2
List with nodes already
Node added: 'check'
ListSize:2
Node 0's data: check
>>trans 4 4
Argument 1: trans
Argument 2: 4
Argument 3: 4
Last spot(4) is: (null)
name of command: trans
ID 3
List with nodes already
Node added: 'trans'
ListSize:3
Node 0's data: trans
Node 1's data: trans
>>check 5
Argument 1: check
Argument 2: 5
Last spot(3) is: (null)
name of command: check
ID 4
List with nodes already
Node added: 'check'
ListSize:4
Node 0's data: check
Node 1's data: check
Node 2's data: check
(The OP tells me that the nodes need to have arrays of strings, so the pointer-to-a-pointer thing is actually correct).
Anyhow, it looks like your problem is that every node has a pointer to the same buffer. You just keep copying different strings into the same buffer, and then you assign the address of a pointer to that buffer to each new node.
First, I'd get rid of those typedefs. I don't know how much clarity they're really adding.
Next, you need to allocate new storage for each string. The standard library strdup() function is a handy way to do that:
// Turns out it's a fixed-size array, so we can blow off some memory
// management complexity.
#define CMDARRAYSIZE 21
struct node {
Node next;
char * transData[ CMDARRAYSIZE ];
};
// Node initialization:
int i = 0;
struct node * nod = (struct node *)malloc( sizeof( struct node ) );
// Initialize alloc'd memory to all zeroes. This sets the next pointer
// to NULL, and all the char *'s as well.
memset( nod, 0, sizeof( struct node ) );
for ( i = 0; i < CMDARRAYSIZE; ++i ) {
if ( NULL != data[ i ] ) {
nod->transData[ i ] = strdup( data[ i ] );
}
}
...but then be sure that when you free each node, you call free( nod->transData[n] ) for every non-NULL string pointer in nod->transData. C is not a labor-saving language.
Your issue is probably due to pointer copying. You are likely referencing the same buffer in all your nodes. Try to make a copy of your string data with strdup for example.
Not the main issue, but your printList won't print out the last element.
Instead of while(nod->next != NULL) use while(nod != NULL)
Related
I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!
How would you iterate this 2D linked list?
typedef struct _NODE
{
char *pszName;
unsigned long ulIntVal;
char *pszString;
struct _NODE *pNext;
struct _NODE *pDown;
} NODE;
I could do something like this..
NODE *pHEad;
while (pHead != NULL) {
printf("%s", pHead->pDown->pszName);
pHead = pHead->pNext;
}
.. but it would only give me the one node under every next node. What if it is another node under that one again? And under that one again? Or if there is a pNext attached to the pDown?
In the simplest case, you could use something like the following recursive function:
void processNode(NODE *current) {
if (current != NULL) {
printf("%s", current->pszName);
processNode(current->pNext);
processNode(current->pDown);
}
}
int main(void) {
NODE *pHead;
/* ... Do something to fill your list ... */
processNode(pHead);
/* ... */
}
Also be aware that this can cause a deep nesting of the function calls depending on your processed list. So if you are on an embedded system with limited stack size or if you are processing huge lists, you might run out of stack. In that case, you should find another approach for the processing.
Note that this will first process the pNext-list and then start with processing the first node of the pDown-list of the last node. So assuming the following structure (to the right is pNext and downwards is pDown):
pHead -> p1 -------> p2
|- p1_1 |- p2_1 -> p2_1_1
\- p1_2 |- p2_2
\- p2_3 -> p2_3_1
it should print the nodes in the following order:
pHead, p1, p2, p2_1, p2_1_1, p2_2, p2_3, p2_3_1, p1_1, p1_2
Look at this answer. Don't be overwhelmed by the amount of the code. I have added enough comments to help you proceed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node{
char data[100]; // Assume that this linked list will contain only 100 chars of data
struct Node* next;
} NODE;
// Global Variables are bad, but oh well.
NODE* head = NULL;
// Function to create a node
NODE* createNode(char* str)
{
// First allocate memory for struct
NODE* newNode = malloc(sizeof(NODE));
if(newNode == NULL)
{
printf("Unable to create a new node.");
}
else
{
// Use strcpy or strncpy or memcpy instead of doing something like newNode -> data = str, which changes the pointer, but doesn't copy the contents
// That is do not do newNode -> data = "hello" or something
strncpy(newNode -> data, str, strlen(str));
newNode -> next = NULL;
}
return newNode;
}
void addNode(char* str)
{
// Returns a node which contains str, but points to NULL
NODE* newNode = createNode(str);
// If the linked list is empty, then we make this node itself as the first node(or head)
if(head == NULL)
{
head = newNode;
}
// Else if the linked list is not empty, then we add this node at the start of the linked list
else
{
newNode -> next = head;
head = newNode;
}
}
int main()
{
// Example Linked List Generated(say you already have it in some form)
addNode("This");
addNode("Is");
addNode("Linked List");
// Now let's print the linked list
// Temporary NODE pointer ptr is used in order to not mess with the original NODE pointer head.
NODE* ptr = head;
// Traverse through the linked list starting from head and at the same time printing the corresponding data, until ptr is null
// This ptr != NULL check is exactly what you are looking for. This is your way of stopping the traversal of Linked List once you
// are at the end of it. You don't have to know the number of nodes to stop the traversal this way.
while(ptr != NULL)
{
printf("%s ", ptr -> data);
ptr = ptr -> next;
}
}
However note that the output will be printed in reverse order, since in this implementation of linked list we are adding things towards the back. Just try running the program and start reading the program starting from main function. I have made the code into separate functions to make it easier for you to understand. Just run the code first to get a grasp of what's happening.
You can use iteration instead of recursion by adding a queue, too, if you want to avoid the possibility of a stack overflow—though this will use slightly more heap memory, and there is still a risk that you can run out of heap memory if you have a large list or if you're running on a memory-constrained system. The important part is the print_list function at the end; the other stuff is just a (mostly) self-managing queue implementation I've provided:
typedef struct node_queue NodeQueue;
struct node_queue {
NODE *n;
NodeQueue *next;
};
/*
* Add an item to the end of the queue.
*
* If the item could not be added, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int enqueue(NodeQueue **headp, NodeQueue **endp, NODE *n)
{
NodeQueue *old_end = *endp;
NodeQueue *new_end;
new_end = malloc(sizeof *new_end);
if (new_end == NULL) {
return 0;
}
new_end->n = n;
new_end->next = NULL;
if (old_end != NULL) {
old_end->next = new_end;
}
if (*headp == NULL) {
*headp = new_end;
}
*endp = new_end;
return 1;
}
/*
* Remove an item from the head of the queue,
* storing it in the object that "nret" points to.
*
* If no item is in the queue, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int dequeue(NodeQueue **headp, NodeQueue **endp, NODE **nret)
{
NodeQueue *old_head = *headp;
NodeQueue *new_head;
if (old_head == NULL) {
return 0;
}
if (nret != NULL) {
*nret = old_head->n;
}
new_head = old_head->next;
free(old_head);
if (new_head == NULL) {
*endp = NULL;
}
*headp = new_head;
return 1;
}
void print_list(NODE *start)
{
NodeQueue *head = NULL;
NodeQueue *end = NULL;
NODE *current;
current = start;
/* Iterate all `pNext` nodes, then pop each `pDown` node and repeat. */
for (;;) {
/* Add the "down" node to the node queue. */
if (current->pDown != NULL) {
if (!enqueue(&head, &end, current->pDown)) {
perror("warning: could not add node to queue");
}
}
printf("%s", current->pszNode);
/*
* Move to the "next" node.
* If there is no next node, get the first "down" node from the queue.
* If there is no "down" node, break the loop to end processing.
*/
current = current->pNext;
if (current == NULL) {
if (!dequeue(&head, &end, ¤t)) {
break;
}
}
}
}
This will iterate through all pNext items before moving to a pDown item. The following 2-D list will be printed as A B C D E F G H I J K L M N O P Q:
A
|
B--C
|
D--E-----------F
| |
G-----H I-----J
| | | |
K--L M--N O P
|
Q
You can reverse the priority of pDown/pNext in the print_list function by swapping pNext and pDown inside it, so pNext items are added to the queue and pDown items are iterated until exhausted, which will change the order in which the items are printed to A B D C E G K F I O H M Q L J P N unless you change the structure of the list.
You can see an example using both the code above and the first sample 2-D linked list above at https://repl.it/NjyV/1, though I changed the definition of NODE to make the code using its fields a bit simpler.
While writing an adjacency list from scratch I'm facing some problem with addressing and allocating memory for an array of struct. (ignore directed/undirected list).After hours of debugging I've found the code is keeping (updates) only the last two inputs in the adjacency list. I want to know what and how actually I'm messing up the memory allocation and accessing it.
Don't forget to give me further study links on this topic/issue, please. Thank's in advance.
Here's my code-
/*a single node of an adjacency list*/
typedef struct adjList{
int dest;
struct adjList *next;
} adjList;
/*Image of a graph...*/
typedef struct Image{
int source;
adjList *head;
} Image;
void add_adj_edge(Image graph[], int source, int destiny);
int main() {
int vertices = 6;
Image graph[vertices];
//need not to mention detailed here
// initialize_graph(graph, vertices);
add_adj_edge(graph, 1, 2);
add_adj_edge(graph, 1, 4);
add_adj_edge(graph, 1, 5);
add_adj_edge(graph, 1, 6);
print_graph(graph, vertices);
printf("graph[1].head->dest: %d\n", graph[1].head->dest);
return 0;
}
void add_adj_edge(Image *graph, int src, int dest){
adjList *cache = malloc(sizeof(adjList));
/*create a single node*/
cache->dest = dest;
cache->next = NULL;
if(graph[src].head == NULL){
graph[src].head = cache;
}
else{
while( graph[src].head->next != NULL){
graph[src].head = graph[src].head->next;
}
graph[src].head->next = cache;
}
return;
}
The output
node: 1 5 6
node: 2
node: 3
node: 4
node: 5
node: 6
graph[1].head->dest: 5
Instead of
node: 1 2 4 5 6
node: 2
node: 3
node: 4
node: 5
node: 6
graph[1].head->dest: 2
As I mentioned as comment, your source code has some missing and also misunderstanding on how to update a linked-list.
First problem: (allocating Image graph[vertices]; in your main() doesn't initialize value).
It is necessary to set adjList *head; property to NULL to be sure
that if(graph[src].head == NULL) will be true at the first access.
int vertices = 6;
Image graph[vertices];
for(int i=0;i<vertices;i++) {
graph[i].head = NULL; // list is empty
graph[i].source = 0; // or what ever you want
}
Second problem: (when adding a new node at the end of a linked-list, it is necessary to use a temporary variable to explore previous node).
If you are using graph[src].head = graph[src].head->next; you will
overwrite all previous nodes by the last one.
Use the following method in add_adj_edge()to explore nodes:
adjList *pTmp;
// point to the first node
pTmp = graph[src].head;
// explore node until the last has no node
while( pTmp->next != NULL){
pTmp = pTmp->next;
}
// update the next node
pTmp->next = cache;
I have a struct called employee in my program with the following definition:
struct employee {
int id;
int age;
struct *employee next;
};
How would I take in input from the user, create a struct from their input, and create a singly linked list using pointers? I'm having a lot of issues figuring out how to do this dynamically. In Java, this is easily done through the constructor but how would you do this in C?
EDIT: Assuming the input is simply two ints (id and age).
This is how you create a new employee struct. You are dynamically allocating the memory using malloc function.
struct employee *new_employee = (struct employee*)malloc(sizeof(struct employee));
Now, we need to fill the data into this newly created employee field:
new_employee -> id = input_id;
new_employee -> age = input_age;
As for the next pointer, it is usually given NULL value. This is to prevent the next pointer from pointing to any arbitrary memory location.
new_employee -> next = NULL;
Finally, we have to link the list. To do that, you have to point the next pointer of the previous employee field to the current employee field (ex:as you mentioned in comment, first one (9,3) having a next pointer to the second one (3, 2))
Since it is a singly linked list, we cannot backtrack. So, there are two methods to access the previous field.
First is to maintain a pointer that points to the last field of the link list.
Second is to traverse the entire list till the end, and when you reach the last element, change its next pointer.
Implementation of the second method:
node *temp = *start;
if(temp!=NULL)
{
while(temp -> next)
temp = temp -> next;
temp -> next = new_employee;
}
Hope it helps!
Note : don't give me fish teach me how to fish
This is an example :
struct node {
int value;
struct *node next;
};
How to create new Node pointer dynamically ?
node* aux = (node*) malloc(sizeof(node));
How to get user input ( safely ) ?
char line[256];
int i;
if (fgets(line, sizeof(line), stdin)) {
if (1 == sscanf(line, "%d", &i)) {
/* i can be safely used */
}
}
How to create a linked list's head ?
/* This will be the unchanging first node */
struct node *root;
/* Now root points to a node struct */
root = (struct node *) malloc( sizeof(struct node) );
/* The node root points to has its next pointer equal to a null pointer
set */
root->next = 0;
/* By using the -> operator, you can modify what the node,
a pointer, (root in this case) points to. */
root->value = 5;
How to add new node to the linked list ?
/* This won't change, or we would lose the list in memory */
struct node *root;
/* This will point to each node as it traverses the list */
struct node *conductor;
root = malloc( sizeof(struct node) );
root->next = 0;
root->value = 12;
conductor = root;
if ( conductor != 0 ) {
while ( conductor->next != 0)
{
conductor = conductor->next;
}
}
/* Creates a node at the end of the list */
conductor->next = malloc( sizeof(struct node) );
conductor = conductor->next;
if ( conductor == 0 )
{
printf( "Out of memory" );
return 0;
}
/* initialize the new memory */
conductor->next = 0;
conductor->value = 42;
Now you must be able to solve the problem easily .
Happy Coding :D
I wanted to make a list using double pointer and using void as return.
#include<stdio.h>
#include<stdlib.h>
typedef struct list{
int value;
struct list *next;
}*list;
void addnode(struct list **List, int number) {
if(*List == NULL) {
*List = (struct list*)malloc(sizeof(struct list*));
(*List)->value = number;
(*List)->next = NULL;
} else {
while((*List)->next != NULL) {
(*List) = (*List)->next;
}
*List = (struct list*)malloc(sizeof(struct list*));
(*List)->value = number;
(*List)->next = NULL;
}
}
int main() {
list List1 = NULL;
addnode(&List1, 20);
printf("%d \n", List1->value);
addnode(&List1, 30);
printf("%d \n", List1->value);
printf("%d \n", List1->next->value);
return 0;
}
The first if in addnode is always executed but i want to append the list if its not empty but it seems like it never work. Ill also get segmenation fault because in the last printf it tries to take the next element in the list but its never initialized like i want.
If everthing worked as i wanted i should have printed out
printf("%d\n", List1->value)
20
printf("%d\n", List1->value)
20
printf("%d\n", List1->next->value)
30
The size you are passing to malloc is wrong.
You are allocating a struct list, not a struct list *.
If you are trying to append a new list item, remember (*List)->next will already be NULL on the second call. The malloc following that uses the pointer before the NULL list item (*List) when it should be assigned to the next list item, the one that is NULL, to make it non-NULL ((*List)->next=malloc(struct list);).
Also, your malloc should be using sizeof(struct list), without the *. If you add the *, you're allocating a struct list **. A rule you can use is use one * fewer than the destination type as the sizeof operand. Since your destination is *List, which is of type struct list *, use sizeof(struct list). Alternatively, because your destination is *List, use sizeof **List (use one more * than the destination variable has). This avoids you needing to know the type. It won't matter if List or *List is NULL because the sizeof operation is executed first; pointer dereferencing never occurs since sizeof works on the type of the variable.
Modify your program like this
int addNode(struct list **List, int number)
{
struct list *new, *tmp; // new = create new node, tmp = navigate to last
new = malloc(sizeof(struct list));
if(!new) { //always validate "malloc"
perror("malloc");
exit(1);
}
new -> value = value; // assigning values to new node
new -> next = NULL;
if(!(*list)) { //Check if list is empty or not, plz initialize *list#main() with NULL as like your program. or write seperate function to initialize
*list = new;
return 0; //no need write else condition, bcoz its the first node. and u can directly return
}
tmp = *list;
while(tmp -> next) // To navigate to last node
tmp = tmp -> next;
tmp -> next = new; //creating link to new node
return 0;
}
It's better to write print function seperatly.
int print(struct list **list)
{
struct *current; //current is your current node position
current = *list;
while(current) { //loop till current node addr == NULL
printf("%d\t", current -> value);
current = current -> next;
}
printf("\n");
return 0;
}