I am writing a program in which I add students to a roster using linked lists. I am successful at adding the first student, but upon adding subsequent students, my program prints "Student already exists" even when the student doesn't exist yet. Below is my add function.
struct student *add(struct student *list){
struct student *p;
struct student *new_student = malloc(sizeof(struct student));
printf("Enter the student's last name: ");
read_line(new_student->last, NAME_LEN);
printf("Enter the student's first name: ");
read_line(new_student->first, NAME_LEN);
printf("Enter the student's email: ");
read_line(new_student->email, EMAIL_LEN);
printf("Enter the student's instrument: ");
read_line(new_student->instrument, INSTRUMENT_LEN);
printf("Enter the student's group name: ");
read_line(new_student->group, GROUP_LEN);
if(new_student == NULL){
printf("\nMalloc failed.\n");
return list;
}
if(list==NULL){
return new_student;
}
for(p=list;p!=NULL; p=p->next){
if((strcmp(p->first,new_student->first)==0) &&
(strcmp(p->last, new_student->last)==0)){
printf("\nThis student already exists.\n");
return list;
}
else{
while(p->next==NULL){
p->next = new_student;
new_student->next = NULL;
printf("\nStudent has been added to the roster.\n");
break; //FOR LOOP NOT BREAKING?
}
}
}
return new_student;
}
If anyone can help me understand how to fix this so that the for loop doesn't keep executing after the student is added to the list, I'd appreciate it.
It doesn't seem as though my break statement is working. I've tried making the return to new_student occur within my else statement, but that causes other issues in my program. Any help is appreciated.
printf("\nStudent has been added to the roster.\n");
p = NULL;
break;
What worked for me was getting rid of my else statement and while loop and opting for an if statement. Also, I was only returning the student added to the list, rather than the entire list, so students were not being added.
Related
I am writing a function that is supposed to remove a node of the user's choice from a linked list of students. The program will take user input through a read_line function for the student's name, last name, and email and then 1)locate the node that has these elements, 2) bypass this node, and 3)release the memory occupied by that node. My function will delete any node other than the head node, and I cannot understand if I have an error in my logic.
Here is my function code:
struct student* remove_from_list(struct student *list){
struct student *p;
struct student *cur;
struct student *delete = malloc(sizeof(struct student));
if(delete == NULL){
printf("\nMalloc failed. \n");
}
if(list==NULL){
printf("\nRoster empty. Nothing to remove.\n");
return list;
}
printf("Enter the last name of the student to be removed: ");
read_line(delete->last, NAME_LEN);
printf("Enter the first name of the student to be removed: ");
read_line(delete->first, NAME_LEN);
printf("Enter the email of the student to be removed: ");
read_line(delete->email, EMAIL_LEN);
//to check if student is in the list
for(p=list; p!=NULL; p=p->next){
if(((strcmp(delete->last, p->last))!=0) || (strcmp(delete->first,p->first)!=0)
|| (strcmp(delete->email, p->email)!=0)){
continue;
}
else{
break;
}
printf("\nThis student does not exist.\n");
return list;
}
//to remove any element other than first
for(cur=list; cur->next!= NULL; cur=cur->next){
if(strcmp(cur->next->last, delete->last)==0 &&
strcmp(cur->next->email,delete->email)==0 &&
strcmp(cur->next->first, delete->first)==0){
delete=cur->next;
cur->next = cur->next->next;
free(delete);
printf("\nStudent has been removed from the list.\n");
return list;
}
}
cur=list; //to remove first element
if(cur->next == NULL){
cur=cur->next;
free(delete);
printf("\nStudent has been removed from the list.\n");
return list;
}
}
My function is not deleting the head node, and I'm not sure if it is a small fix or if there is something fundamentally wrong with my logic. I have seen examples that do this with integer input, but am struggling to implement this in my case. Any help or suggestions are appreciated.
Im not sure if this is what you were intending to do, but it looks wrong logically...
for(p=list; p!=NULL; p=p->next){
if(((strcmp(delete->last, p->last))!=0) || (strcmp(delete->first,p->first)!=0)
|| (strcmp(delete->email, p->email)!=0)){
printf("\nThis student does not exist.\n");
return list;
}
}
But isn't this going to fail unless the first node is the one you want to delete? You're beginning a loop, looking at the first node, and if it doesn't match, you return the list?
Instead of looking for the negative, I think the intention was to loop through the nodes, and if it finds a match, end the loop early - otherwise you want to get to the end of the list to check all of the nodes.
for(p=list; p!=NULL; p=p->next){
if(((strcmp(delete->last, p->last))==0) && (strcmp(delete->first,p->first)==0)
|| (strcmp(delete->email, p->email)==0)){
printf("\nFound a match.\n");
// delete this node and end this for loop early, probably better to use a while loop here, while(strcmp()!=0 etc);
}
}
EDIT
Now that you've got your for loop working to find the record, you might want to do another edit. You find the record with the set of strcmp()!=0 inside the first for loop, which if it finds the record, breaks out of the loop. At this point, you can delete the found record!
That means you don't need to repeat your loop again to delete the record, and you won't have two different blocks of code for if it is the first or subsequent record in the list.
//to check if student is in the list
for(p=list; p!=NULL; p=p->next){
if(((strcmp(delete->last, p->last))!=0) || (strcmp(delete->first,p->first)!=0)
|| (strcmp(delete->email, p->email)!=0)){
continue;
}
else {
// we found a match! Delete it
delete=p;
p->next = p->next->next;
free(delete);
printf("Student has been removed from the list.\n");
return list;
}
printf("\nThis student does not exist.\n");
return list;
}
// should never get here any more
} // end func.
If you really want to keep your code the way it is, because it does work for all but the first record, then you need to get the deleting of the first record to work. The check of == NULL looks wrong, because you only delete the first record if there are no others linked to it? Error in that logic, I feel.
// if we get here, we can assume that the first element matched,
// because otherwise we should never have gotten here
cur=list; //to remove first element
if(cur->next != NULL){ // if there is a next element
// set next to be the first
cur=cur->next;
}
free(delete);
printf("\nStudent has been removed from the list.\n");
return list;
}
I have started learning about Linked Lists, which through videos and multiple examples I have pretty much understood what a Linked List is and how it can be represented in a real life analogy. But when it comes to coding it I get lost I suppose through all the pointers I kind of get confused, it took a bit for me to get a stronger grasp on arrays so I assume it will be the same with Linked lists. So here is my code
/*
• The program will use dynamic memory to create a singly linked list(NO ARRAYS PERMITTED)
• The program will store unlimited number of student records(limited only by RAM).
• A student record will consist of Student Name, Age, and GPA…you may need to add additional fields to make this work(Next).
• The program will have a way for the user to add records(in order by name).You can assume that no two students have the same name.The list will always be in order.
• The program will have a way for the user to display ALL records.
• The program needs a way to quit.
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma warning(disable: 4996)// disables warning
typedef struct{
char name[40];
int age;
float gpa;
struct NODE* next;
}NODE;
void addStudent();
int main(void){
NODE* head = NULL;
int userinput;
printf(" **********************************\n");
printf(" * MENU *\n");
printf(" * 1. Add Student *\n");
printf(" * 2. Display all student records*\n");
printf(" * 3. Quit *\n");
printf(" **********************************\n");
scanf_s("%d%*[^\n]", &userinput); '\n' == getchar();
switch (userinput)
{
case 1: do
{
addStudent(head);
printf("Add another record? 1(y) 2(n)\n");
scanf_s("%d%*[^\n]", &userinput); '\n' == getchar();
} while (userinput == 1);
break;
}
}
void addStudent(NODE* head){
head = malloc(sizeof(NODE));
if (head == NULL)
{
return;
}
NODE * current = head;
printf("Please Enter student name:\n");
fgets(current->name, 40, stdin);
printf("Enter student age:\n");
scanf("%d%*[^\n]", ¤t->age); '\n' == getchar();
printf("Enter student gpa:\n");
scanf("%f%*[^\n]", ¤t->gpa); '\n' == getchar();
current->next;
current->next = NULL;
while (current != NULL){
current = head;
printf("%s\n", current->name);
printf("%d\n", current->age);
printf("%0.2f\n", current->gpa);
current = current->next;
}
}
When I compile, it will always print the head I assume its because of current = head within the while loop, I understand why its printing the head over but I am lost on how to arrange this code So that I can create a new node when I add and print all the nodes, through the loop.
The problem is that you never create new nodes to add to the list but always just updating the head. In order to make it work you should:
Allocate a new NODE,
NODE *newNode = malloc(sizeof(NODE));
Load the data into this node
printf("Please Enter student name:\n");
fgets(&newNode->name, 40, stdin);
printf("Enter student age:\n");
scanf("%d%*[^\n]", &newNode->age); '\n' == getchar();
printf("Enter student gpa:\n");
scanf("%f%*[^\n]", &newNode->gpa); '\n' == getchar();
Update the node to point to the node currently pointed by the HEAD
newNode->next = head
Update the head to point to the new Node
head = newNode;
I'm new to c and learning about linked lists, I decided to create a library manager to manage my books using linked list but it doesn't seem to be saving the data to the structure using linked list. When someone tries to add a new book the function hits the checkID function to see if the book with the same id already exists but when i do a display information nothing seems to exists in the structure.
void addBook()
{
int bookId;
BOOK *head = NULL, *temp;
temp = (BOOK*) malloc(sizeof(BOOK));
printf("\n Enter Book Details\n");
printf("Enter book ISBN: ");
scanf("%d", &bookId);
int bInd = checkID(bookId);
if (bInd == 0)
{
printf("Enter book title: ");
scanf("%s", &temp->chTitle);
printf("Enter book type (eg. magazine, novel): ");
scanf("%s", &temp->chType);
printf("Enter book publisher (eg. UTA): ");
scanf("%s", &temp->chPublisher);
printf("Enter book's number of pages: ");
scanf("%d", &temp->nPages);
printf("Enter book's price: ");
scanf("%f", &temp->nPrice);
printf("Enter year published: ");
scanf("%d", &temp->nPubYear);
//temp->next=NULL;
if (head == NULL)
{
head = temp;
temp->next = NULL;
}
else{
temp->next = head;
head = temp;
}
//BOOK[count].nStatus = IN;
count++;
}
else
{
printf("\nSorry another book with that id: Try again!\n" );
addBookFunction();
}
}
int checkID(int t)
{
BOOK *head;
while (head != NULL)
{
if (head->nID == t)
return 1;
head = head->next;
}
return 0;
}
Don't worry ! It's normal ! You are creating a new book library each time you add a book ! :)
At your place, an easy way to solve it would be to pass your "Library collection of book" to your AddBook method :
void addBook(BOOK *libraryBooks)
int checkID(BOOK *libraryBooks, int t)
Then remove your variable declaration 'head'. Change all 'head' by 'libraryBooks' and pass the variable to checkID.
Above this function you'll have to manage your library.
checkID() and addBook() should probably both accept the head of your linked list as an additional parameter. The head pointer that iterates through your linked list in checkID() looks like it's getting used before it's initialized with a proper value. It may just be lucky happenstance that you haven't hit a null pointer exception already.
I was trying to do an example about linked list. First, I added the values to the variables and there was no problem. But when I tried to get values from user, the program crashed when entering midterm 2 grade. I tried other input functions but the result is same. Where is the problem?
#include <stdio.h>
struct student
{
char *name;
int m1,m2,final;
struct student* next;
};
main()
{
addStudent();
system("PAUSE");
}
addStudent()
{
struct student *node = NULL;
struct student *firstnode;
firstnode = (struct student *)malloc(sizeof(struct student));
node = firstnode;
printf("press 0 to exit \n");
while(1)
{
printf("Student name: ");
scanf("%s", node->name)
if(node->name == "0") break;
printf("Midterm 1: ");
scanf("%d", node->m1);
printf("Midterm 2: ");
scanf("%d", node->m2);
printf("Final: ");
scanf("%d", node->final);
node->next = (struct student *)malloc(sizeof(struct student));
node = node->next;
}
node->next = NULL;
node = firstnode;
while(node->next);
while(node->next != NULL)
{
printf("%s - ",node->name);
printf("%d ", node->m1);
printf("%d ", node->m2);
printf("%d ", node->final);
node = node->next;
}
system("PAUSE");
return 0;
}
Fix 1
Remove the line
while(node->next);
Reason: It will put you on an infinite loop in most cases and it is unnecessary.
Fix 2
Replace the loop
while(node->next != NULL) {
}
with
if (node->next != NULL) {
while (node->next->next != NULL) {
}
}
Reason: You are allocating one additional struct each time and keeping it empty for reading next time. So the Linked List will end before the next becomes NULL.
Fix 3
Replace following in struct
char *name;
with
char name[80];
Reason: Memory not being allocated.
Fix 4
Replace at all occurrences of scanf (except for name)
scanf("%d", node->m1);
with
scanf("%d", &node->m1);
Reason: scanf needs memory location of data to be read.
Good luck
Your code has multiple errors.
To start with, the first scanf("%s", node->name) is missing its terminating semicolon.
Next, your function signatures are sloppy. main() should be int main(void). addStudent() should be int addStudent(void). (Or, get rid of its return 0 and let it return void.) Since you don't pre-declare addStudent(), you should define it before main() so that main() can know about it.
The crash, though, is because you haven't allocated memory for node->name. You've allocated memory for a node, but that doesn't give you space to put the name.
I was trying out linked lists and for some reason it isnt doing what it is supposed to do. When I enter the quantity after choosing 1 it is all good until the node is add to the existing list, after which the quantity becomes a weird string of numbers. And also when ever i try adding more than one node to the donate list the program crashes.
EDIT: The above problem is solved but there is another problem which I forgot to mention
It is when I am trying to print the list out, nothing gets printed. This happens when I choose 4.
EDIT2: The print function is only printing out the first node nothing after that.
Please help.
Here's the code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct donation{
char name[50];
int quant;
struct donation* next;
}donate;
donate* addItem(donate *mylist,donate *temp){
donate *front=(donate*)malloc(sizeof(donate*));
if(mylist==NULL)
return temp;
front=mylist;
while(mylist->next!=NULL)
mylist=mylist->next;
mylist->next=temp;
return front;
}
void print(donate* donList){
printf("Printing the Donations Table\n\n");
if(donList!=NULL){
while(donList->next!=NULL){
printf("%s %d\n",donList->name,donList->quant);
donList=donList->next;
}
}
}
main(){
donate *list=NULL;
while(1){
int choice;
printf("1. Add a donation\n);
printf("Enter your choice: ");
scanf("%d",&choice);
if(choice==1){
donate* temp=(donate*)malloc(sizeof(donate*));
printf("\nEnter inventory type: ");
scanf("%s",temp->name);
printf("Enter the amount: ");
scanf("%d",&temp->quant);
temp->next=NULL;
list=addItem(list,temp);
printf("\nDonation Added!\n");
printf("%s %d\n",list->name,list->quant);
}
else if(choice==4){
print(list);
}
}
system("pause");
return 0;
}
Thanks!
One problem is that you are mallocing space for a donate pointer. You need to allocate space for the struct itself.
donate* temp=(donate*)malloc(sizeof(donate*));
should be
donate* temp= malloc(sizeof(donate));
Since you are doing a malloc, prior to adding an item, I think addItem just needs to be:
donate* addItem(donate *mylist,donate *temp)
{
if (mylist != NULL)
temp->next = mylist;
return temp;
}
It looks like you would not print a 1 item list:
printf("Printing the Donations Table\n\n");
if(donList!=NULL){
printf("Not NULL!!!!\n");
while(donList->next!=NULL){
printf("%s %d\n",donList->name,donList->quant);
donList=donList->next;
}
}
I think it should be:
printf("Printing the Donations Table\n\n");
if (donList!=NULL)
{
printf("Not NULL!!!!\n");
do
{
printf("%s %d\n",donList->name,donList->quant)
donList=donList->next;
}
while(donList != NULL);
}
Try running your program linked to efence or with valgrind.
Both will tell you when and where things start to go bad.
There are two issue that I see. First is the issue pointed out by Scooter. Second is you have a memory leak in the first line of addItem().
Edit To answer your second question, you will need to fix the build error; you reference reqList in main() but never declare it.
Here is a corrected version of the code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct donation{
char name[50];
int quant;
struct donation* next;
}donate;
donate* addItem(donate *mylist,donate *temp){
if(mylist==NULL)
return temp;
donate *front=mylist;
while(mylist->next!=NULL)
mylist=mylist->next;
mylist->next=temp;
return front;
}
main(){
donate *list=NULL;
while(1){
int choice;
printf("1. Add a donation\n);
printf("Enter your choice: ");
scanf("%d",&choice);
if(choice==1){
donate* temp=(donate*)malloc(sizeof(donate));
printf("\nEnter inventory type: ");
scanf("%s",temp->name);
printf("Enter the amount: ");
scanf("%d",&temp->quant);
temp->next=NULL;
list=addItem(list,temp);
printf("\nDonation Added!\n");
printf("%s %d\n",list->name,list->quant);
}
}
system("pause");
return 0;
}
just make correction here
donate *front=(donate*)malloc(sizeof(donate*))
to
donate *front=(donate*)malloc(sizeof(donate))