Using getchar() to read text with no trailing newline - c

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.

Related

Balanced Brackets Checker always gives incorrect output

I have created a function which uses Linked List to check whether an expression is balanced or not. A balanced expression has no. of opening brackets equal to no. of closing brackets.
But the function Bracket Balancing always gives "unbalanced" as the output.
CODE:
#include <stdio.h>
#include <stdlib.h>
struct LL {
char data;
struct LL *next;
};
int isEmpty(struct LL *top) {
if (top == NULL) {
return 1;
}
else {
return 0;
}
}
int isFull(struct LL *top) {
struct LL *n = malloc(sizeof(struct LL *));
if (n == NULL) {
return 1;
}
else {
return 0;
}
}
struct LL *push(struct LL *top, char x) {
if (isFull(top)) {
printf("Stack Overflow\n");
}
else {
struct LL *n = malloc(sizeof(struct LL));
n->data = x;
n->next = top;
top = n;
}
return top;
}
struct LL *pop(struct LL *top) {
if (isEmpty(top)) {
printf("Stack Underflow\n");
}
else {
struct LL *n = malloc(sizeof(struct LL));
n = top;
top = top->next;
free(n);
}
return top;
}
int BracketBalancing (char *exp) {
struct LL *top = malloc(sizeof(struct LL));
top->next = NULL;
for (int i = 0; exp[i] != '\0'; i++) {
if (exp[i] == '(') {
push(top, exp[i]);
}
else if (exp[i] == ')') {
if (isEmpty(top)) {
return 0;
}
pop(top);
}
}
if (isEmpty(top)) {
return 1;
}
else {
return 0;
}
}
MAIN:
int main(int argc, char const *argv[]) {
int n;
char *expression = (char *)malloc(sizeof(char));
printf("Enter the length of the expression for Bracket Balancing\n");
scanf("%d", &n);
printf("Enter the expression for Bracket Balancing\n");
for (int i = 0; i < n; i++) {
scanf("%c ", &expression[i]);
}
getchar();
if (BracketBalancing(expression)) {
printf("The expression is balanced\n");
}
else if (!BracketBalancing(expression)) {
printf("This expression is unbalanced\n");
}
return 0;
}
Example:
Input:
Enter the length of the expression for Bracket Balancing
4
Enter the expression for Bracket Balancing
1+()
Output:
This expression is unbalanced
In the above example, Despite the expression being balanced the output generated is "This expression is unbalanced".
Please correct my code.
This is how you initialize your list:
struct LL *top = malloc(sizeof(struct LL));
top->next = NULL;
And this is isEmpty():
int isEmpty(struct LL *top)
{
if (top == NULL)
{
return 1;
}
else
{
return 0;
}
}
But: top starts with a value != NULL, so isEmtpy() will not return 1, although our list should be empty in the beginning.
Your implementation of push() should work fine when you pass NULL, so you can just initialize struct LL *top = NULL; instead of creating the first element rightaway.
there other bugs in your code, e.g.:
in pop() you do
struct LL *n = malloc(sizeof(struct LL));
n = top;
thus, the result of malloc() is directly overwritten() in the next line
in isFull() you produce a memory leak as you call malloc() and never use or free() the buffer returned. That function doesn't make sense anyway, just check the result of malloc()s where your really want to use the buffer returned.
** Edit **
What I haven't seen before, you also never use the return value of push() and pop() so the new top determined by these function is lost. Replace push(top, ...); by top = push(top,...); and pop(top); by top = pop(top);

C singly linked list using Queue

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "locker.h"
void QueueInit(Queue* p)
{
p->front = NULL;
p->rear = NULL;
}
int QIsEmpty(Queue* p)
{
if(p->front == NULL)
{
return 1;
}
return 0;
}
void Enqueue(Queue* p, int data)
{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->next = NULL;
newNode->id = data;
if(QIsEmpty(p))
{
p->front = newNode;
p->rear = newNode;
} else {
p->rear->next = newNode;
p->rear = newNode;
}
}
void attachEnqueue(Queue* p, int user_id)
{
Node* temp = p->front;
temp->user_id = user_id;
p->front = temp;
printf("Locker %d Owned By %d\n", temp->id, temp->user_id);
temp->owned = 1;
temp = temp->next;
}
int Dequeue(Queue* p)
{
Node* temp = p->front;
uint16_t item;
if(QIsEmpty(p))
{
printf("No element exists!");
exit(0);
} else {
item = temp->id;
p->front = temp->next;
free(temp);
if(temp == NULL)
{
p->rear = NULL;
}
return (item);
}
}
void printList(Queue* p)
{
Node* v = p->front;
while(v != NULL){
printf("Locker: %d\n", v->id);
v = v->next;
}
}
int count (Queue p)
{
int c = 0 ;
Node* temp = p.front ;
while ( temp != NULL )
{
temp = temp->next;
c++ ;
}
return c ;
}
void SearchQueue(Queue* p, int val1)
{
Node* v = p->front;
int sw = 0;
while( v != NULL)
{
if(v->id == val1)
{
printf("Locker ID: %d\n", val1);
printf("Lock Status: locked\n");
if(v->owned == 0){
printf("unowned\n");
} else if(v->owned == 1)
{
printf("owned by %d\n", v->user_id);
}
sw = 1;
}
v = v->next;
}
if(!sw)
{
printf("locker %d does not exists\n", val1);
}
}
int main(int argc, char* argv[])
{
Queue queue;
QueueInit(&queue);
char input[50];
char command[20];
int val1;
uint16_t id = 1;
while(1)
{
scanf(" %49[^\n]s", input);
sscanf(input, "%s %d", &command, &val1);
if(strcmp(command, "CREATE") == 0)
{
printf("New Locker created: %d\n", id);
Enqueue(&queue, id);
id++;
} else if(strcmp(command, "DISPLAY") == 0)
{
SearchQueue(&queue, val1);
} else if(strcmp(command, "ATTACH") == 0)
{
attachEnqueue(&queue, val1);
} else if(strcmp(command, "DISPLAYALL") == 0)
{
printList(&queue);
}else if(strcmp(command, "DELETE") == 0)
{
printf("Deleted the locker, %d\n",Dequeue(&queue));
}else if(strcmp(command, "QUIT") == 0)
{
printf("Good Bye!\n");
exit(0);
}
continue;
}
return 0;
}
This is what I have so far and the contents for "locker.h" is:
#ifndef LOCKER_H
#define LOCKER_H
#include <stdint.h>
typedef struct locker_t {
uint16_t id;
uint16_t user_id;
uint8_t locked;
uint8_t owned;
int write_fd;
int read_fd;
struct locker_t* next;
}Node;
typedef struct queue_t {
Node* front;
Node* rear;
size_t size;
}Queue;
#endif
Everything works fine except for the attachEnqueue part.
The purpose is, when I create locker 1 and locker 2 and input ATTACH 20,
locker 1's owner should be 20 and again if I input ATTACH 30, locker 2`s owner should be 30.
However, when I create 2 lockers and firstly ATTACH 20 and then again input ATTACH 30, the locker 1's owner`s value only changes from 20 to 30, not assigning the 30 owner to locker 2.
I am 100% sure that the attachEnqueue function involves the wrong contents but I am really not sure how to modify it..
Also, I need to include a "LOCK" command to make the locker whether to be locked or unlocked, but the problem is, school wants me to do this by using signal SIGUSR. How should I use the signal function to lock or unlock the locker? Would pthread.mutex.lock and unlock work?
Any help or advice would be very thankful!
The comment is right. The last line of attachEnqueue is temp = temp->next;
Maybe you assume temp keeps that information in mind next time you call the function, but right now, absolutely not. This line is of no use, the next time, temp will be assigned to the front of the queue.
To go around that, you may create a flag in your struct as stated above, add a counter argument to your function to keep track of which element in your queue to attach, or make temp a static argument, so its state persists between calls.

read txt, count each alphabet using linked list

#pragma warning (disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#define NUM_OF_ALPHABET 26
#define MAX_HEAP_SIZE 100
typedef struct _CharFrequency
{
char character;
int frequency;
struct _CharFrequency * next;
}CharFrequency;
typedef CharFrequency* pCharFrequency;
pCharFrequency pHead = NULL;
void initList();
void addNode(char ch);
void printAllNode(pCharFrequency pHead);
int main()
{
int i = 0, cnt = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = " \t\n.";
pFile = fopen("C:\\Users\\Home\\Desktop\\dataset.txt", "r");
if (pFile == NULL)
{
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL)
{
ptr = strtok(readLine, token);
while (ptr != NULL)
{
for (i = 0; i < strlen(ptr); i++)
{
addNode(ptr[i]);
}
ptr = strtok(NULL, token);
}
}
printAllNode(pHead);
return 0;
}
void initList()
{
pHead = (CharFrequency*)malloc(sizeof(CharFrequency));
if (!pHead)
{
printf("Fault\n");
return;
}
pHead->character = '\0';
pHead->frequency = 0;
pHead->next = NULL;
}
void addNode(char ch)
{
int i = 0;
pCharFrequency pNode = NULL;
pCharFrequency pCurrent= NULL;
if (isalpha(ch) == 0)
return;
if (ch >= 'A' && ch <= 'Z')
ch = ch + 32;
printf("%c ", ch);
for (pCurrent = pHead; pCurrent != NULL ; pCurrent = pCurrent->next)
{
if (pCurrent->character == ch)
{
pCurrent->frequency++;
}
else
{
pNode = (CharFrequency*)malloc(sizeof(CharFrequency));
pNode->frequency = 0;
pNode->next = NULL;
pNode->character = ch;
pNode->frequency++;
pCurrent->next = pNode;
}
}
pNode = (CharFrequency*)malloc(sizeof(CharFrequency));
pNode->frequency = 0;
pNode->next = NULL;
pNode->character = ch;
pNode->frequency++;
pCurrent->next = pNode;
}
void printAllNode(pCharFrequency pHead)
{
pCharFrequency pCurrent;
pCurrent = pHead;
pCurrent = pHead;
while (pCurrent->next != NULL) {
printf("%c %d", pCurrent->character, pCurrent->frequency);
pCurrent = pCurrent->next;
}
}
I want to build a program that reads txt file, count only alphabet, and count them using linked list. I make struct called CharFrequency to count alphabet.
addNode function gets the character, checks if it's in the list or not, and count them.
It makes error when doing for() in the addNode function.
You need to rethink about the logic inside your addNode method. It is adding a new node every time a character is not found in the list, and even if a match is found,the loop will continue until the last node adding a new node every time.
You could do something like this to get you started and experiment on it to make it more efficient.
pCharFrequency pNode = NULL;
pCharFrequency pCurrent= NULL;
pCharFrequency pTail= NULL;//this will keep track of the last node in the list
//so that we use it to insert a new node
....//your other code
pCurrent = pHead;//start from the head
while (pCurrent!=NULL)
{
if (pCurrent->character == ch)
{
pCurrent->frequency++;
return;//if a match was found, count and return
}
if(pCurrent->next == NULL)
pTail=pCurrent;//save the pointer to the last node in the list if we reach to it
pCurrent=pCurrent->next;//get the next node
}
//if we reach here, then we need to create a new node
pNode = (CharFrequency*)malloc(sizeof(CharFrequency));
if(pNode==NULL)
{
//show error message
return;
}
pNode->frequency = 1;
pNode->next = NULL;
pNode->character = ch;
if(pHead==NULL)
pHead=pNode;//for the very first node,we just assign to head
else
pTail->next = pNode;//otherwise set the last node's next to the node we just created

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

".exe file has stopped working" when run

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.

Resources