Pointers and binary search tree - c

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).

Related

Segmentation fault error in Linked-List program

I'm facing the segmentation fault error in the following dynamic linked list implementation; GDB shows the issue is on the node = node->next line in the "l_print" function of the linked-list ("LIST_CL.H" file). Anyone can help? I even tried "drawing debug" on paper but still I'm not getting the issue here.
Note: I report the whole code for both the insert and the print, in case it's useful. Therefore LIST.C file include the "switch case 6" to insert the element ("l_add" function in "LIST_CL.H" file) and the "switch case 1" to print the list ("l_print" function in "LIST_CL.H" file)
Note: The issue only happen when the list has one or more items. There's no errors when the list is empty ("list_cl" struct has NULL for both head and tail nodes)
LIST.C:
#include <stdio.h>
#include <string.h> //for strcpy
#include "cl_list.h"
#include "list_cl.h"
#define STRING_SIZE 25
int main(){
list_cl class = L_EMPTYLIST_CL;
puts("Select command:");
puts("0. Exit.");
puts("1. Insert node.");
puts("6. Print all nodes in the linked list.");
int k = 0;
scanf("%d", &k);
while(k != 0){
switch(k){
case 1:
char cf[17] = "";
char first_name[STRING_SIZE] = "";
char last_name[STRING_SIZE] = "";
getchar();
puts("Insert name:");
fgets(first_name, sizeof(first_name), stdin);
puts("Insert surname:");
fgets(last_name, sizeof(last_name), stdin);
puts("Insert fiscal code:");
fgets(cf, sizeof(cf), stdin);
client cliente;
strcpy(cliente.cf, cf);
cliente.first_name = first_name;
cliente.last_name = last_name;
class = l_add_cl(class, cliente);
puts("Node inserted.");
break;
case 6:
l_print(class);
break;
default:
break;
}
scanf("%d", &k);
}
}
LIST_CL.H:
list_cl l_add_cl(list_cl l, client p){
l_node node;
node.id = 1;
node.person = p;
node.next = NULL;
if(l.head == NULL){
//List is empty
l.head = &node;
l.tail = &node;
} else {
l.tail -> next = &node;
l.tail = &node;
}
return l;
}
void l_print(list_cl l){
l_node *node = NULL;
node = l.head;
while(node != NULL){
//client *cliente = &node->person;
//printf("ID Elemento: %d | Name: %s Surname: %s Fiscal Code: %s", node->id, cliente->first_name, cliente->last_name, cliente->cf);
node = node->next; // SEGMENTATION FAULT ERROR HERE!
}
}
CL_LIST.H:
#include "client.h"
typedef struct _node {
unsigned int id;
client person;
struct _node *next;
} l_node;
typedef struct {
l_node *head;
l_node *tail;
} list_cl;
#define L_EMPTYLIST_CL {NULL,NULL}
CLIENT.H:
typedef struct {
char cf[17];
char *first_name;
char *last_name;
} client;
Fixed code:
LIST.C:
#include <stdio.h>
#include <string.h> //for strcpy
#include "cl_list.h"
#include "list_cl.h"
#define STRING_SIZE 25
int main(){
list_cl class = L_EMPTYLIST_CL;
puts("Seleziona un comando:");
puts("0. Exit.");
puts("1. Insert one node.");
puts("6. Print all nodes.");
int k = 0;
scanf("%d", &k);
while(k != 0){
switch(k){
case 1:
char cf[17] = "";
//char first_name[STRING_SIZE] = ""; THIS CAUSE DATA INCONSISTENCY
//char last_name[STRING_SIZE] = ""; THIS CAUSE DATA INCONSISTENCY
char *first_name = malloc(sizeof(char)*STRING_SIZE);
char *last_name = malloc(sizeof(char)*STRING_SIZE);
getchar();
puts("Insert name:");
//fgets(first_name, sizeof(first_name), stdin); ISSUE WITH SIZE OF FIRST_NAME
fgets(first_name, sizeof(char)*STRING_SIZE, stdin);
puts("Insert surname:");
//fgets(last_name, sizeof(last_name), stdin); ISSUE WITH SIZE OF LAST_NAME
fgets(last_name, sizeof(char)*STRING_SIZE, stdin);
puts("IInsert fiscal code:");
fgets(cf, sizeof(cf), stdin);
client *cliente = malloc(sizeof(client));
strcpy(cliente->cf, cf);
cliente->first_name = first_name;
cliente->last_name = last_name;
class = l_add_cl(class, *cliente);
puts("Element inserted.");
break;
case 6:
l_print(class);
break;
default:
break;
}
puts("Select command:");
scanf("%d", &k);
}
}
LIST_CL.H
list_cl l_add_cl(list_cl l, client p){
l_node *node = malloc(sizeof(struct _node));
node->id = 1;
node->person = p;
node->next = NULL;
if(l.head == NULL){
//Empty list
l.head = node;
l.tail = node;
} else {
l.tail -> next = node;
l.tail = node;
l.tail -> next = NULL;
}
return l;
}
void l_print(list_cl l){
l_node *node = NULL;
node = l.head;
while(node != NULL){
client *cliente = &node->person;
printf("ID Element: %d | Name: %s Surname: %s Fiscal code: %s", node->id, cliente->first_name, cliente->last_name, cliente->cf);
node = node->next;
}
}
CL_LIST.H
#include "client.h"
typedef struct _node {
unsigned int id;
client person;
struct _node *next;
} l_node;
typedef struct {
l_node *head;
l_node *tail;
} list_cl;
#define L_EMPTYLIST_CL {NULL,NULL}
CLIENT.H
typedef struct {
char cf[17];
char *first_name;
char *last_name;
} client;

Segmentation fault while using malloc

As an exercise I am trying to work on a Binary search tree!
I have created the code and it seems to run, but when I try to add a customer it crashes. After debugging the code I get a segmentation fault in line 82, where I try to allocate memory to root... Researching for a while I see that it is something related to memory, but can't figure what is going on with my code... Any suggestions about what is causing this failure when trying to allocate memory?
#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 = (struct BST_node *)malloc(sizeof(struct 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;
}
Codeblocks debugger gives the following information
Active debugger config: GDB/CDB debugger:Default
Building to ensure sources are up-to-date
Selecting target:
Debug
Adding source dir: C:\debug\
Adding source dir: C:\debug\
Adding file: C:\debug\bin\Debug\debug.exe
Changing directory to: C:/debug/.
Set variable: PATH=.;C:\Program Files\CodeBlocks\MinGW\bin;C:\Program Files\CodeBlocks\MinGW;C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Program Files\ATI Technologies\ATI.ACE\Core-Static;C:\Users\baskon\AppData\Local\Microsoft\WindowsApps
Starting debugger: C:\Program Files\CodeBlocks\MINGW\bin\gdb.exe -nx -fullname -quiet -args C:/debug/bin/Debug/debug.exe
done
Registered new type: wxString
Registered new type: STL String
Registered new type: STL Vector
Setting breakpoints
Debugger name and version: GNU gdb (GDB) 7.6.1
Child process PID: 5908
Program received signal SIGSEGV, Segmentation fault.
In ?? () ()
9 0x00401480 in new_BST_node (root=0x0, l=0xbe0ec8) at C:\debug\main.c:82
C:\debug\main.c:82:1907:beg:0x401480
At C:\debug\main.c:82
9 0x00401480 in new_BST_node (root=0x0, l=0xbe0ec8) at C:\debug\main.c:82
C:\debug\main.c:82:1907:beg:0x401480
The call stack is the following
There are multiple problems in your code:
You have a classic bug here:
struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l) {
if (root == NULL);
{
root = (struct BST_node *)malloc(sizeof(struct BST_node));
The ; at the end of the if statement line is parsed as an empty statement. The subsequent block, introduced by the { will always be executed.
You can avoid this kind of silly bug by always using braces for your compound statements and placing them on the same line as the beginning of the statement, not on the next line. This is close to the original K&R style used by the creators of the C language more than 40 years ago.
The type for variable ch in function flush should be int to allow proper distinction of all values returned by getc(): all values of unsigned char plus the special value EOF:
void flush(void) {
int ch;
while ((ch = getchar()) != EOF && ch != '\n') {
continue;
}
}
Note that you should make the empty statement more explicit as I did above, to avoid confusion and bugs such as the previous one.
You should not use the obsolete unsafe function gets(): Use fgets() and strip the trailing newline with strcspn().
When comparing strings with strcmp(), you should only rely on the sign of the return value. In functions BST_find_customer() and new_BST_node(), you compare with -1: this is unreliable. Use if (strcmp(email, root->data->data->email) < 0) instead.
In function new_BST_node(), You do not return root when you create a new node in the tree. Here is a corrected version:
struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l) {
if (root == NULL) {
root = malloc(sizeof(*root));
if (root == NULL) {
printf("Out of Memory!");
exit(1);
}
root->data = l;
root->left = NULL;
root->right = NULL;
return root;
}
if (strcmp(l->data->email, root->data->data->email) < 0) {
root->left = new_BST_node(root->left, l);
} else {
root->right = new_BST_node(root->right, l);
}
return root;
}
Note that this is causing your bug as you probably have an infinite recursion here.
Finally a couple pieces of advice:
use NULL instead of 0 when comparing pointers to the null pointer. It is more readable.
avoid naming a variable l as this name is graphically too close to 1 with the fixed pitch fonts used in programming environments. Sometimes it is almost indistinguishable.
Ok, so after testing everything i found out what is wrong however i can't figure out why.. Any Suggestions??
I think that strcmp returns values of either 0 or -1 or 1.
But there was the problem, if i didn't define exactly if strcmp ==1 or if strcmp ==-1 ...i had an infinite loop as it seems (i used a printf command to see what is going on, and i discovered the bug..)
By changing
struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l)
{
if (root==NULL)
{
root = (struct BST_node *) malloc (sizeof(struct 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;
};
to
struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l)
{
if (root==NULL)
{
root= (struct BST_node *)malloc(sizeof(struct 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 if ((strcmp(l->data->email, root->data->data->email)) ==1)
root->right =new_BST_node(root->right,l);
return root;
};
everything works fine..
But why didnt the other code work? I am pretty sure it is the same...

c program to display binary tree but it is not showing any output even it is not showing any error. whtat is the error in this program

#include<stdlib.h>
#include<stdio.h>
struct tree{char info;struct tree *left;struct tree *right;};
struct tree *root;
struct tree *stree(struct tree *root,struct tree *r,char info);
void print_tree(struct tree *root,int l);
int main(void)
{
char s[80];
root=NULL;
do {
printf("enter a letter:");
gets(s);
root=stree(root,root, *s);
}
while(*s); // <- ???
print_tree(root,0);
return 0;
}
struct tree *stree(struct tree *root,struct tree *r,char info;{ // <- ???
if(!r) {
r=(struct tree *) malloc(sizeof(struct tree));
if(!r) {
printf("out of memory \n");
exit(0);
}
r->left=NULL;
r->right=NULL;
r->info=info;
if(!root)
return r;
if(info<root->info)
root->left=r;
else
root->right=r;
return r;}if(info<r->info)stree(r,r->left,info);else
stree(r,r->right,info);return root;}
void print_tree(struct tree *r,int l);
{
int i;
if(!r) return ;
print_tree(r->right,l+1);
for(i=0;i<l;++i)
printf(" ");
printf("%c \n",r->info);
print_tree(r->left,l+1);
}
My guess is not the correct output is, because it is not been updated with the return value of stree.
E.g. if(info<r->info)stree(r,r->left,info); <-- It has been discarded return value.
Your code doesn't compile. So, I rewrite code.
#include <stdio.h>
#include <stdlib.h>
struct tree {
char info;
struct tree *left, *right;
};
struct tree *stree(struct tree *root, char info);//no need `struct tree *r`
void print_tree(struct tree *root, int level);
int main(void){
struct tree *root = NULL;//It does not need to be in a global variable
char letter;
for(;;){
printf("enter a letter:");
if(EOF == scanf("%c", &letter) || letter == '\n')//don't use `gets`
break;
scanf("%*[^\n]");//clear upto newline
scanf("%*c");
root = stree(root, letter);
}
print_tree(root, 0);
//deallocate
return 0;
}
struct tree *stree(struct tree *root, char info){
if(!root){
struct tree *r = malloc(sizeof(*r));
if(!r){
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
r->right = r->left = NULL;
r->info = info;
return r;
}
if(info < root->info)
root->left = stree(root->left, info);
else if(info > root->info)
root->right = stree(root->right, info);
else
;//root->right = stree(root->right, info);
return root;
}
void print_tree(struct tree *r, int level){
if(!r) return ;
print_tree(r->right, level + 1);
printf("%*s%c\n", level, "", r->info);
print_tree(r->left, level + 1);
}

Save structs in a file

I'm doing a program to save a list of contacts in a file whit structs. I've tried a lot of things but when I try go read the file to the program, it doesn't read anything.
This is my program without opening files and saving to files:
#include <stdio.h>
#include <stdlib.h>
struct agenda {
int idContacte;
char name[50];
struct agenda *nextContacte;
};
struct agenda *pAgenda;
struct agenda *pFirst = NULL;
struct agenda *pIndex;
void insert();
void show();
int main()
{
//Menu
int opc;
while(1){
printf("1.Insert Contact.\n");
printf("2.Show Contacts.\n");
printf("3.Exit\n");
scanf("%d", &opc);
switch(opc){
case 1:
insert();
break;
case 2:
show();
break;
case 3:
return 0;
}
}
}
void insert(){
pAgenda = (struct agenda *)malloc(sizeof(struct agenda));
printf("Insert ID: ");
scanf("%d", &pAgenda->idContacte);
printf("Insert the name: ");
scanf("%s", pAgenda->name);
printf("\n");
if (pFirst==NULL || pAgenda->idContacte < pFirst->idContacte)
{
pAgenda->nextContacte=pFirst;
pFirst=pAgenda;
}
else if (pAgenda->idContacte > pFirst->idContacte){
pIndex=pFirst;
while(pIndex->nextContacte && pIndex->nextContacte->idContacte < pAgenda->idContacte)
{
pIndex = pIndex->nextContacte;
}
pAgenda->nextContacte = pIndex->nextContacte;
pIndex->nextContacte = pAgenda;
}
}
void show(){
pIndex = pFirst;
while(pIndex && pIndex->idContacte <= 100) {
printf("\nID: %d", pIndex->idContacte);
printf("\nNAME: %s", pIndex->name);
printf("\n\n");
pIndex = pIndex->nextContacte;
}
}
Can you help me how can I get contact at start of the program from a file, and then when insert a contact, rewrite the file and insert all the contacts again in the file?
When you end your program you should do the following
int save_list(struct agenda *head) {
FILE *save = fopen("file.name", "wb");
if(!save) return -1;
while(head) {
fwrite(head, sizeof *head - sizeof head, 1, save);
head = head->nextContacte;
}
fclose(save);
/* Somebody would free list memory after this function execution */
return 0;
}
At the start of your program you should do the following
struct agenda *restore_list() {
FILE *restore= fopen("file.name", "rb");
struct agenda *head = NULL;
struct agenda *cur = head;
struct agenda temp;
if(!restore) return head;
while( fwrite(&temp, sizeof temp - sizeof head, 1, save) == 1) {
struct agenda *node = malloc( sizeof(struct agenda) );
if(NULL == node) {
/* Handle out of memory error here, free list */
return NULL;
}
*node = temp;
node->nextContacte = NULL;
if(head) {
cur->nextContacte = node;
cur = node;
} else {
/* First node */
head = cur = node;
}
}
fclose(restore);
return head;
}

I m trying to sort the node by score. I do not know what error i am having

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct student{
char firstname[20];
char lastname[20];
double grade;
char zipcode[10];
struct student *next;
};
void display(struct student *first)
{
while (first != NULL)
{
printf("\nFirst name: %s", first->firstname);
printf("\tLast name: %s", first->lastname);
printf("\tGrade: %.2f", first->grade);
printf("\t ZipCode: %s", first->zipcode);
first = first->next;
}
}
/*void add_Record(struct student *first)
{
char r[20];
struct student *t;
t = first;
while (t != NULL)
{
if (t == NULL)
{
first = (struct student*)malloc(sizeof(struct student));
printf("\nEnter the first name of the student:");
scanf("%s", first->firstname);
printf("\nEnter the last name of the student:");
scanf("%s", first->lastname);
printf("\nEnter the score of the student:");
scanf("%lf", &first->grade);
printf("\nEnter the zipcode of the student:");
scanf("%s", first->zipcode);
}
}
}
void del()
{
struct student *back, *t, *k;
char r[10];
int flag = 0;
printf("\nEnter the last name of student you want to delete:");
scanf("%s", r);
if (strcmpi(r, first->lastname) == 0)
{
first = first->next;
flag = 1;
}
else
{
back = first;
k = first->next;
while (k != NULL)
{
if (strcmpi(r, k->lastname) == 0)
{
back->next = k->next;
flag = 1;
break;
}
}
}
if (flag == 0)
printf("\nThe element not found!!!");
}
*/
void search(struct student *first)
{
char r[10];
int flag = 0;
printf("\nEnter the zipcode you want to search:");
scanf("%s", r);
struct student *t;
t = first;
while (t != NULL)
{
if (strcmp(r, t->zipcode) == 0)
{
printf("\nFirst name: %s", t->firstname);
printf("\tLast name: %s", t->lastname);
printf("\tGrade: %.2f", t->grade);
printf("\t ZipCode: %s", t->zipcode);
flag = 1;
break;
}t = t->next;
}
if (flag == 0)
printf("\nThe zipcode not in database!!");
}
void sort(struct student *first)
{
struct student *temp;
temp = NULL;
while (first != NULL)
{
if (first-> grade > first->next->grade)
{
strcpy(temp->firstname, first->firstname);
strcpy(temp->lastname, first->lastname);
temp->grade = first->grade;
strcpy(temp->zipcode, first->zipcode);
strcpy(first->firstname, first->next->firstname);
strcpy(first->lastname, first->next->lastname);
first->grade = first->next->grade;
strcpy(first->zipcode, first->next->zipcode);
strcpy(first->next->firstname, temp->firstname);
strcpy(first->next->lastname, temp->lastname);
first->next->grade = temp->grade;
strcpy(first->next->zipcode, temp->zipcode);
break;
}
}
printf("\nThe sorted record by score are: \n");
display(first);
}
int main(void)
{
struct student *first = NULL, *last = NULL;
struct student *temp;
int n;
printf("\nEnter the number of student:");
scanf("%d", &n);
int i;
for (i = 0; i < n; i++)
{
temp = (struct student*)malloc(sizeof(struct student));
printf("\nEnter the first name of the student:");
scanf("%s", temp->firstname);
printf("\nEnter the last name of the student:");
scanf("%s", temp->lastname);
printf("\nEnter the grade of the student:");
scanf("%lf", &temp->grade);
printf("\nEnter the zipcode of the student:");
scanf("%s", temp->zipcode);
temp->next = first;
first = temp;
}
int o;
o = 1;
while (o != 0)
{
printf("\nMENU\n");
printf("\nEnter 1 for displaying database.");
printf("\nEnter 2 for inserting an record.");
printf("\nEnter 3 for deleting a record by lastname.");
printf("\nEnter 4 for searching a record by zipcode.");
printf("\nEnter 5 for sorting record by score.");
printf("\nEnter 0 for exit!");
printf("\nEnter the choice:");
scanf("%d", &o);
switch (o)
{
case 1:display(first); break;
/*case 2:insertafter(*first); break;
case 3:del(); break;*/
case 4:search(first); break;
case 5: sort(first); break;
case 0:exit(0); break;
default:printf("\nYou have entered a wrong choice!!!");
}
}
}
The problem is that how do i sort the scores by score. My code seems right but doesn't work. I made a temp structure and tried to swap values but it doesn't work. Am i doing the loop wrong? Or all my code is wrong?
Here are two answers to the problem
First one sorts the nodes in the node linked list by bubble sorting them, rearranging the linked list
Second one walks the linked list, copies a pointer to each one into an array and then sorts the array by using the struct grade members, the linked list remains unchanged
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define SWAP(T,x,y) {T *p = &(x); T *q = &(y); T z = *p; *p = *q; *q = z;}
struct student{
char firstname[20];
char lastname[20];
double grade;
char zipcode[10];
struct student *next;
};
struct student *head=NULL;
void add(char *f, char *s, double score) {
struct student *a;
a=(struct student*)malloc(sizeof(struct student));
strcpy(a->firstname,f);
strcpy(a->lastname,s);
a->grade = score;
a->next = head;
head = a;
}
void printout(char *label) {
struct student *node;
printf("%s\n",label);
for(node=head; node !=NULL; node=node->next) {
printf("%s %s %f\n", node->firstname, node->lastname, node->grade);
}
}
int main(int argc, char ** argv){
int mark=8;
struct student *walk, *prev;
add("Bob","Smith",10);
add("Eric","Von Däniken",90);
add("Morris","Minor",91);
add("Master","Bates",9);
add("Zoe","Bodkin",20);
add("Mary","Pippin",30);
/* bubble sort */
printout("before");
prev=head;
while(mark) {
mark=0;
for(walk=head;
walk != NULL;
walk=walk->next) {
if (walk->next && walk->grade > walk->next->grade) {
/* printf("swapping %s %s\n", walk->firstname, walk->next->firstname); */
mark=1;
if (walk == head) {
struct student *v2=walk->next;
struct student *v3=walk->next->next;
SWAP(struct student *, v3->next, v2->next);
SWAP(struct student *, head, v3->next);
walk = v3;
} else {
struct student *v1=prev;
struct student *v2=walk;
struct student *v3=walk->next;
SWAP(struct student *, v3->next, v2->next);
SWAP(struct student *, v1->next, v3->next);
walk = v3;
}
}
prev=walk;
}
}
printout("after");
return 0;
}
second version, uses qsort, retains linked list order
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct student{
char firstname[20];
char lastname[20];
double grade;
char zipcode[10];
struct student *next;
};
struct student *head=NULL;
size_t nodecount=0;
void add(char *f, char *s, double score) {
struct student *a;
a=(struct student*)malloc(sizeof(struct student));
strcpy(a->firstname,f);
strcpy(a->lastname,s);
a->grade = score;
a->next = head;
head = a;
nodecount++;
}
static int cmpgrade(const void *p1, const void *p2) {
struct student *g1, *g2;
g1=*(struct student **)p1;
g2=*(struct student **)p2;
return g1->grade > g2->grade;
}
int main(int argc, char ** argv){
int i;
struct student *walk,**sa, **sap;
add("Bob","Smith",10);
add("Eric","Von Däniken",90);
add("Morris","Minor",91);
add("Master","Bates",9);
add("Zoe","Bodkin",20);
add("Mary","Pippin",30);
/*copy into array of pointers*/
sa=calloc(sizeof (struct student*), nodecount);
sap=sa;
for(walk=head; walk != NULL; walk=walk->next) {
*sap = walk;
sap++;
}
printf("before\n");
for (i=0; i< nodecount; i++) {
printf("%s %s %f\n", sa[i]->firstname, sa[i]->lastname, sa[i]->grade);
}
/* qsort */
qsort(sa, nodecount, sizeof (struct student *), cmpgrade);
printf("after\n");
for (i=0; i< nodecount; i++) {
printf("%s %s %f\n", sa[i]->firstname, sa[i]->lastname, sa[i]->grade);
}
return 0;
}

Resources