".exe file has stopped working" when run - c

The program below compiles fine, but gives the error ".exe file ahs stopped working" when I run it. Please help. Any suggestions?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 500
struct key
{
int item;
struct key *left;
struct key *right;
};
typedef struct key star;
void make_tree(star *link, int j, char a[]);
int find_num_of_leaves(star *node);
star *tree;
char input[MAXSIZE];
int main()
{
int i=0;
int num;
printf("Enter the number:\n");
scanf("%[^\n]", input);
tree = (star *) malloc(sizeof(star));
tree->item = -1;
make_tree(tree, i, input);
printf("#######");
num = find_num_of_leaves(tree);
printf("#######");
printf("\n\n%d", num);
return(0);
}
void make_tree(star *link, int j, char a[])
{
if(a[j] == '\0')
{
link->left = NULL;
link->right = NULL;
return;
}
if(a[j+1] == '\0')
{
link->right = NULL;
return;
}
if(int(a[j]) > 0)
{
link->left = (star *) malloc(sizeof(star));
(link->left)->item = a[j];
return make_tree(link->left, j+1, a);
}
if(((10*int(a[j])) + int(a[j+1])) <= 26)
{
link->right = (star *) malloc(sizeof(star));
(link->right)->item = (10*int(a[j])) + int(a[j+1]);
return make_tree(link->right, j+1, a);
}
}
int find_num_of_leaves(star *node)
{
if(node == NULL)
return 0;
if(node->left == NULL && node->right == NULL)
return 1;
else
return find_num_of_leaves(node->left) + find_num_of_leaves(node->right);
/*if(node->left == NULL)
find_num_of_leaves(node->right);
if(node->right == NULL)
find_num_of_leaves(node->left);
if(node->right != NULL && node->left != NULL)
{
find_num_of_leaves(node->left);
find_num_of_leaves(node->right);
}*/
}

When doing make tree your link->left does not get initialised if the code passes through this bit:
(for instance, if you enter a single digit into the console)
if(a[j+1] == '\0')
{
link->right = NULL;
return;
}
Hence, when your code calls find_num_of_leaves which, in turn calls find_num_of_leaves, it crashes when it tries to dereference the left part of the node.

Related

Using getchar() to read text with no trailing newline

I'm working on a program with the goal of reading parentheses/brackets and figuring out if they are balanced on each side, but am running into trouble when reading the last line of text. This may be a little confusing, but I'll attach the input:
3 <-- The number of lines I'll scan
([]) <-- Problem
(([{}])))
([()[]()])()
My program works perfectly when faced with manual input; that is when I input each line myself and press enter. When I copy a block of text though, the program fails to print the final answer (yes or no) unless I press enter. This is my code :
#include <stdio.h>
#include <stdlib.h>
#ifndef status_h
#define status_h
enum status { SUCCESS, FAILURE };
typedef enum status Status;
enum boolean { TRUE, FALSE };
typedef enum boolean Boolean;
#endif
typedef void* NODE;
struct node {
char data;
struct node* next;
} *head;
typedef struct node Node;
void stack_init_default(Node* hStack);
int stack_empty(void);
char stack_top(Node* hStack);
NODE stack_pop(Node* hStack);
NODE stack_push(Node* hStack, char item);
void stack_destroy(void);
int main(int charc, char* argv[])
{
char x;
int num, error = 0, i;
Node* stack;
stack_init_default(stack);
scanf("%d ", &num);
for (i = 0; i < num; i++)
{
stack_destroy();
error = 0;
while ((x = getchar()) != '\n' )
{
if (x == ' ')
continue;
if ((x == '(')||(x == '[')||(x == '{'))
{
stack_push(stack, x);
}
else if ((x == ')')&&(stack_top(stack)=='('))
{
stack_pop(stack);
}
else if ((x == ']')&&(stack_top(stack)=='['))
{
stack_pop(stack);
}
else if ((x == '}')&&(stack_top(stack)=='{'))
{
stack_pop(stack);
}
else
{
error = 1;
}
}
putchar('\n');
if (stack_empty() == 0 || error == 1)
{
printf("No");
}
else
{
printf("Yes");
}
}
printf("\n");
return 0;
}
void stack_init_default(Node* hStack)
{
head = NULL;
}
NODE stack_push(Node* hStack, char item)
{
Node* tmp = (Node*)malloc(sizeof(Node));
if(tmp == NULL)
{
exit(0);
}
tmp->data = item;
tmp->next = head;
head = tmp;
return head;
}
NODE stack_pop(Node* hStack)
{
Node* tmp = head;
head = head->next;
free(tmp);
return head;
}
char stack_top(Node* hStack)
{
if (head == NULL)
{
return '\0';
}
return head->data;
}
int stack_empty(void)
{
return (head == NULL);
}
void stack_destroy(void)
{
Node* phStack = head;
while (head != NULL)
{
phStack = head->next;
free(head);
head = phStack;
}
free(phStack);
head = NULL;
}
My issue looks like this:
3
([])
(([{}])))
([()[]()])()
Yes
No
Yes
So my program outputs yes or no, but freezes on the last problem, waiting for me to press newline to finish the loop. I assume that the issue lies somewhere with the while loop, and that because the pasted text doesn't have a final newline the loop never ends, but I'm unsure how to fix this. Thanks for any help.

Cannot delete vowels from singly linked list

I am having an issue while deleting the vowel from a linked List. The program accept command line arguments, combines them in a single string and add each character to a linked list as node.
When i try to run the program with command line argument "lemon", the successfully deletes the vowels. i.e the program deletes the vowels successfully if the argument doesn't contain consequetive vowels.
On the other hand, if i try to do the same with command line argument "aeiou", the program crashes with message Segmentation fault(core dumped).. I am not getting any idea how to handle this..
The program must not create any global variables so i've used double pointer.
All the functions are working properly this problem may have occured due to some mistakes in locate() and removeVowels() function but i cannot figure out what the mistake is.
can this problem be solved using double pointer??
I cannot figure out what is wrong in this program.. I am new to c programming, please help me with this.. Please rectify me..
Thanks in advance.
The complete code is given below:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct linkedList {
char ch;
struct linkedList *node;
};
void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locate(struct linkedList**);
int delHead(struct linkedList **);
void removeVowels(struct linkedList**);
int isEmpty(struct linkedList **);
int main(int argc, char *argv[]) {
int choice, indexer = 0;
struct linkedList *s;
char *string;
if (argc == 1) {
printf("Parse a sentence");
} else {
s = (struct linkedList *) malloc(sizeof(struct linkedList));
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, &indexer);
while (1) {
printMenu();
scanf("%d", &choice);
if (choice == 1) {
printLinkedList(&s);
} else if (choice == 2) {
if (!delHead(&s))
printf("Failed.Empty linked list");
} else if (choice == 3) {
removeVowels(&s);
} else if (choice == 4) {
if(isEmpty(&s)){
printf("Empty LinkedList");
}
else
printf("Not Empty");
} else if (choice == 5) {
break;
} else
printf("Invalic choice");
printf("\n");
}
}
return 0;
}
int isEmpty(struct linkedList **s){
if(*s == NULL)
return 1;
else
return 0;
}
struct linkedList *locate(struct linkedList **s) {
if ((*s)->node->ch == 'a' || (*s)->node->ch == 'e' || (*s)->node->ch == 'i'
|| (*s)->node->ch == 'o' || (*s)->node->ch == 'u'
|| (*s)->node->ch == 'A' || (*s)->node->ch == 'E'
|| (*s)->node->ch == 'I' || (*s)->node->ch == 'O'
|| (*s)->node->ch == 'U') {
return *s;
} else if ((*s)->node->node == NULL) {
return NULL;
} else
return locate(&((*s)->node));
}
void removeVowels(struct linkedList **s) {
struct linkedList *temp, *tag;
/* Checking whether the first node is null or not */
if ((*s)->ch == 'a' || (*s)->ch == 'e' || (*s)->ch == 'i'
|| (*s)->ch == 'o' || (*s)->ch == 'u'
|| (*s)->ch == 'A' || (*s)->ch == 'E'
|| (*s)->ch == 'I' || (*s)->ch == 'O'
|| (*s)->ch == 'U')
delHead(s);
do {
tag = locate(s);
if (tag != NULL) {
temp = tag->node->node;
free(tag->node);
tag->node = temp;
}
} while (tag != NULL);
}
int delHead(struct linkedList **s) {
struct linkedList *temp;
if ((*s) == NULL) {
return 0;
} else {
temp = (*s)->node;
free(*s);
*s = temp;
return 1;
}
}
void printLinkedList(struct linkedList **s) {
if ((*s) != NULL) {
printf("%c", (*s)->ch);
printLinkedList(&(*s)->node);
}
return;
}
void addTolinkedList(char *str, struct linkedList **s, int *indexer) {
if (*indexer == strlen(str)) {
*s = NULL;
return;
} else {
(*s)->ch = *(str + *indexer);
(*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
++*indexer;
addTolinkedList(str, &(*s)->node, indexer);
}
}
char * combineWithNoSpaces(int argc, char *argv[]) {
int i, j;
int count = 0;
int memory = 0;
char *str;
for (i = 1; i < argc; i++) {
for (j = 0; j < strlen(argv[i]); j++) {
++memory;
}
}
str = (char *) malloc(memory * sizeof(char) + 1);
for (i = 1; i < argc; i++) {
for (j = 0; j < strlen(argv[i]); j++) {
*(str + count) = argv[i][j];
++count;
}
}
return str;
}
void printMenu(void) {
printf("\n\n"
"1. print input arguments (no spaces)\n"
"2. remove first character\n"
"3. remove vowels\n"
"4. is the linked list empty?\n"
"5. exit program\n"
"Enter your choice>");
}
The screen shot for output is :
For argument lemon
For argument aeiou
This code works to my satisfaction. It is more nearly an MCVE (Minimal, Complete, Verifiable Example.
I called the program rv19. When run like this, it gives the output shown:
$ rv19 apple
[apple]
[ppl]
$ rv19 nutmeg
[nutmeg]
[ntmg]
$ rv19 ply
[ply]
[ply]
$ rv19 aeiou
[aeiou]
[]
$ rv19 aardvark abstemiously facetiously aeiou minions lampoon shampoo
[aardvarkabstemiouslyfacetiouslyaeiouminionslampoonshampoo]
[rdvrkbstmslyfctslymnnslmpnshmp]
$
The code (rv19.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct linkedList
{
char ch;
struct linkedList *node;
};
char *combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locate(struct linkedList **);
int delHead(struct linkedList **);
void removeVowels(struct linkedList **);
void freeLinkedList(struct linkedList *);
int main(int argc, char *argv[])
{
int indexer = 0;
struct linkedList *s;
char *string;
if (argc == 1)
{
printf("Parse a sentence. Usage: %s word [word ...]\n", argv[0]);
}
else
{
s = (struct linkedList *) malloc(sizeof(struct linkedList));
printf("s = %p\n", (void *)s);
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, &indexer);
printLinkedList(&s);
removeVowels(&s);
printLinkedList(&s);
printf("s = %p\n", (void *)s);
freeLinkedList(s);
free(string);
}
return 0;
}
static inline int isvowel(char c)
{
return(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U');
}
struct linkedList *locate(struct linkedList **s)
{
if ((*s)->node == NULL)
return NULL;
if (isvowel((*s)->node->ch))
{
return *s;
}
else if ((*s)->node == NULL)
{
return NULL;
}
else
return locate(&((*s)->node));
}
void removeVowels(struct linkedList **s)
{
struct linkedList *temp, *tag;
/* Remove leading vowels */
while ((*s) != NULL && isvowel((*s)->ch))
{
//printf("Remove leading '%c'\n", (*s)->ch);
struct linkedList *ts = *s;
delHead(&ts);
*s = ts;
}
struct linkedList *n = *s;
while (n != NULL && (tag = locate(&n)) != NULL)
{
/* Remove multiple embedded or trailing vowels */
while (tag->node != NULL && isvowel(tag->node->ch))
{
temp = tag->node;
tag->node = tag->node->node;
free(temp);
}
n = tag->node;
}
}
int delHead(struct linkedList **s)
{
struct linkedList *temp;
if ((*s) == NULL)
return 0;
else
{
temp = (*s)->node;
free(*s);
*s = temp;
return 1;
}
}
void printLinkedList(struct linkedList **s)
{
struct linkedList *n = *s;
putchar('[');
while (n != NULL)
{
putchar(n->ch);
n = n->node;
}
putchar(']');
putchar('\n');
}
void addTolinkedList(char *str, struct linkedList **s, int *indexer)
{
if (*indexer == (int)strlen(str))
{
free(*s);
*s = NULL;
}
else
{
(*s)->ch = *(str + *indexer);
(*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
++*indexer;
addTolinkedList(str, &(*s)->node, indexer);
}
}
char *combineWithNoSpaces(int argc, char *argv[])
{
int argl[argc+1];
int memory = 0;
for (int i = 1; i < argc; i++)
{
argl[i] = strlen(argv[i]);
memory += argl[i];
}
char *str = (char *) malloc(memory + 1);
char *base = str;
for (int i = 1; i < argc; i++)
{
strcpy(base, argv[i]);
base += argl[i];
}
return str;
}
void freeLinkedList(struct linkedList *node)
{
while (node != NULL)
{
struct linkedList *next = node->node;
free(node);
node = next;
}
}
This is still not as polished as it could be. I changed the printing so as to get a marker before the start and after the end of the output; it is easier to see unwanted blanks and other characters like that. It's now iterative. I'd change the interface to the function, too, so it takes a struct linkedList * instead of a struct linkedList **. The code in removeVowels() is tricky; it iterates to remove repeated initial vowels; it iterates to remove repeated vowels after a non-vowel. The locate() function now returns a pointer to a non-vowel node that has a vowel in the next node. This code frees both the string and the list (using a new function, freeLinkedList() to free the list).
I've checked it with a couple of debugging versions of malloc(), and it seems to be leak free and corruption free.
I still haven't run it with valgrind because I can't get it to run properly after building it on macOS Sierra 10.12:
valgrind: mmap-FIXED(0x0, 253952) failed in UME (load_segment1) with error 12 (Cannot allocate memory).
This was with the latest code downloaded from SVN (revision 16097).
I tried to simplify all the functions -- some were taking (pointers to) pointers as arguments when they needn't do so.
A few highlights of the many changes:
main: changed the main control structure to a switch statement. Initialized the linkedList pointer to NULL instead of a malloc'd one as entering an empty string would cause addTolinkedList() to leak this memory. Added a call to new function freeLinkedList() when the exit option is selected.
locate: renamed this locateVowel() and restructured with removeVowel() to have only one place that actually looks for vowels. Removed potential memory leak.
combineWithNoSpaces: rewrote this to be string oriented instead of character oriented.
addTolinkedList: made the index(er) argument a simple int that gets incremented on recursion which simplified a number of issues.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct linkedList {
char ch;
struct linkedList *node;
};
void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int);
void printLinkedList(struct linkedList *);
struct linkedList **locateVowel(struct linkedList **);
bool delHead(struct linkedList **);
void removeVowels(struct linkedList **);
bool isEmpty(struct linkedList *);
void freeLinkedList(struct linkedList *);
int main(int argc, char *argv[]) {
int choice;
char *string;
if (argc == 1) {
fprintf(stderr, "Enter a sentence\n");
return EXIT_FAILURE;
}
struct linkedList *s = NULL;
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, 0);
free(string);
while (true) {
printMenu();
(void) scanf("%d", &choice);
printf("\n");
switch (choice) {
case 1:
printLinkedList(s);
break;
case 2:
if (!delHead(&s)) {
printf("Failed. Empty linked list\n");
}
break;
case 3:
removeVowels(&s);
break;
case 4:
if (isEmpty(s)) {
printf("Empty LinkedList\n");
} else {
printf("Not Empty\n");
}
break;
case 5:
freeLinkedList(s);
return EXIT_SUCCESS;
default:
printf("Invalid choice\n");
}
}
return EXIT_SUCCESS;
}
bool isEmpty(struct linkedList *s) {
return (s == NULL);
}
struct linkedList **locateVowel(struct linkedList **s) {
if (*s == NULL) {
return NULL;
}
char ch = tolower((*s)->ch);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
return s;
}
return locateVowel(&((*s)->node));
}
void removeVowels(struct linkedList **s) {
struct linkedList **vowel;
while ((vowel = locateVowel(s)) != NULL) {
struct linkedList *temporary = (*vowel)->node;
if (temporary == NULL) {
free(*vowel); // a vowel with nothing following it
*vowel = NULL;
break;
}
(*vowel)->ch = temporary->ch;
(*vowel)->node = temporary->node;
free(temporary);
s = vowel;
}
}
bool delHead(struct linkedList **s) {
if (*s == NULL) {
return false;
}
struct linkedList *temporary = (*s)->node;
free(*s);
*s = temporary;
return true;
}
void printLinkedList(struct linkedList *s) {
printf("\"");
while (s != NULL) {
printf("%c", s->ch);
s = s->node;
}
printf("\"\n");
}
void addTolinkedList(char *string, struct linkedList **s, int index) {
if (index == strlen(string)) {
*s = NULL;
} else {
*s = malloc(sizeof(struct linkedList));
(*s)->ch = string[index];
(*s)->node = NULL;
addTolinkedList(string, &(*s)->node, index + 1);
}
}
char *combineWithNoSpaces(int argc, char *argv[]) {
int characters = 0;
for (int i = 1; i < argc; i++) {
characters += strlen(argv[i]);
}
char *string = calloc(characters + 1, 1);
for (int i = 1; i < argc; i++) {
(void) strcat(string, argv[i]);
}
return string;
}
void freeLinkedList(struct linkedList *s) {
while (s != NULL) {
struct linkedList *temporary = s;
s = s->node;
free(temporary);
}
}
void printMenu(void) {
printf("\n"
"1. print string (no spaces)\n"
"2. remove first character\n"
"3. remove vowels\n"
"4. is the linked list empty?\n"
"5. exit program\n"
"Enter your choice: ");
}

C passing pointer of a rbtree member of a struct for further processing

I want to read all pInd out of my rbtree neighbourList and store them in an array. The int pInd is simply the index for another array where I want to change values according to the stored adresses in my rbtree.
I have a array of structs (Pixel) and rbtree within each pixel holding the adress of neigbours.
//File rbtree.h
typedef struct rbtree_node_t {
int rInd;
int pInd;
struct rbtree_node_t* left;
struct rbtree_node_t* right;
struct rbtree_node_t* parent;
enum rbtree_node_color color;
} *rbtree_node;
typedef struct rbtree_t {
rbtree_node root;
} *rbtree;
//File rbtree.c
rbtree rbtree_create() {
rbtree t = malloc(sizeof(struct rbtree_t));
t->root = NULL;
verify_properties(t);
return t;
}
//----------------------------------------
//File main.c
typedef struct _Pixel
{
int mean;
rbtree neighbourList;
int index;
}Pixel;
void init(Pixel* p)
{
...
r[index].neighbourList = rbtree_create();
...
}
//----------------------------------------
void changepixel(Pixel* p,int index)
{
int *arr=NULL;
int i;
int size;
rbtree npl = r[index].neigbourList;
size = count(npl);
arr = calloc(size, sizeof(int));
AddNodeToArray(npl, arr, 0);
for (i=0; i<size; i++)
{
printf("arr[%d]: %d\n", i, arr[i]);
}
}
int AddNodeToArray(rbtree node, int arr[],int i);
{
if(node == NULL)
return i;
arr[i] = node->pInd;
i++;
if(node->left != NULL)
i = AddNodeToArray(node->left, arr, i);
if(node->right != NULL)
i = AddNodeToArray(node->right, arr, i);
return i;
}
int count(rbtree* node)
{
int c = 1;
if (node == NULL)
return 0;
else
{
c += count(node->left);
c += count(node->right);
return c;
}
}
//------------------------------
Pixel *p;
p = malloc((nx*ny)*sizeof(struct _Pixel));
Pixel p = r[10];
print_tree(p.npList);
changepixel(p,p.label);
Could someone explain me why printing the tree with
void print_tree_helper(rbtree_node n, int indent);
void print_tree(rbtree t) {
print_tree_helper(t->root, 0);
puts("");
}
void print_tree_helper(rbtree_node n, int indent) {
int i;
if (n == NULL) {
fputs("<empty tree>", stdout);
return;
}
if (n->right != NULL) {
print_tree_helper(n->right, indent + INDENT_STEP);
}
for(i=0; i<indent; i++)
fputs(" ", stdout);
if (n->color == BLACK)
printf("%d(%d)_bl\n", (int)n->rInd,(int)n->pInd);
else
printf("<%d>(%d)_re\n", (int)n->rInd,(int)n->pInd);
if (n->left != NULL) {
print_tree_helper(n->left, indent + INDENT_STEP);
}
}
works whereas my change doesen't? Or how to make it working using all the adresses found in a three for further working with these values?
GCC gives the error:
in function 'count' and in function 'AddNodeToArray'
request for member 'left' in something not a structure or union
Thank you in advance.
There are too many mistakes in your code. But for count and AddNodeToArray the main problem is that you confused with rbtree_node and rbtree types. rbtree_node is the struct with data you need, but rbtree is the struct with only one member - pointer to the root of the tree of type rbtree_node.
I could not test your code to point all of the errors, at least because it's not complete. However I guess to correct it you could try this.
count should be
int count_helper(rbtree_node node) {
int c = 1;
if (node == NULL)
return 0;
else {
c += count_helper(node->left);
c += count_helper(node->right);
return c;
}
}
int count(rbtree tree) {
if (tree == NULL)
return 0;
else {
return count_helper(tree->root);
}
}
and AddNodeToArray something like this
int AddNodeToArray_helper(rbtree_node tree, int arr[], int i) {
if(node == NULL)
return i;
arr[i] = node->pInd;
i++;
if(node->left != NULL)
i = AddNodeToArray_helper(node->left, arr, i);
if(node->right != NULL)
i = AddNodeToArray_helper(node->right, arr, i);
return i;
}
int AddNodeToArray_helper(rbtree tree, int arr[], int i) {
return AddNodeToArray_helper(tree->root, arr, i);
}

finding a dangling pointer

I have a problem with my code. I am getting a segmentation fault error, which I understand is a dangling pointer problem(generally) or a faulty allocation of memory. The compiler dose not show at what line the problem might be, so my question is how do I detect these problems for further concern? and where would my problem be in the code?
here is my code:
`#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
#define ALPHABET_SIZE (256)
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
#define LEVELS 255
// trie node
struct n
{
char value,level,isLeaf;
struct n* children[ALPHABET_SIZE];
struct n* failLink;
};
typedef struct n node;
//trie
struct t
{
node *root;
int count;
};
typedef struct t trie;
void bytesCpy(char *to, char *from, int len)
{
int i;
for(i=0;i<len;i++)
{
to[i]=from[i];
}
}
// Returns new trie node (initialized to NULLs)
node *getNode(trie *t, char value,char level)
{
node *pNode = NULL;
pNode = (node *)malloc(sizeof(node));
if (pNode)
{
printf("ok\n");
int i;
for (i = 0; i < ALPHABET_SIZE; i++)
{
pNode->children[i] = NULL;
}
pNode->failLink = t->root;
pNode->value=value;
pNode->level=level;
pNode->isLeaf=0;
}
else
printf("error\n");
return pNode;
}
// Initializes trie (root is dummy node)
void initialize(trie *t)
{
t->root = getNode(t, '[', 0);
//t->count = 0;
}
// If not present, inserts key into trie
// If the key is prefix of trie node, just marks leaf node
void insert(trie *t, char key[], int len)
{
int level;
char value;
node *node = t->root;
for (level = 0; level<len; level++)
{
value = key[level];
printf("value: %c\n",value);
if (node->children[value] == NULL)
{
node->children[value] = getNode(t, value, level+1);
}
node = node->children[value];
}
node->isLeaf=1;
}
// Returns non zero, if key presents in trie
int search(trie *t, char key[])
{
int level;
int length = strlen(key);
int value;
node *node;
node = t->root;
for (level = 0; level < length; level++)
{
value = key[level];//CHAR_TO_INDEX(key[level]);
if (!node->children[value])
{
node = node->failLink;
return 0;
}
node = node->children[value];
}
return (0 != node);// && node->value);
}
void search1(trie *t, char *c, int len)
{
node *curNode = t->root;
int i;
for(i=0; i<=len; i++)
{
printf("i=%d curnode=%p\n",i,curNode);
if(curNode->isLeaf) //leaf: cuvant gasit
{
printf("if1 curGasit \n");
do{
curNode=curNode->failLink;
if(curNode->isLeaf)
printf("if1 curGasit \n");
else break;
}while(1);
continue;
}
else //nu e gasit inca
{
if(curNode->children[c[i]]==NULL) //fail
{
printf("if2\n");
curNode = curNode->failLink;
continue;
}
else //litera gasita: go on
{
printf("el2\n");
curNode=curNode->children[c[i]];
}
}
}
printf("end of search\n");
}
node* searchAux(trie *t, node *curRoot, char cuv[], char len, int level ,int failLevel)
{
char cuvAux[1024];
bytesCpy(cuvAux,cuv,len);
printf("searchAux level:%d cuvAux:%s curRootLevel:%d\n",level,cuvAux,curRoot->level);
if(cuvAux[level+1] == '\0') //got to the end of cuvAux
{
printf("1st if\n");
return curRoot;
}
if(curRoot->children[cuvAux[level+1]] == NULL) //fail: letter not found
{
printf("3rd if\n");
return searchAux(t, t->root, &cuvAux[failLevel+1], len, 0, failLevel+1);
}
else //letter found: go on
{
printf("3rd else\n");
if(cuvAux[level+2] == '\0') //the found letter was the last of the string
{
printf("4th if\n");
return curRoot->children[cuvAux[level+1]]; //return final pointer
}
else //the found letter was not the last of the string: continue with the next one
{
printf("4th else\n");
return searchAux(t, curRoot->children[cuvAux[level+1]], cuvAux, len, level+1, failLevel);
}
}
}
void createFailLinks(trie *t, node* curRoot, char cuv[], int level)
{
int i;
char cuvAux[1024];
bytesCpy(cuvAux,cuv,1024);
if(curRoot == NULL)
return;
for(i=0;i<ALPHABET_SIZE/*curRoot->children[i] != NULL*/;i++)
{
if(curRoot->children[i] == NULL)
continue;
else
{
cuvAux[level] = curRoot->children[i]->value;
printf("createFailLinks %c%d\n",cuvAux[level],curRoot->children[i]->level);
curRoot->children[i]->failLink = searchAux(t, t->root, cuvAux, level+1, 0, 0);
createFailLinks(t,curRoot->children[i],cuvAux,level+1);
}
}
printf("got\n");
}
void printTrie(node *curRoot)
{
int i;
if(curRoot == NULL)
return;
printf("%c: ", curRoot->value);
for(i=0;i<ALPHABET_SIZE;i++)
if(curRoot->children[i] != NULL)
{
printf("%c ", i);
}
printf("\n");
for(i=0;i<ALPHABET_SIZE;i++)
if(curRoot->children[i] != NULL)
{
printTrie(curRoot->children[i]);
}
}
void checkLinks(node* curRoot)
{
int i;
if(curRoot == NULL)
return;
printf("node %c%d: ",curRoot->value,curRoot->level);
for(i=0;i<256;i++)
if(curRoot->children[i] != NULL)
printf("\n\t%c%d:%c%d",curRoot->children[i]->value, curRoot->children[i]->level, curRoot->children[i]->failLink->value,curRoot->children[i]->failLink->level);
printf("\n");
for(i=0;i<256;i++)
if(curRoot->children[i] != NULL)
checkLinks(curRoot->children[i]);
}
int mai()
{
FILE *fd = fopen("VirusDatabase.txt","r");//O_RDONLY);
int i;
char c;
for(i=0;i<1000;i++)
{
fscanf(fd, "%c", &c);
printf("%c",c);
}
}
int main()
{
// Input keys (use only 'a' through 'z' and lower case)
char keys[][1024] = { "he", "she", "her", "his", "heres"};
char cuv[] = {'\0','\0','\0','\0','\0','\0'};
trie t;
char output[][32] = { "Not present in trie", "Present in trie" };
int i;
char text[]={"andreiherutshevlastashecristihiskatjaheres"};
initialize(&t);
// Construct trie
for (i = 0; i < ARRAY_SIZE(keys); i++)
{
insert(&t, keys[i], strlen(keys[i]));
}
createFailLinks(&t, t.root, cuv, 0);
printTrie(t.root);
printf("\n\n");
checkLinks(t.root);
search1(&t, text, strlen(text));
return 0;
// Search for different keys
printf("%s --- %s\n", "abcd", output[search(&t, "abcd")]);
printf("%s --- %s\n", "ab", output[search(&t, "ab")]);
printf("%s --- %s\n", "ccdd", output[search(&t, "ccdd")]);
printf("%s --- %s\n", "thaw", output[search(&t, "thaw")]);
return 0;
char a = getchar();
}`
Do you have access to a debugger? I ran your code in a debugger and get a memory access violation at line 157 here:
return searchAux(t, t->root, &cuvAux[failLevel+1], len, 0, failLevel+1);
You seem to be recursively calling searchAux. ie you have:
node* searchAux(trie *t, node *curRoot, char cuv[], char len, int level ,int failLevel)
{
char cuvAux[1024];
...
return searchAux(t, t->root, &cuvAux[failLevel+1], len, 0, failLevel+1);
...
Anyway, eventually the buffer size variable failLevel exceeds the size of your buffer so you are attempting to access memory outside the bounds of your array which is why you get an access violation.
The easiest way to debug is use an interactive debugger. On Windows there is a free version of Visual Studio with a very good debugger. On linux you can use GDB.
Failing that you can embed print statements to print out variables before the crash.
You can add print statements at lines of code.
#include <iostream>
std::cout << "At Line: " << __LINE__ << endl;
putting that at various lines of code, you can see what lines got executed, and find where it crashes.
This is for C++. My bad. Same idea, but put printf() statements and see where it stopped executing to narrow down the crash location.

Creating a binary search tree in C99

I've got a programming class assignment due tonight at 8 PM CDT that I'm having trouble with. We are to take a list of the following numbers via reading a file:
9
30
20
40
35
22
48
36
37
38
place them in an array (easy enough), and then read these into a binary search tree using C. The first number in the list is the number of elements in the tree. The rest are placed into the following struct:
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
I think I've got the first part down pat. Take the stuff in using fscanf (I didn't choose to use this method, I like fgets better), call an insertion function on each member of the array, then call a "createNode" function inside the insertion function.
Problem is, I'm only getting one member into the BST. Furthermore, the BST must satisfy the condition node->left->data <= node->data < node->right->data... in other words, the nodes must be in order in the tree.
Here's what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct {
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node* createNode(int data);
Node* bstInsert(Node* root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node* root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if(argc != 2){
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if(in == NULL){
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while(!feof(in)){
fscanf(in, "%d", &num_read);
array[count] = num_read;
count++;
}
fclose(in);
if (array_size != count) {
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
Node *root1 = NULL, *root2 = NULL, *root3 = NULL;
int i;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (i = 0; i < array_size; i++) {
root1 = bstInsert(root1, array[i]);
}
displayTree(root1, 0);
return 0;
}
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
Node* current, previous, right;
current = root;
previous = root->left;
next = root->right;
else{
if(previous->data <= current->data){
}
}
return root;
}
Node* createNode(int data) {
// TODO
Node* aRoot;
if(!data)
return NULL;
aRoot = malloc(sizeof(Node));
if(!aRoot){
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch ,ch, ch);
}
void displayTree(Node* root, int depth){
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
main, createNode, displayTree, and padding are okay, I believe. It's bstInsert where I'm having trouble. I'm just not sure how to order things to create a valid tree.
EDIT:
I've edited bstInsert and injected some more logic. It should be printing out more leaves on the tree, but alas, it's only printing out the number "30". Here's the new function.
Node* bstInsert(Node* root, int data) {
if(root == NULL){
root = createNode(data);
if(root != NULL){
root= createNode(data);
}
else{
printf("%d not inserted, no memory available.\n", data);
}
}
else{
if(data < root->data){
bstInsert(root->left, data);
}
else if(data > root->data || data == root->data){
bstInsert(root->right, data);
}
}
return root;
}
You have to assign the newly created node pointer to the correct part of the tree. This code does that. The key change is using the return value from bstInsert() correctly. The other changes are cosmetic. Note that I checked the input array by printing it out; also, it is sensible to print out the BST as you build it.
Don't use feof() as a loop control condition. It is almost invariably wrong when used as a loop control, but at least you have to also check the input operation that follows. I've written a lot of programs in my time; I've hardly ever used feof() (I found two places in my own code with it; in both, it was correctly used to distinguish between EOF and an error after an input had failed.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// def BST node struct
typedef struct node_struct
{
int data;
struct node_struct* left;
struct node_struct* right;
} Node;
// prototypes
Node *createNode(int data);
Node *bstInsert(Node *root, int data);
// helper function prototypes
void padding(char ch, int n);
void displayTree(Node *root, int depth);
int main(int argc, char **argv)
{
FILE *in = NULL;
int num_read, count=0, array_size = 0;
if (argc != 2)
{
printf("hw3 <input-file>\n");
return 1;
}
in = fopen(argv[1], "r");
if (in == NULL)
{
printf("File can not be opened.\n");
return 2;
}
// read in the first line to get the array size
fscanf(in, "%d", &array_size);
// declare the array
int array[array_size];
// read from the second line to get each element of the array
while (count < array_size && fscanf(in, "%d", &num_read) == 1)
array[count++] = num_read;
fclose(in);
if (array_size != count)
{
printf("data error. Make sure the first line specifies the correct number of elements.");
return 3;
}
for (int i = 0; i < array_size; i++)
printf("%d: %d\n", i, array[i]);
Node *root1 = NULL;
// task1: construct a bst from the unsorted array
printf("=== task1: construct a bst from the unsorted array ===\n");
for (int i = 0; i < array_size; i++)
{
root1 = bstInsert(root1, array[i]);
displayTree(root1, 0);
}
displayTree(root1, 0);
return 0;
}
Node *bstInsert(Node *root, int data)
{
if (root == NULL)
{
root = createNode(data);
if (root == NULL)
printf("%d not inserted, no memory available.\n", data);
}
else if (data < root->data)
root->left = bstInsert(root->left, data);
else
root->right = bstInsert(root->right, data);
return root;
}
Node *createNode(int data)
{
Node *aRoot;
aRoot = malloc(sizeof(Node));
if (!aRoot)
{
printf("Unable to allocate memory for node.\n");
return NULL;
}
aRoot->data = data;
aRoot->left = NULL;
aRoot->right = NULL;
return aRoot;
}
/* helper functions to print a bst; You just need to call displayTree when visualizing a bst */
void padding(char ch, int n)
{
for (int i = 0; i < n; i++)
printf("%c%c%c%c", ch, ch, ch, ch);
}
void displayTree(Node *root, int depth)
{
if (root == NULL) {
padding (' ', depth);
printf("-\n");
}
else {
displayTree(root->right, depth+1);
padding(' ', depth);
printf ( "%d\n", root->data);
displayTree(root->left, depth+1);
}
}
Ok, think about what you want to do in the different tree configurations:
when the tree is empty -> create a root node
when the tree isn't empty -> how do the value to be inserted and the value of the root compare?
above -> insert in the right subtree
below -> insert in the left subtree
equal -> do nothing (this actually depends on how your assignment tells you to treat duplicates)
From this basic algorithm, you should be able to figure out all the corner cases.
A simplified solution (naive insertion with recursion, data input noise removed):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static int nums[] = { 6, 8, 4, 1, 3, 7, 14, 10, 13 }; // instead of the user input
typedef struct _node {
int value;
struct _node *left;
struct _node *right;
} node;
node *node_new(int v)
{
node *n = malloc(sizeof(*n));
assert(n);
n->value = v;
n->left = NULL;
n->right = NULL;
return n;
}
void insert(node **tree, node *leaf)
{
if (*tree == NULL) {
*tree = leaf;
} else if (leaf->value > (*tree)->value) {
insert(&((*tree)->right), leaf);
} else {
insert(&((*tree)->left), leaf);
}
}
void dump(node *tree, int level)
{
static const char *pad = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
if (tree != NULL) {
printf("%sSelf: %d\n", pad + 16 - level, tree->value);
if (tree->left) {
printf("%sLeft node:\n", pad + 16 - level);
dump(tree->left, level + 1);
}
if (tree->right) {
printf("%sRight node:\n", pad + 16 - level);
dump(tree->right, level + 1);
}
} else {
printf("%sEmpty\n", pad + 16 - level);
}
}
int main()
{
size_t n = sizeof(nums) / sizeof(*nums);
int i;
node *tree = NULL;
for (i = 0; i < n; i++) {
insert(&tree, node_new(nums[i]));
}
dump(tree, 0);
// give some work to the kernel
return 0;
}
You should consider doing this recursively. Remember that each node is a tree in itself:
#include <stdio.h>
#include <stdlib.h>
typedef struct tree_struct {
int value;
struct tree_struct* left;
struct tree_struct* right;
} Tree;
Tree* addToTree(int value, Tree* tree)
{
if (tree == NULL) {
tree = malloc(sizeof(Tree));
tree->value = value;
tree->left = NULL;
tree->right = NULL;
} else {
if (value < tree->value) {
tree->left = addToTree(value, tree->left);
} else {
tree->right = addToTree(value, tree->right);
}
}
return tree;
}
int main(int argc, char** argv)
{
Tree* tree = NULL;
int in;
while (scanf("%d", &in) != EOF) {
tree = addToTree(in, tree);
}
return 0;
}

Resources