postfix calculator having trouble with segfaults - c

i'm trying to create a postfix calculator using linked-list.
when i compile, it doesn't show any errors but when it's executed it would show Segmentation Fault. i don't know how to deal with this, please help.
here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct node {
int num;
struct node *next;
} node;
void push(int num, node **head);
int pop(node **head);
void display(node **head);
int is_empty();
int evaluatePostfix();
struct node *head;
int main() {
head = NULL;
char exp[1000]; // = "5 1 2 + 4 * + 3 -";
printf("Input expression:\t");
fgets(exp, 1000, stdin);
for(int i = 1; i <= strlen(exp); i++) {
if(exp[i] == '\n') {
exp[i] = '\0';
}
else if (exp[0] == '\n') {
printf("stack is empty\n");
exit(0);
}
}
printf("%s = %d\n", exp, evaluatePostfix(exp));
return 0;
}
int evaluatePostfix(char* exp) {
char * token;
int counter = 0;
char temp[256][256];
token = strtok(exp, " ");
while(token != NULL) {
strcpy(temp[counter], token);
counter++;
token = strtok(NULL, " ");
}
for (int i = 0; temp[i]; ++i) {
if (isdigit(*(temp[i]))) {
int val = atoi(temp[i]);
push(val, &head);
}
else {
int val1 = pop(&head);
int val2 = pop(&head);
switch (exp[i]) {
case '+': push(val2 + val1, &head);
printf("%d\n", (*head).num);
break;
case '-': push(val2 - val1, &head); break;
case '*': push(val2 * val1, &head); break;
case '/': push(val1 / val2, &head); break;
}
}
}
return pop(&head);
}
void push (int item, node **head) {
node *temp;
node * get_node(int);
temp = get_node(item);
temp->next = *head;
*head = temp;
}
node *get_node(int item) {
node *temp;
temp = (node*)malloc(sizeof(node));
if (temp == NULL)
printf("\nMemory cannot be allocated");
temp->num = item;
temp->next = NULL;
return(temp);
}
int pop(node **head) {
int item;
node *temp;
item = (*head)->num;
temp = *head;
*head = (*head)->next;
free(temp);
return(item);
}
int is_empty(node *temp) {
if (temp == NULL)
return 1;
else
return 0;
}
void display(node **head) {
node *temp;
temp = *head;
if(head == NULL) {
printf("stack is empty\n");
return;
}
printf("\n");
printf("=========\n");
while(temp!=NULL) {
printf("%d\n", (*temp).num);
temp = (*temp).next;
}
printf("=========\n");
}

Given this declaration ...
char temp[256][256];
... the loop termination condition here is wrong:
for (int i = 0; temp[i]; ++i) {
C multi-dimensional arrays are not Java-style arrays of array references. They are arrays of actual arrays. The expression temp[i] will not be false when i exceeds the number of elements of temp[] into which you have written data.
It looks like you want simply
for (int i = 0; i < counter; ++i) {
. Alternatively, there's no particular need to tokenize before your start the computation. You could as easily combine the two loops in function evaluatePostfix() into one. That would be a bit simpler, and would remove any fixed limit on the number of terms in the expression.
Update: That might look like this:
for (token = strtok(exp, " "); token; token = strtok(NULL, " ")) {
/* ... use token instead of temp[i] ... */
}
It is conceivable that there are other errors in your code as well, though I didn't spot any on my scan through it.

"btw, all identifiers for functions in the Standard Library are reserved.
There is a function exp() in math.h, so exp falls into that category.
Technically, using a reserved identifier in your code results in undefined behaviour."
Thanks for the help guys! Changing exp to another variable name did the trick. here's the working code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct node {
int num;
struct node *next;
} node;
void push(int num, node **head);
int pop(node **head);
void display(node **head);
int is_empty(node *temp);
int evaluate(char *expression);
struct node *head;
int main() {
head = NULL;
char expression[1000]; // = "5 1 2 + 4 * + 3 -";
printf("Input expression:\t");
fgets(expression, 1000, stdin);
for(int i = 1; i <= strlen(expression); i++) {
if(expression[i] == '\n') {
expression[i] = '\0';
}
else if (expression[0] == '\n') {
printf("empty stack\n");
exit(0);
}
}
printf("Answer: %d\n", evaluate(expression) );
return 0;
}
int evaluate(char* expression) {
char * token;
int counter = 0;
char temp[256][256];
token = strtok(expression, " ");
while(token != NULL) {
strcpy(temp[counter], token);
token = strtok(NULL, " ");
counter++;
}
for (int i = 0; i < counter; i++) {
if (isdigit(*(temp[i]))) {
int val = atoi(temp[i]);
push(val, &head);
}
else {
int val1 = pop(&head); //pop the last two values from stack
int val2 = pop(&head);
switch (*(temp[i])) { //perform operation
case '+': push(val2 + val1, &head); break;
case '-': push(val2 - val1, &head); break;
case '*': push(val2 * val1, &head); break;
case '/': push(val1 / val2, &head); break;
}
}
}
return pop(&head);
}
void push (int item, node **head) {
node *temp;
node * get_node(int);
temp = get_node(item);
temp->next = *head;
*head = temp;
}
node *get_node(int item) {
node *temp;
temp = (node*)malloc(sizeof(node));
if (temp == NULL)
printf("\nMemory cannot be allocated");
temp->num = item;
temp->next = NULL;
return(temp);
}
int pop(node **head) {
int item;
node *temp;
item = (*head)->num;
temp = *head;
*head = (*head)->next;
free(temp);
return(item);
}
int is_empty(node *temp) {
if (temp == NULL)
return 1;
else
return 0;
}
void display(node **head) {
node *temp;
temp = *head;
if(head == NULL) {
printf("stack is empty\n");
return;
}
printf("\n");
printf("=========\n");
while(temp!=NULL) {
printf("%d\n", (*temp).num);
temp = (*temp).next;
}
printf("=========\n");
}

Related

Program received signal SIGSEGV, Segmentation fault when asking user input for doubly linked list

I am new to C programming and When I asked user to input a number for some reason my whole program gives this error
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555753 in addData (word=0x7fffffffeb70 "", mode=2) at main.c:202
202 if (temp->next == NULL) {
(gdb)
HERE IS MY CODE
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define MEMORY 6
#define MAX_word_LENGTH 11
int numberOfwords;
char words[MEMORY][MAX_word_LENGTH];
struct Node{
int data;
char *word;
struct Node *next, *prev;
};
struct Node *head, *tail;
struct Node* DlListDeleteLastNode(struct Node *head);
void addData(char *word, int mode);
void DisplayForward();
struct Node* deletePos(struct Node *head, int pos);
int getPostion(char *targetWord);
bool search(char *targetWord);
//struct Node* deletePos(struct Node *head, int pos);
int countWord(char *wording);
void insert_specified(char *wording, int pos);
int countNodes();
//void init(){
// head = NULL;
// tail = NULL;
//}
int main()
{
char name[100];
//char searchName[] = "barr";
printf("Enter number of words to be stored in the word stream: ");
int input;
scanf("%d", &input);
int i;
int count = 0;
for (i=0; i<input;i++){
count++;
printf("\nEnter name %d : ",count);
scanf ("%[^\n]%*c", name);
//scanf("%s[^\n]",words[i]);
addData(name, 2);
}
//for (int i = 0; i <4; i++) {
// strcpy(words[i],
//}
//insert_specified(searchName, 0);
//printf("%d\n", numberOfwords);
//DlListDeleteLastNode();
DisplayForward();
//int num = countNodes();
//printf("count %d", num);
//deletePos(head, 3);
//bool x = search(searchName);
//printf("%d\n", x);
//printf("%d\n", numberOfwords);
//DisplayForward();
//fflush(stdin);
printf("\nEntered names are:\n");
for(i=0;i<6;i++)
puts(words[i]);
}
int isEmpty(struct Node *h){
if(h==NULL)
return 1;
else
return 0;
}
void addData(char *word, int mode){
if (mode == 1) {
for (int i=0; i<5; i++) {
if (strcmp(words[i],word) == 0) {
//printf("found\n");
//printf("FOUND%s\n", word);
int x = getPostion(word);
//printf("index found %d/n", x);
//deletePos(head, x);
struct Node* temp = head;
struct Node* temp2 = NULL;
while (x > 1) {
temp = temp->next;
x--;
}
if (temp->next == NULL) {
head = DlListDeleteLastNode(head);
}
else {
temp2 = temp->prev;
temp2->next = temp->next;
temp->next->prev = temp2;
free(temp);
temp = NULL;
}
break;
}
//x index = getPostion()
}
if (numberOfwords >= 5) {
DlListDeleteLastNode(head);
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
numberOfwords++;
}
else {
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
numberOfwords++;
strcpy(words[numberOfwords], word);
}
}
else {
int flag = 0;
//int numWords = countNodes();
for (int i=0; i<8; i++) {
if (strcmp(words[i],word) == 0) {
//printf("found\n");
//printf("FOUND%s\n", word);
int x = getPostion(word);
//printf("index found %d/n", x);
//deletePos(head, x); //
struct Node* temp = head;
struct Node* temp2 = NULL;
while (x > 1) {
temp = temp->next;
x--;
}
if (temp->next == NULL) {
head = DlListDeleteLastNode(head);
}
else {
temp2 = temp->prev;
temp2->next = temp->next;
temp->next->prev = temp2;
free(temp);
temp = NULL;
}
flag = 1;
//DisplayForward();
//numberOfwords--;
break;
}
//x index = getPostion()
}
printf("\nflag num-> %d\n", flag);
//numberOfwords++;
int numWords = countNodes();
if (numWords >= 5 && flag==0) {
//printf("activated");
int max = 0;
char maxWord[50];
for (int i = 0; i < 8; i++) {
int num = countWord(words[i]);
if (num > max) {
max = num;
//printf("%d", max);
strcpy(maxWord, words[i]);
//printf("word %s\n", maxWord);
}
}
printf("most occured word: %s\n", maxWord);
int mostOccuredWordIndex = getPostion(maxWord);
printf("index: %d\n", mostOccuredWordIndex);
mostOccuredWordIndex--;
insert_specified(word, mostOccuredWordIndex);
DlListDeleteLastNode(head);
}
else if (numWords >= 5) {
//DlListDeleteLastNode(head);
//struct Node *ptr;
//ptr= malloc(sizeof *ptr);
//ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
//Get most occured word in words array
//find the position of the most occured word
//int mostOccuredWordIndex = getPostion(maxWord);
//remove last element and insert new word into that position
//if position is in the last index then remove word and replace with the word
//if (mostOccuredWordIndex == 5) {
// printf("occurred");
//}
//
DlListDeleteLastNode(head);
numberOfwords = numberOfwords + 1;
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
}
else {
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
//char nimI[20];
//baru->nim = malloc(12 * sizeof(char));
//strcpy(ptr->word, word);
if(head==NULL)
{
ptr->next = NULL;
ptr->prev=NULL;
strcpy(ptr->word, word);
//ptr->word= word;
head=ptr;
//head = ptr;
//tail = ptr;
}
else
{
//ptr->word=word;
strcpy(ptr->word, word);
ptr->prev=NULL;
ptr->next = head;
head->prev=ptr;
head=ptr;
}
numberOfwords = numberOfwords + 1;
strcpy(words[numberOfwords], word);
}
DisplayForward();
numWords = countNodes();
printf("\nnumber of words%d \n", numWords);
}
}
struct Node* DlListDeleteLastNode(struct Node *head) {
struct Node *temp = head;
struct Node* temp2;
while (temp->next != NULL) {
temp = temp->next;
}
temp2 = temp->prev;
temp2->next = NULL;
free(temp);
numberOfwords--;
return head;
}
void DisplayForward() {
//Node current will point to head
struct Node *current = head;
if(head == NULL) {
printf("List is empty\n");
return;
}
printf("[");
int count = numberOfwords;
// while current->next != Null
while(current!=NULL) {
//Prints each node by incrementing pointer.
printf("%s, ", current->word);
current = current->next;
count--;
}
//current = current->next;
//printf("%s]\n", current->word);
//printf("%d", numberOfwords);
}
bool search(char *targetWord) {
int pos = 0;
if(head==NULL) {
printf("Linked List not initialized");
return;
}
struct Node *current = head;
//current = head;
while(current!=NULL) {
pos++;
if(strcmp(current->word, targetWord) == 0) {
printf("%s found at position %d\n", targetWord, pos);
return true;
}
if(current->next != NULL)
current = current->next;
else
break;
}
return false;
//printf("%s does not exist in the list\n", targetWord);
}
int getPostion(char *targetWord) {
int pos = 0;
if(head==NULL) {
printf("Linked List not initialized");
return -1;
}
struct Node *current = head;
//current = head;
while(current!=NULL) {
pos++;
if(strcmp(current->word, targetWord) == 0) {
//printf("%s found at position %d\n", targetWord, pos);
return pos;
}
if(current->next != NULL)
current = current->next;
else
break;
}
return -1;
//printf("%s does not exist in the list\n", targetWord);
}
int countWord(char *wording) {
int count = 0;
for(int i=0;i<6;i++) {
if (strcmp(words[i], wording)==0) {
//printf("found word");
count++;
}
}
return count;
}
void insert_specified(char * wording, int pos)
{
struct Node *ptr;
ptr= malloc(sizeof *ptr);
ptr->word = malloc(sizeof(char) * 12);
struct Node *temp;
int i;
if(ptr == NULL)
{
printf("\n OVERFLOW");
}
else
{
//printf("\nEnter the location\n");
//scanf("%d",&loc);
temp=head;
for(i=0;i<pos;i++)
{
temp = temp->next;
if(temp == NULL)
{
printf("\ncan't insert\n");
return;
}
}
strcpy(ptr->word, wording);
ptr->next = temp->next;
ptr -> prev = temp;
temp->next = ptr;
temp->next->prev=ptr;
printf("Node Inserted\n");
}
}
int countNodes() {
int counter = 0;
//Node current will point to head
struct Node *current = head;
while(current != NULL) {
//Increment the counter by 1 for each node
counter++;
current = current->next;
}
return counter;
}
I tried to ask the user for a number of words it wants to input for my program to store the items in a doubly linked list but instead gives a segmentation fault error
struct Node *head is a global variable which is zero initialized. In addData() you set struct Node* temp = head; and then you deference temp like your stack trace shows which will segfault.
Anyways, before you even get there the 2nd scanf() fails as it the input buffer contains the \n from reading the previous number. The syntax of the format string also looks wrong to me. In any case as you don't check the return value of you are operating on uninitialized data. Here is the minimal fix:
if(scanf(" %99[^\n]*", name) != 1) {
printf("scanf failed\n");
return 1;
}
I also replaced the hard-coded < 8 with < MEMORY to avoid a buffer overflow. Here is an example run:
Enter number of words to be stored in the word stream: 2
Enter name 1 : test
flag num-> 0
[test,
number of words1
Enter name 2 : test2
flag num-> 0
[test2, test,
number of words2
[test2, test,
Entered names are:
test
test2

Pointer set to NULL but not in debugger

So I am working o AVL tree, however I cant seem to either get the delete function working nor freeing the tree right. The delete function segfaults everytime, but the free function segfaults when in the debugger.
Here is gdb's stack trace:
#0 0x00007fffd935a87a in msvcrt!_memicmp_l () from C:\WINDOWS\System32\msvcrt.dll
#1 0x0000000000402811 in isPresentRecurs (root=0xb756d0, searchedValue=0xb795b0 "aaa", found=0x61fcec) at ../.source/binTree.c:206
#2 0x00000000004027d6 in isPresent (root=0xb756d0, searchKey=0xb795b0 "aaa") at ../.source/binTree.c:200
#3 0x0000000000401c3d in main () at test.c:110
In my tests I check if the root has been set to NULL, which running it normally does finish however running it inside the debugger does not and instead goes into the else statement:
Minimal Example (test.c):
#include "binTree.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRACE 0
#define MAX_SEARCH_ITEMS 20
void fillTree(binTree **tree);
void fillSearchValues( char **valArray);
void fillTree(binTree** tree){
printf( "Constructing tree\n\n" );
char key[200] ="";
for(int j=1 ;j<4;j++ ){
memset(&key,0,199);
for(int i=0; i<26; i++){
for(int k = 0;k<j;k++) key[k]= i+'a';
Var value;
value.data = malloc(sizeof(varData));
value.data->iData = j;
value.type =INTEGER;
(*tree)->root= insert((*tree)->root,key,value);
if(TRACE) printf("key: %s, value: %d\n",(*tree)->root->key,(*tree)->root->value.data->iData);
}
}
(*tree)->nodeCount = getSizeBinaryTree((*tree)->root);
printf( "\n\nTree constructed\n\n" );
}
void fillSearchValues( char **valArray){
char key[200]="";
for(int j=1 ;j<4;j++ ){
memset(&key,0,199);
for(int i=0; i<26; i++){
if(i*j>MAX_SEARCH_ITEMS) break;
for(int k = 0;k<j;k++) key[k]= i+'a';
*(valArray+i*j) = strdup(key);
if (TRACE)printf ("%s read; %s inserted\n", key, valArray[i*j] );
}
}
}
int main(){
binTree *tree = createNewTree();
fillTree(&tree);
printTree(tree->root);
/* //Fails at delete
for(int i=0;i<26;i++){
char string = i+'a';
tree->root = Delete(tree->root,&string);
}*/
printf("\nFreeing Tree: \n=================================\n");
freeTree(tree->root);
if(tree->root==NULL) printf("Tree has been freed successfully\n");
else printf("Failed to free tree \n");
// searching after freeing
int found =0; int lost =0;
char *values[MAX_SEARCH_ITEMS];
fillSearchValues(values);
for(int i=0;i<MAX_SEARCH_ITEMS;i++){
if(isPresent(tree->root,values[i])){
if (TRACE)printf("found search value %s\n",values[i]);
found++;
}else{
lost++;
if(TRACE)printf("didnot find search value %s\n",values[i]);
}
}
printf("found %d of %d while cleared %d\n", found,MAX_SEARCH_ITEMS,lost);
free(tree);
return 0;
}
binTree.h:
#ifndef BINTREE_H
#define BINTREE_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define COUNT 10
typedef enum TYPE {INTEGER, FLOAT, CHARACTER} TYPE;
typedef union {
float fData;
int iData;
char cData;
} varData;
typedef struct Var{
varData * data;
TYPE type;
} Var;
typedef struct Node{
char* key;
Var value;
int height;
struct Node *left;
struct Node *right;
}Node;
typedef struct binTree{
Node *root;
unsigned int nodeCount;
}binTree;
int max(int a,int b);
binTree *createNewTree();
Node *newNode(char *key,Var value);
void freeTree(Node *node);
void freeNode(Node *node);
Node *insert(Node *node,char *key,Var value);
Node *rightRotate(Node *n);
Node *leftRotate(Node *n);
int height(Node *node);
int getBalance(Node *N);
void printTree(Node *root);
void printTreeS(Node *root,int space);
int isPresent(Node *root,char *searchKey);
void isPresentRecurs(Node *root,char *searchedValue,int *found);
Node *minValueNode(Node *node);
Node *search(Node *node,char *key);
Node *Delete(Node *root,char *key);
int getSizeBinaryTree(Node* root);
#endif
binTree.c
#include "binTree.h"
int max(int a, int b){
return (a > b)? a : b;
}
binTree* createNewTree(){
binTree *t = (binTree *) malloc(sizeof(binTree));
if(!t){
printf("Failed at allocationg tree\n");
exit(-1);
}
t->root = NULL;
return t;
}
Node* newNode(char * key,Var value){
Node *p = (Node*)malloc(sizeof(Node));
if(!p){
printf("Failed at allocationg node\n");
exit(-1);
}
p->key = strdup(key);
p->value = value;
p->left=p->right=NULL;
p->height = 1;
return p;
}
void freeTree(Node* node){
if (node==NULL) return;
freeTree(node->left);
freeTree(node->right);
freeNode(node);
node=NULL;
}
void freeNode(Node *node){
free(node->value.data);
node->value.data = NULL;
free(node->key);
node->key = NULL;
free(node);
node = NULL;
}
Node* insert(Node *node, char *key,Var value){
if (node == NULL) return newNode(key,value);
if ( strcasecmp(key ,node->key)<0) node->left = insert(node->left, key,value);
else if (strcasecmp(key ,node->key)>0) node->right = insert(node->right, key,value);
else if(strcasecmp(key,node->key)==0){
if(memcmp(&value.data,&node->value,sizeof(Var))!=0){
memcpy(&node->value,&value,sizeof(Var));
}
return node;
};
node->height = max(height(node->left),height(node->right))+1;
int balance = getBalance(node);
// Left Left Case
if (balance > 1 && strcasecmp(key, node->left->key)<0)
return rightRotate(node);
// Right Right Case
if (balance < -1 && strcasecmp(key, node->right->key)>0)
return leftRotate(node);
// Left Right Case
if (balance > 1 && strcasecmp(key, node->left->key)>0){
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && strcasecmp(key,node->right->key)<0){
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
Node *rightRotate(Node *n){
Node *leftNode =n->left;
if(!leftNode) return n;
Node *rightOfLeft =leftNode->right;
leftNode->right = n;
n->left = rightOfLeft;
n->height = max(height(n->left), height(n->right)) + 1;
leftNode->height = max(height(leftNode->left), height(leftNode->right)) + 1;
return leftNode;
}
Node *leftRotate(Node *n){
Node *rightNode = n->right;
if(!rightNode) return n;
Node *leftOfright = rightNode->left;
rightNode->left = n;
n->right = leftOfright;
n->height = max(height(n->left), height(n->right)) + 1;
rightNode->height = max(height(rightNode->left), height(rightNode->right)) + 1;
return rightNode;
}
int height(Node *node){
if (!node) return 0;
return node->height;
}
int getBalance(Node *N){
if (N == NULL) return 0;
return height(N->left) - height(N->right);
}
void printTree(Node *root){
printTreeS(root, 0);
}
void printTreeS( Node *root, int space){
if (root == NULL)
return;
space += COUNT;
printTreeS(root->right, space);
printf("\n");
for (int i = COUNT; i < space; i++) printf(" ");
if (root->value.type == CHARACTER)printf("type: CHAR key: %s value: %s\n", root->key, root->value.data->cData);
if (root->value.type == INTEGER)printf("type: INT key: %s value: %d\n", root->key, root->value.data->iData);
if (root->value.type == FLOAT)printf("type: FLOAT key: %s value: %f\n", root->key, root->value.data->fData);
printTreeS(root->left, space);
}
int isPresent(Node* root, char* searchKey){
int found = 0;
isPresentRecurs( root, searchKey, &found );
return found;
}
void isPresentRecurs( Node *root,char *searchedValue,int* found ){
if (root) {
if (strcasecmp(root->key,searchedValue)==0)
*found = 1;
else {
isPresentRecurs(root->left, searchedValue, found);
if (!(*found))
isPresentRecurs( root->right, searchedValue, found);
}
}
}
Node * minValueNode(Node* node){
if(!node) return NULL;
if(node->left )return minValueNode(node->left);
return node;
}
Node *search(Node *node, char *key){
if (node == NULL || strcmp(node->key, key)==0)return node;
if (strcmp(node->key, key)<0) return search(node->right, key);
return search(node->left, key);
}
int getSizeBinaryTree(Node* root){
if (root) return 1 +getSizeBinaryTree( root->left ) + getSizeBinaryTree( root->right );
else return 0;
}
Node* Delete(Node* root,char *key) {
if (root==NULL) return root;
else if (strcasecmp(key ,root->key)>0) root->left =Delete(root->left,key);
else if (strcasecmp(key ,root->key)<0) root->right = Delete(root->right,key);
else {
if(root->right==NULL && root->left==NULL) {
free(root);
root = NULL;
}
else if(root->left!=NULL && root->right==NULL) {
Node* temp = root->left;
root = root->left;
freeNode(temp);
}
else if(root->right!=NULL && root->left==NULL) {
Node* temp = root->right;
root = root->right;
freeNode(temp);
}
else {
Node* temp = minValueNode(root->right);
root->key= temp->key;
root->value = temp->value;
root->right = Delete(root->right,temp->key);
}
}
if(root==NULL) return root;
root->height = 1 + max(height(root->left),height(root->right));
int balance = getBalance(root);
//Left Left Case
if(balance > 1 && getBalance(root->left) >=0) return rightRotate(root);
// Right Right Case
if(balance < -1 && getBalance(root->right) <=0) return leftRotate(root);
// Left Right Case
if(balance > 1 && getBalance(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
//Right Left Case
if(balance < -1 && getBalance(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
This is a mistake:
freeTree(tree->root);
if(tree->root==NULL) printf("Tree has been freed successfully\n");
else printf("Failed to free tree \n");
C uses pass-by-value, so it is not possible for freeTree to set tree->root to NULL.
The line node = NULL; inside the freeTree function sets the function parameter (which is a copy of the argument), it does not modify the argument in the calling context.
The function does free the pointed-to memory, which renders all pointers to that memory indeterminate, so the test tree->root == NULL actually causes undefined behaviour by using an indeterminate value.
Your compiler should warn about a dead-store for node=NULL; , if you do not see a warning then try turning up the warning and/or optimization level in your compiler, or running a static analyzer such as clang-tidy. freeNode has a similar issue.
To fix the problem, either change the calling code, e.g. freeTree(tree->root); tree->root = NULL;, or you will have to use pass-by-pointer, i.e. pass the address of the node you want to free.

How to delete nodes in a doubly linked list

I'm having trouble deleting nodes in a doubly linked list, the program crash and i can't figure out the problem. Can you please help me?
This is the full code that creates new nodes, views them and deletes them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
void Delete(Node * head, Node del)
{
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c;
struct Test test;
Node list = NULL;
Node del = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: printf("\nElement to Delete: ");
scanf("%d", &del->structure.id);
Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
I think the problem is related to the scanf() for the Node del, but i'm not sure. When i just pass list or list->next as second argument to the function Delete() it works. Is everything all right with the code?
int main()
{
...
Node del = NULL;
...
scanf("%d", &del->structure.id);
Your program should crash here. You are dereferencing a null pointer.
Probably you will need to read the user input into a temporary id variable, then search the list for a matching item, and if you find one, then you can try deleting it.
Ok, i added a function that searches for the node to be deleted and i modified a bit the Delete() function, this is the workaround, thank you for the suggestions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->structure.id == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head, struct Test temp)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c;
struct Test test, del;
Node list = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
del value is NULL, but you reference it when you delete.
What you need is to search a node in the list for the givent id and then delete it.

LinkedList with Char (String Issue

So I'm having issue with my code with the structure I'm using. I would like my structure to be able add,retrieve or sort but I'm getting a lot of problem with the structure. It work if I use only number but I need to user 3 string. One for firstname, lastname and phonenumber but I can't figure.
This is the code I'm having right now:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
char first[15];
char last[15];
char phone[12];
struct node *next;
}*head;
void append(int num, char f[15], char l[15],char p[12])
{
struct node *temp, *right;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = num;
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);
right = (struct node *)head;
while (right->next != NULL)
right = right->next;
right->next = temp;
right = temp;
right->next = NULL;
}
void add(int num, char f[15], char l[15],char p[12])
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = num;
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
void addafter(int num, char f[15], char l[15],char p[12],int loc)
{
int i;
struct node *temp, *left, *right;
right = head;
for (i = 1; i<loc; i++)
{
left = right;
right = right->next;
}
temp = (struct node *)malloc(sizeof(struct node));
temp->data = num;
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);
left->next = temp;
left = temp;
left->next = right;
return;
}
void insert(int num, char f[15], char l[15],char p[12])
{
int c = 0;
struct node *temp;
temp = head;
if (temp == NULL)
{
add(num,f,l,p);
}
else
{
while (temp != NULL)
{
if (temp->data<num)
c++;
temp = temp->next;
}
if (c == 0)
add(num,f,l,p);
else if (c<count())
addafter(num,f,l,p, ++c);
else
append(num,f,l,p);
}
}
int delete(int num)
{
struct node *temp, *prev;
temp = head;
while (temp != NULL)
{
if (temp->data == num)
{
if (temp == head)
{
head = temp->next;
free(temp);
return 1;
}
else
{
prev->next = temp->next;
free(temp);
return 1;
}
}
else
{
prev = temp;
temp = temp->next;
}
}
return 0;
}
void display(struct node *r)
{
r = head;
if (r == NULL)
{
return;
}
while (r != NULL)
{
printf("%d ", r->data);
r = r->next;
}
printf("\n");
}
int count()
{
struct node *n;
int c = 0;
n = head;
while (n != NULL)
{
n = n->next;
c++;
}
return c;
}
int main()
{
int i, num;
char fname[15], lname[15], phone[12];
struct node *n;
head = NULL;
while (1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Retrieve\n");
printf("4.Delete\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:
printf("Enter the id, first, last and phone (Separte with space) : ");
scanf("%d %s %s %s", &num,fname,lname,phone);
insert(num,fname,lname,phone);
break;
case 2:
if (head == NULL){
printf("List is Empty\n");
}else{
printf("Element(s) in the list are : ");
}
display(n);
break;
case 3:
//To be made
//scanf("Retrieve this : %d\n", count());
break;
case 4:
if (head == NULL){
printf("List is Empty\n");
}else{
printf("Enter the number to delete : ");
scanf("%d", &num);
if (delete(num))
printf("%d deleted successfully\n", num);
else
printf("%d not found in the list\n", num);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
Thanks for anyone that could explain me the issue and or fix it.
Everywhere you have:
temp->data = num;
add the lines
strcpy(temp->first, f);
strcpy(temp->last, l);
strcpy(temp->phone, p);

Inserting and Removing from Linked List

This is a hashtable implementation.
I have the insert kinda working but how do I return the linked list?
I know that the remove is not done yet but I understand the concept, my problem is returning the adjusted list.
I tried to make the hashtable a global variable but the programming would force when I ran it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
struct node {
char * data;
struct node * next;
};
struct hashtable {
struct node ** table;
int size;
int nentries;
};
struct hashtable * hashtable_new(int size) {
struct hashtable * result;
result = malloc(sizeof(struct hashtable));
result -> size = size;
result -> nentries = 0;
result -> table = malloc(sizeof(struct node) * size);
int i = 0;
for (i = 0; i < result->size; i++) {
result->table[i] = NULL;
// result->table[i]->data = NULL;
}
return result;
}
unsigned hash_string(struct hashtable *this, char * str) {
unsigned hash = 0;
int i = 0;
for ( i = 0; str[i] != '\0'; i++ ) {
hash = hash * 37 + str[i];
}
//return hash;
return hash % this-> size;
}
void hashtable_free(struct hashtable * this) {
int i;
struct node *table_nodes, *current, *next;
for(i = 0; i<this->size; i++) {
table_nodes = this->table[i];
current = table_nodes;
while (current != NULL){
next = current->next;
free(current);
current = next;
}
this->table[i] = NULL;
}
free(&this->table);
free(&this->size);
free(&this->nentries);
free(this);
}
void hashtable_insert(struct hashtable * table, char * string) {
struct node * new_node;
unsigned index = hash_string(table, string);
if(table->table[index] == NULL) {
printf("\nIndex: %d", index);
new_node = malloc(sizeof(struct node));
new_node -> next = table->table[index];
new_node -> data = string;
printf("\nData: %s", new_node->data);
table -> table[index] = new_node;
table -> nentries++;
printf("\n");
} else {
new_node = malloc(sizeof(struct node));
new_node->data = string;
new_node->next = NULL;
struct node * current = table->table[index];
struct node * next;
int size = 1;
while (current != NULL) {
next = current->next;
//if(current->data == string){
//return;
//}
if(current-> next == NULL){
//last element in list
current->next = new_node;
table->nentries++;
size++;
printf("\nIndex: %d", index);
printf("\nSize: %d", size);
printf("\nData: %s", current->next->data);
printf("\n");
return;
}
current = next;
size++;
}
}
}
void remove_hash(struct hashtable * this, char * item) {
//unsigned index = hash_string(this, item);
}
int lookup(struct hashtable * this, char * item) {
struct node *temp;
unsigned int index = hash_string(this, item);
temp = this->table[index];
while(temp != NULL) {
// do something
printf("%s, ", temp->data);
if(temp->data == item) {
printf("found %s\n", temp->data);
}
temp = temp->next;
}
return 0;
}
void print(struct hashtable * this) {
int i = 0;
printf("\n Size %d \n", this->size);
if(this == NULL) {
printf("Please construct the hashtable");
return;
}
for (i = 0; i < this->size; i++) {
if(this->table[i] == NULL) {
printf("\n %d: <empty>", i);
} else {
printf("\n %d: %s ", i, this->table[i]->data);
if(this->table[i]->next != NULL) {
printf("%s ", this->table[i]->next->data);
}
}
}
}
int main(int argc, char **argv) {
//struct node *theNode;
struct hashtable *theHash;
theHash = hashtable_new(9);
hashtable_insert(theHash, "I");
hashtable_insert(theHash, "am");
hashtable_insert(theHash, "a");;
hashtable_insert(theHash, "fish");
hashtable_insert(theHash, "glub");
print(theHash);
hashtable_insert(theHash, "glub");
lookup(theHash, "I");
print(theHash);
//printf("\n\n\n");
hashtable_free(theHash);
//print(theHash);
return 0;
}
Since C doesn't let you pass by reference, you can try returning the hashtable then reassigning your variable with the result of hashtable_insert:
struct hashtable *hashtable_insert(struct hashtable *table, char *string) {
// awesome code here
return current;
}
And then call it with:
theHash = hashtable_insert(theHash, "Wow!");

Resources