I'm new to C and need your assistance please.
I have posted already 2 parts of the big Linked List issues I was having because i didn't want to bombard you all with a big code so i'm doing this in parts. This is a new question though so if you could explain me I would really appreciate it as always.
I have a function on my doubly linked list that is supposed to delete a string that's on my list but I seem to have a problem it's not deleted anything. In fact it get's me stuck and i can't input anything. I would like to paste my code for you to maybe understand better with what i'm dealing with. Love your help!
This is my struct node:
struct node
{
char data[100];
struct node *previous; // Points to the previous node
struct node *next; // Points out to the next node
}*head, *last;
This is my function called: delete_from_middle
char delete_from_middle(char words[99])
{
struct node *temp,*var,*temp1;
temp=head;
strcpy(temp->data, words);
while (temp!=NULL)
{
if (temp->data == words)
{
if (temp->previous==NULL)
{
free(temp);
head=NULL;
last=NULL;
return 0;
}
else
{
var->next=temp1;
temp1->previous=var;
free(temp);
return 0;
}
}
else
{
var=temp;
temp=temp->next;
temp1=temp->next;
}
}
printf(" Data deleted from list is %s \n", words);
return 0;
}
And this is where i assign it on my main
int main()
{
char loc[99];
char words[99];
int i, dat;
head=NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Begning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.)Exit");
while(1)
{
printf("\n\n Enter the choice of operation you want to do ");
scanf("%d",&i);
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node ");
scanf(" %s",words);
insert_beginning(words);
display();
break;
}
case 2:
{
printf("Enter a word you want to insert in the last node ");
scanf(" %s",words);
insert_end(words);
display();
break;
}
case 3:
{
printf("After which data you want to insert your new data ");
scanf(" %s",words);
printf("Enter the data you want to insert in list ");
scanf(" %s",loc);
insert_after(words, loc);
display();
break;
}
case 4:
{
delete_from_end();
display();
break;
}
case 5:
{
printf("Enter the value you want to delete");
scanf(" %s",words);
delete_from_middle(words);
display();
break;
}
really sorry if the code seems long but i really tried to figure how to do it.
Any help?
please let me know if i'm missing something or if my question is not correctly asked.
Well, the line
if (temp->data == words) {
certainly does not do what you expect it to do: You are comparing pointers, not the strings behind the pointers! Use strcmp() for that.
To be precise: the == operator is written to compare two arrays, but these arrays decay into pointers to their first elements, the code is equivalent to
if (&temp->data[0] == &words[0]) {
But that is probably a lesson you should learn later on, it confuses enough seasoned C programmers...
You start the function by setting temp to point to head of the list. Then you replace head->data with your search string. Obviously now head->data == words and previous == null so head is deallocated and function returns zero
Your code is very complex and seems to contain more than one problem. You should probably cut the function into smaller parts to find errors easier.
ex:
struct node *find(char words[99])
{
struct node *temp;
temp = head;
while (temp != NULL)
{
if (strcmp(temp, words) == 0)
return temp;
}
return NULL;
}
void deleteNode(struct node *n)
{
if (n->previous != NULL)
n->previous->next = n->next;
else // n is head
head = n->next;
if (n->next != NULL)
n->next->previous = n->previous;
else
last = n->previous;
free(n);
}
char delete_from_middle(char words[99])
{
struct node *target = find(words);
if (target != NULL)
deleteNote(target);
}
There is a problem in your code.
Try:
Traverse the whole linked list
like
for(node temp=head; temp!=null; temp=temp->next)
{
if(temp->data==words)
{
//update links
temp->previous=temp->next;
temp->next->previous=temp->previous->next;
break;
}
}
free (temp); //delete/free node
First in while loop, if condition is always true because of this line -
strcpy(temp->data, words);
Now there are two parts in if -> first ( if(temp->previous == NULL)
) if there is only a single element in the list then list will set
to null by setting head = NULL and last = NULL;
Second part -> If list has more than one elements then your
operations are
var->next=temp1; //This one is wrong cause var is not assigned its only declared
temp1->previous = var; //this one is causing problem free(temp); you freed the memory that was allocated for temp but
//forget to delete temp .
return 0;
//At last your element is not actually deleted and you freed the
//memory that was allocated for that element.
For deleting a specific element simplest code is ->
char delete_from_middle(char words[99])
{
struct node *h;
h = head;
while ( h! = NULL ) {
if ( strcmp(h->data, words) == 0)
{
if ( h->previous == NULL )
{
if( head == last )
{
head = NULL;
last = NULL;
}
else
{
head = head->next;
head->previous = NULL;
}
}
else
{
if( h->next!=NULL ) h->next->previous = h->previous;
h->previous->next = h->next;
}
printf(" Data deleted from list is %s \n", words);
free(h);
return 0;
}
h = h->next;
}
printf(" Data not found");
return 0; }
There are so many problems in the code, while deleting the integrity of the list is not maintained. The following should be the way to delete a node from the list:
void delete_from_middle(char words[99])
{
struct node *temp;
temp=head;
while (temp!=NULL)
{
if (strcmp(temp->data,words)==0) //this is the data we are looking for, go and delete this
{
if (temp->previous==NULL) //this is the head
{
head=temp->next;
temp->next->previous=NULL;
free(temp);
printf(" Data deleted from list is %s \n", words);
return;
}
else if(temp->next==NULL) //this is last node
{
temp->previous->next=NULL;
free(temp);
printf(" Data deleted from list is %s \n", words);
return;
}
else
{
temp->previous->next=temp->next;
temp->next->previous=temp->previous;
free(temp);
printf(" Data deleted from list is %s \n", words);
return;
}
}
else //this node does not contain the data, go to the next node
{
temp=temp->next;
}
}
//search ended
printf(" Data not found\n");
return;
}
Related
I've written a linked list program and want to take input with spaces but it's not working.It works fine when I simply use "scanf" with %s but since I want to take input with multiple spaces I tried using "gets" and "puts" I've also tried using scanf("%[^\n]*c"); but on the console it gives me random garbage value for scanf("%[^\n]*c"); and for "gets" it reads blank space,
now let me tell you guys some info about the code and how it works
createNode(); function basically just creates a new node to store in the list and returns the address of this newly created node to the insertend(); function where it aligns the new node at the end of the list and in start=t=newnode start is the head pointer which points to the very first node and t is used to traverse the list until t's value becomes NULL,As you could see in the else part of the insertend(); function we're using another pointer t and storing the value of start in it so that we can traverse the list without losing the the address of the first node which is originally kept in the start pointer.
here's the code ->
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct Node
{
char first[20];
struct Node* next;
};
struct Node* start=NULL;
struct Node* t,*u;
int i=1;
struct Node* createNode() //this function creates a newnode everytime it's called
{
struct Node* create=(struct Node*)malloc(sizeof(struct Node));
return create;
}
int length() //to measure the length of the list.
{
int count = 0;
struct Node* temp;
temp=start;
while(temp!=NULL)
{
count++;
temp = temp->next;
}
return count;
}
void insertend() //to insert a node at the end of the list.
{
int l;
struct Node* newnode = createNode();
printf("Enter Name : ");
fgets(newnode->first,sizeof(newnode->first),stdin);
if(start==NULL)
{
start=t=newnode;
start->next=NULL;
}
else
{
t=start;
while(t->next!=NULL)
t=t->next;
t->next=newnode;
t=newnode;
t->next=NULL;
printf("%s successfully added to the list!",newnode->first);
}
l=length();
printf("The length of the list is %d",l);
}
void display() //to display the list
{
struct Node* dis;
dis=start;
if(start==NULL)
{
system("cls");
printf("No elements to display in the list");
}
else
{
system("cls");
for(int j=1;dis!=NULL;j++)
{
printf("%d.) %s\n",j,dis->first);
dis=dis->next;
}
}
}
int menu() //this is just a menu it returns the user input to the main function
{
int men;
printf("Please select a choice from the options below :-\n\n");
printf("1.) Add at the end of the list\n");
printf("2.) Display list\n");
printf("3.) exit\n");
printf(" Enter your choice : ");
scanf("%d",&men);
return men;
}
int main()
{
while(1)
{
system("cls");
switch(menu())
{
case 1 : insertend();
break;
case 2 : display();
break;
case 3: exit(0);
default : system("cls"); printf("Ivalid choice!Please select an appropriate option!");
fflush(stdin);
break;
}
getch();
}
return 0;
}
gets is not to be used, it has been removed from C standard due to it's lack of security.
If you want to know more read Why is the gets function so dangerous that it should not be used?
If you use [^\n] it should work, though it's also problematic since this specifier does not limit the lenght of the stream to be read only that it must stop when finding a newline character.
I suspect the problem might be in the container rather than in the reading, maybe uninitialized memory, If you provide the struct code it'll be easier to diagnose.
You can try:
fgets(newnode->first, sizeof(newnode->first), stdin)
There is a caveat:
If the inputed stream is larger than the container, the extra characters will remain in the input buffer, you might need to discard them.
EDIT:
So the main problem was the fact that through your code you have lingering characters in the buffer, in the particular case of your fgets input it would catch a '\n' left in the buffer, so it would read it before the inputed stream, leaving it, again, in the buffer.
I added a function to clean up buffer, note that fflush(stdin) leads to undefined behaviour so it's a bad option.
I also added a few small tweaks.
- Note that conio.h is windows specific as is system("cls") and getch()(ncurses.h in Linux systems) so I commented it for this sample.
Live sample here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
struct Node
{
char first[20];
struct Node *next;
};
struct Node *start = NULL;
struct Node *t, *u;
void clear_buf(){ //clear stdin buffer
int c;
while((c = fgetc(stdin)) != '\n' && c != EOF){}
}
struct Node *createNode() //this function creates a newnode everytime it's called
{
struct Node *create = malloc(sizeof(struct Node));
return create;
}
int length() //to measure the length of the list.
{
int count = 0;
struct Node *temp;
temp = start;
while (temp != NULL)
{
count++;
temp = temp->next;
}
return count;
}
void insertend() //to insert a node at the end of the list.
{
int l;
struct Node *newnode = createNode();
printf("Enter Name : ");
clear_buf(); //clear buffer before input
fgets(newnode->first, sizeof(newnode->first), stdin);
newnode->first[strcspn(newnode->first, "\n")] = '\0'; //remove '\n' from char array
if (start == NULL)
{
start = t = newnode;
start->next = NULL;
printf("%s successfully added to the list!", newnode->first);
}
else
{
t = start;
while (t->next != NULL)
t = t->next;
t->next = newnode;
t = newnode;
t->next = NULL;
printf("%s successfully added to the list!", newnode->first);
}
l = length();
printf("The length of the list is %d", l);
}
void display() //to display the list
{
const struct Node *dis;
dis = start;
if (start == NULL)
{
system("cls");
printf("No elements to display in the list");
}
else
{
system("cls");
for (int j = 1; dis != NULL; j++)
{
printf("%d.) %s\n", j, dis->first);
dis = dis->next;
}
}
}
int menu() //this is just a menu it returns the user input to the main function
{
int men;
printf("\nPlease select a choice from the options below :-\n\n");
printf("1.) Add at the end of the list\n");
printf("2.) Display list\n");
printf("3.) exit\n");
printf(" Enter your choice : ");
scanf("%d", &men);
return men;
}
int main()
{
while (1)
{
system("cls");
switch (menu())
{
case 1:
insertend();
break;
case 2:
display();
break;
case 3:
exit(0);
default:
system("cls");
printf("Ivalid choice!Please select an appropriate option!");
clear_buf();
break;
}
getch();
}
return 0;
}
I am trying to create a linked list with names, for example:
Tom -> David -> John...
In my main function, I have a switch menu where the program asks if you want to create a new list or exit.
When the user choose 1, the program calls insertIntoLinkedList(name, &head) function where the user can add name(s) or type "end" to exit.
Everything works fine, however if the user enter end and choose option 1 again, the program creates a new linked list whereas I want to add names to an existing list.
Can someone please help me to figure out my problem? Thank you for your time.
EDIT
Here is my source code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NAME_SIZE 30
#define EXIT "end"
// Node structure
struct node {
char name[NAME_SIZE];
struct node *next;
};
typedef struct node Node;
typedef struct node* NodePointer;
int userChoice(void);
void insertIntoLinkedList(char [], NodePointer *);
void displayNames(NodePointer);
int nodeCounter = 0;
int main(void) {
int choice = 99;
do {
printf("\n--- MENU ---\n\n");
printf("1.\tCreate a new friend list\n");
printf("2.\tExit o_O");
printf("\n\n------------\n");
printf("Go to:\t");
choice = userChoice();
switch (choice) {
case 1: {
char name[NAME_SIZE] = "";
NodePointer head = NULL;
while(0 != strcmp(name, EXIT)){
printf("Enter new friend name or \"%s\" to return back to the main menu: ", EXIT);
scanf("%s", name);
if(0 != strcmp(name, EXIT)){
insertIntoLinkedList(name, &head);
displayNames(head);
}
}
displayNames(head);
break;
}
case 2: {
printf("\n\nYou have %d node(s) in your linked list. Have a great day.\n\n", nodeCounter);
break;
}
default:
printf("There is no such option. Please choose one of the option from 1 to 2.\n");
}
} while(choice != 2);
return 0;
}
int userChoice() {
int num;
scanf("%d", &num);
return num;
}
void insertIntoLinkedList(char word[], NodePointer *head){
NodePointer newNode = NULL;
NodePointer previous = NULL;
NodePointer current = *head;
newNode = malloc(sizeof(Node));
if(NULL != newNode){
strcpy(newNode -> name, word);
while(NULL != current && strcmp(word, current -> name) > 0){
previous = current;
current = current -> next;
}
if(NULL == previous){
newNode -> next = current;
*head = newNode;
} else {
previous -> next = newNode;
newNode -> next = current;
}
}
}
void displayNames(NodePointer current) {
nodeCounter = 0;
if(NULL == current){
printf("Friend list is empty... I am sorry :(\n\n");
return;
} else {
printf("\nCurrent friend list: ");
while(NULL != current){
nodeCounter++;
printf("%s → ", current -> name);
current = current -> next;
}
printf("\nNumber of friends in your current list:\t%d\n\n", nodeCounter);
}
}
Well U Can Just Declare A New Function For That. Because Every Time You Call This Function Head Is Re-declared .
E.g case 3:printf("\nEnter A New Friend Name:\n");
scanf("%s",name);
insertIntoLinkedList(name, &head);
displayNames(head);
break;
Everything works fine, however if the user enter end and choose option 1 again, the program creates a new linked list whereas I want to add names to an existing list.
The issue is that you have to declare the pointer which sores the head of the list outside the while loop.
NodePointer head = NULL;
do {
....
switch (choice) {
case 1: {
char name[NAME_SIZE] = "";
while(0 != strcmp(name, EXIT)){
....
}
....
}
} while(choice != 2);
Note you have declared the variable in the block scope inside the case. See Scope rules in C.
At the end of the scope the variable is not longer accessible and its content is lost. When you "reach" the code the next time, the you get a completely new initialized variable.
I'm trying to write a program that enqueue, dequeue, delete a chosen number and print the list. I have problems with the dequeue that i think is because of the menu part when you write a number, I've tried to fix it but the it removes the last number and not the first. The print shows the wrong number and when I tried to solve that problem I got the same problem as I had in dequeue. It's sometinhg wrong in delete but i cant figure it out.
I appreciate all the help i can get
edit:
I've changed it a lot and now everything else works except delete. I want delete to find the number i enter and delete it.
queue.c
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int info;
struct node *ptr;
int next;
}*first, *last, *temp, *first1;
void enq(int data);
void deq();
void empty();
void display();
void create();
void delete_queue();
int count = 0;
void main()
{
int no, ch;
printf("\n 1 - Enqueue");
printf("\n 2 - Dequeue");
printf("\n 3 - Delete");
printf("\n 4 - Display");
printf("\n 5 - Exit");
create();
while (1)
{
printf("\n Enter choice : ");
scanf_s("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf_s("%d", &no);
enq(no);
break;
case 2:
deq();
break;
case 3:
printf("Enter data : ");
scanf_s("%d", &no);
delete_queue(no);
case 4:
display();
break;
case 5:
exit(0);
default:
printf("Wrong choice, Please enter correct choice ");
break;
}
}
}
void create()
{
first = last = NULL;
}
void enq(int data)
{
if (last == NULL)
{
last = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = NULL;
last->info = data;
first = last;
}
else
{
temp = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = temp;
temp->info = data;
temp->ptr = NULL;
last = temp;
}
count++;
}
void display()
{
first1 = first;
if ((first1 == NULL) && (last == NULL))
{
printf("Queue is empty");
return;
}
while (first1 != last)
{
printf("%d ", first1->info);
first1 = first1->ptr;
}
if (first1 == last)
printf("%d", first1->info);
}
void deq()
{
first1 = first;
if (first1 == NULL)
{
printf("\n Error: Trying to display elements from empty queue");
return;
}
else
if (first1->ptr != NULL)
{
first1 = first1->ptr;
printf("\n Dequed value : %d", first->info);
free(first);
first = first1;
}
else
{
printf("\n Dequed value : %d", first->info);
free(first);
first = NULL;
last = NULL;
}
count--;
}
void delete_queue()
{
int retval = -1;
if (first)
{
struct node *temp = first;
first = first->next;
if (!first) { last = first; }
retval = temp->next;
free(temp);
}
return retval;
}
void empty()
{
if ((first == NULL) && (last == NULL))
printf("\n Queue empty");
else
printf("Queue not empty");
}
Let me start with a few points of advice about design and style:
I do not recommend this:
typedef struct node {
int data;
struct node *next;
} node;
you are typedefing struct node to node. while it is not illegal, it is confusing. I would recommend
typedef struct _node {
int data;
struct _node *next;
} node;
Additionally, I do not recommend use of global variable with static storage class to keep track of your queue, instead you should create a queue in your main. Use global variables only when you have compelling reasons to do so.
Do remember that when you get rid of your global variable, you will need to rewrite your enqueue dequeue delete etc... functions to take in a queue_c * as parameter (because it wont have access to queueref any more)
Now for the reason that your code is not working properly and #Weather Vane alluded to:
you have a big problem in your delete function.
int delete(int data)
{
int result = 0;
node *curr_ptr; //pointer just created and not initialized
node *prev_ptr; //not initialized
node *temp_ptr; //not initialized
while (curr_ptr != NULL)
//curr_ptr was just created, where is it pointing? fatal error here
{
//inside this block lets imagine curr_ptr is pointing to a valid
//node in the global queue
if (curr_ptr->data == data)
{
result = 1;
if (curr_ptr->next != NULL)
{
temp_ptr = curr_ptr;
//both pointers point to the same thing
destroy_node(temp_ptr);
//now you just destroyed both nodes
prev_ptr->next = curr_ptr->next;
//the first time this block runs prev_ptr is uninitialized
//so prev_ptr->next will most likely seg fault
//this happens for example if you call this function
//for the first time with a long queue
}
else
{
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
//again you are destroying both curr_ptr and temp_ptr
}
}
curr_ptr = curr_ptr->next;
prev_ptr = prev_ptr->next;
return result;
}
}
Perhaps it would be better if you think edge cases very carefully and rethink some of the logic from scratch. (test edge cases as you go)
I'm working on a "simple" program in C, where we create a linked list with a structure that acts as a movie which stores, a title, year it was made, rating (1-5), and a pointer to the next node. We are not allowed to add anything to this structure, or define functions.
On top of that, we (for some reason) are required to write the entire linked list in the body of main(), so that adds a certain layer of spaghetti to the problem. Anyways, in this program, we are supposed to have the user enter either 'U' for update or 'S' for search for a movie. The update does what you would expect, you enter a title, year, rating. From this, we are supposed to insert the node at the end of the linked list.
Our search should iterate through this linked list and if it finds a match, should print out the movie, title, and year.
Although the update part of my code works, I can't seem to get search to work. I'm using a movie struct called temp, that starts at head and iterates through the list in an attempt to find the movie. After running some tests through printf, I'm finding that temp is just a null node no matter what, and no matter what movies I enter.
I am assuming this has something to do with the way I'm calling malloc? Or something to do with not assigning nodes correctly? I'm honestly not sure, and unfortunately, the lab's TA had no idea what was wrong either D:
Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct movie_node {
char title[250];
int year;
unsigned char rating;
struct movie_node *next;
};
typedef struct movie_node movie;
int main() {
// variables
int loop = 1;
movie *head = NULL; // represents first
movie *current; // represents the last node
movie *temp; // used for traversing the linked list
head = malloc(sizeof(movie));
int amountOfMovies = 0; // increment after each addition
char choice; // either 'u' (update) or 's' (search)
// ask user for input
while(loop) {
printf("%d Movie(s) in the database. Update or search (U/S): ", amountOfMovies);
scanf(" %c", &choice);
/* CHOICE 1, UPDATE */
if(choice == 'U') {
// case 1, head is null, we must create a new node
if(head == NULL) {
// get input
printf("Name of the movie: ");
scanf(" %[^\n]%*c", head->title);
printf("Year: ");
scanf("%d", &head->year);
printf("Rating: ");
scanf("%hhu", &head->rating);
head->next = NULL;
head = current; // set head to point to current
} else {
current = head;
// need to find where current is
while(current != NULL) {
current = current->next;
} // end while
// current is now at the null position, indicating empty node
current = malloc(sizeof(movie)); // allocate mem
// get user input
printf("Name of the movie: ");
scanf(" %[^\n]%*c", current->title);
printf("Year: ");
scanf("%d", ¤t->year);
printf("Rating: ");
scanf("%hhu", ¤t->rating);
current->next = NULL;
} // end else
// output movie
printf("Movie \"%s\" is added to the database.\n", current->title);
amountOfMovies++; // increment amount of movies in database
} else if(choice == 'S') {
/* CHOICE 2, SEARCH */
// temp string
char tempTitle[250];
// flag to let us know if we found something
bool found = false;
// temp linked list to traverse
temp = head;
temp = malloc(sizeof(movie));
// ask user for input
printf("Name of movie: ");
scanf(" %[^\n]%*c", tempTitle);
printf("NAME OF MOVIE IN HEAD: %s\n", temp->title); // test, take out later
while(temp != NULL) {
printf("NAME OF CURRENT MOVIE TO COMPARE TO: %s\n", temp->title); // test
if(strcmp(temp->title, tempTitle) == 0) {
// match
printf("Year: %d\n", temp->year);
printf("Rating: %hhu\n", temp->rating);
found = true;
break;
} else { // no match so far
temp = temp->next;
printf("HAVEN'T FOUND MATCH, NEXT TITLE TO CHECK IS: %s\n", temp->title); // test print
found = false;
} // end else
} // end while
if(found == false) { // no match confirmed
printf("Movie \"%s\" does not exist in the database.\n", tempTitle);
}
} else { // choice is invalid
loop = 0; // exit
} // end if-else
} // end while
// free all the nodes
return 0;
}
Note: the only thing I haven't implemented yet is freeing the memory.. which I'm not a hundred percent sure how I should accomplish it.
Any help is greatly appreciated..
The problem is with your malloc() calls. First you do:
movie *head = NULL;
// ...
head = malloc(sizeof(movie));
This means that head is no longer null and you won't be able to insert first movie the way you want to - move that malloc() somewhere else.
Secondly, few lines of code below, you do:
current = head; // <- this is OK
// ...
current = malloc(sizeof(movie)); // allocate mem <- this is NOT OK, for the same reason as before
Also, you can read titles of the movies like that: scanf("%249s", head->title).
Let me know if you know how to go from there.
Apart from the problems in your code, there is another problem: the lab's TA had no idea what was wrong either.
sample to fix
movie *new_node(void){//aggregate the creation of a new node
movie *node = malloc(sizeof(*node));//error check omit
printf("Name of the movie: ");
scanf(" %249[^\n]%*c", node->title);
printf("Year: ");
scanf("%d", &node->year);
printf("Rating: ");
scanf("%hhu", &node->rating);
node->next = NULL;
return node;
}
int main() {
int loop = 1;
movie *head = NULL;
movie *current;
movie *temp;
//head = malloc(sizeof(movie));//"if(head == NULL) {" don't work
int amountOfMovies = 0;
char choice;
while(loop) {
printf("%d Movie(s) in the database. Update or search (U/S): ", amountOfMovies);
scanf(" %c", &choice);
if(choice == 'U') {
if(head == NULL) {
current = head = new_node();//need set to current
} else {
current = head;
while(current->next != NULL) {//"current != NULL" can't link
current = current->next;
}
current = current->next = new_node();
}
printf("Movie \"%s\" is added to the database.\n", current->title);
amountOfMovies++;
} else if(choice == 'S') {
char tempTitle[250];
bool found = false;//need <stdbool.h>
temp = head;
//temp = malloc(sizeof(movie));//Unnecessary
printf("Name of movie: ");
scanf(" %249[^\n]%*c", tempTitle);
//printf("NAME OF MOVIE IN HEAD: %s\n", temp->title);
while(temp != NULL) {
//printf("NAME OF CURRENT MOVIE TO COMPARE TO: %s\n", temp->title);
if(strcmp(temp->title, tempTitle) == 0) {
printf("Year: %d\n", temp->year);
printf("Rating: %hhu\n", temp->rating);
found = true;
break;
} else {
temp = temp->next;
printf("HAVEN'T FOUND MATCH, NEXT TITLE TO CHECK IS: %s\n", temp->title);
//found = false;//Unnecessary
}
}
if(found == false) {
printf("Movie \"%s\" does not exist in the database.\n", tempTitle);
}
} else {
loop = 0;
}
}
// free all the nodes
return 0;
}
I already posted something similar before but this is another part of a problem that I'm having and I would appreciate your ideas and if you can help me fix my mistake.
As stated on my title i'm building a Doubly Linked List and I would like to know if my function insert_after works or not. When I run the full code I can't insert after the value that I chose which is why I'm posting this. Please let me know if I'm not clear or if this question is wrongly asked. I'm new in C and just need your help understanding.
This is my struct:
struct node
{
char data[100];
struct node *previous; // Points to the previous node
struct node *next; // Points out to the next node
}*head, *last;
This is my function to insert after a the chosen word:
char insert_after(char words[99], char loc[99])
{
struct node *temp, *var, *temp1;
var=(struct node *)malloc(sizeof(struct node));
strncpy(var->data, words,100);
if (head==NULL)
{
head=var;
head->previous=NULL;
head->next=NULL;
}
else
{
temp=head;
while ((temp!=NULL) && (temp->data!=loc))
{
temp=temp->next;
}
if (temp==NULL)
{
printf("\n %s not presented at list\n", loc);
}
else
{
temp1=temp->next;
temp->next=var;
var->previous=temp;
var->next=temp1;
temp1->previous=var;
}
}
last=head;
while (last->next!=NULL)
{
last=last->next;
}
return 0;// take it out after
}
And this is my main: --> Case 3 is my problem
int main()
{
char loc[99];
char words[99];
int i, dat;
head=NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Begning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.)Exit");
while(1)
{
printf("\n\n Enter the choice of operation you want to do ");
scanf("%d",&i);
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node ");
scanf(" %s",words);
insert_beginning(words);
display();
break;
}
case 2:
{
printf("Enter a word you want to insert in the last node ");
scanf(" %s",words);
insert_end(words);
display();
break;
}
case 3:
{
printf("After which data you want to insert your new data ");
scanf(" %s",words);
printf("Enter the data you want to insert in list ");
scanf(" %s",loc);
insert_after(words, loc);
display();
break;
}
I didn't put the full code because it's pretty long which is why i posted the important stuff.
Please let me know if my question is not clear.
Thanks
This is a problem:
while ((temp!=NULL) && (temp->data!=loc))
temp->data != loc is not comparing strings, it just compares pointer addresses.
You could use strcmp or a similar string comparision function. strcmp returns non-zero if
the two parameters differ.
while ((temp!=NULL) && (strcmp(temp->data, words))
Note that it is words that is to compared to the values in the list as words is the value that loc is to be inserted after.
If you use char arrays as the parameters to insert_after function care will be needed to ensure that the entire length of the array is initialised correctly.
Note that a check on the following node is necessary in case there is only one node in the list (the following node will be NULL in this case).
char insert_after(char *words, char *loc)
{
struct node *temp, *var;
var=(struct node *)malloc(sizeof(struct node));
strcpy(var->data, loc);
if (head==NULL)
{
head=var;
head->previous=NULL;
head->next=NULL;
}
else
{
temp=head;
while ((temp!=NULL) && (strcmp(temp->data, words)))
{
temp=temp->next;
}
if (temp==NULL)
{
printf("\n %s not presented at list\n", words);
}
else
{
struct node * followingNode = temp->next;
temp->next=var;
var->previous=temp;
var->next= followingNode;
if (followingNode)
followingNode->previous = var;
}
}
}
Issues
char words[99] has 99 elements but you're allowing up to 100 here, strncpy(var->data, words,100);. That may cause a problem if words is not '\0' terminated. You could unintentially write word[99] to var->data which shouldn't be allowed. Change the statement to this:
strncpy(var->data, words, 99);
var->data[99] = '\0'; // In case words wasn't a string
You cannot compare strings like this, temp->data!=loc. You're actually comparing addresses. Change this line to the following:
while((temp != NULL) && (strcmp(temp->data, loc) != 0));
var->next=temp1 is incorrect. We're at the end of the list so this line should be rewritten as follows:
var->next = NULL;
You must use memcmp or, better yet, strcmp for string comparison instead of !=.