I am having issues searching a linked list in C. I manage to search and find an integer entry but am having problems with strings (first and last names). Basically, there are three functions that search a telephone directory for entries by first, last name and number. Would it be possible to display the entry when a search is found too? Please find the code below. Thanks for your help.
struct node {
char firstname[32];
char lastname[32];
int *number;
struct node *next;
}*head;
struct node *start=NULL;
struct node *getnode() {
return((struct node *)malloc(sizeof(struct node)));
}
void insert() {
struct node *temp,*nn;
nn=getnode();
temp=start;
while(temp->next!=NULL)
{
temp=temp->next;
}
printf("Enter First name:\n");
scanf("%s",&nn->firstname);
printf("Enter Last name:\n");
scanf("%s",&nn->lastname);
printf("Enter number:\n");
scanf("%d",&nn->number);
temp->next=nn;
nn->next=NULL;
display(start);
}
struct node *create() {
struct node *temp,*nn;
if(start!=NULL) insert();
else {
nn=getnode();
start=nn;
temp=start;
printf("Enter First name:\n");
scanf("%s",&nn->firstname);
printf("Enter Last name:\n");
scanf("%s",&nn->lastname);
printf("Enter number:\n");
scanf("%d",&nn->number);
nn->next=NULL;
}
}
void searchByFirstName() {
char *f;
struct node* temp, *nn;
temp = start;
while (temp != NULL){
printf("Enter First Name to be searched:\n"); scanf("%s",&f);
printf("%s", &f);
if (temp -> firstname == f){
printf ("\n Record Found!\n");
temp = temp -> next;
}else{
printf ("\n Record not found\n");
}
}
}
void searchByLastName() {
char *f;
struct node* temp, *nn;
temp = start;
if (temp != NULL){
printf("Enter Last Name to be searched:\n"); scanf("%s",&f);
printf("%s", &f);
if (temp -> lastname == f){
printf ("\n Record Found!\n");
temp = temp -> next;
}else{
printf ("\n Record not found\n");
}
}
}
void searchByNumber() {
int *l;
struct node* temp, *nn;
temp = start;
if (temp != NULL){
printf("Enter Number to be searched:\n"); scanf("%d",&l);
if (temp -> number == l){
printf ("\n Record Found!\n");
temp = temp -> next;
}else{
printf ("\n Record not found\n");
}
}
}
In C, you cannot just compare two strings (aka char *) using operator ==. When you work with strings in C, you can use the standard functions (#include <string.h>), like:
strcmp(temp->lastname, f) // returns 0 in case of a perfect match
2nd EDIT: added Pretty functions (last section) - examples of how printing messages could be modified.
EDIT: added free(l) in the searchByNumber2(), fixing a memory leak
For the thing you was asking for:
void searchByLastName() {
char f = char[32];
struct node* temp, *nn;
temp = start;
printf("Enter Last Name to be searched:\n"); scanf("%s",f);
printf("%s", f);
while (temp != NULL){//!we search through whole list
if (strcmp(temp -> lastname, f) == 0) {
printf ("\n Record Found!\n");
temp = temp -> next;
}else{
printf ("\n Record not found\n");
/*!you probably wanna pull this printf for after the loop;
I would either add bool Found and add if after the loop
or after the loop always print "search finished" or sth */
}
}
}
And two versions of fixed searching by numbers (the second uses int *l, as an example; the first uses int l and is cleaner)
void searchByNumber() {
int l;
struct node* temp, *nn;
temp = start;
printf("Enter Number to be searched:\n"); scanf("%d",&l);//&l is address of the int l
while (temp != NULL){
if (*(temp -> number) == l){//notice: temp->number is a pointer to int, not an int itself, l is an int here
printf ("\n Record Found!\n");
temp = temp -> next;
}else{
printf ("\n Record not found\n");
}
}
}
void searchByNumber2() {
int *l = malloc(sizeof int);
struct node* temp, *nn;
temp = start;
printf("Enter Number to be searched:\n"); scanf("%d",l);
while (temp != NULL){
if (*(temp -> number) == *l){//we want to compare int values, not their adresses, both temp->number and l are pointers here
printf ("\n Record Found!\n");
temp = temp -> next;
}else{
printf ("\n Record not found\n");
}
}
free(l);
}
Last edit
Note: this version of searchByLastNamePretty prints Found message the number of times the last name appears, and prints Finished message after a search.
On th other hand, searchByNumberPretty prints a Found message or a Not-Found message (only one message, always; doesn't matter if there is a lot of occurences of the number).
Use them as examples of what you could do. Analyze usage of bool Found.
void searchByLastNamePretty() {
char f = char[32];
struct node* temp, *nn;
temp = start;
printf("Enter Last Name to be searched:\n"); scanf("%s",f);
printf("%s\n", f); //better practice, to end printf with \n to flush it
while (temp != NULL){//!we search through whole list
if (strcmp(temp -> lastname, f) == 0) {
printf ("Record Found!\n");
temp = temp -> next;
}
printf("Search finished\n");
}
}
void searchByNumberPretty() {
int l;
struct node* temp, *nn;
temp = start;
printf("Enter Number to be searched:\n");
scanf("%d",&l);//&l is address of the int l
bool found = false;
while (temp != NULL && !found){//!we search till the first occurence
if (*(temp -> number) == l){//note: (temp->number) is a pointer to int, not an int
found = true;
temp = temp -> next;
}
}
if (found) {
printf("Record Found!\n");
}
else {
printf("Record not found\n");
}
}
Related
I am trying to build a simple linked list.
I have successfully built a linked list only with int variables but when I add *char variables the output is wrong.
The int values seem to be correct but the *char type are wrong.
The *char type seem to always be the last one inserted.
Sample Input
Number: 5
Character: a
Number: 4
Character: b
Sample Output
5
b
**************
4
b
#include <stdio.h>
#include <stdlib.h>
typedef struct BOOKS
{
int value;
char *char_value;
struct BOOKS *next;
} BOOKS;
BOOKS *insert_value(BOOKS *node, int n, char *char_value);
BOOKS *read_list(BOOKS *head);
int main()
{
int aux = 0;
int menu = 0;
int option;
BOOKS *head = NULL;
BOOKS *tail = NULL;
while (menu != -2)
{
int choices;
printf("1. Insert Book\n");
printf("2. Print Books\n");
printf("3. Exit\n");
scanf("%d", &choices);
switch (choices)
{
case 1:
{
int n;
char char_value[2000] = "";
printf("Number:");
scanf("%d", &n);
printf("Character: ");
scanf("%s", &char_value);
if (aux == 0)
{
/*FIRST INTERACTION*/
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
aux = 1;
}
else
{
tail->next = malloc(sizeof(BOOKS));
/*FORMING TAIL->NEXT*/
tail->next = insert_value(tail->next, n, char_value);
/*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
tail = tail->next;
}
break;
}
case 2:
{ /*READ THE LIST*/
read_list(head);
break;
}
case 3:
{
menu = -2;
break;
}
default:
printf("Invalid choice\n");
break;
}
}
}
BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
node->value = n;
node->char_value = char_value;
node->next = NULL;
return node;
}
BOOKS *read_list(BOOKS *head)
{
BOOKS *a = head;
while (a != NULL)
{
printf("%d\n", a->value);
printf("%s\n", a->char_value);
printf("\n********************\n");
a = a->next;
}
}
You're passing char_value from main to your insert_books function, and then saving this pointer in your newly created node. The address of char_value from main doesn't change, so you're saving the same address to each node you create. Since all these pointers point to the same place, they will all read back whatever value was written there last. If you want to make a copy of string in each node, you can use (non standard) strdup or malloc more memory and use strcpy. But, it's an odd design choice you're using a character array to accept one character anyway. I recommend changing char_value in both main and struct BOOKS to char char_value;, then you can simply use equals assignment as with value to save copies of the char. Be sure to scanf a char the correct way.
A couple of other things:
As written, you can change scanf("%s", &char_value); to scanf("%s", char_value);. char_value is a character array, which decays to a char* in this context, there's no need to specify the address of char_value.
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
This is a memory leak. You're allocating separate memory for head and tail, but then setting both pointers equal to the memory allocated for tail (the return value of insert_value). The memory allocated for head is never freed nor used.
This will help with the errors:-
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct BOOKS
{
int value;
char char_value[2000];
struct BOOKS *next;
} BOOKS;
BOOKS *insert_value(BOOKS *node, int n, char *char_value);
BOOKS *read_list(BOOKS *head);
int main()
{
int aux = 0;
int menu = 0;
int option;
BOOKS *head = NULL;
BOOKS *tail = NULL;
while (menu != -2)
{
int choices;
printf("1. Insert Book\n");
printf("2. Print Books\n");
printf("3. Exit\n");
scanf("%d", &choices);
switch (choices)
{
case 1:
{
int n;
char char_value[2000];
printf("Number:");
scanf("%d", &n);
printf("Character: ");
scanf("%s", char_value);
if (aux == 0)
{
/*FIRST INTERACTION*/
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
aux = 1;
}
else
{
tail->next = malloc(sizeof(BOOKS));
/*FORMING TAIL->NEXT*/
tail->next = insert_value(tail->next, n, char_value);
/*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
tail = tail->next;
}
break;
}
case 2:
{ /*READ THE LIST*/
read_list(head);
break;
}
case 3:
{
menu = -2;
break;
}
default:
printf("Invalid choice\n");
break;
}
}
}
BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
node->value = n;
int size = sizeof(char_value)/sizeof(char);
strncpy(node->char_value, char_value, size);
node->next = NULL;
return node;
}
BOOKS *read_list(BOOKS *head)
{
BOOKS *a = head;
while (a != NULL)
{
printf("%d\n", a->value);
printf("%s\n", a->char_value);
printf("\n********************\n");
a = a->next;
}
}
I need to make a function that removes elements of a linked list (elements of the list are words) that contain a letter the user inputs. Basically, I have a .txt file that has random words in it, after loading the words into the linked list, I need to make several functions (this post is only dedicated for the 4th function from the menu), one of which is the function I'm having trouble with.
My idea was to make a separate function that will send 1 if the word contains the letter and 0 if it does not, then I made a function that goes through my linked list and using the first function checks if that element of the list contains the word, if it does then I remove it and move onto the next element.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Element Element;
struct Element
{
char word[50];
Element *next;
};
Element *load_file(Element *head)
{
char file[500];
scanf("%s", file);
Element *temp = head;
FILE* fp = fopen(file, "r");
if(fp == NULL)
{
printf("Error while loading file.");
return 0;
}
while(!feof(fp))
{
Element *newE = (Element*)malloc(sizeof(Element));
fscanf(fp, "%s", newE->word);
newE->next = NULL;
if(!temp)
{
head = temp = newE;
}
else
{
temp->next = newE;
temp = newE;
}
}
fclose(fp);
printf("\nFile loaded successfully\n");
return head;
}
int frequency(Element *head, char *word)
{
Element *temp = head;
int counter = 0;
while(temp != NULL)
{
if(strcmp(temp->word, word) == 0)
{
counter++;
}
temp = temp->next;
}
return counter;
}
int contains(char word[], char letter)
{
int end = strlen(word);
int flag = 0;
for(int i = 0; i < end-1; i++)
{
if(letter == word[i])
{
flag = 1;
break;
}
}
return flag;
}
Element *delete_word(Element *head, char letter)
{
Element *temp = head;
Element *before = NULL;
Element *newHead = head;
while(temp != NULL)
{
if(contains(temp->word, letter))
{
if(before == NULL)
{
newHead = temp->next;
free(temp);
temp = newHead;
}
else
{
before->next = temp->next;
free(temp);
temp = before->next;
}
}
else
{
before = temp;
temp = temp->next;
}
}
return newHead;
}
void printElement(Element *element)
{
printf("%s \n", element->word);
}
void printList(Element *head)
{
Element *temp = head;
while(temp != NULL)
{
printElement(temp);
temp = temp->next;
}
}
void meni()
{
printf("************** MENI **************\n");
printf("1. Loading text from file \n");
printf("2. Print all elements of the list \n");
printf("3. Frequency of a certain word \n");
printf("4. Delete words that contain a letter \n");
printf("5. Load the list into a file \n");
printf("6. Exit \n\n");
}
int main()
{
Element *head = NULL;
int option;
while(1)
{
meni();
scanf("%d", &option);
switch(option)
{
case 1:
{
printf("Input a name of the file: \n");
head = load_file(head);
break;
}
case 2:
{
printList(head);
break;
}
case 3:
{
char word[100];
printf("Input a word: ");
scanf("%s", word);
int num = frequency(head, word);
printf("%d\n", num);
break;
}
case 4:
{
char word[100];
printf("Input a word: ");
scanf("%s", word);
head = delete_word(head, word);
printList(head);
break;
}
case 5:
{
}
case 6:
{
return 0;
}
}
}
return 0;
}
For some reason, it makes no changes on the list whatsoever.
Your delete_word() function is declared as:
Element *delete_word(Element *head, char letter);
But you call it with a char*:
char word[100];
head = delete_word(head, word);
The menu option says Delete words that contain a letter but when the user selects that option, he/she is instructed to Input a word: (confusing).
You then send the address of the first char in word to the function. From that address one char is picked. It'll be random at best and it will most probably corrupt the stack (since you, by picking one char only, probably pick 1 byte out of 4 or 8).
You could make it work like this:
case 4:
{
char word[100];
printf("Input characters: ");
if(scanf("%s", word)==1) {
int len = strlen(word);
for(int i=0; i<len; ++i) {
head = delete_word(head, word[i]);
}
}
printList(head);
break;
}
This would allow the user to enter some characters and all words containing any of those would be removed.
I am trying to print out the results of the linked list in the reverse order that they were entered in. The program takes 3 inputs, Song name, song length (in seconds) and copyright. The program should take the list of songs and print the in the reverse order that they were entered in.
I am not too familiar with linked list. This is my first time using it as sort of a database.
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//defining struct
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//defining prototypes
node *create(int n);
void display(node *head);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
//fgets(temp->songName, 20, stdin);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display(node *head)
{
node *p = NULL;
if (head == NULL)
{
printf("List is empty\n");
}
else
{
p = head;
while (p != NULL)
{
printf("Song: %s, ", p->songName);
printf("%d minutes, ", p->songLength);
if (p->copyright == 1)
{
printf("Copyrighted\n");
}
else if (p->copyright == 0)
{
printf("No copyright\n");
}
p = p->next;
}
}
}
So if Input the following:
Song 1 - All Star (song name), 237 (seconds), 0 (no copyrights)
song 2 - Crab Rave, 193, 0
song 3 - 7 rings, 185, 1(copyrights)
The output should be:
7 rings, 185, 1
Crab Rave, 193, 0
All Star, 237, 0
If you have a single (forward) linked list, the probably easiest way to print it in reverse order is using recursion:
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
...
}
Recursion means that a function is calling itself (until some end-condition, the anchor, is reached).
By that way, program flow will build up a "stack" of display_recursive- function calls, with the first node, then the second node, ..., until it reaches the last node; by then, recursion stops, and the print part of display_recursive is handled, starting with the last node backwards.
Hope this explanation helps; Try it out in the debugger to see what happens.
I can't figure out why my code breaks. Every thing works, except when I try to reverse the linked list. It "stops working." (This function; void reverseList(struct produceItem** inHead)) Any ideas? I've been stuck on this for some time now. I think the issue might be that it doesn't read a NULL some where, but I cannot figure it out.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
struct produceItem{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct produceItem *next;
};
struct produceItem* append(struct produceItem *inHead, char *nextProduce, char *nextType, char *nextSoldBy, char *nextPrice, char *nextQuantityInStock){
struct produceItem *temp;
temp =(struct produceItem *)malloc(sizeof(struct produceItem));
strcpy(temp->produce, nextProduce);
strcpy(temp->type, nextType);
strcpy(temp->soldBy, nextSoldBy);
temp->price = atof(nextPrice);
temp->quantityInStock = atoi(nextQuantityInStock);
if(inHead == NULL){
inHead = temp;
temp->next = NULL;
}
else{
temp->next = inHead;
inHead = temp;
}
return inHead;
}
struct produceItem* readData(struct produceItem *inHead){
const char comma[2] = ",";
char *produceTemp;
char *typeTemp;
char *soldByTemp;
char *priceTemp;
char *quantityInStockTemp;
char dataLine[100];
char fileName[] = "AssignmentTwoInput.txt";
FILE *inputFile;
printf("\nFile %s has been read.\n\n", fileName);
inputFile = fopen(fileName, "r");
if( inputFile == NULL){
printf("%sList Does not exist\n", fileName);
return;
}
while((fgets(dataLine, 100, inputFile)) != NULL){
produceTemp = strtok(dataLine, comma);
typeTemp = strtok(NULL, comma);
soldByTemp = strtok(NULL, comma);
priceTemp = strtok(NULL, comma);
quantityInStockTemp = strtok(NULL, comma);
inHead = append(inHead, produceTemp,typeTemp,soldByTemp,priceTemp,quantityInStockTemp);
}
fclose(inputFile);
return inHead;
}
void display(struct produceItem *inHead){
int i = 1;
if(inHead == NULL){
printf("List does not exist.\n");
return;
}
printf("=========================================================================\n");
printf("Item # Produce Type Sold By Price In Stock\n");
printf("==========================================================================\n");
for(i=1; i<27; i++){
//while(inHead != NULL){
printf("\n%5d", i);
printf(" %-12s ", inHead->produce);
printf("%-16s ", inHead->type);
printf("%-16s ", inHead->soldBy);
printf("%3.2f ", inHead->price);
printf("%8d", inHead->quantityInStock);
inHead = inHead->next;
//i++;
}
printf("\n\n");
}
exportData(struct produceItem *n){
char fileName[] = "AssignmentTwoOutput.txt";
FILE *exportFile;
int i =1;
if(n == NULL){
printf("List does not exist.\n");
return;
}
exportFile = fopen(fileName, "w");
//printf("hi");
fprintf(exportFile,"================================================================\n");
//printf("hi");
fprintf(exportFile,"Item# Produce Type Sold By Price In Stock\n");
fprintf(exportFile,"================================================================\n");
for(i=1; i<27; i++){
//while(n->next != NULL){
//printf("hi");
fprintf(exportFile,"\n%3d", i);
fprintf(exportFile," %-12s ", n->produce);
fprintf(exportFile,"%-15s ", n->type);
fprintf(exportFile,"%-15s ", n->soldBy);
fprintf(exportFile,"%3.2f ", n->price);
fprintf(exportFile,"%8d", n->quantityInStock);
n = n->next;
}
printf("\nYour data has been written to AssignmentTwoOutput.txt, thank you.\n\n");
fclose(exportFile);
}
//void recursiveReverse(struct node** head_ref)
//{
//struct node* first;
// struct node* rest;
/* empty list */
// if (*head_ref == NULL)
//return;
/* suppose first = {1, 2, 3}, rest = {2, 3} */
//first = *head_ref;
//rest = first->next;
/* List has only one node */
//if (rest == NULL)
//return;
/* reverse the rest list and put the first element at the end */
//recursiveReverse(&rest);
//first->next->next = first;
/* tricky step -- see the diagram */
//first->next = NULL;
/* fix the head pointer */
//*head_ref = rest;
//}
void reverseList(struct produceItem** inHead){
//printf("1");
struct produceItem* first;
struct produceItem* follow;
//printf("2");
if (*inHead==NULL){
// printf("3");
printf("List does not exist.\n");
return;}
first = *inHead;
//printf("4");
follow = first->next;
if(follow==NULL)
//printf("5");
return;
reverseList(&follow);
first->next->next = first;
first->next = NULL;
*inHead = follow;
}
int main (void){
int choice;
struct produceItem *head;
while(1){
printf("List of Operations\n");
printf("===============\n");
printf("1. Stock Produce Department\n");
printf("2. Display Produce Inventory\n");
printf("3. Reverse Order of Produce Inventory\n");
printf("4. Export Produce Inventory\n");
printf("5. Exit\n");
printf("Enter you choice: ");
scanf("%d", &choice);
if(choice <= 0 || choice > 5){
printf("Enter a valid response please: \n");
exit(0);
}
switch(choice){
case 1:
//reading from thefile
head = readData(head);
break;
case 2:
//displays the list
display(head);
break;
case 3:
//reverse the list
reverseList(&head);
break;
case 4:
exportData(head);
break;
case 5:
//Exits the operation
printf("Exiting, Thank you.");
exit(0);
break;
}
}
}
in this recursive function:
void reverseList(struct produceItem** inHead){
//printf("1");
struct produceItem* first;
struct produceItem* follow;
//printf("2");
if (*inHead==NULL){
// printf("3");
printf("List does not exist.\n");
return;}
first = *inHead;
//printf("4");
follow = first->next;
if(follow==NULL)
//printf("5");
return;
reverseList(&follow);
first->next->next = first;
first->next = NULL;
*inHead = follow;
}
This function will run recursively through the list.
Ok lets look at your code:
2 local variables (does nothing really)
code to exit if input is null (mostly for safety)
You set your local variables to the current and next node.
code to exit if this is the last node in the list.
You call your function recursively.
Note that at this stage actually nothing has happened.
This means that your processing (the lines at the end of your function) will happen in reverse order of the list. From back to front.
This seems correct for what you want to do.
Next line:
first->next->next = first;
This seems correct as it would set the next of the "following" node to point to this one. As in change the direction of the next pointer within the list.
Now you have this line:
first->next = NULL;
Remember that we said your "processing" of the nodes will happen in the reverse order. So effectively one by one you will set all your next pointers to NULL. Which I think will completely disconnect your queue completely?
The last line I understand is simply to enable you to find the new head pointer for your queue and that seems fine.
btw doing this kind of algorithm with recursion is a bad idea normally.
As you can easily cause stack overflow problems if your list is getting long.
Also if for some reason your list has a problem and it is circular then it is difficult to detect that and not cause problems.
Also generally in terms of performance this type of recursive algorithm will be slower than just a proper loop implementation.
Pseudo code to "reverse" list:
reverseList(** head)
{
current = head
prev = null
next = null
int i = 0;
while (current)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
i++;
if (i > MAX) reportError();
}
head = prev;
}
I am coding for a simple linked list , but facing a little problem. The program is like it is accepting name, age and DOB through user, and memory for it is dynamically allocated. After taking data from the user, it is searching a name, asked by user, if the name exists, it should print all the details related to it.
Here is my code-
//function declarations
struct node *initnode(char *, char *, char *);
void add(struct node *);
struct node *printnode(struct node *);
struct node *searchname(struct node *, char *);
struct node {
char name[25];
char age[10];
char dob[10];
struct node *next;
};
struct node *head = (struct node *) NULL;
struct node *initnode(char *name, char *age, char *dob1)
{
struct node *ptr;
ptr = (struct node *) malloc(sizeof(struct node));
if (ptr == NULL)
return (struct node *) NULL;
else {
strcpy(ptr->name, name);
strcpy(ptr->age, age);
strcpy(ptr->dob, dob1);
ptr->next = NULL;
return ptr;
}
}
struct node *printnode(struct node *ptr)
{
printf("Name -> %s\n", ptr->name);
printf("age -> %s \n", ptr->age);
printf("dob ->%s\n", ptr->dob);
return ptr;
}
void add(struct node *newp)
{
struct node *temp = (struct node *) malloc(sizeof(struct node));
if (head == NULL)
head = newp;
else {
for (temp = head; temp->next != NULL; temp = temp->next);
temp->next = newp;
temp = newp;
}
free(temp);
}
struct node *searchname(struct node *ptr, char *name1)
{
if (strcmp(name1, ptr->name) == 0) {
printf("\n name found \n");
printf("\n details are -\n");
printnode(ptr);
return ptr;
} else {
printf("\n name not found in the database \n");
}
}
int main()
{
char name[25];
char name1[25];
char rep;
char age[10];
char dob[10];
int i;
int flag = 1;
struct node *ptr;
do {
fflush(stdin);
while (flag != 0) {
printf("Enter name -- ");
gets(name);
for (i = 0; name[i] != '\0'; i++)
if (isdigit(name[i])) {
printf("Error in user input, name should be in alphabets\n");
flag = 1;
break;
}
else
flag = 0;
}
flag = 1;
while (flag != 0) {
printf("Enter age -- ");
scanf("%s", &age);
fflush(stdin);
for (i = 0; age[i] != '\0'; i++)
if (isalpha(age[i])) {
printf("Error in user input, age should be in numbers\n");
flag = 1;
break;
} else {
flag = 0;
}
}
flag = 1;
while (flag != 0) {
printf("Enter dob in DD/MM/YY format-- ");
scanf("%s", &dob);
fflush(stdin);
for (i = 0; dob[i] != '\0'; i++) {
if (isalpha(dob[i])) {
printf("Error in user input, dob should be in numbers\n");
flag = 1;
break;
} else
flag = 0;
}
}
flag = 1;
ptr = initnode(name, age, dob);
add(ptr);
printf("\n Do you want to continue?<Y/N>:\n ");
scanf("%s", &rep);
//rep = getchar();
}
while (rep == 'Y' || rep == 'y');
printf("\n do u want to search for a name in the database? <Y/N>:\n");
scanf("%s", &rep);
if (rep == 'Y' || rep == 'y') {
printf("Enter name you want to search-- ");
scanf("%s", &name1);
ptr = searchname(head, name1);
} else {
printf("\n goodbye \n");
}
do {
printf("\n do u want to search again? <Y/N>:\n");
scanf("%s", &rep);
if (rep == 'Y' || rep == 'y') {
printf("Enter name you want to search-- ");
scanf("%s", &name1);
ptr = searchname(head, name1);
} else {
printf("\n goodbye \n");
}
}
while (rep == 'Y' || rep == 'y');
return 0;
}
The issue is that it is searching for the first entry only and not others, can anyone help me to sort out this? I am compiling through "gcc".
At a first glance, your search function is only comparing one element, the head of the list.
After comparing one element you must go to the next element. This can either be done recursively or with a while:
Recursive use:
struct node *searchname(struct node *ptr, char *name1)
{
if (ptr==NULL) //Reached end of the list
{
printf("\n name not found in the database \n");
return NULL;
}
if (strcmp(name1, ptr->name) == 0) { //found the element
printf("\n name found \n");
printf("\n details are -\n");
printnode(ptr);
return ptr;
} else { //search next element
return searchname(ptr->next,name1); //this will call your function again for the next element on the list
}
}
While use:
struct node *searchname(struct node *ptr, char *name1)
{
struct node *aux; // usually i use an auxiliary pointer in order to avoid unwanted overwrite at my pointer.
aux = ptr;
while (aux!=NULL)
{
if (strcmp(name1, aux->name) == 0) { //found the element
printf("\n name found \n");
printf("\n details are -\n");
printnode(aux);
return aux;
}
else { //move pointer to next element
aux=aux->next;
}
}
//if it reaches this point, the element was not found
printf("\n name not found in the database \n");
return NULL;
}
Check your add function, it is wrong. Step mentally through it, and see what happens
to your pointer, and to the memory it points to.
What are the malloc and free used for in the add function?