Pointer's value changes without modifying - c

I'm studying linked list and try to implement some basic function.
My code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LEN_NAME 5
#define INSERT_NODE 1
#define APPEND_NODE 2
#define DEL_HEAD 3
#define DEL_TAIL 4
#define SHOW_LIST 5
struct people {
int id;
char name[MAX_LEN_NAME];
struct people *next;
};
typedef struct people people_list;
static void node_insert(people_list** head_ref, int id, const char* name);
static void node_append(people_list** head_ref, int id, const char* name);
static void node_del_head(people_list** head_ref);
static void node_del_tail(people_list** head_ref);
static void node_show(people_list** head_ref);
static void node_insert(people_list** head_ref, int id, const char* name)
{
people_list* new_node = NULL;
new_node = malloc(sizeof(people_list));
memset(new_node, 0, sizeof(people_list));
if (new_node == NULL) {
printf("Fail to allocate memory for new node\n");
exit(1);
}
new_node->id = id;
memcpy(new_node->name, name, sizeof(name));
new_node->next = *head_ref;
*head_ref = new_node;
}
static void node_append(people_list** head_ref, int id, const char* name)
{
return;
}
static void node_del_head(people_list** head_ref)
{
return;
}
static void node_del_tail(people_list** head_ref)
{
return;
}
static void node_show(people_list** head_ref)
{
people_list* current = NULL;
current = *head_ref;
if (current == NULL) {
printf("Empty list, nothing to show\n");
return;
}
printf("Elements in the list: \n");
while (current != NULL) {
printf("id = %d, name = %s\n", current->id, current->name);
current = current->next;
if (current == NULL) {
printf("This is the last element\n");
}
}
}
int main(void)
{
people_list* list = NULL;
#if 0
people_list* second = NULL;
people_list* third = NULL;
list = malloc(sizeof(people_list));
memset(list, 0, sizeof(people_list));
second = malloc(sizeof(people_list));
memset(second, 0, sizeof(people_list));
third = malloc(sizeof(people_list));
memset(third, 0, sizeof(people_list));
list->id = 1;
memcpy(list->name, "duc", sizeof("duc"));
list->next = second;
second->id = 2;
memcpy(second->name, "hy", sizeof("hy"));
second->next = third;
third->id = 3;
memcpy(third->name, "bo", sizeof("bo"));
third->next = NULL;
#endif
char id;
char name[MAX_LEN_NAME] = {0};
int option = 0;
while (1) {
printf("******************\n");
printf("1: Insert new node\n");
printf("2: Append new node\n");
printf("3: Delete head node\n");
printf("4: Delete tail node\n");
printf("5: Show list\n");
printf("Insert your choice: ");
scanf("%d", &option);
switch (option) {
case INSERT_NODE:
printf("debug: list=%08Xh\n", list);
printf("Enter id's value: ");
scanf("%d", &id);
printf("Enter name: ");
scanf("%s", name);
printf("debug: list=%08Xh\n", list);
node_insert(&list, id, name);
memset(name, 0, MAX_LEN_NAME);
break;
case APPEND_NODE:
printf("Enter id's value: ");
scanf("%d", &id);
printf("Enter name: ");
scanf("%s", name);
node_insert(&list, id, name);
memset(name, 0, MAX_LEN_NAME);
break;
case DEL_HEAD:
node_del_head(&list);
break;
case DEL_TAIL:
node_del_tail(&list);
break;
case SHOW_LIST:
node_show(&list);
break;
default:
printf ("Invalid input, closing program...\n");
exit(0);
break;
}
}
}
How I test:
Insert first node (1, jon)
Insert second node (2, may)
Show list => Only second node is printed.
I found that, the second->next does not point to the first node, it points to a NULL node. I keep debugging as below
case INSERT_NODE:
printf("debug: list=%08Xh\n", list);
printf("Enter id's value: ");
scanf("%d", &id);
printf("Enter name: ");
scanf("%s", name);
printf("debug: list=%08Xh\n", list);
node_insert(&list, id, name);
memset(name, 0, MAX_LEN_NAME);
break;
and the console log is
Insert your choice: 1
debug: list=001F29A8h => This is the address holding value of the first node
Enter id's value: 2
Enter name: may
debug: list=00000000h => The value of list is clear ???
As you can see, the value of the ponter list changes without modifying. Please help me to fix this. Thank you.

As pointed out in the comments, with scanf("%d", &id);, %d is expecting an int *. Change
char id;
char name[MAX_LEN_NAME] = {0};
to
int id;
char name[MAX_LEN_NAME] = {0};
Otherwise you invoke Undefined Behaviour by passing an unexpected type to scanf.
With good compiler warnings, we get the following:
warning: 'memcpy' call operates on objects of type 'const char'
while the size is based on a different type 'const char *'
[-Wsizeof-pointer-memaccess]
memcpy(new_node->name, name, sizeof(name));
When the sizeof operator is used on a pointer (in this case, a const char *) the result is the size of the pointer in bytes, not the object it points to.
Change this function call to
memcpy(new_node->name, name, sizeof new_node->name);
/* OR memcpy(new_node->name, name, MAX_LEN_NAME); */
or more appropriately, use strcpy
strcpy(new_node->name, name);
Suggest changing #define MAX_LEN_NAME 5 to something more reasonable like #define MAX_LEN_NAME 128.
At the same time, scanf("%s", name); should be changed to have a field width specifier that limits the length of the input read, to avoid buffer overflows. This should be the buffer size minus one (e.g., scanf("%127s", name);).
Additionally, the return value of scanf should not be ignored. Ensure it is the expected number of successful conversions, and otherwise handle failure. E.g.,
if (2 != scanf("%d%u", &si, &us)) {
fprintf(stderr, "Failed to read inputs.\n");
exit(EXIT_FAILURE);
}
Aside: These function calls
people_list* new_node = NULL;
new_node = malloc(sizeof(people_list));
memset(new_node, 0, sizeof(people_list));
can be simplified with calloc
people_list *new_node = calloc(1, sizeof *new_node);

Related

Having Trouble printing a doubly linked list

I am currently having trouble trying to print my doubly linked list out. The problem is either in the getSongInfo function or in the printSongInfo function. I am very new to coding and all the help is greatly appreciated. I also don't know how to use the tail pointer when using a doubly linked list.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#pragma warning(disable : 4996)
#pragma warning(disable : 6387)
#pragma once
//structs
typedef struct {
char* title;
char* artist;
int rating;
SongNode* next;
SongNode* prev;
}SongNode;
//Constants
#define kInfiniteLoop 1
#define kStringLength 30
//Prototypes
int getNum(void);
void eliminateEndOfLine(char* buffer);
void printSongInfo(SongNode* head);
SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating);
int main() {
char title[kStringLength];
char artist[kStringLength];
int rating = 0;
SongNode* head = NULL;
SongNode* tail = NULL;
printf("Enter Title, Artist and Rating\n");
printf("Enter'.' to get out of the loop and print list\n");
while (kInfiniteLoop) {
printf("Title: ");
fgets(title, kStringLength, stdin);
eliminateEndOfLine(title);
if (strcmp(title, ".") == 0) {
break;
}
printf("Artist: ");
fgets(artist, kStringLength, stdin);
eliminateEndOfLine(artist);
printf("Rating: ");
while (rating = getNum()) { // error check the rating this will check to make sure the rating is in the range 1-5.
if (rating < 1 || rating>5) {
printf("The number you have entered is invaild\n");
rating = 0;
printf("Rating: ");
continue;
}
break;
head=getSongInfo(&head, &tail, title, artist, rating);
printf("\n");
}
}
printSongInfo(head);
return 0;
}
/*===============================================================================================================*/
/*FUNCTION :getNum(void) */
/*PARAMETERS :void */
/*RETURNS :number */
/*DESCRIPTION:This function is the user input function to get a number rating */
/*===============================================================================================================*/
int getNum(void)
{/* the array is 121 bytes in size; we'll see in a later lecture how we can improve this code */
char record[121] = { 0 }; /* record stores the string */
int number = 0;
/* NOTE to student: indent and brace this function consistent with your others */
/* use fgets() to get a string from the keyboard */
fgets(record, 121, stdin);
/* extract the number from the string; sscanf() returns a number
* corresponding with the number of items it found in the string */
if (sscanf(record, "%d", &number) != 1)
{
/* if the user did not enter a number recognizable by
* the system, set number to -1 */
number = -1;
}
return number;
}
/*=======================================================================================================*/
/*FUCNTION :void eliminateEndOfLine */
/*PARAMETER :(char* buffer) */
/*RETURNS :void */
/*DESCRIPTION :This function takes a pointer to a string and looks through the string to find the */
/* newline.It takes the new line out of the string. */
/*=======================================================================================================*/
void eliminateEndOfLine(char* buffer)
{
char* target = strchr(buffer, '\n');
if (target != NULL)
{
*target = '\0';
}
}
SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating)
{
SongNode *newBlock = NULL;
newBlock = (SongNode*)malloc(sizeof(SongNode));
if (newBlock == NULL) {
printf("No memory to be Allocated\n");
return (*head);
}
newBlock->title=(char*)malloc(strlen(title) + 1);
if (newBlock->title == NULL) {
printf("No memory can be allocated for title\n");
return (*head);
}
newBlock->artist = (char*)malloc(strlen(artist) + 1);
if (newBlock->rating == NULL) {
printf("No memory can be alocated for artist\n");
return (*head);
}
newBlock->rating = (int)malloc(sizeof(int));
if (newBlock->rating == NULL) {
printf("No memory can be alllocated for rating \n");
return (*head);
}
strcpy(newBlock->title, title);
strcpy(newBlock->artist, artist);
newBlock->rating = rating;
newBlock->next = (*head);
newBlock->prev = NULL;
if ((*head) != NULL)
(*head)->prev = newBlock;
(*head) = newBlock;
return (*head);
}
void printSongInfo(SongNode* head) {
SongNode* ptr;
ptr = head;
printf("\n");
printf("%-35s %-35s %-35s\n", "Title", "Artist","Rating");
while (ptr != NULL) {
printf("%-35s %-35s %-35d\n", ptr->title, ptr->artist);
ptr = ptr->next;
}
}
You have a break statement in the while (rating = getnum()) loop that shouldn't be there. It will cause the loop to terminate before getting any song info.
Other problems:
newBlock->rating = (int)malloc(sizeof(int)); will leak memory, because you allocate some but never free it. Because rating is an int, memory does not need to be allocated for it. (Also, see Do I cast the result of malloc?).
getSongInfo should either return the new head, or update the current one, but not both.
Updating tail is similar to updating head, but does not need to be done all the time when inserting at the head (there's a condition that you'll need to check for).
You don't need #pragma once in a C source file. That should be in a header (and is only supported on some compilers).

C- Linked List with *chars

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;
}
}

string.h and strncpy with pointers in C

I'm trying to create a user input created list that contains a structure with one int and two strings. But i seem unable to use correctly the strncopy from the string.h.
I'm supposed to use the order of the parameters like:
1. name of pointer
2. string to be copied
3. string length
The error i get says that 'name' and 'lastn' which are strings are not declared...so what am i missing here?
CODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stats
{
int age;
char name[25];
char lastn[25];
struct stats *next;
};
void fill_structure(struct stats *s);
struct stats *create(void);
int main()
{
struct stats *first;
struct stats *current;
struct stats *new;
int x = 5;
//create first structure
first = create();
current = first;
for(x=0; x<5; x++)
{
if(x==0)
{
first = create();
current = first;
}
else
{
new = create();
current->next = new;
current = new;
}
fill_structure(current);
}
current->next = NULL;
current = first; //reset the list
while(current)
{
printf("Age %d, name %s and last name %s", current->age, strncpy(current->name, name, strlen(name)), strncpy(current->lastn, lastn, strlen(lastn)));
}
return(0);
}
//fill a structure
void fill_structure(struct stats *s)
{
printf("Insert Age: \n");
scanf("%d", &s->age);
printf("Insert Name: \n");
scanf("%s", &s->name);
printf("Insert Last Name: ");
scanf("%s", &s->lastn);
s->next = NULL;
}
//allocate storage for one new structure
struct stats *create(void)
{
struct stats *baby;
baby = (struct stats *)malloc(sizeof(struct stats));
if( baby == NULL)
{
puts("Memory error");
exit(1);
}
return(baby);
};
strncpy(current->name, name, strlen(name))
^ ^
You didn't declare any object named name. In your program the only name identifier is the name member of struct stats structure type.
The following line uses name and lastn, which are not defined.
printf("Age %d, name %s and last name %s", current->age, strncpy(current->name, name, strlen(name)), strncpy(current->lastn, lastn, strlen(lastn)));
It's not clear what you are trying to accomplish by the calls to strncpy here. It will be sufficient to use:
printf("Age %d, name %s and last name %s", current->age, current->name, current->lastn);
Also, while(current) will run for ever since you are not changing current in the loop. Use:
while(current)
{
printf("Age %d, name %s and last name %s", current->age, current->name, current->lastn);
current = current->next; // Need this
}
In fill_structure, instead of:
scanf("%s", &s->name);
scanf("%s", &s->lastn);
use
scanf("%s", s->name); // Drop the &
scanf("%s", s->lastn);

Create an address book using a linked list

I opened a thread yesterday asking about how I should proceed. Here is what I've got so far (sorry for the language, the program will be in Albanian but I'm sure you are getting the point).
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void regjistrim();
void kerkim();
void modifikim();
void fshirje();
void rradhitje();
void display();
void load();
#define EMRI 50
#define MBIEMRI 50
#define ID 20
#define TEL 20
#define EMAIL 25
typedef struct node
{
char emri[EMRI];
char mbiemri[MBIEMRI];
char id[ID];
char tel[TEL];
char email[EMAIL];
struct node* next;
} node;
FILE* addressbook;
node* mynode;
node* curr;
int main(void)
{
char input[2];
int choice;
load();
printf("----------------ADDRESS BOOK----------------");
printf("\n\n\t1 - Regjistrimi i ri\n");
printf("\n\t2 - Kerkim\n");
printf("\n\t3 - Modifikim\n");
printf("\n\t4 - Fshirje\n");
printf("\n\t5 - Rradhitje\n");
printf("\n\t6 - Afishim i address book\n");
printf("\n\t0 - Exit\n");
fgets(input, 4, stdin);
sscanf(input, "%d", &choice);
while (choice < 0 || choice > 6)
{
printf("\nShtypni nje numer nga 0 - 6: \n");
fgets(input, 4, stdin);
sscanf(input, "%d", &choice);
}
switch (choice)
{
case 1:
regjistrim();
break;
case 2:
kerkim();
break;
case 3:
modifikim();
break;
case 4:
fshirje();
break;
case 5:
rradhitje();
break;
case 6:
display();
break;
case 0:
exit(0);
break;
}
return 0;
}
void load()
{
addressbook = fopen("Addressbook.txt", "r");
if (addressbook == NULL)
printf("Could not open file.");
node* mynode = malloc(sizeof(node));
while (fscanf(addressbook, "%s %s %s %s %s", mynode->emri, mynode->mbiemri, mynode->id, mynode->tel, mynode->email) != EOF)
{
node* mynode = malloc(sizeof(node));
mynode = mynode->next;
}
mynode = curr;
}
//Regjistron nje qytetar ne addressbook
void regjistrim()
{
char input[2];
char answer;
do
{
node* newnode = malloc(sizeof(node));
curr->next = newnode;
addressbook = fopen("Addressbook.txt", "a+");
printf("\nShtypni emrin: ");
fgets(newnode->emri, EMRI, stdin);
printf("\nShtypni mbiemrin: ");
fgets(newnode->mbiemri, MBIEMRI, stdin);
printf("\nShtypni ID-in: ");
fgets(newnode->id, ID, stdin);
printf("\nShtypni nr. telefoni: ");
fgets(newnode->tel, TEL, stdin);
printf("\nShtypni email-in: ");
fgets(newnode->email, EMAIL, stdin);
fprintf(addressbook, "Emri: %sMbiemri: %sID: %sNr. telefoni: %sEmail: %s\n", newnode->emri, newnode->mbiemri, newnode->id, newnode->tel, newnode->email);
fclose(addressbook);
printf("\nShtypni y/Y neqoftese doni te regjistroni person tjeter: ");
fgets(input, 50, stdin);
sscanf(input, "%c", &answer);
curr = newnode;
}
while(answer == 'y' || answer == 'Y');
}
void kerkim()
{
//TODO
}
void modifikim()
{
//TODO
}
void fshirje()
{
//TODO
}
void rradhitje()
{
//TODO
}
void display()
{
//TODO
}
Currently I'm getting a segfault at this point: while (fscanf(addressbook, "%s %s %s %s %s", mynode->emri, mynode->mbiemri, mynode->id, mynode->tel, mynode->email) != EOF)
I am mainly concerned about the load() function which will load any entries to the linked list, if there are any, before the user does any action.
Thank you in advance.
I recommend you check out existing implementations of linked lists. Add helper functions for inserting nodes, appending nodes, deleting nodes, and those sorts of things. Once you have a working implementation for the lists themselves, you will have an easier time writing code that takes advantage of the linked list data structure.
Consider changing your node structure to include a pointer to the actual data and a pointer to the next node (instead of actually having the data in the struct itself). Better practice this way. You could even expand your linked list implementation to support any data type by using void pointers as "generic" pointers.
A segmentation fault with linked lists usually indicates that you are dereferencing a NULL pointer somewhere in your code (but is not the case all of the time!). Ensure that you are not referencing nodes that have been deleted or nodes that have not been allocated yet.
If you are satisfied with your current implementation, step through the code with gdb and set a breakpoint where the program is segfaulting. You should not have a hard time tracking down where the bug is.
If you want to create a linked list try doing this
Replace this code
node* mynode = malloc(sizeof(node));
while (fscanf(addressbook, "%s %s %s %s %s", mynode->emri, mynode->mbiemri, mynode->id, mynode->tel, mynode->email) == 5)
{
node* mynode = malloc(sizeof(node));
mynode = mynode->next;
}
mynode = curr;
with this
node* mynodeLocal = malloc(sizeof(node));
node *secondLastNode;
while (fscanf(addressbook, "%s %s %s %s %s", mynodeLocal->emri, mynodeLocal->mbiemri, mynodeLocal->id, mynodeLocal->tel, mynodeLocal->email) != EOF)
{
secondLastNode = mynodeLocal;
mynodeLocal->next = malloc(sizeof(node));
mynodeLocal = mynodeLocal->next;
mynodeLocal->next = NULL;
}
secondeLastNode->next = NULL;
mynode = curr;//Change this line according to your requirement.

Linked list program in C

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?

Resources