I'm trying to do a program that inserts and deletes students from a linked list and when I try to insert a student at the end of the list but it doesn't work. I'm pretty sur that I the function algorithm is right, but still. Anyways, here's the code:
void InsetEnd(){
stud *temp, *newnode;
char n[15];
int a;
printf("Student: \n");
printf("Name: ");
scanf("%s", n);
printf("Age: ");
scanf("%d", &a);
strcpy(newnode->name, n);
newnode->age=a;
temp=head;
while(temp!=NULL){
temp=temp->next;
}
temp = (stud *) malloc (sizeof(stud));
newnode->next = NULL;
temp->next = newnode; }
For starters the pointer newnode has indeterminate value. Thus these statements
strcpy(newnode->name, n);
newnode->age=a;
result in undefined behavior.
This loop
while(temp!=NULL){
temp=temp->next;
}
does not make sense because it is evident that after the loop the pointer temp will be equal to NULL.
And you have to change the last pointer in the list after which the new node is inserted.
The function can look at least the following way (though using the function scanf with a character array as it is used in your program is unsafe)
void InsetEnd()
{
stud *newnode;
stud **temp;
char n[15];
int a;
printf("Student: \n");
printf("Name: ");
scanf("%s", n);
printf("Age: ");
scanf("%d", &a);
newnode = ( stud * )malloc( sizeof( stud ) );
strcpy( newnode->name, n );
newnode->age = a;
newnode->next = NULL;
temp = &head;
while ( *temp != NULL ) temp = &( *temp )->next;
*temp = newnode;
}
I was able to solve the problem. It was just the allocation place in the function. I actually had to allocate memory before creating the node, which if you inverse it will not create anything and it will only display garbage.
void InsetEnd(){
stud *temp, *newnode;
char n[15];
int a;
printf("Student: \n");
printf("Name: ");
scanf("%s", n);
printf("Age: ");
scanf("%d", &a);
newnode = (stud *) malloc (sizeof(stud));
strcpy(newnode->name, n);
newnode->age=a;
temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
newnode->next = NULL;
temp->next = newnode; }
Seems like you caught your own issue. Allocating memory before trying to access or set data is essential! There are a few more things I felt like I need to mention to help you in the future.
void InsetEnd(stud *head) { // pass head pointer, becomes local pointer so its not overriden
if (!head)
return; // dont do anything if list does not exist
stud *newnode; // no need for tmp anymore
char n[15] = ""; // initialize
int a;
printf("Student: \n");
printf("Name: ");
scanf("%14s", n); // take only 14 chars, leaving the 15th '\0' or you'll have problems reading long names after
printf("Age: ");
scanf("%d", &a);
newnode = calloc(1,sizeof(*newnode)); // use calloc to avoid junk
// ^ type casting a return of void* is not necessary in c
strcpy(newnode->name, n);
newnode->age=a;
while(head->next) // NULL is pretty much false
head=head->next;
// no need to set newnode next to null, its already null from calloc
head->next = newnode;
}
Hope this helps!
I will try to explain it from the following example
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class Node {
public:
double data; // data
Node* next; // pointer
};
class List {
public:
List(void) { head = NULL; } // constructor
~List(void); // destructor
bool IsEmpty() { return head == NULL; } //boş kontrolü
Node* InsertNode(int index, double x); //node ekle
int FindNode(double x); //node bul
int DeleteNode(double x); //node sil
void DisplayList(void); //liste görüntüle
private:
Node* head; //baş kısmı
};
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = new Node;
newNode->data = x;
if (index == 0) {
newNode->next = head;
head = newNode;
}
else{
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
int List::FindNode(double x) {
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
currNode = currNode->next;
currIndex++;
}
if (currNode) return currIndex;
return 0;
}
int List::DeleteNode(double x) {
Node* prevNode = NULL;
Node* currNode = head;
int currIndex = 1;
while (currNode && currNode->data != x) {
prevNode = currNode;
currNode = currNode->next;
currIndex++;
}
if (currNode) {
if (prevNode) {
prevNode->next = currNode->next;
delete currNode;
}
else {
head = currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
void List::DisplayList()
{
int num = 0;
Node* currNode = head;
while (currNode != NULL)
{
printf("\n%lf",currNode->data);
currNode = currNode->next;
num++;
}
printf("\nNumber of nodes in the list: %d",num);
}
List::~List(void) {
Node* currNode = head, *nextNode = NULL;
while (currNode != NULL)
{
nextNode = currNode->next;
// destroy the current node
delete currNode;
currNode = nextNode;
}
}
int main(int argc, char** argv) {
List list;
list.InsertNode(0,5.4); //başarılı
list.InsertNode(1,6.5); //başarılı
list.InsertNode(-2,5.5);//başarsız
list.InsertNode(2,10.0);//başarılı
list.DisplayList();
list.DeleteNode(5.4);
list.DisplayList();
return 0;
}
Now edit node part
class Node {
public:
int no;
char name[15];
char surname[15];
int age;
Node* next;
};
and insert function. Flow chart is here.
Node* List::InsertNode(int index, int no,char name[15],char surname[15],int age){
if (index < 0) return NULL;
int currIndex = 1;
Node* currNode = head;
while (currNode && index > currIndex) {
currNode = currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode = new Node;
newNode->no = no;
strcpy_s(newNode->name, name);
strcpy_s(newNode->surname, surname);
strcpy_s(newNode->age, age);
if (index == 0) {
newNode->next = head;
head = newNode;
}
else {
newNode->next = currNode->next;
currNode->next = newNode;
}
return newNode;
}
Related
The insert seems to go smoothly but the display only shows the head element only. I wanted to do this on my own and tried to use the logic. I am confused whether the fault lies in the Insert function or the Display.
I am not really that great at programming and just started learning C++.Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *prev;
struct node *next;
};
struct node *head = NULL;
void insert(struct node **head)
{
struct node *newnode = (struct node *)malloc(sizeof(struct node));
newnode->next = NULL;
newnode->prev = NULL;
if ((*head) == NULL)
{
int x;
printf("\nEnter the value of the starting node :");
scanf("%d", &x);
newnode->data = x;
(*head) = newnode;
}
else
{
int pos, x;
printf("\nEnter the pos ");
scanf("%d", &pos);
if (pos == 0)
{
newnode->next = (*head);
newnode->prev = NULL;
(*head)->prev = newnode;
(*head) = newnode;
printf("\nEnter data in %d pos : ", pos);
scanf("%d", &x);
newnode->data = x;
}
else
{
struct node *temp;
struct node *ptr = (*head);
while(ptr->next!=NULL)
{
for (int i = 0; i < pos - 1; i++)
{ ptr = ptr->next;}
}
if (ptr->next == NULL)
{
newnode->prev = ptr;
newnode->next = NULL;
printf("\nEnter data in %d pos : ", pos);
scanf("%d", &x);
newnode->data = x;
}
else
{
printf("\nEnter data in %d pos : ", pos);
scanf("%d", &x);
newnode->data = x;
temp = ptr->next;
newnode->prev = ptr;
newnode->next = temp;
ptr->next = newnode;
temp->prev = newnode;
}
}
}
}
void delete (struct node **head)
{
struct node *ptr;
ptr = (*head);
if ((*head) == NULL)
{
printf("\nUnderflow\n");
}
else
{
int pos;
printf("\nEnter the pos ");
scanf("%d", &pos);
struct node *temp;
for (int i = 0; i < pos; i++)
{
ptr = ptr->next;
}
temp = ptr->next;
temp->prev = ptr->prev;
ptr->next = NULL;
ptr->prev = NULL;
}
}
void display(struct node **head)
{
struct node *ptr = (*head);
if (ptr != NULL)
{
printf(" %d ",ptr->data);
}
else
{
printf("\nUnderflow OR empty\n");
}
}
int main()
{
while (1)
{
int x;
printf("\n1.Insert\n2.Delete\n3.Display\n4.Exit\n\nChoose option :\n");
scanf("%d", &x);
switch (x)
{
case 1:
{
insert(&head);
break;
}
case 2:
{
delete (&head);
break;
}
case 3:
{
display(&head);
break;
}
default:
{
printf("\nWrong operation.Select again :");
continue;
}
}
}
return 0;
}
The display was supposed to show the list like
a-> b -> c......
In the display function you should take the next node and print that too
// head->next1->next2->NULL
struct node *ptr = (*head);
while (ptr != NULL) {
printf("%d->", ptr->data);
ptr = ptr->next;
}
printf("NULL");
Is it possible to have multiple data inside a single linked list node in C? And how do you input and access data with this?
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
char name[30];
struct node *next;
};
struct node *head, *tail = NULL;
void addNode(int data, char string) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->name[30] = string;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s", current->data, current->name);
current = current->next;
}
printf("\n");
}
int main()
{
char string1[10] = "Aaron";
char string2[10] = "Baron";
char string3[10] = "Carla";
addNode(9, string1);
addNode(7, string2);
addNode(2, string3);
printf("Original list: \n");
display();
sortList();
printf("Sorted list: \n");
display();
return 0;
}
I don't understand why my code didn't work. I was trying to make use of single linked list where it can accept/input and print/output the number and the name at the same time.
What I want it to happen is to print the number and the name.
The output should be:
Carla - 2
Baron - 7
Aaron - 9
Please read my comments marked as // CHANGE HERE.
// CHANGE HERE: accept a character array as argument
void addNode(int data, char string[]) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
// CHANGE HERE: copy char array argument to name
strncpy(newNode->name, string, 30);
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
char temp1[30];
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
// CHANGE HERE: swap the name along with data
strncpy(temp1, current->name, 30);
strncpy(current->name, index->name, 30);
strncpy(index->name, temp1, 30);
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s\n", current->data, current->name);
current = current->next;
}
printf("\n");
}
I am trying to implement a linked list in C:
struct Node{
struct Node *next;
void *data;
};
With an insert function:
void insert(void *p2Node, void *data)
{
struct Node *newNode;
struct Node **p2p2Node= (struct Node **)p2Node;
if (newNode = malloc(sizeof(struct Node))) /* if successfully allocated */
{
newNode->data = data;
if ((*p2p2Node) != NULL) /* if the list is not empty */
{
newNode->next = (*p2p2Node)->next;
(*p2p2Node)->next = newNode;
}
else
(*p2p2Node) = newNode;
p2Node = p2p2Node;
}
printf("Inside the insert: %s\n", (*p2p2Node)->data);
}
I called insert in main():
int main()
{
char *setA = "liquid ";
char *setB = " lgd";
char *setC = "sample";
struct Node *nList = malloc(sizeof(struct Node));
insert(nList, setC);
printf("2Get %s\n", nList->data);
return 0;
}
No error or warning was reported, but the value was only changed inside the insert. Back to main() the linked list is still empty.
I do not understand: nList in main() is a void pointer. Inside insert(), *p2Node is not altered, I used p2p2Node to change the value p2Node points to, why is it not working? Did I mismatch the pointers? Is there a way I can make it work without modifying the parameter of insert()?
Thank you.
Use this code to insert values to the linked list.
struct node{
int data;
struct node* link;
};
struct node *root = NULL;
int len;
int main()
{
append();
display();
addatbegin();
display();
addatafter();
display();
}
Add values to the end of the list.
void append(){
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
printf("Enter the data: ");
scanf("%d", &temp->data);
temp->link = NULL;
if(root == NULL) //list is empty
{
root=temp;
}else
{
struct node* p;
p=root;
while(p->link != NULL)
{
p = p->link;
}
p->link = temp;
}
}
Add values to the beginning of the list.
void addatbegin()
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
printf("Enter the data : ");
scanf("%d", &temp->data);
temp->link = NULL;
if(root == NULL)
{
temp = root;
}
else
{
temp->link = root;
root = temp;
}
}
Add value after a node
void addatafter()
{
struct node* temp, *p;
int loc, i=1;
printf("Enter the location : ");
scanf("%d", &loc);
if(loc > len)
{
printf("Invalid input.");
}
else
{
p = root;
while(i > loc)
{
p = p->link;
i++;
}
temp = (struct node*)malloc(sizeof(struct node));
printf("Enter the data : ");
scanf("%d", &temp->data);
temp->link = NULL;
temp->link = p->link;
p->link = temp;
}
}
To display the linked list
void display(){
struct node* temp;
temp = root;
if(temp == NULL)
{
printf("List id empty.\n");
}
else
{
while (temp != NULL){
printf("%d -> ", temp->data);
temp = temp->link;
}
printf("\n\n");
}
}
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node ** head, int n);
void display_list(node * head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
printf("Insert size of list: ");
scanf("%d",&n);
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void create_list(node **head,int n){
node *new,*tmp;
int num,i;
*head = malloc(sizeof(node));
if(*head == NULL){
printf("Memory can not be allocated.");
}
else{
printf("Insert element 1: ");
scanf("%d",&num);
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for(i=2;i<=n;i++){
new = malloc(sizeof(node));
if(new == NULL){
printf("Memory can not be allocated.");
break;
}
else{
printf("Insert element %d: ",i);
scanf("%d",&num);
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
scanf("%d", &num);
new->data = num;
new->next = NULL;
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
}
}
I don't understand why after using the add_e() function, the display_list() function gives to me only the last two number of the list. The add_e() fucntion should be add an element at the end of the list. What am i doing wrong?
Edit: Added create_list() function so you can understand better but now it says to me to add more details so I'm writing something.
In main, n is unitialized, so you'll get random/bad results.
The add_e should not use *head in the while or even do a while. The printf says "insert at beginning", which is different/simpler. This is what I've currently coded up/fixed.
You'd want to use a loop, if you [really] wanted to insert/append to the end of the list. But, the loop would still be incorrect, because you don't want to advance head when finding the end.
I've also fixed the printf for prompts and scanf
Here's a refactored/fixed version of your code with the bugs annotated:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_e(node ** head);
int
main(void)
{
int n;
node *head;
head = NULL;
// NOTE/BUG: n is unitialized
#if 1
n = 5;
#endif
create_list(&head, n);
display_list(head);
add_e(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
if (head == NULL) {
printf("Empty list.");
}
else {
while (head != NULL) {
printf("DATA: %d\n", head->data);
head = head->next;
}
puts("null");
}
}
void
create_list(node **head, int n)
{
node *new,
*tmp;
int num,
i;
*head = malloc(sizeof(node));
if (*head == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element 1: ");
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
(*head)->data = num;
(*head)->next = NULL;
tmp = *head;
for (i = 2; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
else {
printf("Insert element %d: ", i);
#if 1
fflush(stdout);
#endif
#if 0
scanf("%d", &num);
#else
scanf(" %d", &num);
#endif
new->data = num;
new->next = NULL;
tmp->next = new;
tmp = tmp->next;
}
}
}
}
void
add_e(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
}
else {
printf("Insert element at the beginnig: ");
fflush(stdout);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
#if 0
while ((*head)->next != NULL) {
*head = (*head)->next;
}
(*head)->next = new;
#else
if (*head == NULL)
*head = new;
else {
new->next = *head;
*head = new;
}
#endif
}
}
UPDATE:
In add_e, because I couldn't be sure if you wanted to insert at beginning of list [based on the printf] or at the end [based on the code], I created a version that is cleaned up a bit more and demonstrates both types:
#include <stdio.h>
#include <stdlib.h>
typedef struct str_node {
int data;
struct str_node *next;
} node;
void create_list(node **head, int n);
void display_list(node *head);
void add_begin(node **head);
void add_end(node **head);
int
main(void)
{
int n;
node *head;
setbuf(stdout,NULL);
head = NULL;
printf("Enter initial number of list elements: ");
scanf(" %d",&n);
create_list(&head, n);
display_list(head);
add_begin(&head);
display_list(head);
add_end(&head);
display_list(head);
return 0;
}
void
display_list(node *head)
{
node *cur;
if (head == NULL) {
printf("Empty list.\n");
}
for (cur = head; cur != NULL; cur = cur->next)
printf("DATA: %d\n", cur->data);
}
void
create_list(node **head, int n)
{
node *new, *tmp;
int num, i;
tmp = *head;
for (i = 1; i <= n; i++) {
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
break;
}
printf("Insert element %d: ", i);
scanf(" %d", &num);
new->data = num;
new->next = NULL;
if (*head == NULL)
*head = new;
else
tmp->next = new;
tmp = new;
}
}
// add_begin -- insert at before head of list
void
add_begin(node **head)
{
node *new;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Insert element at the beginning: ");
scanf(" %d", &num);
new->data = num;
new->next = *head;
*head = new;
}
// add_end -- add to tail/end of list
void
add_end(node **head)
{
node *new;
node *tmp;
node *tail;
int num;
new = malloc(sizeof(node));
if (new == NULL) {
printf("Memory can not be allocated.");
exit(1);
}
printf("Append element at the end: ");
scanf(" %d", &num);
new->data = num;
new->next = NULL;
// find the tail
tail = NULL;
for (tmp = *head; tmp != NULL; tmp = tmp->next)
tail = tmp;
if (tail != NULL)
tail->next = new;
else
*head = new;
}
Please point out the error in the code.
The function insertatend() inserts for the first time but not again.
I'm trying to insert a node at the end of a circular linked list, but after inserting an element for the first time, it gets stuck in the while loop if we try to enter data again.
struct node {
int data;
struct node *next;
};
typedef struct node node;
node *head = NULL;
node *insertatend(node *head, int value)
{
node *temp, *p;
p = head;
temp = (node *)malloc(sizeof(node));
temp->data = value;
temp->next = head;
if (head == NULL)
{
head = temp;
}
else
{
while (p->next != head)
p = p->next;
p->next = temp;
}
return head;
}
void display(node *head)
{
node *p = head;
if (head == NULL)
{
printf("\nlinked list is empty\n");
return;
}
while (p->next != head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
int ch = 1, value;
while (ch)
{
printf("1.Insert 2.Display");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("enter an element:");
scanf("%d", &value);
head = insertatend(head, value);
break;
case 2:
display(head);
break;
}
}
return 0;
}
I think the mistake is here:
temp->next=head;
if(head==NULL){
head=temp;
}
When you enter your first element, head is null. So temp->next is set to NULL and head is set to temp.
When you enter your second element, it does this:
else{
while(p->next!=head)
p=p->next;
p->next=temp;}
Where p->next is null, so you will never have the situation that p->next == head and you will always be in the loop!
Edit:
So the solution aproach would be to change it to:
if(head==NULL){
head=temp;
}
temp->next=head;
Edit: second mistake in the display function: the loop doesn't print the last element. I just tested it and it is working fine.
So the complete code woud look like:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node node;
node *head = NULL;
node *insertatend(node *head, int value)
{
node *temp, *p;
p = head;
temp = (node *)malloc(sizeof(node));
temp->data = value;
if (head == NULL)
{
head = temp;
}
else
{
while (p->next != head)
p = p->next;
p->next = temp;
}
temp->next = head;
return head;
}
void display(node *head)
{
node *p = head;
if (head == NULL)
{
printf("\nlinked list is empty\n");
return;
}
do
{
printf("%d ", p->data);
p = p->next;
} while (p != head);
printf("\n");
}
int main()
{
int ch = 1, value;
while (ch)
{
printf("1.Insert 2.Display");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("enter an element:");
scanf("%d", &value);
head = insertatend(head, value);
break;
case 2:
display(head);
break;
}
}
return 0;
}
Alternate version, using tail pointer instead of head pointer, for faster appends.
#include <stdlib.h>
#include <stdio.h>
struct node {
struct node *next;
int data;
};
typedef struct node node;
node *insertatend(node *tail, int value)
{
node *p;
p = malloc(sizeof(node));
p->data = value;
if(tail == NULL){
p->next = p;
} else {
p->next = tail->next;
tail->next = p;
}
return p;
}
void display(node *tail)
{
node *p = tail;
if (p == NULL)
{
printf("\nlinked list is empty\n");
return;
}
do{
p = p->next;
printf("%d ", p->data);
}while(p != tail);
printf("\n");
}
int main()
{
node *tail = NULL;
int i;
for(i = 0; i < 8; i++)
tail = insertatend(tail, i);
display(tail);
return 0;
}