So this program is supposed to create a linked list for a car with the information of the year, Safety Rating, and Model. However when outputting the safety rating, say if the user enters "5", the program outputs it as some very large number that isn't what the user entered.
Example: If the user enters
Enter Year for Car: 1992
Enter Rating for Car (0.00 - 100.00): 25.5
Enter Model for Car: Chevy
The program output is...
The Cars in the List Are As Follows:
Year:1992 Rating:79960111893652368676401906121179136.00 Model:Chevy
When it should be....
The Cars in the List Are As Follows:
Year:1992 Rating:25.50 Model:Chevy
What am I doing wrong? Here is my full code...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 400
struct car {
int year;
float safeRating;
char model[MAXSIZE];
struct car *next;
};
typedef struct car Car;
typedef struct car *CarPtr;
void menu();
void printList(CarPtr);
CarPtr makeCar(int, float, char *);
CarPtr removeCar(CarPtr, int);
CarPtr addCar(CarPtr sPtr, int infoA, float infoB, char *infoC);
void viewCar(CarPtr sPtr, int infoA, float infoB, char *infoC);
int main()
{
CarPtr startPtr;
int infoA, choice;
float infoB;
char infoC;
startPtr = NULL;
menu();
scanf("%d", &choice);
while (choice != 5){
switch (choice){
case 1: printf("\nEnter Year for Car: ");
scanf("%d", &infoA);
printf("\nEnter Rating for Car (0.00 - 100.00): ");
scanf("%f", &infoB);
printf("\nEnter Model for Car: ");
scanf("%s", &infoC);
startPtr = addCar(startPtr, infoA, infoB, &infoC);
printList(startPtr);
printf("\n");
break;
case 2: printf("\nEnter Car for deletion : ");
scanf("%d", &infoA);
startPtr = removeCar(startPtr, infoA);
printList(startPtr);
printf("\n");
break;
case 3: printf("\nEnter Car Number to View : ");
scanf("%d", &infoA);
viewCar(startPtr, infoA, infoB, &infoC);
printf("\n");
break;
case 4: printList(startPtr);
printf("\n");
break;
default: printf ("Invalid Option... Please Try Again \n");
break;
}
menu();
scanf("%d", &choice);
}
return 0;
}
void menu()
{
printf ("\t1: Insert Car into Ordered List\n");
printf ("\t2: Remove Car from List\n");
printf ("\t3: View Car from List\n");
printf ("\t4: Printing the List\n");
printf ("\t5: Exit\n");
printf ("\tEnter Choice: ");
}
CarPtr makeCar(int infoA, float infoB, char *infoC)
{
CarPtr np = (CarPtr) malloc(sizeof(Car));
np->year = infoA;
np->safeRating = infoB;
strcpy(np->model, infoC);
np->next = NULL;
return np;
}
void printList(CarPtr sPtr)
{
if(sPtr == NULL){
printf ("\nThere are no Cars to be Printed\n");
}
else {
printf("The Cars in the List Are As Follows Sorted by Year: \n");
while (sPtr != NULL) {
printf("Year:%d Rating:%.2f Model:%s\n", sPtr->year, sPtr->safeRating, sPtr->model);
sPtr = sPtr->next;
}
}
}
CarPtr addCar(CarPtr sPtr, int infoA, float infoB, char *infoC)
{
CarPtr newPtr, currPtr, prevPtr;
newPtr = makeCar(infoA, infoB, infoC);
prevPtr = NULL;
currPtr = sPtr;
while (currPtr != NULL && infoA > currPtr->year) {
prevPtr = currPtr;
currPtr = currPtr->next;
}
if (prevPtr == NULL) { // inserting at the start of the list
newPtr->next = sPtr;
sPtr = newPtr; // start of list has now changed
}
else {
newPtr->next = currPtr;
prevPtr->next = newPtr;
}
return sPtr;
}
CarPtr removeCar(CarPtr sPtr, int infoA)
{
CarPtr previousPtr, currentPtr, tempPtr;
previousPtr = NULL;
currentPtr = sPtr;
if(sPtr == NULL){
printf ("\nThe List is empty... No cars to be Removed\n");
return sPtr;
}
while (currentPtr != NULL && currentPtr->year != infoA) {
previousPtr = currentPtr;
currentPtr = currentPtr->next;
}
if(currentPtr == NULL){
printf("\nCar ( %d ) was not found \n", infoA);
}
else if (previousPtr == NULL){ // if node to be deleted is the first node
tempPtr = sPtr;
sPtr = sPtr->next; // start of list has been changed
printf("\nCar ( %d ) was deleted \n", tempPtr->year);
free(tempPtr);
}
else{
tempPtr = currentPtr;
previousPtr->next = currentPtr->next;
printf("\nCar ( %d ) was deleted \n", tempPtr->year);
free(tempPtr);
}
return sPtr;
}
void viewCar(CarPtr sPtr, int infoA, float infoB, char *infoC)
{
CarPtr previousPtr, currentPtr;
previousPtr = NULL;
currentPtr = sPtr;
int position = 0;
if(sPtr == NULL){
printf ("\nThe List is empty... No cars to View\n");
return;
}
while (currentPtr != NULL && currentPtr->year != infoA) {
previousPtr = currentPtr;
currentPtr = currentPtr->next;
position++;
}
if(currentPtr == NULL){
printf("\nCar ( %d ) was not found \n", infoA);
}
else{
printf("\nCar ( %d ) Rating: %.2f Model: %s was found at position : %d\n", currentPtr->year, currentPtr->safeRating, currentPtr->model, (position + 1));
}
}
You're not allocating any space for the car model string. You're scanf("%s", &infoC);, but infoC is a single char, there's no space for a string. That's overwriting something and probably mucking with things. Then you go strcpy when you make your car, that will copy until it hits a NULL byte. ,, etc, etc, ,, UB. Best to define it as char infoC[MAXSIZE] to match what you have in struct car.
Related
I was asked to make a hash table program which input name and age. I declared name and age as char. While doing the search function, I need to print the name and the age but the age do not print. What is wrong with my code?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
int n;
int count;
struct data
{
char name [100];
char age[5];
struct data *next;
};
struct data *chain[100000];
struct data* insert(char name[], char age[]){
struct data *curr = (struct data*) malloc (sizeof(data));
strcpy(curr->name, name);
strcpy(curr->age, age);
curr->next = NULL;
return curr;
};
//hash function
int hashing(char name[]){
int first = name[0];
return first % n;
}
//buat tau di index ke x dia data ke brp
void add(struct data *newNode){
int hash = hashing(newNode->name);
printf("index->%d\n", hash);
if(chain[hash] == NULL){
chain[hash] = newNode;
}
else
{
struct data *temp = chain[hash];
while(temp->next != NULL){
temp = temp->next;
//count++;
}
count++;
temp->next = newNode;
//count++;
}
printf("data-> %d\n", count);
}
void view(){
for(int i = 0 ; i < n ; i ++)
{
int count = 0;
if(chain[i]!=NULL){
printf("=== index %d data ===\n", i );
struct data *temp = chain[i];
while(temp!=NULL){
printf("data %d\n", count);
printf("name=%s age=%s\n", temp->name, temp->age);
temp = temp->next;
count ++;
}
}
}
printf("\n");
}
void search(int hash){
char age[5];
char search[100];
printf("Search name:");
scanf(" %[^\n]s", search);
int key = hashing(search);
printf("Search data %s from index %d data....\n", search, key);
if(strcmp(chain[key]->name, search)==0){
printf("data found at node %d\n", key);
printf("name = %s age = %s\n", search, age);
}
else
{
struct data *temp = chain[key];
while(temp->next!=NULL){
if(strcmp(chain[key]->name, search)==0){
printf("data found at node %d\n", key);
printf("name = %s age = %s\n", search, age);
}
temp = temp->next;
}
if(strcmp(temp->name, search)==0 && temp->next==NULL){
printf("data found at node %d\n", key);
printf("name = %s age = %s\n", search, age);
}
else{
printf("no data found!\n");
}
}
}
//void remove(int hash){
// //int key = item->key;
// int hash = hashing(key);
// int option;
// printf("input option:");
// scanf("%d", &option);
// char search[100];
// printf("delete name:");
// scanf(" %[^\n]s", search);
// int first = search[0];
// int key = first % n;
// printf("Search data %s from index %d data....\n", search, key);
// if(chain[key]==hash){
// chain[key]=-1;
// }
// else
// {
// printf("try");
// }
//}
int main(){
char name[100];
char age[5];
printf("input the number of hash table: ");
scanf("%d", &n); getchar();
struct data *chain[n];
int chainSize[n]={0};
printf("\n");
int option;
do{
printf("=== Option Menu ===\n");
printf("1. insert data\n");
printf("2. delete data\n");
printf("3. search data\n");
printf("4. view data\n");
printf("5. exit\n");
printf("input option: ");
scanf("%d", &option); getchar();
switch(option){
case 1:{
printf("input name: ");
scanf(" %[^\n]s", name);
printf("input age: ");
scanf(" %[^\n]s", age);
add(insert(name,age));
printf("\n");
break;
}
case 2:
{
//remove();
break;
}
case 3:
{
search(n);
break;
}
case 4:
{
view();
break;
}
}
}while(option!=5);
}
the output is like this
name = hansol
age =
when it is supposed to be like this:
name = hansol
age = 23
so the age variable does not print while doing the search function
I have been getting Thread 1 : EXC_BAD_ACCESS error when trying to push a string element into the stack. I've changed the char* name to char name[21] but the assignment char[21] is not assignable to curr->name. Also I've tried fgets but the error still there. Anyone know where the error?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct parts
{
char* name;
char* type;
int quantity;
int price;
int num;
struct parts * next;
}*head,*tail,*curr,komponen;
void menu();
void show_Parts();
void push(char* nm, char* tip, int jml, int harga, int nom);
void del();
int main() {
menu();
del();
getchar();
return 0;
}
void push(char* nm, char* tip, int jml, int harga, int nom)
{
// 1.
curr = (struct parts *)malloc(sizeof(struct parts));
// 2.
if (curr == NULL) {
exit(0);
}
head = NULL;
head = curr->next;
curr->name = nm;
curr->type = tip;
curr->quantity = jml;
curr->price = harga;
curr->num = nom;
curr = head;
//
printf("Input name of the new item [3..20]: ");
scanf("%s",nm);
if (strlen(nm) < 3 || strlen(nm) > 20) {
printf("Length of name must between 3 and 20");
exit(0);
}
printf("Input type of the new item [processor/graphic card/memory]: ");
scanf("%s",tip);
if (tip != "processor" || tip != "graphic card" || tip != "memory") {
printf("Input type of existing item. Error");
exit(0);
}
printf("Input quantity of the new item [1..20]: ");
scanf("%d",&jml);
if (jml < 1 || jml > 20) {
printf("Quantity between 1 and 20\n");
exit(0);
}
printf("Input price of new item [$1..$1000]: ");
scanf("%d",&harga);
if (harga < 1 || harga > 1000) {
printf("Price between 1 and 1000\n");
exit(0);
}
nom++;
printf("--- Add New Item Success ---\n");
tail->next = NULL;
}
void del()
{
if (curr == NULL) {
exit(0);
}
curr = head;
head = head->next;
free(curr);
}
void menu()
{
int choic;
do {
printf("BLUE COMPUTER ADMINISTRATOR\n");
printf("++++++++++++++++++++++++++++\n");
printf("1. Item list\n");
printf("2. Add <PUSH> New item\n");
printf("3. Exit\n");
printf(">> Input your choice : ");
switch (choic) {
case 1:
show_Parts();
break;
case 2:
push(komponen.name,komponen.type,komponen.price, komponen.quantity, komponen.num);
break;
case 3:
del();
exit(0);
break;
}
scanf("%d",&choic);
} while (choic != 3);
}
void show_Parts()
{
if (curr == NULL) {
printf("No item in list\n");
exit(0);
}
printf(" ---- ITEM LIST ---- \n\n");
printf("-----+------------------+--------+-----------+--------\n");
printf("|No. | Name | Type | Quantity | Price|\n");
do {
printf("|%d |%s |%s |%d |%d \n",curr->num, curr->name, curr->type, curr->quantity, curr->price);
curr = curr->next;
}while (curr != NULL);
}
Thanks.
I'm reading in from a text file likewise:
George Washington, 2345678
John Adams, 3456789
Thomas Jefferson, 4567890
James Madison, 0987654
James Monroe, 9876543
John Quincy Adams, 8765432
Andrew Jackson, 7654321
Martin Van Buren, 6543210
William Henry Harrison, 5432109
John Tyler, 4321098
The function to delete the name works, however when it is successful the printf statements just continue to loop in the command window. I tried using a break statement at the end of the loop, however that only led to saying that the name wasn't found. Can someone offer any insight?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Creates node for holding student's information
struct node
{
char name [50];
int id;
struct node *next;
}*head;
//Create Function Prototypes
void readDataFile ();
void insert(char *inName, char *inID);
void display(struct node *d);
int deleteID(int num);
void deleteName(char *delete_name);
//Main function
int main()
{
//Declare variables
int i, num, delete_id, id;
char *name;
char nameDelete [50];
char nameInsert [50];
struct node *n;
//initialize link list
head = NULL;
//Read in file
readDataFile();
//Create list of operations utilized in program
while (1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Delete by ID\n");
printf("4.Delete by Name\n");
printf("5.Exit\n");
printf("Enter your choice : ");
if(scanf("%d", &i) <= 0)
{
printf("Enter only an Integer\n");
exit(0);
}
else
{
switch(i)
{
case 1:
getchar();
printf("Enter the name to insert:");
scanf("%[^\n]s", nameInsert);
printf("\nEnter the ID associated with the name: ");
scanf("%d", &id);
break;
case 2:
if (head == NULL)
printf("List is Empty\n");
else
{
printf("Elements in the list are:\n");
}
display(n);
break;
case 3:
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter the ID number to delete: ");
scanf("%d", &delete_id);
}
if(deleteID(delete_id))
printf("%d deleted successfully \n", delete_id);
else
printf("%d not found in the list\n", delete_id);
break;
case 4:
getchar();
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter name to delete: ");
scanf("%[^\n]s", nameDelete);
printf("Checking for name %s...\n", nameDelete);
printf("%s not found in the list\n", nameDelete);
deleteName(nameDelete);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
//Define the functions
//Function to delete by name
void deleteName(char *delete_name)
{
//Create temporary and helper node
struct node *temp, *helper;
//Set temp equal to head
temp = head;
//Loop until the end of the list
while(temp != NULL)
{
if(strcmp(temp->name, delete_name) == 0)
{
if(temp == head)
{
head = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
}
else
{
helper->next = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
}
}
else
{
helper = temp;
temp = temp->next;
}
}
break;
}
Please learn how to make an MCVE (How to create a Minimal, Complete, and Verifiable Example?) or SSCCE (Short, Self-Contained, Correct Example) — two names and links for the same basic idea.
Here's an MCVE derived from your code. I added the missing break; or return; from the loop in deleteName(). I rewrote main() essentially completely, but it works cleanly:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char name[50];
int id;
struct node *next;
} *head;
void deleteName(char *delete_name);
int main(void)
{
struct node *n;
head = NULL;
head = malloc(sizeof(*head));
assert(head != 0);
strcpy(head->name, "Abraham Lincoln");
head->id = 1;
head->next = 0;
n = malloc(sizeof(*n));
strcpy(n->name, "George Washington");
n->id = 2;
n->next = head;
head = n;
n = malloc(sizeof(*n));
strcpy(n->name, "John Adams");
n->id = 3;
n->next = head;
head = n;
deleteName("George Washington");
deleteName("John Adams");
deleteName("Abraham Lincoln");
return 0;
}
void deleteName(char *delete_name)
{
struct node *temp, *helper = 0;
temp = head;
while (temp != NULL)
{
if (strcmp(temp->name, delete_name) == 0)
{
if (temp == head)
{
head = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
}
else
{
helper->next = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
}
return; // The key change!
}
else
{
helper = temp;
temp = temp->next;
}
}
}
This ran cleanly under valgrind and Mac OS X 10.10.2 with GCC 4.9.1.
Found George Washington!
George Washington deleted successfully
Found John Adams!
John Adams deleted successfully
Found Abraham Lincoln!
Abraham Lincoln deleted successfully
It is important to learn how to be brutal about stripping out irrelevant code when creating an MCVE.
The break keyword will break out of the nearest switch or loop. Therefore, you can try this:
while(temp != NULL)
{
if(strcmp(temp->name, delete_name) == 0)
{
if(temp == head)
{
head = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
break;
}
else
{
helper->next = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
break;
}
}
else
{
helper = temp;
temp = temp->next;
}
}
An alternate solution is to set temp to NULL after you free it (this is good practice anyway, so that might be another idea)
Add the return statement at the end of the if block once you have found the name to be deleted
void deleteName(char *delete_name)
{
//Create temporary and helper node
struct node *temp, *helper;
//Set temp equal to head
temp = head;
//Loop until the end of the list
while(temp != NULL)
{
if(strcmp(temp->name, delete_name) == 0)
{
if(temp == head)
{
head = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
}
else
{
helper->next = temp->next;
free(temp);
printf("Found %s!\n", delete_name);
printf("%s deleted successfully\n", delete_name);
}
return;
}
else
{
helper = temp;
temp = temp->next;
}
}
}
Also you how are planning to indicate that the name isn't part of the list, as opposed to being found and deleted. You can change modify the function such that it returns an error code when it hasn't found the name in the list, which is then used to indicate the name was never in the list to begin with.
I did not really look at the delete() function,
however, the following code illustrates how the
code should be formatted, etc.
notice the checking for input errors, which should always be performed
notice the separation of the struct definition from the struct declaration
notice the easy readability of the switch cases
by incorporating some vertical white space
notice the simple comments after the closing braces
notice that no call to an action is performed if the linked list is empty
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//define node for holding student's information
struct node
{
char name [50];
int id;
struct node *next;
};
// create head pointer for linked list of student info
// and initialize
struct node *head = NULL;
// Function Prototypes
// note: if all these functions are only accessed within this file
// then they should be declared with the 'static' modifier
void readDataFile (void);
void insert (char *inName, char *inID);
void display (struct node *d);
void deleteID (int delete_ID);
void deleteName (char *delete_name);
//Main function
int main()
{
//Declare local variables
// notice use of meaningful names
// notice, for readability and documentation,
// only one variable declared per line
int i; // receives user menu selection input
int idDelete;
int idInsert;
char nameDelete [50];
char nameInsert [50];
// struct node *n; // unused variable
int done = 0; // used to exit when user enters '5'
//Read in file
readDataFile();
//Create list of operations utilized in program
while (!done)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Delete by ID\n");
printf("4.Delete by Name\n");
printf("5.Exit\n");
printf("Enter your choice : ");
if( 1 != scanf("%d", &i) )
{ // then, scanf failed
perror( "scanf for choice failed");
exit( EXIT_FAILURE );
}
// implied else, scanf successful
switch(i)
{
case 1:
int ch;
while(EOF != (ch = getchar()) && (ch != '\n'));
printf("Enter the name to insert:");
if( 1 != (scanf("%[^\n]s", nameInsert) ) )
{ // then scanf failed
perror( "scanf for new student name failed");
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("\nEnter the ID associated with the name: ");
if( 1 != (scanf("%d", &idInsert) ) )
{ // then scanf failed
perror( "scanf for new student ID failed");
exit( EXIT_FAILURE );
}
// implied else, scanf successful
insert( nameInsert, idInsert );
break;
case 2:
if (head == NULL)
printf("List is Empty\n");
else
{
printf("Elements in the list are:\n");
display(n);
} // end if
break;
case 3:
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter the ID number to delete: ");
if( 1 != (scanf("%d", &idDelete) ) )
{ // then, scanf failed
perror( "scanf for ID to delete failed");
exit( EXIT_FAILURE );
}
// implied else, scanf successful
deleteID(idDelete);
} // end if
break;
case 4:
int ch;
while(EOF != (ch = getchar()) && (ch != '\n'));
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter name to delete: ");
if( 1 != (scanf("%[^\n]s", nameDelete) ) )
{ // then, scanf failed
perror( "scanf for name to delete failed");
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Checking for name %s...\n", nameDelete);
deleteName(nameDelete);
} // end if
break;
case 5:
done = 1; // this will cause while() loop to exit
break;
default:
printf("Invalid option\n");
break;
} // end switch
} // end while
return 0;
} // end of function: main
I added a "search" function for my linked list menu and I don't know what is wrong in my code. When I enter a search key which is a name that is not in the list, instead of printing the "Search Key: %s Not Found!", the program will just stop. How to fix it? Any suggestion on how can I improve my program?
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct list
{
char name[20];
int age;
char gender[10];
struct list *next;
};
void main(void)
{
struct list *HEAD = NULL;
struct list *temp,*current, *trav;
struct list *prev,*temp1,*temp2;
char choice;
while(1)
{
clrscr();
printf("MENU\n");
printf("A) ADD\n");
printf("B) DISPLAY\n");
printf("C) DELETE\n");
printf("D) SEARCH\n");
printf("X) EXIT\n");
scanf("%c", &choice);
switch(toupper(choice))
{
case 'A':
temp= (struct list*)malloc(sizeof(struct list));
temp->next=NULL;
printf("Fill-Up the following:\n");
printf("Name:");
fflush(stdin);
gets(temp->name);
printf("Age:");
fflush(stdin);
scanf("%d",&temp->age);
printf("Gender:");
fflush(stdin);
gets(temp->gender);
if(HEAD == NULL)
{
HEAD = temp;
}
else if(HEAD!=NULL)
{
for(trav=HEAD; trav->next != NULL; trav= trav->next);
trav->next=temp;
}
else
{
printf("Not Enough Memory!\n");
}
break;
case 'B':
if(HEAD==NULL)
{
printf("Linked List is Empty!\n");
getch();
}
else{
for(trav=HEAD; trav != NULL; trav=trav->next )
{
printf("\nName: %s\n", trav->name);
printf("Age: %d\n", trav->age);
printf("Gender: %s\n\n", trav->gender);
}
getch();
}
break;
case 'C' :
temp1=( struct list*)malloc(sizeof(struct list));
temp1->next=NULL;
if(HEAD==NULL)
{
printf("No item to be delete. List is Empty!\n");
getch();
}
else {
printf("Enter The Name of the item you want to Delete: ");
fflush(stdin);
gets(temp1->name);
current=HEAD;
if(strcmp(temp1->name,current->name)== 0)
{
HEAD=HEAD->next;
free(current);
printf("Item has been successfully deleted from the list.\n");
getch();
}
else
{
for(prev=HEAD,trav=HEAD->next; strcmp(trav->name,temp1->name) == 1 ; trav=trav->next,prev=prev->next);
if(trav==NULL)
{
printf("Name: %s not found!", temp1->name);
getch();
}
else{
prev->next=trav->next;
free(trav);
printf("Item has been successfully deleted from the list.\n");
getch();
}
}
}
break;
case 'D':
temp2=( struct list*)malloc(sizeof(struct list));
temp2->next=NULL;
if(HEAD==NULL)
{
printf("No item to search. List is Empty.\n");
getch();
}
else{
printf("Enter Name (Search Key): ");
fflush(stdin);
gets(temp2->name);
int count=0;
struct list *trav2=HEAD;
while( trav2 !=NULL)
{
for(struct list *trav1=trav2; strcmp(trav1->name,temp2->name)!=0;trav1=trav1->next);
if(trav1!=NULL)
{
printf("\nName: %s\n", trav1->name);
printf("Age: %d\n", trav1->age);
printf("Gender: %s\n",trav1->gender);
trav2=trav1->next;
count++;
}
else {
trav2=NULL;
}
}
getch();
if(count==0)
{
printf("Search Key: %s Not Found!\n", temp2->name);
getch();
}
}
break;
case 'X':
if(HEAD!=NULL){free(HEAD); }
if(trav!=NULL){ free(trav); }
if(trav1!=NULL){ free(trav1); }
if(trav2!=NULL){ free(trav2); }
if(temp!=NULL){ free(temp); }
if(temp1!=NULL){ free(temp1); }
exit(1);
break;
}
}
}
In your search routine..
for(struct list *trav1=trav2; strcmp(trav1->name,temp2->name)!=0;trav1=trav1->next);
here trav1 will be null at the end of list but you are still going ahead and derefrencing it.
Add a check temp1 in your for loop like this:
for(struct list *trav1=trav2; trav1 && (strcmp(trav1->name,temp2->name)!=0);trav1=trav1->next);
Or, for better readability:
for (struct list *trav1 = trav2; trav1 != NULL; trav1 = trav1->next)
{
if (strcmp(trav1->name, temp2->name) !=0 )
break;
}
A few other comments on your code:
Do not use fflush(stdin) use something like this since that is not guaranteed by the standard to work.
int c;
while ((c = getchar()) != EOF && c != '\n')
;
Stop using gets(). It is impossible to use gets() safely. Use fgets() instead (but be aware it keeps the newline where gets() discards it).
Your loop continues while while( trav2 !=NULL). But where do you set trav2 = trav2->next? Without that, you loop will just continue forever.
But your code seems to have more problems than just that. Why are you allocating a new list item? Just declare a pointer to a list item (struct list*) and then point it to the head of your list.
for (temp = HEAD; temp != NULL; temp = temp->next)
{
// Examine temp for the value you are looking for
}
I suspect you are still new to understanding pointers. That is key to getting this code working right.
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?