I am trying to implement a hash table with linked list chaining. The following code below works -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABSIZ 200
struct record {
struct record *next;
char name[BUFSIZ];
int data;
};
static struct record *htable[TABSIZ];
unsigned hash(char *s)
{
unsigned h;
for (h = 0; *s; s++)
h = *s;
//printf("%d", h%TABSIZ);
//I know its not a good hash function but i wanted to check chaining
return h % TABSIZ;
}
struct record *find(char *name)
{
struct record *item;
for (item = htable[hash(name)]; item; item = item->next)
{
if (strcmp(name, item->name) == 0)
return item;
}
return NULL;
}
struct record *insert(char *name,int value)
{
struct record *item;
unsigned h;
if ((item = find(name)) == NULL)
{
if ((item = malloc(sizeof (*item))) == NULL)
return NULL;
strcpy(item->name, name);
item->data=value;
h = hash(name);
item->next = htable[h];
htable[h] = item;
}
return item;
}
void printTable()
{
int i=0;
struct record *temp;
for(i=0;i<=TABSIZ;i++)
{
temp=htable[i];
while(temp!=NULL)
{
printf("\n%d - %s - %d\n", i,temp->name, temp->data);
temp=temp->next;
}
}
}
int main(void)
{
char buf[BUFSIZ];int value;
struct record *item;
do{
printf("Enter the name of the student:\n");
scanf("%s", buf);
if(strcmp(buf,"stop")==0) break;
printf("Enter the marks of the student:\n");
scanf("%d", &value);
if(insert(buf, value)==NULL)
{
break;
}
}while((strcmp(buf,"stop"))!=0);
printf("Enter a name to find: ");
scanf("%s", buf);
if((item=find(buf))!=NULL)
printf("The marks of the student is %d\n", item->data);
else printf("\n Not Found\n");
printTable();
return 0;
}
Now I am trying to remove the global variable and use local variable for the array of structures. I removed the global declaration of htable and declared it in main as
struct record *htable[TABSIZ];
and changed the functions to
struct record *find(struct record *htable, char *name);
struct record *insert(struct record *htable, char *name,int value);
and I'm calling the functions as
find(htable, name);
insert(htable,name,value);
but now my program is segfaulting. Am i passing the array of structures right? and have I declared it correctly. Any help would be greatly appreciated.
I was going down the wrong path with my earlier answer.
When it's a global, it's automatically initialized to 0.
When it's declared on the stack of main, it's not initialized.
Add a memset( htable, 0, sizeof(htable)) in main(), and that should return it to the previous behavior.
In printTable():
for(i=0;i<=TABSIZ;i++)
looks suspect. You prabably want:
void printTable()
{
unsigned int i;
struct record *temp;
for(i=0; i < TABSIZ;i++)
{
for (temp=htable[i]; temp!=NULL; temp=temp->next )
{
printf("\n%d - %s - %d\n", i,temp->name, temp->data);
}
}
}
Related
My code is following:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
struct stack {
int data;
struct stack* next;
};
struct Student
{
unsigned long int rollnumber;
char name[100];
struct Student *next;
}* head;
// Utility function to initialize stack
void initStack(struct stack** s) { *s = NULL; }
// Utility function to check if stack is empty
int isEmpty(struct stack* s)
{
if (s == NULL)
return 1;
return 0;
}
// Utility function to push an item to stack
void push(struct stack** s, int x, unsigned long int rollnumber, char *name)
{
struct stack* p = (struct stack*)malloc(sizeof(*p));
if (p == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
return;
}
p->data = x;
p->next = *s;
*s = p;
}
// Utility function to remove an item from stack
int pop(struct stack** s)
{
int x;
struct stack* temp;
x = (*s)->data;
temp = *s;
(*s) = (*s)->next;
free(temp);
return x;
}
// Function to find top item
int top(struct stack* s) { return (s->data); }
// Recursive function to insert an item x in sorted way
void sortedInsert(struct stack** s, int x, unsigned long int rollnumber, char *name)
{
// Base case: Either stack is empty or newly inserted
// item is less than top (more than all existing)
if (isEmpty(*s) || x < top(*s)) {
push(s, x, rollnumber, name);
return;
}
else{
// If top is less, remove the top item and recur
int temp = pop(s);
sortedInsert(s, x, rollnumber, name);
// Put back the top item removed earlier
push(s, temp, rollnumber, name);}
}
// Function to sort stack
void sortStack(struct stack** s)
{
// If stack is not empty
char *name;
unsigned long int rollnumber;
if (!isEmpty(*s)) {
// Remove the top item
int x = pop(s);
// Sort remaining stack
sortStack(s);
// Push the top item back in sorted stack
sortedInsert(s, x, rollnumber, name);
}
}
// Utility function to print contents of stack
void printStack(struct stack* s, unsigned long int rollnumber, char* name)
{
struct Student* student = (struct Student *) malloc(sizeof(struct Student));
struct Student* temp = head;
while (s && temp!=NULL) {
printf("%lu %s\n", temp->rollnumber, temp->name);
s = s->next;
temp = temp->next;
}
printf("\n");
}
void insert(unsigned long int rollnumber, char* name)
{
struct Student * student = (struct Student *) malloc(sizeof(struct Student));
student->rollnumber = rollnumber;
strcpy(student->name, name);
student->next = NULL;
if(head==NULL){
// if head is NULL
// set student as the new head
head = student;
}
else{
// if list is not empty
// insert student in beginning of head
student->next = head;
head = student;
}
}
void Delete(unsigned long int rollnumber)
{
struct Student * temp1 = head;
struct Student * temp2 = head;
while(temp1!=NULL){
if(temp1->rollnumber==rollnumber){
printf("Record with roll number %lu Found\n", rollnumber);
if(temp1==temp2){
// this condition will run if
// the record that we need to delete is the first node
// of the linked list
head = head->next;
free(temp1);
}
else{
// temp1 is the node we need to delete
// temp2 is the node previous to temp1
temp2->next = temp1->next;
free(temp1);
}
printf("Record successfully deleted\n");
return;
}
temp2 = temp1;
temp1 = temp1->next;
}
printf("Student with roll number %lu is not found\n", rollnumber);
}
void display()
{
struct Student * temp = head;
while(temp!=NULL){
printf("Roll Number: %lu\n", temp->rollnumber);
printf("Name: %s\n", temp->name);
temp = temp->next;
}
}
int main(void)
{
head = NULL;
int choice;
int fc_,id_,year_, fc_year;
char name[100];
struct student* s;
unsigned long int rollnumber;
struct stack* faculty;
struct stack* year;
struct stack* id;
initStack(&faculty);
initStack(&year);
initStack(&id);
printf("1 - Enter school number\n2 - Display school numbers by ID\n3 - Display school numbers sorted by year\n4 - Display school numbers sorted by the faculty codes\n5 - Delete a record by school number\n6 - Exit");
do
{
printf("\nEnter Choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("Enter roll number: ");
scanf("%lu", &rollnumber);
fc_ = rollnumber/pow(10, 6);
id_ = rollnumber%(10*10*10*10);
fc_year = rollnumber/pow(10,4);
year_ = fc_year%(100);
printf("Enter name: ");
scanf("%s", name);
insert(rollnumber, name);
push(&faculty, fc_, rollnumber, name);
push(&year, year_, rollnumber, name);
push(&id, id_, rollnumber, name);
break;
case 2:
printf("Sorted by ID: \n");
sortStack(&id);
printStack(id, rollnumber, name);
break;
case 3:
printf("Sorted by year: \n");
sortStack(&year);
printStack(year, rollnumber, name);
break;
case 4:
printf("Sorted by faculty code: \n");
sortStack(&faculty);
printStack(faculty, rollnumber, name);
break;
case 5:
printf("Enter roll number to delete: ");
scanf("%lu", &rollnumber);
Delete(rollnumber);
break;
case 6:
break;
}
} while (choice != 6);
}
When, for example, the choice is 2, I want to display the student name and whole rollnumber in ascending order. But when I run it that is what I get (C, B, A are the names given by me):
Enter Choice: 2
705102020 C
705102010 B
705102005 A
I am sure that I sorted it correctly, but probably my printStack function is not working properly. How can I reverse this?
It would be better to define a stack struct independantly of the rest of your code:
struct stack {
void *data;
struct stack *next;
};
void stack_init(struct stack **ss)
{
*ss = NULL;
}
bool stack_push(struct stack **ss, void *data)
{
struct stack *node = malloc(sizeof *node);
if (!node) return false;
node->data = data; // Copy address, not data
node->next = *ss;
*ss = node;
return true;
}
bool stack_pop(struct stack **ss, void **data)
{
if (!*ss) return false;
struct stack *rm = *ss;
*ss = (*ss)->next;
if (data) *data = rm->data; // If nothing is provided (i.e. NULL), data will leak if it was allocated dynamically.
free(rm);
return true;
}
bool stack_top(const struct stack *ss, void **data)
{
if (!ss) return false;
*data = ss->data;
return true;
}
void stack_print(const struct stack *ss, void print(const struct stack*))
{
for (const struct stack *sp = ss; sp; sp = sp->next)
print(sp);
}
You can implement your stack sorting function like that:
struct stack *stack_find_min(struct stack *ss, int (*cmp)(const void*, const void*))
{
struct stack *min = ss;
for (struct stack *sp = ss; sp; sp = sp->next)
if (cmp(sp->data, min->data) < 0)
min = sp;
return min;
}
void stack_sort(struct stack *ss, int (*cmp)(const void*, const void*))
{
if (!ss) return;
for (struct stack *sp = ss; sp; sp = sp->next) {
struct stack *min = stack_find_min(sp, cmp);
swap(&sp->data, &min->data);
}
}
swap() swaps two pointers:
void swap(void **p1, void **p2)
{
void *tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
After that, define your student data structure:
struct student {
unsigned long rollnumber;
char name[100];
struct student *next;
};
struct student *student_insert(struct student **head, unsigned long rollnumber, const char *name)
{
struct student *st = malloc(sizeof(*st));
if (!st) return NULL;
st->rollnumber = rollnumber;
strncpy(st->name, name, 99);
st->next = *head;
*head = st;
return st;
}
void student_print(const struct stack *ss)
{
struct student *st = ss->data;
printf("%ld\t%s\n", st->rollnumber, st->name);
}
int student_compare_id(const void *s1, const void *s2)
{
// MUST cast void* into (struct student*) first.
const struct student *student1 = s1;
const struct student *student2 = s2;
unsigned long rollnumber1 = student1->rollnumber;
unsigned long rollnumber2 = student2->rollnumber;
unsigned long id1 = rollnumber1 % 10000;
unsigned long id2 = rollnumber2 % 10000;
return id1 == id2 ? 0 : (id1 < id2 ? -1 : 1);
}
If you want to test the above:
int main(void)
{
struct stack *ss;
stack_init(&ss);
struct student *st = NULL;
student_insert(&st, 100181234, "James");
student_insert(&st, 200195678, "John");
student_insert(&st, 300200324, "Goku");
student_insert(&st, 400214321, "Taylor");
for (struct student *p = st; p; p = p->next)
stack_push(&ss, p);
puts("Unsorted stack:");
stack_print(ss, student_print);
stack_sort(ss, student_compare_id);
puts("\nSorted by ID:");
stack_print(ss, student_print);
// Don't forget to free the memory allocated for students
// and pop all nodes of the stack (ommited here).
}
Output:
Unsorted stack:
100181234 James
200195678 John
300200324 Goku
400214321 Taylor
Sorted by ID:
300200324 Goku
100181234 James
400214321 Taylor
200195678 John
Few more things:
Don't use scanf() to read user input. fgets() is safer.
You can replace pow(10, 4) directly by 10000. Why wasting CPU cycles to calculate constants?
In your insert() function, there is no need to test for *head == NULL. The code in the else statement handles this case.
EDIT: In student_compare_id(), the const void* pointers MUST BE CASTED to const struct student* first before dereferencing. The previous version seemed to work because the rollnumber happened to be the first field in the struct. That was an undefined behavior in all its glory. Fixed that now.
Here is the previous version that NO ONE SHOULD USE:
int student_compare_id(const void *s1, const void *s2)
{
unsigned long rollnumber1 = *(unsigned long*)s1; // WRONG!
unsigned long rollnumber2 = *(unsigned long*)s2; // WRONG!
unsigned long id1 = rollnumber1 % 10000;
unsigned long id2 = rollnumber2 % 10000;
return id1 == id2 ? 0 : (id1 < id2 ? -1 : 1);
}
The primary problem is that there is no connection between your stack(s) and your student list, but the code assumes that there is. You can reorder the stacks however you like, but that does not reorder the list. When you print, the students simply come out in the reverse of their insertion order (because you insert at the front of the list, and then traverse the list from front to back).
You have two main alternatives:
combine the list and all the stacks into one linked list. You can use this both list-style and stack-style if you like. OR
Give the stack nodes pointers to the corresponding list elements, and traverse those when you print a stack to get the students in the order implied by the stack.
This code is written in C. The first line of Node_reset() function occurs an error. (Structure array is allocated dynamically in main function.) I think there's something wrong in member-access of Node_reset(), also Create() might occur same kind of error. Input.txt, the following format is provided:
2
3 dfs(3)
786 368 603
5 bfs(4)
825 162 768 724 635
The number in the first line (i.e., 2) shows the number of test cases to be processed. From the second line, test cases are given, and the information for each case is provided over two lines.
In the first line (line number 2 in the example above), the first number (i.e., 3) indicates the number of integers in that case, and the next string (i.e., dfs(3)) shows the location of the target number that you need to look for. In this example, the target number is on the third node of DFS.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_QUEUE_SIZE 100
#define FALSE 1;
#define TRUE 0;
typedef struct BST_node{
int data;
int visited;
struct BST_node * leftChild;
struct BST_node * rightChild;
}node;
typedef node* TreeNode;
typedef struct {
TreeNode data[MAX_QUEUE_SIZE];
int front;
int rear;
}Queue;
void Node_reset(TreeNode* input_tree, int BST_size)
{
for(int i=0;i<BST_size;i++)
{
input_tree[i]->data = 0; //"Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)"occurs
input_tree[i]->leftChild=NULL;
input_tree[i]->rightChild=NULL;
input_tree[i]->visited=FALSE;
}
}
void Create(TreeNode* input_tree, int data[], int BST_size)
{
for(int i=0;i<BST_size;i++)
{
input_tree[i]->data=data[i];
}
for(int i=0;i<BST_size-1;i++)
{
if(input_tree[i]->data > input_tree[i+1]->data) input_tree[i]->leftChild=input_tree[i+1];
else input_tree[i]->rightChild=input_tree[i+1];
}
}
void init_Q(Queue* q)
{
q->front = q->rear =0;
}
int IsEmpty(Queue* q)
{
return (q->front == q->rear);
}
int IsFull(Queue* q)
{
return ((q->rear+1)%MAX_QUEUE_SIZE==q->front);
}
void enqueue(Queue* q,TreeNode data)
{
if(IsFull(q))
{
printf("Queue is Full");
}
q->rear = (q->rear+1)%MAX_QUEUE_SIZE;
q->data[q->rear]=data;
}
TreeNode dequeue(Queue* q)
{
if(IsEmpty(q))
{
printf("Queue is empty");
return NULL;
}
q->front = (q->front+1)%MAX_QUEUE_SIZE;
return q->data[q->front];
}
int DFS_search(TreeNode Node, int *searching_times)
{
while(*searching_times==0){
*searching_times--;
if(Node->leftChild!=NULL) DFS_search(Node->leftChild, searching_times);
if(Node->rightChild!=NULL) DFS_search(Node->rightChild, searching_times);
}
return Node->data;
}
int BFS_search(TreeNode* Node, int searching_times)
{
Queue q;
init_Q(&q);
for(int i=0;i<searching_times;i++)
{
enqueue(&q, Node[i]);
if(Node[i]->leftChild)
enqueue(&q, Node[i]->leftChild);
if(Node[i]->rightChild)
enqueue(&q, Node[i]->rightChild);
}
for(int i=0;i<searching_times;i++)
{
if(i==searching_times-1) return dequeue(&q)->data;
else dequeue(&q);
}
return 0;
}
void pass_result(int result_num,int *result,int result_arr[])
{
result_arr[result_num]=(*result);
}
void return_result(int result_arr[],int how_many)
{
FILE *of = fopen("output.txt","w");
for(int i=0;i<how_many;i++)
{
fprintf(of, "%d\n",result_arr[i]);
}
fclose(of);
}
int main()
{
int how_many_times; //the number of input expression
int BST_size; //input the number of element here
char string[7]={0}; //input string data here
char temp[2]={0}; //input searching num
int searching_times; //the number of input expression
int result; //result of expression
FILE *fp = fopen("input.txt","r");
fscanf(fp, "%d", &how_many_times);
int *result_arr=(int*)malloc(sizeof(int)*how_many_times);
for(int i=0;i<how_many_times;i++)
{
memset(string, 0, sizeof(char)*7); //reset string[]
memset(temp, 0, sizeof(char)*2); //reset temp[]
fscanf(fp, "%d", &BST_size); //pass BST size
int* input=(int*)malloc(sizeof(int)*BST_size); //allocate heep memory as long as input BST size
fscanf(fp, "%s", string); //pass string input data to string[]
TreeNode* tree=(TreeNode*)malloc(sizeof(TreeNode)*BST_size);
Node_reset(tree, BST_size);
for(int i=0;i<BST_size;i++) //input elements in array
{
fscanf(fp, "%d",&input[i]);
}
Create(tree, input, BST_size);
for(int i=0;i<2;i++)
{
temp[i]=string[i+4];
}
searching_times=atoi(temp); //input data about searching times becomes integer type
if(strcmp(&string[0],"d")) result=DFS_search(tree[0], &searching_times);
if(strcmp(&string[0],"b")) result=BFS_search(tree, searching_times);
pass_result(i, &result, result_arr); //pass the result
free(input);
}
return_result(result_arr, how_many_times); //return result in txt file
free(result_arr); //free result heep data
}
This is the part that occurs error. If needed please refer full code or tell me what I could do more. 😂
#define MAX_QUEUE_SIZE 100
#define FALSE 1;
#define TRUE 0;
typedef struct BST_node{
int data;
int visited;
struct BST_node * leftChild;
struct BST_node * rightChild;
}node;
typedef node* TreeNode;
typedef struct {
TreeNode data[MAX_QUEUE_SIZE];
int front;
int rear;
}Queue;
void Node_reset(TreeNode* input_tree, int BST_size)
{
for(int i=0;i<BST_size;i++)
{
input_tree[i]->data = 0;
input_tree[i]->leftChild=NULL;
input_tree[i]->rightChild=NULL;
input_tree[i]->visited=FALSE;
}
}
void Create(TreeNode* input_tree, int data[], int BST_size)
{
for(int i=0;i<BST_size;i++)
{
input_tree[i]->data=data[i];
}
for(int i=0;i<BST_size-1;i++)
{
if(input_tree[i]->data > input_tree[i+1]->data) input_tree[i]->leftChild=input_tree[i+1];
else input_tree[i]->rightChild=input_tree[i+1];
}
}
int main()
{
int how_many_times; //the number of input expression
int BST_size; //input the number of element here
char string[7]={0}; //input string data here
char temp[2]={0}; //input searching num
int searching_times; //the number of input expression
int result; //result of expression
FILE *fp = fopen("input.txt","r");
fscanf(fp, "%d", &how_many_times);
int *result_arr=(int*)malloc(sizeof(int)*how_many_times);
for(int i=0;i<how_many_times;i++)
{
fscanf(fp, "%d", &BST_size); //pass BST size
int* input=(int*)malloc(sizeof(int)*BST_size); //allocate heep memory as long as input BST size
fscanf(fp, "%s", string); //pass string input data to string[]
TreeNode* tree=(TreeNode*)malloc(sizeof(TreeNode)*BST_size);
Node_reset(tree, BST_size);
for(int i=0;i<BST_size;i++) //input elements in array
{
fscanf(fp, "%d",&input[i]);
}
Create(tree, input, BST_size);
}
}
My teacher gave me a library that describes a single linked list. I am writing a main file to test it, and i ran into a very weird problem.
This is the header for the linked list library (There are more function, but i only putin the one i used):
#ifndef DSSINGLYLINKEDLIST_H
#define DSSINGLYLINKEDLIST_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _SListEntry SListEntry;
typedef struct _SListIterator SListIterator;
typedef void *SListValue;
/**
* Definition of a #ref SListIterator.
*/
struct _SListIterator {
SListEntry **prevNext;
SListEntry *current;
};
#define SLIST_NULL ((void *) 0)
typedef int (*SListCompareFunc)(SListValue value1, SListValue value2);
typedef int (*SListEqualFunc)(SListValue value1, SListValue value2);
SListEntry *slist_append(SListEntry **list, SListValue data);
SListValue slist_nthData(SListEntry *list, unsigned int n);
unsigned int slist_length(SListEntry *list);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef DSSINGLYLINKEDLIST_H */
This is my .c file:
#include <stdlib.h>
#include <stdio.h>
#include "dssinglylinkedlist.h"
struct _SListEntry {
SListValue data;
SListEntry *next;
};
SListEntry *slist_append(SListEntry **list, SListValue data)
{
/* Create new list entry */
SListEntry *newEntry = malloc(sizeof(SListEntry));
if (newEntry == NULL) {
return NULL;
}
newEntry->data = data;
newEntry->next = NULL;
/* Hooking into the list is different if the list is empty */
SListEntry *rover;
if (*list == NULL) {
/* Create the start of the list */
*list = newEntry;
} else {
/* Find the end of list */
rover=*list;
while (rover->next != NULL) {
rover = rover->next;
}
/* Add to the end of list */
rover->next = newEntry;
}
return newEntry;
}
SListValue slist_nthData(SListEntry *list, unsigned int n)
{
/* Find the specified entry */
SListEntry *entry = slist_nthEntry(list, n);
/* If out of range, return NULL, otherwise return the data */
if (entry == NULL) {
return SLIST_NULL;
} else {
return entry->data;
}
}
unsigned int slist_length(SListEntry *list)
{
SListEntry *entry = list;
unsigned int length = 0;
while (entry != NULL) {
/* Count the number of entries */
++length;
entry = entry->next;
}
return length;
}
I think there's nothing wrong with these code.
I am writing a main using this library to store information of two polynomial:
#include <stdio.h>
#include <stdlib.h>
#include "dssinglylinkedlist.h"
void printPolynomial(SListEntry*);
int main()
{
SListEntry *poly1;
int n;
printf("Input n for poly1: ");
scanf("%d", &n);
printf("Input poly1: ");
for (int i=0; i<=n; i++) {
int *temp = (int *) malloc(sizeof (int));
scanf("%d", temp);
slist_append(&poly1, temp);
}
printPolynomial(poly1);
SListEntry *poly2;
printf("Input n for poly2: ");
scanf("%d", &n);
printf("Input poly2: ");
// for (int i=0; i<=n; i++) {
// int *temp = (int *) malloc(sizeof (int));
// scanf("%d", temp);
// slist_append(&poly2, temp);
// }
// printPolynomial(poly2);
return 0;
}
void printPolynomial(SListEntry *list)
{
int length = (int)slist_length(list);
for (int i = 0; i < length; i++) {
int temp = *((int *)slist_nthData(list,(unsigned int)i));
if (i >0 && temp >= 0) {
printf("+");
}
printf("%d*x^%d", temp, length-i-1);
}
printf("\n");
}
So if i comments the second loop (after i print 'Input poly2', like i wrote above), i can still input my poly1 and print it. But if i un-comments it, my program crashes immediately when i append the first element of poly1.
What is the problem of my code?
I'm trying to make a code that will allow the user to input any amount of entries he wants, and then print them out (and other functions, still have to get to that). But when I try to launch the code it allows me to input the entries, but when I want to print them out, it doesn't register current.name or current.telNo (only prints out 1: has tel. No. ) and a segmentation error follows after it. Any idea how I can fix that.
#include <stdio.h>
#include <stdlib.h>
int listSize;
int counter = 0;
struct Entry {
char name[20];
char telNo[9];
struct Entry *next;
} current;
int main()
{
struct Entry *linkedList = (struct Entry * )malloc(sizeof(struct Entry));
struct Entry *current = linkedList;
first(current);
print(current);
return 0;
}
void first(struct Entry linkedList)
{
int i;
printf("enter list size: ");
scanf("%d", &listSize);
printf("Now enter entries one by one: \n");
for (i = 0; i < listSize; i++) {
counter++;
printf("Name: ");
scanf("%s", linkedList.name);
printf("Telephone: ");
scanf("%s", linkedList.telNo);
if (i != listSize -1) {
linkedList.next = (struct Entry *)malloc(sizeof(struct Entry));
linkedList = *linkedList.next;
} else {
linkedList.next = NULL;
}
}
}
void print(struct Entry linkedList)
{
int nr = 1;
printf("\nTelephone book is:\n");
while (current.name != NULL) {
printf("%d: %s has tel. No.\t%s\n", nr, current.name, current.telNo);
current = *current.next;
nr++;
}
}
Instead of . you should have used -> and in your print() you were traversing current instead of linkedList which was causing the issue. Also your functions definitions should come before its usage. Please check the below snippet, i have made the corresponding changes.
#include <stdio.h>
#include <stdlib.h>
int listSize;
int counter = 0;
struct Entry {
char name[20];
char telNo[9];
struct Entry *next;
} current;
void print(struct Entry *linkedList)
{
int nr = 1;
printf("\nTelephone book is:\n");
while (linkedList->name != NULL) {
printf("%d: %s has tel. No.\t%s\n", nr, linkedList->name, linkedList->telNo);
linkedList = linkedList->next;
nr++;
}
}
void first(struct Entry *linkedList)
{
int i;
printf("enter list size: ");
scanf("%d", &listSize);
printf("Now enter entries one by one: \n");
for (i = 0; i < listSize; i++) {
counter++;
printf("Name: ");
scanf("%s", linkedList->name);
printf("Telephone: ");
scanf("%s", linkedList->telNo);
if (i != listSize -1) {
linkedList->next = (struct Entry *)malloc(sizeof(struct Entry));
linkedList = linkedList->next;
} else {
linkedList->next = NULL;
}
}
}
int main()
{
struct Entry *linkedList = (struct Entry * )malloc(sizeof(struct Entry));
struct Entry *current = linkedList;
first(current);
print(current);
return 0;
}
while (current.name != NULL)
should be
while (current != NULL)
otherwise current = *current.next will become NULL and crash on the while condition
current.name is a pointer to reserved 20-byte area, which is always non-NULL.
I would initialize *next with NULL every time I allocate it (there are few ways to do that, easiest: assign NULL to it right after malloc). And do the check like that: if (current.next != NULL).
You also can check for current.name[0] != 0, but the first option is cleaner.
There are a number of errors in your code but, essentially two main 'points of confusion':
First, you seem to be confusing a structure (struct Entry) with a pointer-to-structure (as in, for example, struct Entry *next;).
Second, you have two different variables called current - one defined globally (which is the only one that is 'visible' to your print function), and another one defined locally inside main (this one will 'hide' the former).
Here is a corrected version of your code, with triple-slash (///) comments wherever I've made changes. Feel free to ask for further clarification and/or explanation.
#include <stdio.h>
#include <stdlib.h>
int listSize;
int counter = 0;
struct Entry {
char name[20];
char telNo[9];
struct Entry* next;
} *current; /// Here, we define a GLOBAL variable, "current" that is a POINTER to the struct
void first(struct Entry* linkedList); /// Put "Function Prototypes* here, so that "main" knows what they are
void print(struct Entry* linkedList); /// You need to pass POINTERS to structures, not the actual structures
int main()
{
struct Entry* linkedList = (struct Entry*)malloc(sizeof(struct Entry));
// struct Entry* current = linkedList; /// This declaration 'hides' the global variable
current = linkedList; /// Here, we (properly) assign the global pointer's value
first(current);
print(current);
return 0;
}
void first(struct Entry* linkedList) /// Pointer (see above)
{
int i;
printf("enter list size: ");
scanf("%d", &listSize);
printf("Now enter entries one by one: \n");
for (i = 0; i < listSize; i++) {
counter++;
printf("Name: ");
scanf("%s", linkedList->name); /// Use "->" instead of "." to get a pointer's member (and elsewhere)
printf("Telephone: ");
scanf("%s", linkedList->telNo); /// See above
if (i != listSize - 1) {
linkedList->next = (struct Entry*)malloc(sizeof(struct Entry)); /// See above
linkedList = linkedList->next; /// Again - changed here to use pointers!
}
else {
linkedList->next = NULL; /// See above
}
}
}
void print(struct Entry* linkedList) /// Pointer (see above)
{
int nr = 1;
printf("\nTelephone book is:\n");
while (current != NULL) { /// You need to check if "current" is not NULL before trying to access any of its members...
// while (current.name != NULL) {
printf("%d: %s has tel. No.\t%s\n", nr, current->name, current->telNo); /// Same "." to "->" changes as before
current = current->next; /// And again!
nr++;
}
}
There are other ways to 'fix' your code (and also improve it): for example, you never use the argument you pass to print, relying instead on the 'global' variable I mentioned earlier.
I am working on a program that uses a binary search tree (as an exercise).
My problem is that when I try to add a customer(in the middle of my code lines 65-69) I get an error that BS_node is undeclared, though I insert struct BST_node *root in this function..
Part of my code is below, just for the readers to read it easier, if requested I can upload the full code ! Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING 50
void flush();
struct customer {
char *name;
char *address;
char *email;
};
struct double_linked_list {
struct customer *data;
struct double_linked_list *previous;
struct double_linked_list *next;
};
struct double_linked_list *customers_head=0;
struct BST_node {
struct double_linked_list *data;
struct BST_node *left;
struct BST_node *right;
};
struct BST_node *BST_email_root = 0;
struct BST_node *BST_find_customer(struct BST_node *root, char *email) {
if (root==NULL)
return NULL;
if (strcmp(email,root->data->data->email)==0)
return root;
else
{
if (strcmp(email,root->data->data->email)==-1)
return BST_find_customer(root->left,email);
else
return BST_find_customer(root->right,email);
}
}
void find_customer() {
char email[MAX_STRING];
struct double_linked_list *l;
struct BST_node *b;
printf("Give the email of the customer (up to %d characters) : ", MAX_STRING-1);
gets(email);
b = BST_find_customer(BST_email_root, email);
if (b==0)
printf("There is no customer with this email.\n");
else
{
l = b->data;
printf("Customer found! \n");
printf("Name : %s\n", l->data->name);
printf("Address : %s\n", l->data->address);
printf("Email : %s\n", l->data->email);
}
}
struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l)
{
if (root==NULL);
{
root = (BST_node *) malloc (sizeof(BST_node ));
if (root==NULL)
{
printf("Out of Memory!");
exit(1);
}
root->data=l;
root->left=NULL;
root->right=NULL;
}
if (strcmp(l->data->email,root->data->data->email)==-1)
root->left =new_BST_node(root->left,l);
else root->right =new_BST_node(root->right,l);
return root;
};
struct double_linked_list *new_customer()
{
char name[MAX_STRING], address[MAX_STRING], email[MAX_STRING];
struct BST_node *b;
struct double_linked_list *l;
struct customer *c;
printf("\nADDING NEW CUSTOMER\n=\n\n");
printf("Give name (up to %d characters): ", MAX_STRING-1);
gets(name);
printf("Give address (up to %d characters): ", MAX_STRING - 1);
gets(address);
printf("Give email (up to %d characters): ", MAX_STRING - 1);
gets(email);
b = BST_find_customer(BST_email_root, email);
if (b)
{
printf("Duplicate email. Customer aborted.\n");
return 0;
}
c = (struct customer *) malloc(sizeof(struct customer));
if (c == 0)
{
printf("Not enough memory.\n");
return 0;
}
c->name = strdup(name); // check for memory allocation problem
if (c->name == 0) return 0;
c->address = strdup(address); // check for memory allocation problem
if (c->address == 0) return 0;
c->email = strdup(email); // check for memory allocation problem
if (c->email == 0) return 0;
l = (struct double_linked_list*) malloc(sizeof(struct double_linked_list));
if (l == 0)
{
printf("Not enough memory.\n");
free(c->name);
free(c->address);
free(c->email);
free(c);
return 0;
}
l->data = c;
l->previous = 0;
l->next = customers_head;
if (customers_head)
customers_head->previous = l;
customers_head = l;
BST_email_root = new_BST_node(BST_email_root, l);
return l;
}
void displaymenu() {
printf("\n\n");
printf("1. New customer\n");
printf("2. Find customer using email\n");
printf("0. Exit\n\n");
printf("Give a choice (0-6) : ");
}
void flush()
{
char ch;
while ((ch = getchar()) != '\n' && ch != EOF);
}
int main() {
int choice;
do {
displaymenu();
scanf("%d", &choice);
flush();
switch (choice) {
case 1:
new_customer();
break;
case 2:
find_customer();
break;
} while (choice != 0);
return 0;
}
On the line 69, you have to specify struct BST_node instead of BST_node:
root = (struct BST_node *) malloc (sizeof(struct BST_node ));
As for the rest of the code: read the manual for gets, it's clearly a function one should not use, I'd advise replacing it with fgets. There's also a little closing bracket missing in your final switch (line 178).