C: Evaluating Expression in a queue not working - c

I have created a queue using linked list that takes a string in the format 1 + 3 + 5 =or 1-3+2-4 = but the following code which is supposed to do the calculation given the sign and produce the answer is not working right for example if I passed a string like 66 - 31 - 21 + 43 = is passed the answer turns out to be -47 instead of 57. Can someone help me solve it or point to what I'm doing wrong.
void printQueue(struct node* head)
{
struct node* temp;
char *token, *del=" ";
int total = 0;
while (head != NULL)
{
token = strtok(head->data, del);
while (token != NULL) {
int a = strcmp(token, "+");
int b = strcmp(token, "-");
if (a == 0)
{
printf("+");
total = total + *token;
}
else if (b == 0) {
printf("+");
total = total - *token;
}
printf("%s ", token);
token = strtok(NULL, del);
}
printf(" %d\n",subtraction);
head = head->next;
}
}

Your code is ignoring the numbers, adding up character codes of '+' and '-' characters instead. The number -47 is the result of computing -45-45+43: 45 is the character code for the dash; 43 is the character code for the plus.
In order to work properly, make these changes to your code:
Add a sign variable of int type, with the initial value of 1
When you see a plus sign, set the sign to 1
When you see a minus sign, set the sign to -1
When you see a token that is neither a plus nor minus, convert it to an int val (e.g. by calling atoi), and add val * sign to the running total.
This change will make your code work for valid expressions, but it would not fail for some invalid ones. For example, it would take "expressions" such as 1 2 3 as if it were 1+2+3, and so on.

There are a few oddities in your code, here's a few:
Your inner loop that checks if token != NULL always has 1 iteration, it probably should be an if statement
You are searching only for the tokens '+' and '-' and adding their character value to your total, rather than the next number, you are ignoring the tokens that hold numbers
When subtracting you are still printing '+' to the screen

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct node{
int value;
struct node *next;
} Node;
typedef struct queque {
Node *top;
Node *tail;
} Queque;
Queque *Q_new(void){
return calloc(1, sizeof(Queque));
}
void Q_enq(Queque *q, int value){
Node *node = calloc(1, sizeof(Node));
if(!node) exit((printf("failed Securing memory\n"),1));
node->value = value;
q->tail = q->top ? (q->tail->next = node) : (q->top = node);
}
Node *Q_deq(Queque *q){
if(q->top){
Node *node = q->top;
q->top = q->top->next;
return node;
}
return NULL;
}
void Q_drop(Queque *q){
Node *node;
while(node = Q_deq(q))
free(node);
free(q);
}
void strToQ(const char *str, Queque *q){
char *p = (char*)str;
int num;
while(*p){
if(isspace(*p)){
++p;
continue;
} else if(*p == '+' || *p == '-' || *p == '='){//not used to a number sign
Q_enq(q, *p++);
continue;
}
num = strtol(p, &p, 10);
Q_enq(q, num);
}
}
int Q_calc(Queque *q){
int total = 0;
Node *node = Q_deq(q);
if(!node)
return 0;
total = node->value;
free(node);
while(node = Q_deq(q)){
if(node->value == '='){
free(node);
break;
} else {
int op = node->value;
free(node);
node = Q_deq(q);//NOT NULL(if NULL then invalid syntax)
if(op == '+')
total += node->value;
else if(op == '-')
total -= node->value;
free(node);
}
}
return total;
}
int main(){
Queque *q = Q_new();
strToQ("1 + 3 + 5 =", q);
printf("%d\n", Q_calc(q));//9, q to be empty
strToQ("1-3+2-4 =", q);
printf("%d\n", Q_calc(q));//-4
strToQ("66 - 31 - 21 + 43 =", q);
printf("%d\n", Q_calc(q));//57
Q_drop(q);
}

Related

C program with linked list to add/delete integers & calculate avg [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
I am trying to modify this code to add new numbers to the list with symbol "+" and delete with symbol "-". If the number entered is even, it should insert the number at the start of the list, if its odd, it should insert it at the end. The program will end after 0 (+0 or -0) is entered. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *ptr;
} node;
node * insert(node *head, int num)
{
node *temp = malloc(sizeof(node));
temp->data = num;
if (head == NULL || head->data > num)
{
temp->ptr = head;
head = temp;
}
else
{
node *current = head;
while ((current->ptr != NULL) && !(num < current->ptr->data))
{
current = current->ptr;
}
temp->ptr = current->ptr;
current->ptr = temp;
}
return head;
}
node * delete_if_less( node *head, int data )
{
while ( head != NULL && head->data < data )
{
node *temp = head;
head = head->ptr;
free( temp );
}
if ( head != NULL )
{
for ( node *current = head; current->ptr != NULL; )
{
if ( current->ptr->data < data )
{
node *temp = current->ptr;
current->ptr = current->ptr->ptr;
free( temp );
}
else
{
current = current->ptr;
}
}
}
return head;
}
void free_list(node *head) {
node *prev = head;
node *cur = head;
while(cur) {
prev = cur;
cur = prev->ptr;
free(prev);
}
}
int main(){
int num, min;
node *head, *p;
head = NULL;
do {
printf("Enter a number: ");
scanf("%d",&num);
if(num) {
head = insert(head, num);
for ( p = head; p != NULL; p = p->ptr )
{
printf("%d ", p->data);
}
printf("\n");
}
} while(num);
p = head;
printf("\nThe entered numbers are:\n");
while(p) {
printf("%d ", p->data);
p = p->ptr;
}
free_list(head);
head = delete_if_less( head, num );
if ( num != 0 ) {
printf( "There are deleted %zu nodes.\n", num );
}
printf("\nEnter minimum: ");
scanf("%d", & min);
return 0;
}
I want it then to calculate 1) the sum of all added integers 2) the sum of all deleted integers 3) the total sum of the remaining numbers of the list 4) the number of integers left and 5) the arithmetic average of the remaining numbers. The input should look like something like this:
Enter +/- to add/del a number: +1
1
Enter +/- to add/del a number: +2
2 1
Enter +/- to add/del a number: +3
2 1 3
Enter +/- to add/del a number: +1
2 1 3 1
Enter +/- to add/del a number: +5
2 1 3 1 5
Enter +/- to add/del a number: -4
Numbers not in list.
2 1 3 1 5
Enter +/- to add/del a number: -3
2 1 1 5
Enter +/- to add/del a number: -1
2 1 5
Enter +/- to add/del a number: +0
2 1 5
add sum: 13
del sum: 5
total sum: 8
elements: 3
average: 2.67
Can anyone help me with this? I would appreciate it alot. :)
Here is my approach to your code!
I used linked lists with a sentinel to optimize a bit. Also since in your example you wanted to keep the information about the deleted values, there are actually two linked lists in the program, one for present values, and another for bin values.
It works exactly as you have described in the input section,though I have added several more functionalities.
Here are the possible inputs:
in each of them n is an integer from 0 to 9
+on -> adds n to a linked list
-on -> deletes n from a linked list if it exists, if n not present prints an error message
-an -> deletes all occurrences of n from a linked list, if n not present prints an error message
+m -> deletes the maximum of a linked list
-m -> deletes the minimum of a linked list
0 -> terminates the function
Of course you could parse it differently to include larger int values but I guess I will leave that part to you!
At each operation the two linked lists will be printed out on the terminal so you can see the result of your operation and the current state of the two lists. If your message did not match the parsing, an error will be raised and will be printed on the terminal. Same goes for deleting a value that does not exist in the linked list.
After entering 0 the program will calculate different properties of the list based on what you have asked in your example.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <err.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
typedef struct node
{
int value;
struct node *next;
} node;
// Prints a string of characters.
static inline void print(const char* f, ...)
{
va_list args;
va_start(args, f);
vprintf(f, args);
va_end(args);
}
// Prints a string of characters followed by a new line.
static inline void println(const char* f, ...)
{
va_list args;
va_start(args, f);
vprintf(f, args);
va_end(args);
printf("\n");
}
static inline void* mem_alloc(size_t size)
{
void* p = malloc(size);
if (p == NULL)
{
err(EXIT_FAILURE, "Problem with malloc().");
}
return p;
}
// Verify if node is empty
int node_is_empty(node * head)
{
return head == NULL;
}
// Verify if node is not empty
int node_is_not_empty(node * head)
{
return head != NULL;
}
//Builds the sentinell of the node structure
node* node_build_sentinel()
{
// Creates the sentinel.
node* head = mem_alloc(sizeof(node));
head->value = 0;
head->next = NULL;
// Returns the head of the node which is the sentinell.
return head;
}
//Prints the contents of a node
void node_print(node* head)
{
print("{");
while(head->next)
{
head = head->next;
print(" %d", head->value);
}
println(" }");
}
//Frees the allocated node
void node_free(node* head)
{
node* previous;
while (head)
{
previous = head;
head = head->next;
free(previous);
}
}
// Inserts a value right after the head
/*
HEAD -> 1 -> 2 -> ..... -> 8
node_insert_beg(node* HEAD, int 42);
HEAD -> 42 -> 1 -> 2 -> ..... -> 8
*/
void node_insert_beg(node* head, int value)
{
node* tmp = mem_alloc(sizeof(node));
tmp->value = value;
tmp->next = head->next;
head->next = tmp;
}
// Inserts a value right after the head
/*
HEAD -> 1 -> 2 -> ..... -> 8
node_insert_end(node* HEAD, int 42);
HEAD -> 1 -> 2 -> ..... -> 8 -> 42
*/
void node_insert_end(node* head, int value)
{
node* tmp = mem_alloc(sizeof(node));
for (; node_is_not_empty(head->next); head = head->next)
{
//This loop runs to the last node and quits with head being that last node
continue;
}
tmp->value = value;
tmp->next = head->next;
head->next = tmp;
}
//Inserts odd values to the end and even values to the beginning
void node_insert_num(node* head, int value)
{
//odd
if(value % 2)
{
node_insert_end(head, value);
}
//even
else
{
node_insert_beg(head, value);
}
}
//Extracts the minimum value of the node (in other words deletes it from the node)
void node_extract_min(node* list,node *sup)
{
node *before_min = list;
while (list->next != NULL)
{
if (list->next->value < before_min->next->value)
{
before_min = list;
}
list = list->next;
}
node *output = before_min->next;
before_min->next = before_min->next->next;
output->next = NULL;
while (sup->next!=NULL)
{
sup = sup->next;
}
sup->next = output;
}
//Extracts the maximum value of the node (in other words deletes it from the node)
void node_extract_max(node* list, node* sup)
{
node *before_max = list;
while (list->next != NULL)
{
if (list->next->value > before_max->next->value)
{
before_max = list;
}
list = list->next;
}
node *output = before_max->next;
before_max->next = before_max->next->next;
output->next = NULL;
while (sup->next!=NULL)
{
sup = sup->next;
}
sup->next = output;
}
//Deletes the first occurence of value in node
int node_delete_first_occurence(node* head, node* sup, int value)
{
int seen = 0;
node *tmp = head;
while (head->next != NULL)
{
if (head->next->value == value)
{
tmp = head;
seen+=1;
break;
}
head = head->next;
}
if(seen == 0)
{
return seen;
}
node *output = head->next;
tmp->next = tmp->next->next;
output->next = NULL;
while (sup->next!=NULL)
{
sup = sup->next;
}
sup->next = output;
return seen;
}
//Deletes all occurences of value in node
int node_delete_all_occurences(node* head, node* sup, int value)
{
int seen = 0;
node *tmp = head;
while (head->next != NULL)
{
if (head->next->value == value)
{
seen+=1;
tmp = head;
node *output = head->next;
tmp->next = tmp->next->next;
output->next = NULL;
while (sup->next!=NULL)
{
sup = sup->next;
}
sup->next = output;
continue;
}
head = head->next;
}
return seen;
}
//Get a node at index if index invalid return NULL
//DOES NOT DELETE THE NODE
node * node_get_at(node* node, unsigned long index)
{
while (node != NULL && index > 0)
{
node = node->next;
index--;
}
if (node != NULL)
{
node = node->next;
}
return node;
}
int* node_sum(node * head)
{
int * sum_elem = malloc(sizeof(int)*2);
int sum = 0;
int elements = 0;
while (head->next != NULL)
{
elements+=1;
sum += head->next->value;
head = head->next;
}
sum_elem[0] = sum;
sum_elem[1] = elements;
return sum_elem;
}
int main()
{
node * present_node = node_build_sentinel();
node * deleted_nodes = node_build_sentinel();
char message[4];
while (1)
{
printf("Enter +/- followed by type (o = one/a = all/m = min or max) followed by the number to add/del a number or 0 to quit the app:");
scanf("%3s",message);
if(message[0] == '+')
{
if(message[1] == 'o')
{
node_insert_num(present_node,message[2] - '0');
node_print(present_node);
node_print(deleted_nodes);
continue;
}
if(message[1] == 'm')
{
node_extract_max(present_node,deleted_nodes);
node_print(present_node);
node_print(deleted_nodes);
continue;
}
if(message[1] == 'a')
{
printf("Invalid syntax on opperand 2 after + (no a is possible) please try again!\n");
}
else
{
printf("Invalid syntax on opperand 2 after + please try again!\n");
}
continue;
}
if(message[0] == '-')
{
if(message[1] == 'o')
{
int err = node_delete_first_occurence(present_node,deleted_nodes,message[2] - '0');
if(err == 0)
{
printf("The number to delete was not present in the node!\n");
}
node_print(present_node);
node_print(deleted_nodes);
continue;
}
if(message[1] == 'a')
{
int err = node_delete_all_occurences(present_node,deleted_nodes,message[2] - '0');
if(err == 0)
{
printf("The number to delete was not present in the node!\n");
}
node_print(present_node);
node_print(deleted_nodes);
continue;
}
if(message[1] == 'm')
{
node_extract_min(present_node,deleted_nodes);
node_print(present_node);
node_print(deleted_nodes);
continue;
}
else
{
printf("Invalid syntax on opperand 2 after - please try again!\n");
}
continue;
}
if(message[0] == '0')
{
break;
}
else
{
printf("Invalid syntax on opperand 1 please try again!\n");
}
}
int * present_sum_elem = node_sum(present_node);
printf("The sum of present node: %d \n",present_sum_elem[0]);
printf("The number of elements in present node: %d\n",present_sum_elem[1]);
if(present_sum_elem[1]!=0)
{
printf("The average of the present node %4f \n", (float)present_sum_elem[0]/(float)present_sum_elem[1]);
}
int * deleted_sum_elem = node_sum(deleted_nodes);
printf("The sum of deleted node: %d \n",deleted_sum_elem[0]);
printf("The number of elements in deleted node: %d\n",deleted_sum_elem[1]);
if(deleted_sum_elem[1] != 0)
{
printf("The average of the deleted node %4f \n", (float)deleted_sum_elem[0]/(float)deleted_sum_elem[1]);
}
free(present_sum_elem);
free(deleted_sum_elem);
node_free(present_node);
node_free(deleted_nodes);
return 0;
}

Very strange behavior with printf in C program

I'm currently working on a lesson in the free edX.org C Programming course. I'm working through the final examples on linked list and playing around with the code below. This code is not complete yet, but what I'm baffled by is that when uncommenting the commented line in main, none of the printf statements give output to the console. Even the printfs before that line.
When I run it I'm simply entering 123 and then pressing the enter key.The printfs output fine as long as the line is commented out. I should also mention that when setting breakpoints around the printfs while it's commented out, it appears the program is continuing to execute through and past the breakpoints, but no output appears on the console.
Could anyone give insight into why this is happening? I'm running this in STM32CubeIDE on Fedora Linux with GCC toolchain. Please let me know if I could provide more detail. Thanks.
#include <stdio.h>
#include <stdlib.h>
struct digit {
int num;
struct digit *next;
};
struct digit * createDigit(int);
struct digit * append(struct digit * end, struct digit * newDigptr);
void printNumber(struct digit *);
void freeNumber(struct digit *start);
struct digit * readNumber();
struct digit * searchNumber(struct digit * start, int number);
struct digit * reverseNumber(struct digit* start);
int main(void) {
struct digit *start, *backwards;
printf("Please enter a number: ");
start = readNumber();
printf("a\n");
printNumber(start);
printf("b\n");
//backwards = reverseNumber(start);
printf("c\n");
freeNumber(start);
return 0;
}
struct digit *createDigit(int dig) {
struct digit *ptr;
ptr = (struct digit *) malloc(sizeof(struct digit));
ptr->num = dig;
ptr->next = NULL;
return ptr;
}
struct digit * append(struct digit * end, struct digit * newDigptr) {
end->next = newDigptr;
return(end->next);
}
void printNumber(struct digit *start) {
struct digit * ptr = start;
while (ptr != NULL) {
printf("%d", ptr->num);
ptr = ptr->next;
}
printf("\n");
}
void freeNumber(struct digit *start) {
struct digit * ptr = start;
struct digit * tmp;
while (ptr != NULL) {
tmp = ptr->next;
free(ptr);
ptr = tmp;
}
}
struct digit * readNumber() {
char c;
int d;
struct digit *start, *end, *newptr;
start = NULL;
scanf("%c", &c);
while (c!='\n') {
d = c - 48;
newptr = createDigit(d);
if (start == NULL) {
start = newptr;
end = start;
}
else {
end = append(end, newptr);
}
scanf("%c", &c);
}
return start;
}
struct digit * searchNumber(struct digit * start, int number) {
struct digit * ptr = start;
while (ptr != NULL && ptr->num != number) {
ptr = ptr->next;
}
return(ptr);
}
struct digit* reverseNumber(struct digit* start) {
// iterate the original list and for each element make it the end in the new list
struct digit *next, *newListStart;
newListStart = next = start;
if (newListStart == NULL)
printf("yay");
else
printf("nay");
while (next != NULL) {
next = next->next;
newListStart->next = createDigit(newListStart->num);
newListStart = createDigit(next->num);
}
return newListStart;
}
The issue is your newListStart = createDigit(next->num). Trying to access num results in a dereference of a null pointer (you cannot access *next's fields since it isn't pointing to anywhere).

Creating a recursive function that creates a expression tree from a prefix expression (in a char array) in C

Each element (operands, operators, parenthese) in the prefix expression is seperated by a white space.
These are some of the functions needed.
void createExpTree ( BTNode ** root , char * prefix );
void printTree ( BTNode * node );
void printTreePostfix ( BTNode * node );
and this is the structure of the BTnode
typedef struct _btnode{
int item;
struct _btnode *left;
struct _btnode *right;
} BTNode;
this is my code for the function createExpTree but I dont understand what is wrong
void createExpTree(BTNode** root,char* prefix)
{
int j, x;
char c;
char d[SIZE];
static int count=0;
c = prefix[count];
if (count == strlen(prefix)) {
return;
}
if (c == ' ')
count++;
c = prefix[count];
if (c=='*' || c=='/' || c=='+' || c=='-') {
// if prefix exp is OPT
// create children
BTNode* nn = (BTNode*)malloc(sizeof(BTNode));
nn->left = (BTNode*)malloc(sizeof(BTNode));
nn->right = (BTNode*)malloc(sizeof(BTNode));
nn->item = (int)c;
nn->left = NULL;
nn->right = NULL;
*root = nn;
count++;
createExpTree(&((*root)->left), prefix);
createExpTree(&((*root)->right), prefix);
}
else { //if prefix exp is OPERAND
j=0;
while (c!=' ') {
d[j]=c;
j++; count++;
c = prefix[count];
}
d[j]='\0';
x = atoi(d);
BTNode* nn = (BTNode*)malloc(sizeof(BTNode));
nn->item = x;
nn->left = NULL;
nn->right = NULL;
*root = nn;
count++;
return;
}
}
these are my codes for printTree and printTreePostfix
void printTree(BTNode *node){
if (node == NULL) {
return;
}
else {
printTree(node->left);
if(node->item >= 0 || node->item <= INT_MAX)
printf("%d ",node->item);
else
printf("%c ",(char)(node->item));
printTree(node->right);
}
}
void printTreePostfix(BTNode *node){
if (node == NULL) {
return;
}
else {
printTreePostfix(node->left);
printTreePostfix(node->right);
if(node->item >= 0 || node->item <= INT_MAX)
printf("%d ",node->item);
else
printf("%c ",(char)(node->item));
}
}
The input for this question is something like "+ 99 / + 88 77 - * 66 - 55 44 33", the integers are presumably 2-digit integers.
Am I creating the expression tree correctly? I keep getting segmentation faults in codeblocks
Would appreciate any help!! Thanks!!
**Updated code: there still seems to be a segmentation fault after i fixed the prefix++ to prefix[count] with a static int count
A possible solution, using strtok(), is the following:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
typedef struct _btnode {
int item;
struct _btnode *left;
struct _btnode *right;
} BTNode;
void createExpTree(BTNode **root, char *prefix) {
*root = malloc(sizeof(BTNode));
char *token = strtok(prefix, " "); // set string prefix, delimited by spaces, to be tokenized
if( isdigit(token[0]) ) { // external nodes (= leaves) are operands
(*root)->item = atoi(token);
(*root)->left = NULL;
(*root)->right = NULL;
}
else { // internal nodes are binary operators
(*root)->item = token[0];
createExpTree(&(*root)->left, NULL); // continue using the same string prefix
createExpTree(&(*root)->right, NULL); // continue using the same string prefix
}
}
void printTree(BTNode *node){
if( node == NULL ) return;
if( node->left == NULL && node->right == NULL ) // external node
printf("%d", node->item);
else { // internal node
printf("(");
printTree(node->left);
printf(" %c ", (char)node->item);
printTree(node->right);
printf(")");
}
}
void printTreePostfix(BTNode *node){
if( node == NULL ) return;
printTreePostfix(node->left);
printTreePostfix(node->right);
if(node->left ==NULL && node->right == NULL) // external node
printf("%d ",node->item);
else // internal node
printf("%c ",(char)(node->item));
}
int main(void) {
BTNode *root1;
char prefix1[513] = "* + 1 2 - 3 4";
createExpTree(&root1, prefix1);
printf("Infix Tree: ");
printTree(root1);
printf("\nPostfix Tree: ");
printTreePostfix(root1);
puts("");
BTNode *root2;
char prefix2[513] = "+ 99 / + 88 77 - * 66 - 55 44 33";
createExpTree(&root2, prefix2);
printf("Infix Tree: ");
printTree(root2);
printf("\nPostfix Tree: ");
printTreePostfix(root2);
puts("");
return 0;
}
Output:
Infix Tree: ((1 + 2) * (3 - 4))
Postfix Tree: 1 2 + 3 4 - *
Infix Tree: (99 + ((88 + 77) / ((66 * (55 - 44)) - 33)))
Postfix Tree: 99 88 77 + 66 55 44 - * 33 - / +
REMARK: If you cannot use the predefined function strtok() in your solution, try to create your own function that behaves like strtok().

Having trouble pushing elements onto a stack

I'm working on a project where I must take an expression in reverse polish notation, push the integers and operators onto a stack, then pop them out off the stack as they are inserted into a binary search tree.
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
struct snode
{
int datum;
struct snode* bottom;
};
struct tnode
{
int datum;
struct tnode* left;
struct tnode*right;
};
struct snode*
push(struct snode* stack, int x) {
struct snode *S = (struct snode*)malloc(sizeof(struct snode));
S->datum = x;
S->bottom = stack;
return S;
}
struct snode* pop(struct snode* stack) {
struct snode *S;
if (stack == NULL)
return NULL;
S = stack->bottom;
free(stack);
return S;
}
int
peek(struct snode* stack){
return stack->datum;
}
struct tnode*
create_node(int x){
struct tnode* tmp;
tmp = (struct tnode*)malloc(sizeof(struct tnode));
tmp->datum = x;
tmp->right = NULL;
tmp->left = NULL;
return tmp;
}
void
print_table(struct tnode *AST){
if(AST !=NULL){
print_table(AST->left);
printf("%d ", AST->datum);
print_table(AST->right);
}
}
struct tnode*
build_tree(struct snode *S)
{
struct tnode* root;
if (S==NULL){
return NULL;
}else{
int top = peek(S);
if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77){
return create_node(top);
}else{
root= create_node(top);
root->right = build_tree(pop(S));
root->left = build_tree(pop(S));
return root;
}
}
}
int
main(int argc, const char *argv[])
{
int i = 1;
struct tnode *tree = NULL;
struct snode *stack = NULL;
while (argv[i]!= NULL){
stack = push(stack, argv[i][0]);
i++;
}
tree = build_tree(stack);
print_table(tree);
return EXIT_SUCCESS;
}
I feel like this should work. Everything compiles clean. I run it by saying
./project 5 4 A
and what comes out is
135208 135224 135208 135240 135208 135224 135208 0 135208 135224 135208 52 0 53 0
when it should be
4 65 5
I think this is happening where because of how I'm pushing the elements on to the stack.
EDIT:
I initialized i so that i = 1.
this is the result I am getting.
134480 134496 134480 0 5 4 5
EDIT2:
I decided to get rid of the atol(argv[i]) and change it to just argv[i][0].
see code.
Now my out put is just
65
Finally figured out what was going on!
Here is the newly modified sections that should make your code work (please view the // <== EDIT comments) :
struct tnode*
build_tree(struct snode *S)
{
struct tnode* root;
if (S == NULL)
return NULL;
int top = peek(S);
if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
{
root = create_node(top);
S = pop(S); // <== EDIT
root->right = build_tree(S);
S = pop(S); // <== EDIT
root->left = build_tree(S);
return root;
}
root= create_node(top);
return root;
}
int
main(int argc, const char *argv[])
{
int i = 1;
struct tnode *tree = NULL;
struct snode *stack = NULL;
int value = 0;
while (argv[i]!= NULL)
{
if ((value = atoi(argv[i])) == 0) // <== EDIT
value = argv[i][0];
stack = push(stack, value);
i++;
}
tree = build_tree(stack);
print_table(tree);
return EXIT_SUCCESS;
}
I have noticed 3 issues that are causing the values that you have.
First issue :
The result that you are looking for is 4 65 5, which means that if the input is a number (4, 5, etc) you must use the result of atoi(). If the input is not a number, you must use the ASCII value.
To do this, I have used the following lines :
if ((value = atoi(argv[i])) == 0) // <== EDIT
value = argv[i][0];
stack = push(stack, value);
In my implementation of atoi(), when the conversion fails, atoi() returns 0. Therefore, I check the value of the assignment : if atoi() returned 0, use the ASCII value.
Second issue :
The second problem you are having is that the build_tree() function seems to have faulty logic. Since this is a tree, I would expect the character A to be the root and the numbers 4 and 5 to be the branches, like so :
A
/ \
4 5
Your logic seems to reverse the situation, the way you are setup, the numbers become root values and the letters are branches. Reversing your logic solves this :
int top = peek(S);
if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
{
root = create_node(top);
S = pop(S); // <== EDIT
root->right = build_tree(S);
S = pop(S); // <== EDIT
root->left = build_tree(S);
return root;
}
root= create_node(top);
return root;
Last issue :
This is the big one. When you call build_tree(), you pass the result of pop() directly. The problem with that, is that you are not affecting the new root value to S. Because of this :
When you call build_tree(pop(S)) the first time, you end up freeing the memory space for S.
Later, when you call build_tree(pop(S)) a second time, you end up calling pop(S) on the initial value (the one that has been freed early on).
The solution is to reassign S when you call pop(), and calling build_tree(S) afterwards.
S = pop(S); // <== EDIT
root->right = build_tree(S);
S = pop(S); // <== EDIT
root->left = build_tree(S);
TL;DR :
I reformated your code a bit and the issue should be fixed now. Copy paste and you should be good.

character strings being mutated somehow

I am working on a a small program and it has a tiny logic error which I can't seem to trace. It tracks records input of this form:
time userID weight
It searches a linked list of all previous records to find the most recent one where the userID matches the current userID. It then compares the time and weight and calculates the rate of change in the weight. If the weight has changed abruptly it print "suspicious weight change". If there is not match and the input is valid it simply adds the new record to the list.
I have it working except when the userID is added to the list it seems to overwrite all the previous userID's. So even if a new record is input which has a unique userID, it finds a match, because all the ID's a made the same.
I just need a second pair of eyes to help spot where this is happening, I am new to C so it is probably some newbie mistake. But after 8 hrs of trying to find it, I am desperate for some help!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define DELIM " " /* the delimiter */
#define MAX_CHANGE (10.0/86400.0) /* 10kg/day */
/* seconds in a day is 24 hours * 60 minutes * 60 seconds */
/* return 0 if the passed strings don't math, 1 otherwise */
/* defines the structure of Node */
struct Node
{
char * id;
float weight;
int time;
struct Node * next;
} *head, *p, *t, *last;
/* Constructor which returns a pointer to a new node*/
struct Node *newNode(int *time, char * id, float *w)
{
/*note malloc returns a pointer */
struct Node *r = (struct Node *)malloc( sizeof(struct Node) );
r->time = *time;
r->id = id;
r->weight = *w;
r->next = NULL;
return r;
}
/* prints the list starting with head */
printList(struct Node * head)
{
while(head != NULL)
{
printf("%d %s %f\n",head->time,head->id,head->weight);
head = head->next;
}
}
main()
{
char line[1024];
int lasttime = 0;
int success;
int timestamp;
int duration;
char userID[1000] = "";
char *token;
char temp[1000];
float weight;
float lastweight;
float change;
float changePerTime;
head = (struct Node*)malloc(sizeof(struct Node));
head->id = "";
head->weight = 0.0;
head->time = 0;
head->next = NULL;
last = head;
/*FILE * f = fopen("C:\\Users\\Chris\\Documents\\School\\York\\Computer Science\\2031 Software Tools\\Labs\\lab3\\testcases\\06.in","r"); */
/* last points to the last node in the list
head is always the same node
p is used to travers the list
t is a pointer the most recent occurrense of a user record
*/
while (fgets(line,1024,stdin) != NULL)
{
userID[0] ='\0'; // resets userID
token = strtok(line, DELIM);
success = sscanf(token,"%d",&timestamp);
if (success < 1 || timestamp == 0)
{
printf("Invalid time\n");
continue;
}
while((token = strtok(NULL,DELIM) ) != NULL && token[0] != '.' && ! isdigit(token[0]) )
{
strcpy(temp,token); //
strcat(temp,DELIM ); // adds space between each token
strcat(userID, temp); // src temp must be a const string, not a pointer
temp[0] = '\0';
}
userID[strlen(userID)-1] = '\0'; //erases the tailing space.
if(strlen(userID) > 179 || !strlen(userID) )
{
printf("Illegal userID\n");
continue;
}
else if(token == NULL || sscanf(token,"%f", &weight) < 1 || weight < 30.0 || weight > 300.0)
{
printf("Illegal weight\n");
continue;
}
else if (lasttime >= timestamp)
{
printf("Nonmonotonic timestamps\n");
continue;
}
else
{
/* sets t to last found user record and sets "last" to the last record*/
for(p = head; p != NULL; p = p->next)
{
if(strcmp(userID,p->id) == 0)
{
t=p;
}
last = p; // set last to last p.
}
if(t == NULL)
printf("OK newuser\n");
else if(t != NULL)
{
duration = timestamp - t->time;
change = weight - t->weight;
changePerTime = change / duration;
if(changePerTime < -MAX_CHANGE || changePerTime > MAX_CHANGE)
printf("Suspiciously large weight change\n");
else
printf("OK\n");
}
/* adds node to end of list */
last->next = newNode(&timestamp,userID,&weight);
printList(head);
}
}
//fclose(f);
}
I can fix the over-writing by changing newNode to:
struct Node *newNode(int *time, char * id, float *w)
{ /*note malloc returns a pointer */
struct Node *r = (struct Node *)malloc( sizeof(struct Node) );
r->time = *time;
r->id = strdup(id);
r->weight = *w;
r->next = NULL;
return r;
}
Note the addition of the call to strdup.

Resources