Delete a node from a linked list after finding it - c

I'm having trouble deleting a node from a linked list by inputting the telephone number of the record. This is the code that is supposed to do this:
typedef struct record
{
char name[20];
char surname[20];
char telephone[20];
}Record;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
void delete() {
Node *n = head;
Node* previous = NULL;
Node *next = n;
.
.
. (here i wrote the code to enter the number (stored in telNumber[20])and find the record containing the number
while (n != NULL) {
if (&n->data.telephone == telNumber) {
if (previous == NULL) {
n = n->next;
free(head);
}
else {
previous->next = n->next;
free(n);
n = previous->next;
}
}
else {
previous = n;
n = n->next;
}
}
printf("You have successfully deleted the telephone record");
The record still remains there.

This:
if (&n->data.telephone == telNumber)
is not how to compare strings for equality in C. That will compare the addresses, which will never match.
It should be:
if (strcmp(n->data.telephone, telNumber) == 0)

Related

How do you get a data section from a Linked list to compare?

I have just started learning linked list and was messing around with it but then I ran into a problem. I was not sure how to access the data member to actually compare it. In my code, I prompt the user to input grades and when they input -1 then it signals that they are finished. My first thought was to get the pointer pointing to the node to get the data like I did in scanf, however I can't compare pointers to integers. Is there a way to get data members from linked lists to compare? Also, pointing out other errors would be appreciated as well because I don't know linked lists too well. I have the following code:
int main() {
struct Node
{
int grade;
struct Node *next;
};
struct Node *head;
struct Node *first;
struct Node *temp = 0;
first = 0;
while (****** != -1) { //This is what I need the data from linked list for
head = (struct Node*)malloc(sizeof(struct Node));
printf("Enter the grade: \n ");
scanf("%d", &head -> grade);
if (first != 0) {
temp -> next = head;
temp = head;
}
else
{
first = temp = head;
}
}
}
There is a number of issue with your code:
1) Don't scan directly into the list - use a temp variable
2) Always check return values
3) Make sure to initialize variables, i.e. head
Try something like:
struct Node
{
int grade;
struct Node *next;
};
int main() {
struct Node *head = NULL;
struct Node *temp;
int data;
while (1)
{
printf("Enter the grade: \n ");
if (scanf("%d", &data) != 1)
{
// Illegal input
exit(1);
}
if (data == -1) break; // Stop the loop
temp = malloc(sizeof *temp); // Allocate new element
if (temp == NULL)
{
// Out of mem
exit(1);
}
temp -> next = head; // Insert new element in the front of list
temp -> grade = data;
head = temp; // Move the front (aka head) to the new element
}
// .... add code that uses the list
return 0;
}

BST dictionary error?

I'm building a BST dictionary tree. I'm getting an error at the strcmp line but i have no idea why. the error is EXC_BAD_ACCESS(Code = 1). This tree would be just a right tree because the first line of the file is a so it would be the root with no left children. I commented beside the line of the error.
first couple of lines from text;
a un, uno, una[Article]
aardvark cerdo hormiguero
aardvark oso hormiguero[Noun]
aardvarks cerdos hormigueros
aardvarks osos hormigueros
my code;
#include <stdio.h>
typedef struct node{
char lineOfChar[200];
struct node *left;
struct node *right;
}BST;
typedef struct nodeSec{
BST *next;
}mainLink;
int main(int argc, const char * argv[]) {
struct node *head = malloc(sizeof(BST)); //Define the Head of the linked list of BST
struct nodeSec *headOfHead = malloc(sizeof(mainLink));
headOfHead->next = head;
struct node *current = &head; //Progress down the tree
FILE *file;
file = fopen("/Users/bassammetwally/Desktop/Homework5/text","r");
int times = 0;
char arrayOfLine[200];
while(fgets(arrayOfLine, 200, file)){ //While loop to read lines into the node's array
if (times == 0) // head of linked list to run once
{
for (int counterFirstTime = 0; counterFirstTime < 140; counterFirstTime++)
{
head->lineOfChar[counterFirstTime] = arrayOfLine[counterFirstTime]; // copy the array into the node array
}
times++; // increase times so the previous block would not repeat
}
else {
struct node *temp = malloc(sizeof(BST)); //start a temp node to store the current information for further sorting
for (int counterFirstTime = 0; counterFirstTime < 40; counterFirstTime++)
{
temp->lineOfChar[counterFirstTime] = arrayOfLine[counterFirstTime];//copying line into the node array
}
int q = 2;
while (q == 2)
{
int characterCompare;
if (head != NULL && temp != NULL)
{
characterCompare = strcmp(temp->lineOfChar, head->lineOfChar);//compares the two characters of the array WHERE I GET THE ERROR
}
if (characterCompare > 0) // if temp is bigger..
{
current = head;
head = head->right;// go to the right of the tree
if (head == NULL)// if its NULL and empty then just store it there
{
head = malloc(sizeof(BST));
head = temp;
current->right= head;
break;
}
}
else if (characterCompare < 0){ //since there will not be any duplicates
current = head;
head = head->left;
if (head == NULL)// if its NULL and empty then just store it there
{
head = malloc(sizeof(BST));
head = temp;
current->left = head;
break;
}
}
else if( characterCompare == 0)
{
continue;
}
}
}
head = headOfHead->next;
}
return 0;
}
You have a few problems with pointers. Note that 'head' is a pointer to 'node' structs. In the line;
struct node *current = &head;
you are not assigning current to point to head, you are assigning current to point to the pointer head (you are taking the address of a pointer).
You also have set headOfNext to point to head and then later with;
head = headOfHead->next;
you are simply setting head back to itself.
Finally, there is no need for struct for nodesec. It only contains one element, so you can just use that element. (Unless you have a future plan to expand the struct.)

Delete a node from a linked list

I'm having trouble deleting a node from a linked list by inputting the telephone number of the record ... This is the code that is supposed to do this:
typedef struct record
{
char name[20];
char surname[20];
char telephone[20];
}Record;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
void delete() {
Node *n = head;
Node* previous = NULL;
Node *next = n;
int length;
int valid;
char telNumber[20];
char confirm = 1;
do {
valid = 0;
printf(" TELEPHONE NO. (8 digits) : ");
gets();
gets(telNumber);
length = strlen(telNumber);
for (int i = 0; i < length; i++)
{
if (!isdigit(telNumber[i]) || (length != 8))
{
printf("You enterred an invalid number\n");
valid = 1; break;
}
}
} while (valid == 1);
while (n != NULL) {
if (strcmp(&n->data.telephone, telNumber) == 0) {
if (previous == NULL) {
n = n->next;
free(head);
}
else {
previous->next = n->next;
free(n);
n = previous->next;
}
}
else {
previous = n;
n = n->next;
}
}
printf("You have successfully deleted the telephone record");
.
.
.
The record still remains there. Also, when I have two records, if i try to delete the first record, the program doesn't find it
You are not moving the head forward when first node is deleted.
while (n != NULL) {
if (strcmp(&n->data.telephone, telNumber) == 0) {
if (previous == NULL) {
n = n->next;
free(head);
head = n; /* missing*/
}
...
Well there is no error in deletion part. Maybe the head is not initialized and passes the null value to 'n'. So, since 'n' has null value, deletion is not possible. Or updated value of n is not returned or passed properly to the main function.

C: Swap two nodes of a linked list

I'm having trouble when there are only two nodes (not more) in a linked list that need to be swapped. When displaying this list, the swapping is done however only the last node is displayed.
this is part of the code that does the swapping:
typedef struct record
{
char name[20];
char surname[20];
char telephone[20];
}Record;
typedef struct node
{
Record data;
struct node *next;
}Node;
Node *head = NULL;
int cmpRecord(const Record* x, const Record* y) {
int cmp = strcmp(x->name, y->name);
return (cmp > 0) - (cmp < 0);
}
void addRecord(Record x)
{
Node *previousNode = NULL;
Node *newNode;
Node *n;
newNode = (Node*)malloc(sizeof(Node));
newNode->data = x;
newNode->next = NULL;
if (head == NULL) // The list is empty
{
head = newNode;
}
Here is the logic for swapping the nodes
else if (length == 1)
{
n = head;
if (cmpRecord(&n->data.name, &newNode->data.name) > 0)
{
newNode->next = n;
n = newNode;
return;
}
}
You don't update head, and the cmpRecord call parameters are off. Try
else if (length == 1)
{
n = head;
if (cmpRecord(&(n->data), &(newNode->data)) > 0) //<-- fix types
{
newNode->next = n;
head = newNode; // <---- update head if the new record should be first
return;
}
}

Creating a Linked List from File Input

Basically what I'm trying to do is take in a txt file and create a linked list off of it. The txt file contains either a "i" or "d" followed by a space and then a number.
Example of txt file:
i 10
i 12
d 10
i 5
I am trying to take in the input file and based off the input create a linked list. If the letter is an "i", I am trying to add it to the linked list. If it is a "d", I am trying to delete it from the list.
This is what I have so far. I have taken in the file and read it line by line, separating the letters from the number and stores them in char pointers. I tried earlier to create a linked list but it did not work out properly. Could someone please point me in the right direction on where and how I should implement the linked list.
#include<stdio.h>
#include<stdlib.h>
#include <ctype.h>
#include <string.h>
struct node { // creation of node structure
int data; // data inside node
struct node *next; // address to the next node int the list
};
void Insert (struct node *root, int x){ // this method will insert a node into the linked list
struct node *newnode;
newnode = (struct node*)malloc(sizeof(struct node));
newnode->data=x;
newnode->next = NULL; // this creates the node and stores the input into the data variable
if (root == NULL){ // if the root node is empty, point the root node to this pointer.
root = newnode;
}
else {
newnode->next=root; // if the link list is not empty, set whatever head point was pointing to previously equal to newnode-> next
root=newnode; // now make the head node point to the newnode
}
}
void printlist(struct node *root)
{
struct node *temp;
temp=root;
while(temp!=NULL)
{
printf("%d",temp->data);
temp=temp->next;
}
printf("\n");
}
int main (int argc, char *argv[]){
// Need to create a Root Node
struct node *root;
if (argc != 2) { // if the input is more than one, error
return EXIT_FAILURE;
}
// argv[1] will contain the file name input.
FILE *file = fopen(argv[1], "r");
// we need to make sure the file is not empty, error case.
if (file == NULL){
printf("error\n");
exit(0);
}
// if the file is empty, print an empty line. ******** MAKE SURE TO COME BACK TO THIS ************
char linestring[BUFSIZ]; // this will hold our file input after we read/scan it.
// now we need to read the file
while (fgets(linestring, sizeof(linestring), file)) // reads the entire file until it hits Null
{
// need to split up the lines so that we separate letters from integars.
// look for \t or " " and use strtok.
char* letter = strtok(linestring, " \t\n"); // stores the letter from the line
char* number = strtok(NULL, " \t\n"); // stores the numbers from the line
// now we need to now check the letter and see whether it is an "i" or a "d"
// use sting compare (it returns a 0 if the letter is equal to what we are checking)
if (strcmp(letter, "i") == 0){ // This checks the letter and if it is "i", we are going to be inserting a node
// need to create the new node to be inserted and assign the number value to it.
int x;
x = atoi(number); // converts the string input into a integar
Insert(root, x); // method which inserts the input onto the linked list.
}
if (strcmp(letter, "d") == 0){ // This checks the letter and if it is "d", we are going to be deleting a node
}
}
printlist(root);
fclose(file);
}
I assume that values does not repeated.
struct node
{ // creation of node structure
int data; // data inside node
struct node *next; // address to the next node int the list
};
//insertion in last
int insertNode(node **root, node *data)
{
if(!data) return 0;
//check if root available. if not data will be the root
if(!*root)
{
*root = data;
data->next = NULL;
return 1;
}
node *temp = *root;
while(temp->next)
{
temp = temp->next;
}
temp->next = data;
return 1;
}
//deletion. if multiple ocures first will delete
int deleteNode(node **root, int num)
{
if(!root) return 0;
node *temp = *root;
if(temp->data == num)
{
if(temp->next)
{
*root = temp->next;
}
free(temp);
return 1;
}
while(temp->next)
{
node* deleteThis = temp->next;
if((temp->next->next) && temp->next->data == num)
{
//delete next
temp->next = temp->next->next;
free(deleteThis);
return 1;
}
else if(temp->next->data == num)
{
//the last node
temp->next = NULL;
free(deleteThis);
return 1;
}
temp = temp->next;
}
return 0;
}
int main(int argc, char *argv[]){
//make root node
node* root = NULL;
// if the input is more than one, error
if (argc != 2) return EXIT_FAILURE;
// argv[1] will contain the file name input.
FILE *file = fopen(argv[1], "r");
// we need to make sure the file is not empty, error case.
if (file == NULL)
{
printf("error\n");
exit(0);
}
// if the file is empty, print an empty line.
/*int size = ftell(file);
if (size == 0){
printf("\n");
}
printf("%d",size);*/
char linestring[BUFSIZ]; // this will hold our file input after we read/scan it.
// now we need to read the file
while (fgets(linestring, sizeof(linestring), file)) // reads the entire file until it hits Null
{
// printf("%s", linestring); // stores each line into linestring.
// need to split up the lines so that we separate letters from integars.
// look for \t or " " and use strtok.
char* letter = strtok(linestring, " \t\n"); // stores the letter from the line
char* number = strtok(NULL, " \t\n"); // stores the numbers from the line
//changed from here
int n =atoi(number);//convert string to int
if(*letter == 'i')
{
//creates node to be inserted
node *data = NULL;
data = (struct node*)malloc(sizeof(node));
data->data = n;
data->next = NULL;
if(!insertNode(&root,data)) //if insertion gose wrong 0 will return
printf("insert %s was faild\n", number);
}
else
{
if(!deleteNode(&root,n))
printf("Couldnt Delete (%s not in the list)\n )", number);
}
}
}
**FULL WORKING CODE IN C++ FOR REFERENCE**
#include<bits/stdc++.h>
#include<fstream>
using namespace std;
struct node{
int data;
struct node* next;
};
typedef struct node node;
typedef struct node* nodeptr;
nodeptr Create(nodeptr head,nodeptr &current,int x){
nodeptr temp = (nodeptr)malloc(sizeof(node));
temp->next=NULL;
temp->data=x;
if(current==NULL){
current=temp;
head=temp;
}
else{
current->next=temp;
current=temp;
}
return head;
}
nodeptr Delete(nodeptr head, int x){
nodeptr temp = head;
nodeptr temp1;
while(temp->data!=x){
temp1=temp;
temp=temp->next;
}
temp1->next=temp->next;
free(temp);
temp=NULL;
return head;
}
void PrintC(nodeptr head){
nodeptr temp = head;
while(temp!=NULL){
cout<<temp->data<<" ";
temp=temp->next;
}
}
int main(){
nodeptr current = NULL;
nodeptr head = current;
string str;
ofstream myfile;
myfile.open("file.txt",ios::out);
myfile << "i 1 i 2 i 3 i 4 i 5 d 2 d 3";
myfile.close();
ifstream myfile1("file.txt");
getline(myfile1,str);
myfile1.close();
int i=0;
while(str[i]!='\0'){
if(str[i]!=' '){
if(str[i]=='i'){
int n = str[i+2]-48;
head=Create(head,current,n);
i=i+2;
}
else if(str[i]=='d'){
int n = str[i+2]-48;
head = Delete(head,n);
i=i+2;
}
}
i++;
}
cout<<endl;
PrintC(head);
return 0;
}

Resources