I want to perform a binary operation between two nodes, store the result in one node and eliminate the other. This is what I've written:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
struct n{
double value;
char op;
struct n *next;
};
void delete(struct n *head);
void add_item(struct n **ptr, double *data);
int main(){
struct n *head = NULL;
double result;
add_item(&head, 5);
add_item(&head, 3);
head->op = '*';
result = (head->next)->value * head->value;
(head->next)->value = result;
delete(head);
printf("%lf\n",head->value);
free(head);
return 0;
}
void add_item(struct n **ptr, double *data)
{
struct n *item = malloc(sizeof *item);
item->value = *data;
item->next = *ptr;
item->op = '?';
*ptr = item;
}
void delete(struct n *head)
{
struct n *temp;
temp = head->next;
head->next = temp->next;
free(temp);
}
In this example I have a list like this 3 -> 5 -> NUll. I'd like to get this 15 -> NUll.
When I try to print the value of the node remaining I get 3 instead of 15
The both functions are invalid.
To the function add_item you do not pass data by reference (and it does not make sense to pass data by reference).
add_item(&head, 5);
add_item(&head, 3);
So the function should be declared and defined like
void add_item(struct n **ptr, double data)
{
struct n *item = malloc(sizeof *item);
item->value = data;
item->next = *ptr;
item->op = '?';
*ptr = item;
}
You have to pass the head node to the function delete also by reference.
void delete(struct n **head)
{
if ( *head )
{
struct n *temp = *head;
*head = ( *head )->next;
free( temp );
}
}
and call it like
delete( &head );
When I try to print the value of the node remaining I get 3 instead of
15
It is because you deleted the node after the head instead of deleting the head node though the result of the operation you wrote in the node after the head.
(head->next)->value = result;
Here is your updated program
#include <stdio.h>
#include <stdlib.h>
struct n{
double value;
char op;
struct n *next;
};
void delete(struct n **head);
void add_item(struct n **ptr, double data);
int main(){
struct n *head = NULL;
double result;
add_item(&head, 5);
add_item(&head, 3);
head->op = '*';
result = (head->next)->value * head->value;
(head->next)->value = result;
delete(&head);
printf("%lf\n",head->value);
free(head);
return 0;
}
void add_item(struct n **ptr, double data)
{
struct n *item = malloc(sizeof *item);
item->value = data;
item->next = *ptr;
item->op = '?';
*ptr = item;
}
void delete(struct n **head)
{
if ( *head )
{
struct n *temp = *head;
*head = ( *head )->next;
free( temp );
}
}
Its output is
15.000000
As is in general with C, for a function to have the power to change an object passed to it via the argument list, the address of the object must be passed, not the object itself. ( read more on this here )
In this example, the object, head, if it is to be changed in any way, requires that its address ( &head ) be passed to the function, not the object itself.
So the statement:
delete(head); //passing the object will not allow it to be changed
Should be changed to
delete(&head); //The object's address is passed, allowing the object to be changed
And because the object being passed was created as a pointer: struct n *head = NULL;, the prototype for the delete function needs to accommodate the address of a pointer in its argument. This is done with a pointer to a pointer:
void delete(struct n **head);//accommodates the address of a pointer object
Then, inside the delete function, work on the object itself, (which is now *head) to make the changes.
void delete(struct n **head)
{
if (*head == NULL) return;
struct n *temp = *head;
*head = temp->next;//point head to next node
free(temp);//free old head
}
Conversely, in your void add_item(struct n **ptr, double *data); function, data does not need to be changed, only used within the body. Indeed the way it has been called in your code is the correct way to send the data:
add_item(&head, 5); // 2nd argument passes object directly, i.e. not an address
Therefore, because the function needs the data itself, and not a pointer to the data, change the prototype to accommodate:
void add_item(struct n **ptr, double data);
Change the code in the body of the code accordingly.
Related
This question already has answers here:
initial value of int array in C
(10 answers)
Closed 2 years ago.
Having this linked list:
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
typedef struct node node_t;
void printlist(const node_t*);
node_t *create_node(int);
int main(void){
int values[3] = {1,2,3};
node_t *nodes[3];
for(int i =0; i<3 ; i++)
{
nodes[i] = create_node(values[i]);
if(i!=2)
nodes[i]->next = nodes[i+1]; //HERE, can I assign next (un)initialized node?
}
node_t *header = nodes[0];
printlist(header);
}
void printlist(const node_t* header){
for(const node_t *i = header; i; i=i->next)
printf("value is %i\n",i->value);
}
node_t *create_node(int value){
node_t *new = malloc(sizeof(node_t));
new->value=value;
new->next = 0;
return new;
}
Which gives:
value is 1
value is 29590344
Command terminated
As I can see from output, the first node (header), does not have assign next struct member, which should happened from the loop. But I am assigning the next (pointer to new node) to an (un)initialized member from array (of pointer to nodes). I expect a initilization of array should also initilize a memory, when it has size. But does it? If so, then I do not understand why the assignment does not work, otherwise I understand and have to implement other loop. Thanks for answers.
Your code does not create the dynamic list as you have an array of 3 nodes. next is not needed.
You probably want something like this.
/* you need to check if memory allocation was successful */
#include <stdlib.h>
#include <stdio.h>
typedef struct node {
int value;
struct node *next;
} node_t;
void printlist(const node_t*);
node_t *append_node(node_t *, int);
int main()
{
node_t *head = NULL, *parent = head;
for(int x = 0; x < 10; x++)
if(!head)
{
head = append_node(NULL, x);
parent = head;
}
else
{
parent = append_node(parent, x);
}
printlist(head);
}
void printlist(const node_t* head){
while(head)
{
printf("value is %i\n",head->value);
head = head -> next;
}
}
node_t *append_node(node_t *parent, int value){
node_t *new = malloc(sizeof(*new));
new->value=value;
new->next = NULL;
if(parent) parent -> next = new;
return new;
}
This program should delete the N-node in a singly linked list. If i put N = 1 or N = 2 it's ok, the program works. But with N = 0 the output prints infinite nodes with random values (after deleting the node 0). I think the program can't see the new head. Thx for the help!
#include <stdio.h>
#include <stdlib.h>
#define N 0
struct node {
int data;
struct node *next;
};
void printlist(struct node *head){
struct node *current=head;
int i=0;
while (current!=NULL){
printf("node number %d \t : %d\n", i, current->data);
current=current->next;
i++;
}
}
int deletenode(struct node *head,int n){
struct node *current=head;
struct node *previous=head;
int i=0;
while(current!= NULL){
if (n==i && i!=0){
previous->next=current->next;
free(current);
return 1;
}
else if (n==i && i==0){
head=head->next;
free(current);
return 1;
}
i++;
previous=current;
current=current->next;
return 0;
}
printf("error\n");
exit(EXIT_FAILURE);
}
void main(){
struct node *n1=malloc(sizeof(struct node));
struct node *n2=malloc(sizeof(struct node));
struct node *n3=malloc(sizeof(struct node));
struct node *head=n1;
n1->data=5;
n1->next=n2;
n2->data=10;
n2->next=n3;
n3->data=15;
n3->next=NULL;
printf("\n\nbefore\n");
printlist(head);
deletenode(head,N);
printf("\n\nafter\n");
printlist(head);
}
I'm using currentas a temp pointer , because after the head shift on the second node i need a pointer to the old head and use free.
C always passes by value, so changing a parameter has no effect on the caller.
void foo(int i) {
i = 1234; // No effect on caller.
}
void foo(int *p) {
p = NULL; // No effect on caller.
}
If you want to modify a variable (such as the caller's head), you need to pass a pointer to it. (You can still change that to which a pointer references.)
int deletenode(struct node **head, int n) {
...
}
deletenode(&head, N);
Now, you could simply replace every instance of head in your code with (*head) to account for the new calling convention, but that would waste an opportunity for simplification. By having a pointer to a struct node *, we don't need to handle head (a struct node *) and prev_node->next (a struct node *) differently.
int delete_node_n(struct node **ptr, unsigned n) {
// Make `ptr` point to the pointer we want to modify.
// This will either be the `head` variable
// or the `next` field of some node.
while (1) {
if (!*ptr)
return 0;
if (!n)
break;
ptr = &( (*ptr)->next );
--n;
}
struct node *to_free = *ptr;
*ptr = (*ptr)->next;
free(to_free);
return 1;
}
I am practicing creating a link list, but encountered a problem when trying to insert an item to the front of the list. The code in my insert function works properly if I put it within main, but not when run separately as a function.
I am using a pointer as a argument in the function so I don't understand why the value in my print statement isn't changing to 100 which should be at the front of the linked list using the insert function (When I run the function 61 is printed, I am aiming for 100 to be printed).
Thanks for the help!
#include <stdio.h>
#include <stdlib.h>
typedef struct node *nodePtr;
typedef struct node node;
struct node {
int value;
nodePtr next;
};
node insert(node *first, int value)
{
nodePtr temp;
temp = malloc(sizeof(node));
temp->value = value;
temp->next = first;
first = temp;
}
int main()
{
nodePtr first;
first = malloc(sizeof(node));
first->value = 61;
first->next = NULL;
insert(first, 100);
printf("%d", first->value);
}
your passing a pointer to the node as a argument to the function and changing the value of formal parameter does not change the value of the actual parameter do this it should work.
enter code here
#include <stdio.h>
#include <stdlib.h>
typedef struct node *nodePtr;
typedef struct node node;
struct node {
int value;
nodePtr next;
};
void insert(node **first, int value)
{
nodePtr temp;
temp = malloc(sizeof(node));
temp->value = value;
temp->next = *first;
*first = temp;
}
int main()
{
nodePtr first;
first = malloc(sizeof(node));
first->value = 61;
first->next = NULL;
insert(&first, 100);
printf("%d",first->value);
}
You have passed a pointer to function insert() and stored it in a variable first whose scope is local to function insert(). Now you have
updated pointer first in function insert().
When you will return to main() function updated value of pointer next is lost that is why you are getting unexpected result while printing value in main().
To summarise:
first = malloc(sizeof(node)); // let's say first is p1
...
insert(first, 100); // first is P1
....
node insert(node *first, int value) // first is p1
....
tmp = malloc(sizeof(node)); // let's say tmp is p2
first = temp; // Now first has become p2 but its scope is local to insert()
....
printf("%d", first->value); // first is still p1 here
Solution
node* insert(node *first, int value)
{
nodePtr temp;
temp = malloc(sizeof(node));
temp->value = value;
temp->next = first;
first = temp;
return first;
}
int main()
{
nodePtr first;
first = malloc(sizeof(node));
first->value = 61;
first->next = NULL;
first = insert(first, 100);
printf("%d", first->value);
return 0;
}
This simple code (adding element to linked list and printing it) works fine
#include <stdio.h>
struct node{
int item;
struct node* next;
};
void print_node (struct node* n){
while (n!= NULL){
printf("%d ", (*n).item);
n = n->next;
}
printf("\n");
}
void append_node(struct node *list, struct node *n){
while(list->next != NULL)
list = list->next;
list->next = n;
}
int main(){
struct node n1, n2;
n1.item = 1;
n1.next = NULL;
n2.item = 2;
n2.next = NULL;
print_node(&n1);
print_node(&n2);
append_node(&n1,&n2);
print_node(&n1);
printf("done\n");
return 0;
}
If instead I define the append_node as following
void append_node(struct node *list, struct node n){
while(list->next != NULL)
list = list->next;
list->next = &n;
}
and call it accordingly in the main (i.e., append_node(&n1, n2) ) I get a segmentation fault when running the program. And I don't understand why :)
When you call append_node(struct node *list, struct node n), the argument n is copied on the function context.
When the function is leave, the context is freed, and the copy n of your data is lost.
You could use your function append_node(struct node *list, struct node n) if you make a copy of n (using malloc) before putting it in linked list.
EDIT
This may help you: What's the difference between passing by reference vs. passing by value?
I am having trouble with inserting items in linked list. All the elements end up having the same *data content that is inserted in the last. The program compiles successfully. I use gcc and gdb.
I am new to coding so please mention troubles if any that you see in my programming style.
typedef struct Node{
void* data;
struct Node* next;
} *node;
node allocate(){
node current = malloc(sizeof(struct Node));
current->data = NULL;
current->next = NULL;
return current;
}
void insert(node *head, void *data){
// if head has no data then set the data on head and return
if(((*head)->data == NULL)&&((*head)->next == NULL)){
(*head)->data = data;
return;
}
node newHead = allocate();
newHead->data = data;
newHead->next = *head;
*head = newHead;
//printf("Node Data : %d\tNext Node Data : %d",
//*(int *)((*head)->data), *(int *)((*head)->data));
}
int main(int argc, char *argv[]){
node head = allocate();
int count = inputSequence(&head);
int *aod = calloc((size_t) count, sizeof(int));
generateAOD(head, aod);
if(checkJolly(aod, count) == TRUE)
printf("Jolly\n");
else
printf("Not Jolly\n");
return 0;
}
int inputSequence(node *input){
int *num = malloc(sizeof(int));
int count = 0;
while((scanf("%d", num) != EOF)){
insert(input, (void *)num);
count++;
}
traverse(*input, fn);
return count;
}
Your insert logic is non-existant. And you're literally making your life harder by attempting to manage a linked list in the fashion you're using.
The head pointer itself should indicate whether the list is empty. If it is NULL, its empty. If it isn't, there's data. Code the insertion logic accordingly.
And your inputSequence is utterly broken. It only allocates ONE data point, then uses the same data allocation for every insertion. You need one for each insertion.
First, change allocate() to accept the data being inserted. It will make the remaining code less cluttered:
node allocate(void *data)
{
node current = malloc(sizeof(*current));
current->data = data;
current->next = NULL;
return current;
}
Second, insert by allocating a new node as needed.
void insert(node *head, void *data)
{
node p = allocate(data);
p->next = *head;
*head = p;
}
Next, fix inputSequence() to properly allocate memory for each entry:
int inputSequence(node *input)
{
int count = 0;
int num = 0;
// note: check for number of params *successfully* parsed.
// if it isn't 1, its time to leave the loop.
while(scanf("%d", &num) == 1)
{
int *data = malloc(sizeof(num));
*data = num;
insert(input, data);
++count;
}
return count;
}
And lastly, make sure your head pointer is initially NULL in main().
int main(int argc, char *argv[])
{
node head = NULL;
// load linked list
inputSequence(&head);
// ... the rest of your code....;
return 0;
}
With the above, the logical answer of "Is my list empty" is simply if (!head) Further, this makes things like traversal trivial.
void traverse(node ptr, void (*pfn)(void *))
{
while (ptr)
{
pfn(ptr->data);
ptr = ptr->next;
}
}
Freeing the list is equally trivial:
void destroy(node *head)
{
while (*head)
{
node p = *head;
*head = p->next;
free(p->data);
free(p);
}
}
typedef struct Node{
void* data; // Make it as int or any other data type
struct Node* next;
} *node;
In function inputSequence() you are allocating memory for num at the very beginning and making node->data point to this memory each time you are adding a node. Hence data pointer of each node of your linked list points to the same memory location and hence contains the same value.
If you still want to continue with data as a void pointer, allocate num for each iteration of the while loop and pass this to insert function.
while((scanf("%d", num) != EOF)){
num = malloc(sizeof(int);
insert(input, (void *)num);
count++;
}