Link list program to Display Student marks - c

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void Insert();
void DisplayList();
struct Student
{
char Name[10];
int Marks;
struct Student *Next;
} *Start;
int main()
{
Start = NULL;
int Choise;
while (1)
{
printf("enter number to choose ");
scanf_s("%d", &Choise);
switch (Choise)
{
case 1:
Insert();
break;
case 3:
DisplayList();
break;
default:
printf("Incorrect assignment Press relevant key :");
}
}
}
void Insert()
{
struct Student *Temp, *current=NULL;
Temp = (struct Student *) malloc(sizeof(struct Student));
printf("Enter Name Of Student");
scanf_s("%s",&Temp->Name);
printf("Enter Marks Of Student");
scanf_s("%d", &Temp->Marks);
Temp->Next = NULL;
if (Start == NULL)
{
Start = Temp;
Temp->Next = NULL;
}
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
}
void DisplayList()
{
struct Student *current, *Temp;
current = Start->Next;
if (Start == NULL)
{
printf("No Element in the list");
}
else
{
for (current = Start; current != NULL; current = current->Next)
{
printf("The List are\n");
printf_s("%d",current->Marks);
}
}
this is a Program written for single linked list.when i display the list it give only one element in the list. Whenever i am trying to print the elements of the linked list, it gives the output only one element
what mistake i do please help?

change
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
to
else {
current = Start;
while (current->Next != NULL)
{
current = current->Next;
}
current->Next = Temp;
}
and
scanf_s("%s", Temp->Name, sizeof(Temp->Name)); //remove & and add size(see Amnon's answer)

When using scanf_s which is the safe version of scanf, you are expected to pass not only the address of the buffer but also its size as the next parameter, i.e.:
scanf_s("%s", Temp->Name, _countof(Temp->Name));
You can read more about it in http://msdn.microsoft.com/en-us/library/w40768et.aspx
The other issue with the code is that you're initializing current with NULL but then trying to access its Next field.

Change the code here:
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
to this:
else {
current = Start;
while (current->Next != NULL)
{
current = current->Next;
}
current->Next = Temp;
temp->next=NULL;
}
you forget to add NULL at next pointer and therefore you are getting only single output.

Related

Keep printing the last element in the linked list

I created a standard linked list in C. It asks the user to input a number, and program end if user input #. If the user inputs anything else the program will stop.
The problem is that my program runs forever and prints the normal list at first then keeping print the last element of the linked list.
Hope someone could tell me where did I made mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *list) {
NodeT *p, *temp;
p = list;
while (p != NULL) {
temp = p->next;
free(p);
p = temp;
}
}
void showLL(NodeT *list) {
NodeT *temp = list;
temp = temp->next;
printf("Done. The list is ");
printf("%d", temp->data);
temp = temp->next;
//iterate the entire linked list and print the data
while (temp != NULL) {
printf("-->");
printf("%d", temp->data);
temp = temp->next;
}
}
NodeT *joinLL(NodeT *list, int v) {
NodeT *current = list;
NodeT *head;
head->data = v;
head->next = NULL;
while (current->next != NULL) {
current = current->next;
}
current->next = head;
return head;
}
int main() {
int data;
NodeT *list = NULL;
list = (NodeT *)malloc(sizeof(NodeT));
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
} else {
printf("Enter a number: ");
joinLL(list, data);
while (1 == scanf("%d", &data)) {
printf("Enter a number: ");
joinLL(list, data);
}
showLL(list);
freeLL(list);
}
return 0;
}
I believe the problem is in the joinLL function which add a new node at the end of the linked list.
The problem is you do not allocate elements in joinLL: only a single element in allocated in main().
You should instead always allocate the element in joinLL and update the head pointer from the return value.
Similary, freeLL should take a pointer to head and set it to NULL for consistency.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *p) {
while (p != NULL) {
NodeT *temp = p->next;
free(p);
p = temp;
}
}
void showLL(const NodeT *list) {
NodeT *p = list;
printf("The list is ");
if (p == NULL) {
printf("empty");
} else {
printf(" %d", temp->data);
while ((p = p->next) != NULL) {
printf("--> %d", temp->data);
}
}
printf("\n");
}
NodeT *joinLL(NodeT *head, int v) {
NodeT *newp = malloc(sizeof(*p));
NodeT *current;
if (newp == NULL) {
fprintf(stderr, "allocation failure\n");
exit(1);
}
newp->data = v;
newp->next = NULL;
if (head == NULL) {
return newp;
}
for (current = head; current->next != NULL; current = current->next)
continue;
current->next = newp;
return head;
}
int main() {
NodeT *list = NULL;
for (;;) {
int data;
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
break;
}
list = joinLL(list, data);
}
showLL(list);
freeLL(list);
return 0;
}
Your program keeps running because of a memory access error, you did not allocate memory for your head(you set a pointer, but use it directly without initializing it)
Change to this may solve the problem:
head=(NodeT*)malloc(sizeof(NodeT));
if(NULL==head)
{
// failed : do something...
return NULL;
}
head->data=v;
head->next=NULL;
When I just tested it, I found that there was another problem:
list = (NodeT*)malloc(sizeof(NodeT));
malloc will not be initialize your list, so the value that your list->next initially points to is uncertain.
in c, malloc does not need to be cast.

I made a stack using linked list (without array), but my pop function is not working

In my pop function, I am storing the address of head in temp and then going forward. When I get a dead-end in temp, I remove it by assigning NULL to it. When I am printing the stack however, it is not removing the last push.
I have tried using temp->next=NULL . Only then it is working, but if temp->next=NULL is working. Shouldn't temp=NULL also work?
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct student
{
char name[20];
int id;
double cgpa;
struct student* next;
} *head;
void print()
{
struct student* temp = head;
while(temp != NULL)
{
printf("id %d name %s cgpa %lf\n", temp->id, temp->name, temp->cgpa);
temp = temp->next;
}
}
void push(struct student* temp)
{
if(head == NULL)
{
head = temp;
return;
}
struct student* current = head;
while(current->next != NULL)
{
current = current->next;
}
current->next=temp;
}
void pop()
{
struct student* temp = head;
if(head == NULL)
{
printf("\n no element to pop\n");
}
else
{
while(temp->next != NULL)
{
temp = temp->next;
}
temp = NULL;
}
}
int main()
{
char operation;
struct student* temp = NULL;
head = NULL;
while(1)
{
// a for ADD, r for POP, s for print
scanf("%c", &operation);
if(operation == 'a')
{
temp = (struct student*)malloc(sizeof(struct student));
scanf("%d %s %lf", &temp->id, &temp->name, &temp->cgpa);
temp->next = NULL;
push(temp);
}
else if(operation == 'r')
{
pop();
}
else if(operation == 's')
{
print();
}
}
}
a
1 joy 2.3
a
5 boy 3.3
s
r
s
The expected result should be:
1 joy 2.3
5 boy 3.3
1 joy 2.3
But the actual results are
1 joy 2.3
5 boy 3.3
1 joy 2.3
5 boy 3.3
The function changes the local variable temp instead of changing the data member next of the node before the last node of the list.
It can look the following way
void pop()
{
if ( head == NULL )
{
printf("\n no element to pop\n");
}
else
{
struct student **temp = &head;
while ( ( *temp )->next != NULL )
{
temp = &( *temp )->next;
}
free( *temp );
*temp = NULL;
}
}
Now the variable temp points exactly to the data member next of the node before the last node. That is the list itself is changed.
Do not forget to free the last node.
The code temp=NULL sets the variable temp to null, not the field next of temp. With the latter it isn't actually removing the node.
Your right that the pop would not work. All you are is setting the temp pointer to NULL when you found the end element. What you need to do is to free the element at temp first, and then set the pointer that points to it from the previous element to NULL.
void pop()
{
if(head==NULL){
printf("\n no element to pop\n");
}
else
{
struct student* temp=head;
struct student* previous=head;
while(temp->next!=null){
previous=temp;
temp=temp->next;
}
if(previous!=next) //if there was more than one
{
previous->next=NULL;
}
else
{
head=NULL;
}
free(temp);
}
}

Airline Reservation System using linked list

Im doing airline reservation system in c programming, using linked list. It reserves a seat, views the reservation, cancels the reservation. The program runs properly for the first time without adding any data.
But when i add data and want to delete it, it gives this error "Exception thrown at 0x0FFAFBB3 (ucrtbased.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x0004B000."
For deleting data, im comparing the phone number data. And when it compares, it deletes the record. But instead it is giving error. Anyone identify the error area and provide suggestion??
Below is the code for making reservation and deleting a reservation.
void new_reservation()
{
curr = start;
if (start == NULL)
{
//Empty list
start = curr = (struct passenger *)malloc(sizeof(struct passenger));
dataentry();
curr->next = NULL;
printf("\n\t Reservation successful");
return;
}
//Reach end of list
while (curr->next)
curr = curr->next;
curr->next = (struct passenger *)malloc(sizeof(struct passenger));
curr = curr->next;
dataentry();
curr->next = NULL;
printf("\n\t Reservation successful");
printf("\n\t Saved to Reservation list");
}
void del()
{
struct passenger *temp; // assigning a temporary pointer to struct airplane
char str[20];
printf("Enter phone number:");
gets(str);
fflush(stdin);
curr = start;
while (curr)
{
if (strcmp(start->Phone, str) == 0)
{
temp = start;
start = start->next;
free(temp);
return;
}
if (strcmp(curr->next->Phone, str) == 0)
{
temp = curr->next;
curr->next = curr->next->next;
free(temp);
break;
}
else if (strcmp(curr->next->Phone, str) != 0)
{
printf("\n\n No reservations found!!");
break;
}
}
printf("\n\n Deletion successful!!");
}
if (strcmp(start->Phone, str) == 0){...}
if (strcmp(curr->next->Phone, str) == 0){...}
else if (strcmp(curr->next->Phone, str) != 0){...}
This method is too complicated, it is bound to run in to errors unless you carefully check the pointers and that pointer's next member. You can simplify this and make only one comparison. Just make sure to keep track of the node's position, if the node being deleted is the start or it is another node. Example:
void del()
{
char str[20];
struct passenger *walk = start;
if (!walk)
return;
printf("Enter phone number:");
scanf("%s", str);
struct passenger *previous = 0;
while (walk)
{
if (strcmp(walk->Phone, str) == 0)
{
struct passenger *next = walk->next;
free(walk);
if (previous == 0)
{
//deleting the first item
start = next;
}
else
{
//deleting an item in middle or end
previous->next = next;
}
return;
}
previous = walk;
walk = walk->next;
}
}
new_reservation is probably not causing any errors, but it too can be simplified. You only need to allocate once, then insert it either at the end, or assign it as start. Also you can use scanf to read a string.
void new_reservation()
{
//create new item
curr = malloc(sizeof(struct passenger));
curr->next = NULL;
//I don't know this part of your code...
dataentry();
if (start == NULL)
{
//Empty list
start = curr;
}
else
{
//find the end of the list
struct passenger *walk = start;
while (walk->next)
walk = walk->next;
walk->next = curr;
}
}

How to delete a certain element in linked list in C

I'm trying to delete a certain element in my linked list.
When I print all elements on the screen, they have a certain order (see case 2). When in case 7, I can choose an element to delete based on that order.
The code in case 7 doesn't work. Here is my code:
#include "stdio.h"
#include "ctype.h"
#include "stdlib.h"
#include "math.h"
#include "string.h"
#define SIZE 100
double dummy = sin(0.0);
struct sputnik {
char nazvanie[30];
char nazvanie_main[30];
int year;
float d;
int period;
struct sputnik *next;
};
int main(void) {
char choice;
int punkt;
int i, count = 0;
struct sputnik *head = NULL;
struct sputnik *prev, *current;
int res, kolvo, j, number;
struct sputnik a[SIZE];
system("clear");
while (1) {
printf("Menu: ");
printf("1- Create table with sputniks \n 2-All sputniks \n 3-Write 4-Read \n 5-Add \n 6-Change \n 7-Delete \n 8-Exit \n");
scanf("%d", &punkt);
while (getchar()!='\n')
continue;
switch(punkt) {
case 1:
while (1) {
printf("Create new table? (N-new; O-old)");
choice = toupper(getchar());
if (choice == 'N') {
count = 0;
prev = head;
while (prev != NULL) {
current = prev->next;
free(prev);
prev = current;
}
head = NULL;
}
if (choice != 'N' && choice != 'O') {
while (getchar() != '\n')
continue;
continue;
}
while (getchar()!='\n')
continue;
break;
}
for ( ; ; count++) {
current = (struct sputnik *)malloc(sizeof(struct sputnik));
if (head == NULL) {
head = current;
} else {
prev->next = current;
}
current->next = NULL;
printf("Name %d sputnika:", count + 1);
gets(current->nazvanie);
printf("Name planet:");
gets(current->nazvanie_main);
printf("Open year:");
scanf("%d", &current->year);
while (getchar() != '\n')
continue;
printf("Diameter:");
scanf("%f", &current->d);
while (getchar() != '\n')
continue;
printf("Period:");
scanf("%d", &current->period);
while (getchar() != '\n')
continue;
prev = current;
printf("Finish vvod?: y/n: \n");
if (toupper(getchar()) == 'Y') {
count++;
break;
} else {
while (getchar() != '\n')
continue;
continue;
};
}
break;
case 2:
if (head == NULL) {
printf ("No data \n");
} else {
printf(" Sputniks: \n");
}
current = head;
i = 0;
while (current != NULL) {
printf("%d sputnik - %s planet %s god %d diametr %4.3f period %d\n", ++i, current->nazvanie, current->nazvanie_main, current->year, current->d, current->period);
current = current->next;
}
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
int nummer;
printf("Number for sputnik to delete:\n");
scanf("%d", &nummer);
while (getchar() != '\n')
continue;
current = head;
i = 0;
while (current != NULL) {
if (i == nummer - 1) {
prev = current;
free(current);
current = prev->next;
} else {
current = current->next;
i = i + 1;
}
}
break;
case 8:
prev = head;
while (prev != NULL) {
current = prev->next;
free(prev);
prev = current;
}
printf("Finish \n");
return 0;
break;
default:
printf ("Dont right choose!\n");
break;
}
}
return 0;
}
Your current algorithm is completely broken.
You never link the node prior to the deleted node with the one following.
Your algorithm does not account for deletion the head node at all.
You needlessly march through the rest of the list even after deleting your target.
In short, this needs to be done over.
There a a number of ways to do this, many using at least one pair of pointers (a prev and a current) and marching them down the list, which appears to be what you tried and what several answers are trying to fix. Being different, I'll show you how you can do this with a single pointer-to-pointer. This has the added benefit of eliminating the need to special-case head-pointer checking.
Including basic error checking it is done something like this:
int nummer;
printf("Number for sputnik to delete:\n");
if (scanf("%d", &nummer) == 1 && nummer > 0)
{
struct sputnik** pp = &head;
while (--nummer && *pp)
pp = &(*pp)->next;;
if (*pp)
{
struct sputnik *p = *pp;
*pp = p->next;
free(p);
}
}
while (getchar() != '\n')
continue;
This walks the actual pointers in the linked list; not just their values. As a result when we arrive at the pointer referring to the node we intend to delete, we do so using the pointer in the list that got us there (including the head pointer if the request was for node(1)). This allows us to update that pointer to its successors address, then delete the node and finish up.
When it comes to single-linked-list manipulation, pointer-to-pointer algorithms often offer surprisingly elegant solutions and generally concise code. Stare at it awhile and perhaps compare it to different two/three pointer methods.
Best of luck.
You should properly relink your list when deleting its item. And also don't try to read from deleted element (prev=current;current=prev->next; free(prev);)
So your case 7 may look like this code:
int nummer;
printf(" Number for sputnik to delete:\n");
scanf ("%d",&nummer);
while(getchar()!='\n') continue;
current=head; prev=NULL;
i=0;
while(current!=NULL) {
if (i==nummer-1){
if (prev==NULL) {
// move head pointer if first element should be removed
head=current->next;
} else {
prev->next = current->next; // relink list items
}
free(current); // free allocated memory
break;
}
else
{
prev=current; current=current->next; i=i+1; // go to next item
}
}
break;
Your deletion logic is not right;
struct sputnik *prev = NULL, *current = NULL;
current = head;
if (number == 1) {
head = head->next;
free(current);
current = NULL;
return;
}
while (i < (number - 1)) {
current = current->next;
i++;
}
prev = current;
current = current->next;
if (current->next == NULL) {
free(current);
current = NULL;
prev->next = NULL;
return;
} else {
prev->next = current->next;
free(current);
current = NULL;
return;
}

Linked list structures initialized in functions not being assigned properly

I'm sure this has been asked before, but I cannot find anything on this website or any other about it after searching for quite awhile.
I''m having trouble getting the values of structures that I'm creating and modifying in a function. The code looks something like:
struct node {
char name[35];
int employeeID;
struct node *next;
}
typedef struct node employee;
void insertInOrder(employee *head, employee *curr) {
if (head == NULL) {
*curr->next = *head;
*head = *curr;
} else {
if ((head->employeeID<curr->employeeID)&&(curr->employeeID <head->next->employeeID)) {
*curr->next = *head->next;
*head->next = *curr;
} else {
insertInOrder(head->next, curr);
}
}
}
void addEmployee(char name[], employee *head, employee *curr) {
int id;
scanf("%d", &id);
curr = malloc(sizeof(employee));
strcpy(curr->name, name);
curr->employeeID = id;
insertInOrder(head, curr);
}
int main(void) {
char name[35];
int quit = 1;
employee *head, *curr;
head = NULL;
printf("Enter data about the books: \n");
while (quit) {
scanf("%[^\n]%*c", title);
if (title[0] != '#') {
addBook(name, head, curr);
} else {
quit = 0;
}
}
During my debugging, my code iterates into all of my functions, but once I get back to main after adding all of the data I want, all of the variables are empty. I know it has something to do with the way I'm using or passing pointers, but when I look at the code I keep coming to the logical conclusion that what I have should do what I want. Please, someone point out where my algorithm is flawed.
addBook takes pointers of type Book but you are passing pointers of type Employee
Edit:
So, first you don't need to do things like *curr->next = *head. It should be curr->next = head.
Also, head->next can be null which is not being checked. Finally, head needs to always be pointed at the start of the list.
Edit 2:
Following code should work. head always points to the start of the list. In order to do that, we must pass the address of the head pointer. We need to do this because we will be modifying the address of head.
I've also cleaned up a few things.
void insertInOrder(employee **head, employee *curr) {
if (*head == NULL) {
// We are inserting the first element
*head = curr;
}
else if ((*head)->next == NULL) {
// This is the second element. We either insert it in front of head or before head.
if ((*head)->employeeID < curr->employeeID) {
(*head)->next = curr;
}
else {
curr->next = *head;
*head = curr;
(*head)->next = NULL;
}
}
else {
// We iterate through the list trying to find the best spot to insert curr.
employee *temp = *head;
while (temp->next != NULL) {
if ((temp->employeeID < curr->employeeID) && (curr->employeeID < temp->next->employeeID)) {
curr->next = temp->next;
temp->next = curr;
break;
}
temp = temp->next;
}
// curr has the greatest id so it is inserted at the end
if (temp->next == NULL)
temp->next = curr;
}
}
void addEmployee(char name[], employee **head) {
int id;
printf("Enter id\n");
scanf("%d", &id);
employee *curr = malloc(sizeof(employee));
strcpy(curr->name, name);
curr->employeeID = id;
curr->next = NULL;
insertInOrder(head, curr);
}
int main(void) {
int quit = 1;
employee *head = NULL;
char title[100];
printf("Enter data about the employees: \n");
while (quit) {
scanf("%s", title);
if (title[0] != '#')
addEmployee(title, &head);
else break;
}
return 0;
}
inside the function no need to use *head or *curr ..because -> is made up for pointers only instead directly use head->left & curr->next
thanks

Resources