I am trying to write a c program that ask user some information about a brand and store it into linked list. But whenever user enters data it always overwrites the previous data, instead I wanted it to create new node and store it there. This is what I manage so far. How can I do it without using any temporary nodes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int count = 1;
struct modelNode{
char name[50];
int year;
int amount;
struct modelNode *next;
};
struct modelNode * addModel(struct modelNode *p);
void getBestModel(struct modelNode *p);
int main(){
int command;
struct modelNode * modelList = NULL;
do
{
printf("1. Add a model\n");
printf("2. Display the model with the highest selling amount\n");
printf("3. Exit\n");
printf("Enter command: ");
scanf("%d", &command);
switch(command)
{
case 1:
addModel(modelList);
printf("test %s\n", modelList->name);
//printf("test %s\n", modelList->next->name);
break;
case 2:
printf("45\n");
break;
case 3:
puts("Bye");
break;
default:
printf("default\n");
}
}while(command != 3);
return 0;
}
struct modelNode * addModel(struct modelNode *p){
int iter = 0;
while(iter<count)
{
p = (struct modelNode*)malloc(sizeof(struct modelNode));
p->next=NULL;
iter++;
}
printf("test %s\n", p->name);
printf("Enter the name: ");
scanf("%s", &p->name);
printf("Enter the release year: ");
scanf("%d", &p->year);
printf("Enter the selling amount: ");
scanf("%d", &p->amount);
p->next=NULL;
printf("test %s\n", p->name);
count++;
}
}
This looks like a school exercise, so i doubt anyone here will solve it for you.
But you should try to insert "at the head" , you don't need temp nodes.
Pass the [head] as a param of function addNodes:
Inside addNodes:
Create [new-node]
Set the "next" pointer from [new-node] to the [head]:
[new-node]->next = [head]
Return [new-node]
Resulting linked list (head is the old-head) :
[new-node] ----> [head]
If you do this twice you'll get this:
[newer-node] -----> [new-node] ----> [head]
And so on....
If you want to insert as "tail" , you just need to traverse the linked list recursively, this way you don't use temp nodes.
If i missed the point, please leave a comment explaining further.
The generic functions for adding a node to a linked list would be
typedef struct node_t {
struct node_t* next;
} node_t;
node_t* add(node_t* list, node_t* new_node) {
if (list == NULL) {
return new_node;
} else {
node_t* tmp = list;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = new_node;
return list;
}
}
and you could use it like
node_t* list = NULL;
list = add(list, malloc(sizeof(node_t)));
list = add(list, malloc(sizeof(node_t)));
list = add(list, malloc(sizeof(node_t)));
list = add(list, malloc(sizeof(node_t)));
// list would now be a list of 4 nodes
and if you really don't want to use a tmp variable to walk the list, you can do it like this
void add_without_tmp(node_t* list, node_t* new_node) {
if (list == NULL) {
// some error handling
} else {
while(list->next != NULL) {
list = list->next;
}
list->next = new_node;
}
}
node_t* list = malloc(sizeof(node_t));
add_without_tmp(list, malloc(sizeof(node_t)));
add_without_tmp(list, malloc(sizeof(node_t)));
add_without_tmp(list, malloc(sizeof(node_t)));
// list would now be a list of 4 nodes
Edit: fixed the error with the declaration of node_t and added the missing * to the statement node_t* tmp = list;.
Related
I am working in C. Here, I have a structure Node with data members passengers and station. I have a function which inputs the passenger number and stop Name from the user.
struct Node
{
int stopNo;
int passenger;
char station[50];
struct node* next;
};
I have a function which takes the input as the name of station and passengers no and automatically increase the stopNo by 1.
I am trying to Use a linked list to store the stations.
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int stopNo;
int passenger;
char station[50];
struct node* next;
};
void takeInput(struct Node* head)
{
head->stopNo = head->stopNo +1;
printf("Station Name");
scanf(" %[^\n]s",head->station);
printf("New Passengers ");
scanf("%d",&head->passenger);
}
void printStops(struct Node* head)
{
for(int i=0;i<=head->stopNo;i++)
{
printf("Stop %d. %s with %d passenger",head->stopNo,head->station,head->passenger);
}
}
int main()
{ int n;
struct Node* head = NULL;
struct Node* second = NULL;
//Memory Allocation into heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
while(1){
//Menu
printf("1.Log Stops\n");
printf("2.Print Stop");
printf("3.Exit");
scanf("%d",&n);
switch(n){
case 1:
takeInput(struct Node*);
break;
case 2:
printStops(struct Node*);
break;
case 3:
exit(0);
default:
printf("Enter the numbers from 1 to 2");
}
}
}
I am confused what to pass as an argument through the function.
You are mis-using the linked list concept.
The principle is to dynamically add new nodes at the beginning (simpler) or at the end (slightly more complex). Here, as you already have a function dedicated to feeding the list, you could just allocate the nodes there. A possible way is to pass the address of the current head, and let the function change it. But you have to define a sentinel value to tell the function that you do not want to input more nodes.
In the following code "STOP" is that sentinel:
void takeInput(struct Node **head)
{
int stopNo = 0;
for (;;) {
struct Node *node = malloc(sizeof (*node));
node->stopNo = stopNo++;
node->next = *head;
printf("Station Name");
scanf(" %[^\n]",node->station);
if (strcmp(node->station, "STOP") == 0) { // no more station
free(node);
break;
}
printf("New Passengers ");
scanf("%d",&node->passenger);
*head = node;
}
}
That way, you can iterate the list to print its content:
void printStops(struct Node* head)
{
while (head != NULL)
{
printf("Stop %d. %s with %d passenger\n",head->stopNo,head->station,head->passenger);
head = head->next;
}
}
Finally, you main would become:
int main()
{ int n;
struct Node* head = NULL;
while(1){
//Menu
printf("1.Log Stops\n");
printf("2.Print Stop\n");
printf("3.Exit\n");
scanf("%d",&n);
switch(n){
case 1:
takeInput(&head);
break;
...
struct node
{
int info;
struct node *next;
};
typedef struct node node;
void *printRev(node *head){
int count=0;
int i;
node *beforeFin;
node *tempHead;
tempHead = head;
while(tempHead->next != NULL){
count++;
tempHead->next = tempHead->next->next; //LAST ITERATION SHOULD BE AT THE END OF LIST
}
printf("COUNT IS: %d\n", count);
for(i = 0; i <= count; i++){
beforeFin = Prev(head, tempHead->next);
printf("%d", beforeFin->info);
}
printf("\n");
}
As of now this prints out:
COUNT IS: 3
Segmentation fault (core dumped)
Prev returns a pointer to the node before the given pointer (tempHead->next) my intention was for this to print out the singly linked list in reverse order using the for loop above. So the ->info of the given node should return 5 in the example below (after the first iteration).
Before the printf that prints the count, tempHead->next should point to the final node.
Right now I am passing in 2 3 5 4 and this is giving me the count before the 4. Id like for this to print out 4 5 3 2
I would appreciate any help given, I am a beginner as you might be able to tell. Thank you all in advance!
I could do this using recursion but I'd like to learn figure out this method.
To print a single linked list in reverse order you can use a recursive function. You have to step into the recursion to the end and print the elements of the list right before you leave the recursion function:
void printReverse(node *act)
{
if ( act == NULL ) // terminate if end of list is reached
return;
printRev( act->next ); // print next node
printf( "%d ", act->info ); // print this node
}
If you do not want to use recursion, you can of course reverse the list, then print the list and finally reverse it again.
Reversing a list is not difficult. Traverse through the list, take each element and reorder it in front of the head of the list.
node * reverse(node *head)
{
node *act, *prev;
if ( head == NULL )
return;
prev = head;
act = head->next;
while ( act != NULL )
{
prev->next = act->next;
act->next = head;
head = act;
act = prev->next;
}
return head;
}
void printReverse(node *head)
{
node *act;
act = reverse(head);
while ( act != NULL )
{
printf( "%d ", act->info ); // print this node
act = act->next;
}
reverse(head);
}
As you want to avoid recursion, you need to reverse the list first. I see some attempt in the original code but it doesn't look correct. Try the following:
node *current = head;
if (current != NULL) {
node *prev = NULL;
for (node *next = current->next; ; next = (current = next)->next) {
current->next = prev;
prev = current;
if (next == NULL)
break;
}
}
Then current will point to the head of the list and you can traverse using the next link over the list. Note that it will modify your original list but this is expected as I understood the original requirement.
The issue with the recursive algorithm is that, if you're a bit paranoid like me, the list could be large enough to cause the recursive calls to sum up and overflow the stack. If the list is from some user input then this could be used for a denial of service attack. Thus I see two reasonable choices:
Create a reversed copy of the list and print that.
Reverse the list in place, print it, possibly reverse it back.
The later is interesting if you're working in a memory constrained setting or with large lists.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
struct node {
int value;
struct node * next;
};
void reverse_inplace (struct node ** list) {
assert(list != NULL);
struct node * follow = NULL, * lead = *list;
while (lead != NULL) {
struct node * next = lead->next;
lead->next = follow;
follow = lead;
lead = next;
}
*list = follow;
}
void print (struct node const * head) {
printf("( ");
while (head) {
printf("%d ", head->value);
head = head->next;
}
printf(")");
}
void link (struct node * array, size_t count) {
struct node * follow = NULL;
while (count-->0) {
array[count].next = follow;
follow = &(array[count]);
}
}
void fill (struct node * list, int value, int const step) {
while (list != NULL) {
list->value = value;
value += step;
list = list->next;
}
}
int main () {
size_t const sizes[] = {1, 2, 6};
size_t const num =
sizeof(sizes) / sizeof(sizes[0]);
size_t caseId = 0;
for (; caseId < num; ++caseId) {
struct node * head =
malloc(sizeof(*head) * sizes[caseId]);
printf("Case %zu: List of size %zu\n",
caseId, sizes[caseId]);
link(head, sizes[caseId]);
fill(head, caseId, caseId);
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print (head);
printf(" \n");
reverse_inplace(& head);
free(head);
}
printf("Case %zu: empty list \n", caseId);
struct node * head = NULL;
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print(head);
printf(" \n");
return 0;
}
(Live on ideone)
I am trying to create an (ordered) linked list of (ordered) linked lists. The list-of-list links are carried by the first nodes of its member lists. I am trying to achieve this via the following code, but my program crashes when I try displaying the second list. First list displays perfectly.
Here's a schematic of the data structure I am trying to construct:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node{
int number;
struct node*next;
struct node*lsnext;
};
typedef struct node Node;
Node* insertValue(Node * list, int value);
void display(Node*);
Node* insertArr(Node * list, int value);
Node* addNodeBottom(int val, Node *start);
int main()
{
Node *globalList = NULL, *lists,*start,*save;
int nbrOfLists, listNo, nbrOfVal, valNo, val;
start=NULL;
printf("\n Enter the number of lists:");
scanf("%d", &nbrOfLists);
if(nbrOfLists < 0)
return -1;
for(listNo = 0; listNo < nbrOfLists; listNo++)
{
printf("\n\n Enter the number of inputs to the list %d: \n ",listNo+1);
scanf("%d", &nbrOfVal);
lists = NULL;
for(valNo = 0; valNo < nbrOfVal; valNo++)
{
printf("Enter node value %d:", valNo+1);
scanf("%d", &val);
// Here we insert the value in both lists
lists= insertValue(lists, val);
globalList = insertValue(globalList, val);
}
start=addNodeBottom(val,lists);
if(listNo==0){
save=start;
}
printf("\n The list %d is: ",listNo+1);
display(lists);
}
printf("\n\n The final list is: ");
display(globalList);
printf("The first list is");
display(save);
printf("The second list is");
display(save->lsnext); //crashes here
return 0;
}
Node* insertValue(Node * list, int value) //to insert node at the end
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number=value;
if(list == NULL)
{
newNode->next=NULL;
return newNode;
}
if(value < list->number)
{
newNode->next = list;
return newNode;
}
m = list;
while(m->next)
{
if(value < m->next->number)
break;
m = m->next;
}
newNode->next = m->next;
m->next = newNode;
return list;
}
Node* addNodeBottom(int val, Node *start)
{
Node*rear;
Node* node1=(Node*) malloc(sizeof(Node));
node1->number=val;
node1->lsnext=NULL;
if(start==NULL){
start=rear=node1;
}
else{
rear->lsnext=node1;
rear=node1;
}
return start;
}
void display(Node*nodex){
while(nodex)
{
printf("%d ->",nodex->number);
nodex=nodex->next;
}
}
This code invokes undefined behaviour. In particular, your function addNodeBottom is buggy: If invoked with start not NULL, it modifies the member rear->lsnext, but rear is uninitialised at that point. I assume, you intended to modify start instead. Here, you return start unmodified, so it's member lsnext is not set to anything useful, which probably eventually leads to a segmentation fault. However, in principle already the offending function call to addNodeBottom could lead to unexpected program termination.
I am trying to make a program that initialize a singular linked list and then ask user for more data and add them at the end of current linked list. However, my programming is trapped in infinite loop.
#include <stdio.h>
#include <stdlib.h>
typedef struct linked_list
{
int data;
struct linked_list *next;
}element;
typedef element *elementptr;
void addend(elementptr *,int);
void traverse(elementptr);
int main()
{
// create a linked list
elementptr first = NULL,
last = NULL;
int input,num;
printf("Please enter first integer data: \n");
scanf("%d",&input);
//Create a linked list with user initialized data
first = (elementptr)malloc(sizeof(element));
last = first;
last -> data = input;
last -> next = NULL;
printf("Please enter number of data you want to add in the end of linked list\n");
scanf("%d",&num);
addend(&last,num);
traverse(first);
return 0;
}
void addend(elementptr *l, int num)
{
int i = 0,extradata;
while(i<num)
{
i++;
printf("Please enter a data: \n");
scanf("%d",&extradata);
(*l) -> next = (elementptr)malloc(sizeof(element));
*l = (*l) ->next;
(*l) -> data = extradata;
(*l) -> next = NULL;
}
printf("The data sets are added\n");
}
void traverse(elementptr f)
{
elementptr current;
int count = 0;
current = f;
while (current != NULL)
{
count++;
printf("The data is %d \n", current->data);
}
printf("The linked list has %d elements \n",count);
}
In your code
while (current != NULL)
{
count++;
printf("The data is %d \n", current->data);
}
you never change the value of current. Either it starts as NULL and the loop never executes, or it starts non-NULL and the loop runs forever.
You should add
current = current->next
after your printf to advance to the next element in the linked list.
current = current -> next; you are missing this statement in the while loop. Although I would suggest :
#include<stdio.h>
#include<stdlib.h>
struct linked_list
{
int number;
struct linked_list *next;
struct linked_list *prev;
};
typedef struct linked_list node;
void create(node *p);
void print(node *p);
int main()
{
node *head;
printf("---Start of the list ---\n");
printf("enter -1 to exit\n");
head = (node*)malloc(sizeof(node));
create(head);
print(head);
}
void create(node *list)
{
printf("enter the data");
scanf(" %d",&list->number);
if(list->number == -1)//Enter -1 to exit untill then keep on taking values
{
list->next=NULL;
}
else
{
list->next = (node*)malloc(sizeof(node));
create(list->next);
}
}
void print(node *list)
{
if(list->next != NULL)
{
printf("%d-->",list->number);
if((list->next->next == NULL) && (list->next->number!=-1))
printf("%d -->End of the List",list->next->number);
print(list->next);
}
}
In your traverse function, the current node is not pointing to next node. So the while condition while (current != NULL) will not be true and hence the while loop is running infinitely.
To fix it, current node should point to the next node (current = current->next) in the list after printing the data.
For example:
void traverse(elementptr f)
{
elementptr current;
int count = 0;
current = f;
while (current != NULL)
{
count++;
printf("The data is %d \n", current->data);
// Fix
current = current->next; // Point to next node in link list
}
}
I'm trying to create a program which creates and display linked list.
Now i'm having trouble with my create_list() function, it doesn't create any list.
What i'm doing wrong ?
Sorry for bad english :/
CODE :
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int main(){
node *start;
start = NULL;
int a,n,on = 1;
while(on == 1){
printf(" \n choose: \n 1 --- create list \n 2 --- display list \n");
scanf("%d",&n);
switch(n){
case 1:
printf("-------------------------------------------- \n");
printf(" Enter the elements. The last element is 0 \n");
printf("-------------------------------------------- \n");
Create_list();
Display_list(start);
break;
case 2:
Display_list(start);
break;
}
}
system("pause");
return 0;
}
void Display_list(node *curr){
if(curr){
while (curr->next != NULL){
printf("%d \n",curr->data);
curr=curr->next;
}
} else {
printf(" \n The list is not created ! \n");
}
}
void Create_list(node *curr){
int i;
node *start = NULL;
if (start == NULL){
curr = (node *)malloc(sizeof(node));
start=curr;
while ( i != 0){
scanf("%d",&i);
if(i == 0){
curr->next=NULL;
curr=start;
} else {
curr->data=i;
curr->next=(node *)malloc(sizeof(node));
curr=curr->next;
}
}
} else {
printf(" \n list already exists ! \n");
}
}
The function Create_List(node *curr) needs some arguments. You are not passing any arguments from main(). Did your code compile?
The function Create_List(node *curr) needs some arguments. You are not passing any arguments from main(). Did your code compile?
What you should do is take a node in main which will store location of first node of the linked list.
void Insert(struct node **q, int num) //Num is the data to be added and **q is the pointer to the first node of the list.
{
struct node *temp, *r;
temp = *q;
if (*q == NULL) {
temp = ((struct node *)malloc(sizeof(struct node)));
temp->data = num;
temp->link = NULL;
*q = temp;
}
else {
while (temp->link != NULL)
temp = temp->link;
r = ((struct node *)malloc(sizeof(struct node)));
r->data = num;
r->link = NULL;
temp->link = r;
}
}
The start in Create_list is not related to the start in main. Since both are local to their respective functions, one can't even see the other. So setting start doesn't actually set start, if you will. :P
You'll need to either bring start outside of the functions and make it global, or pass &start (as a node**) from main into Create_list and modify *start to set the list head. (The latter is generally preferable, as globals are often trouble waiting to happen.)