This document provides instructions for implementing a basic four-function calculator using stacks and queues. It describes converting an infix expression to postfix notation, evaluating the postfix expression, and handling parentheses. Code is provided to get started, and the tasks are to complete functions to convert infix to postfix, evaluate postfix expressions, and update infix to postfix to handle parentheses. Test cases should be run to demonstrate the functionality.
1. For any help regarding Electrical Engineering Assignment Help
Visit :- https://www.programminghomeworkhelp.com/ ,
Email :- support@programminghomeworkhelp.com or
call us at :- +1 678 648 4277
Programming Homework Help
2. Problem 1
In this problem, we will implement a simple “four-function” calculator using stacks and queues. This
calculator takes as input a space-delimited infix expression (e.g. 3 + 4 * 7), which you will convert to postfix
notation and evaluate. There are four (binary) operators your calculator must handle: addition (+),
subtraction (-), multiplication (*), and division (/). In addition, your calculator must handle the unary negation
operator (also -). The usual order of operations is in effect:
• the unary negation operator - has higher precedence than the binary operators, and is eval uated right-
to-left (right-associative)
• *and /have higher precedence than +and
• all binary operators are evaluated left-to-right (left-associative)
To start, we will not consider parentheses in our expressions. The code is started for you in prob1.c, which is
available for download from Stellar. Read over the file, paying special attention to the data structures used
for tokens, the stack, and queue, as well as the functions you will complete.
(a) We have provided code to translate the string to a queue of tokens, arranged in infix (natural) order. You
must:
– fill in the infix to postfix() function to construct a queue of tokens arranged in postfix order (the infix
queue should be empty when you’re done)
– complete the evaluate postfix() function to evaluate the expression stored in the postfix queue and
return the answer
You may assume the input is a valid infix expression, but it is good practice to make your code robust
by handling possible errors (e.g. not enough tokens) . Turn in a printout of your code, along with a
printout showing the output from your program for a few test cases (infix expressions of your choosing)
to demonstrate it works properly.
Programming Homework Help
3. Answer: Here’s one possible implementation: (only functions infix to postfix()and
evaluate postfix()shown)
/∗ crea tes a queue of tokens in p os tf i x order from a queue of tokens in i n f i x order ∗/
/∗ postcondition : returned queue contains a l l the tokens , and pqueue infix should be empty ∗/
struct token queue i n f i x t o p o s t f i x ( struct token queue ∗ pqueue infix ) {
/∗ TODO: construct postfix −ordered queue from i nf i x −ordered queue ;
a l l tokens from i n f i x queue should be added to p o st fi x queue or freed ∗/ p expr token
stack top = NULL, ptoken ;
struct token queue queue postfix ;
queue postfix . front = queue postfix . back = NULL;
for ( ptoken = dequeue ( pqueue infix ) ; ptoken ; ptoken = dequeue ( pqueue infix )) {
switch ( ptoken−>t ype ) {
case OPERAND:
/∗ operands added d i r e c t l y to po s tfi x queue ∗/ enqueue(& queue p
ostfix , ptoken ) ;
break ;
case OPERATOR:
/∗ operator added to stack , a f t e r operators of higher precedence are
moved to queue ∗/
while ( stack top &&
( op precedences [ stack top−>value . op code ] >
op precedences [ ptoken−>value . op code ] | |
( op precedences [ stack top−>value . op code ] == op precedenc
es [ ptoken−>value . op code ] &&
o p a s s o c i a t i v i t y [ op precedences [ ptoken−>value . op code ] ] == LEFT)) )
enqueue(& queue postfix , pop(& stack top ) ) ;
push(& stack top , ptoken ) ;
break ;
default : /∗ oth er tokens ignored ∗/ fr e e ( ptoken ) ;
break ;
}
}
be empty ∗/
Programming Homework Help
4. a l l tokens from postfix −ordered queue i s freed
∗/
double ans = 0 . ;
p expr token stack values = NULL, ptoken , pvalue
;
double operands [ 2 ] ; /∗ max two operands ∗/
union token value value ;
int i ;
while ( ( ptoken = dequeue ( pqueue postfix )) ) {
switch ( ptoken−>t ype ) {
case OPERAND:
/∗ operands always pushed to s t a c k ∗/
push(& stack values , ptoken ) ;
break ;
case OPERATOR:
}
/∗ evalutes the p o stfi x expression stored in the queue ∗/
/∗ postcondition : returned value i s f i n a l answer , and pqueue postfix
should
double eva l u a te p o st fi x ( struct token queue ∗ pqueue postfix ) {
/∗ TODO: process postfix −ordered queue and return f i n a l answer ;
while ( stack top ) /∗ pop remaining operators o f f stack ∗/
enqueue(& queue postfix , pop(& stack top ) ) ;
return queue postfix ;
Programming Homework Help
5. /∗ pop operands from s t a c k ∗/
for ( i = 0 ; i < op operands [ ptoken−>v alue . op code ]
;
i f ( ( pvalue = pop(& s t a c k v a l u e s ) ) ) {
operands [ i ] = pvalue −>v alue . operand ;
f r e e ( pvalue ) ; /∗ done with token ∗/
} else
i ++) {
goto error ;
}
/∗ process operands according to opcode ∗/
/∗ note operands are popped i n r e v e r s e order
∗/
switch ( ptoken−>v alue . op code ) {
case ADD:
value . operand = operands [1]+ operands [ 0 ] ;
break ;
case SUBTRACT:
value . operand = operands [1] − operands [ 0 ] ;
break ;
case MULTIPLY:
value . operand = operands [ 1 ] ∗ operands [ 0 ] ;
break ; case
DIVIDE :
value . operand = operands [ 1 ] / operands [ 0 ] ;
break ; case
NEGATE:
value . operand = −operands [ 0 ] ;
}
/∗ push new token with operator r e s u l t to stack
∗/
value ) );
push(& stack values , new token
(OPERAND,
default :
Programming Homework Help
6. fr e e ( ptoken ) ; /∗ f r e e token ∗/
break ;
}
}
/∗ return value i s on top of stack ( should be l a s t value on stack ) ∗/
if ( stack values )
ans = stack values −>value . operand ;
cleanup :
/∗ f r e e any remaining tokens ∗/
while ( ( ptoken = dequeue ( pqueue postfix )) ) fr e e
( ptoken ) ;
while ( ( pvalue = pop(& stack val ues )) ) fr e e (
pvalue ) ;
return ans ;
error :
fputs ("Error evaluating the expression.n", stderr ) ;
goto cleanup ;
}
(b) Now, an infix calculator really is not complete if parentheses are not allowed. So, in this part,
update the function infix to postfix() to handle parentheses as we discussed in class. Note:
your postfix queue should contain no parentheses tokens. Turn in a printout of your code,
along with a printout showing the output from your program for a few test cases utilizing
parentheses.
Programming Homework Help
7. Answer: Here’s an implementation: (only function infix to postfix()shown)
/∗ crea tes a queue of tokens in p os tf i x order from a queue of tokens in i n f i x order
∗/
/∗ postcondition : returned queue contains a l l the tokens , and pqueue infix
should be empty ∗/
struct token queue i n f i x t o p o s t f i x ( struct token queue ∗ pqueue infix ) {
/∗ TODO: construct postfix −ordered queue from i nfi x −ordered queue ;
a l l tokens from i n f i x queue should be added to p o st fi x queue or freed ∗/ p
expr token stack top = NULL, ptoken ;
struct token queue queue postfix ;
queue postfix . front = queue postfix . back = NULL;
for ( ptoken = dequeue ( pqueue infix ) ; ptoken ; ptoken = dequeue ( pqueue infix )) {
switch ( ptoken−>t ype ) {
case OPERAND:
/∗ operands added d i r e c t l y to po s tf i x queue ∗/
enqueue(& queue postfix , ptoken ) ;
break ;
case OPERATOR:
/∗ operator added to stack , a f t e r operators of higher
precedence are moved to queue ∗/
while ( stack top && stack top−>type == OPERATOR && ( op
precedences [ stack top−>value . op code ] >
op precedences [ ptoken−>value . op code ] | |
( op precedences [ stack top−>value . op code ] == op
precedences [ ptoken−>value . op code ] &&
o p a s s o c i a t i v i t y [ op precedences [ ptoken−>value . op code ] ] ==
LEFT)) ) enqueue(& queue postfix , pop(& stack top ) ) ;
push(& stack top , ptoken ) ;
break ;
case LPARENS:
/∗ pushed to operator stack ∗/
ptoken );
push(&stack top ,
break;
case RPARENS:
/∗ pop operators
Programming Homework Help
8. while ( ( ptoken = pop(& s t a c k t o p ) ) ) {
i f ( ptoken−>t ype == LPARENS) {
fr e e ( ptoken ) ;
break ;
}
enqueue(& queue postfix , ptoken ) ;
}
}
}
while ( stack top ) /∗ pop remaining operators o f f stack ∗/
enqueue(& queue postfix , pop(& stack top ) ) ;
return queue postfix ;
}
Problem 2
A useful data structure for storing lots of strings is the “trie.” This tree structure has the special
property that a node’s key is a prefix of the keys of its children. For instance, if we associate a node
with the string “a,” that node may have a child node with the key “an,” which in turn may have a
child node “any.” When many strings share a common prefix, this structure is a very inexpensive
o f f stack un t i l l e f t parentheses reached ∗/ fr
e e ( ptoken ) ; /∗ parentheses not included in p o st fi x queue
∗/
Programming Homework Help
9. way to store them. Another consequence of this storage method is that the trie supports very fast
searching – the complexity of finding a string with m characters is O(m).
(root)
pointer array of childre �
�
� �
� �
�
�
"a" "c"
�
�
�
�
�
�
�
�
"an" "ca"
�
�
� �
� �
�
�
�
�
�
�
"and" "ant" "cat"
Figure 6.2-1: Trie structure (translations not shown). For each node, its key (e.g. “and”) is not explicitly stored in the
node; instead, the key is defined by the node’s position in the tree: the key of its parent node + its index in that
parent’s pointer array of children.
In this problem, you will utilize a trie structure and to implement a simple one-way English- to-French dictionary. The
trie structure, shown in Figure 6.2-1, consists of nodes, each of which contains a string for storing translations for
the word specified at that node and an array of pointers to child nodes. Each node, by virtue of its position in the trie,
is associated with a string; in the dictionary context, this string is the word (or part of a word) in the dictionary. The
dictionary may contain multiple translations for the same word; in this case, words should be separated by commas.
For example: the word like, which has two meanings, could translate as comme, a preposition, or as aimer, a verb.
Thus, the translation string should be “comme,aimer.” To get you started, we’ve provided code in prob2.c, which
can be downloaded from Stellar. You will need to:
• fill in the helper functions new node(), deletenode()
• complete the function add word(), which adds a word to thetrie
• complete the function lookup word(), which searches the trie for a word and returns its translation(s)
Once your code is working, run a few test cases. Hand in a copy of your code, and a printout of your program
running in gdb, with a few example translations to demonstrate functionality.
Programming Homework Help
10. Answer: one possible implementation of the four functions is shownbelow:
/∗ a l l o c a t e new node on the heap
output : pointer to new node ( must be freed ) ∗/
struct s tr i e n o d e ∗ new node ( void) {
/∗ TODO: a l l o c a t e a new node on the heap , and i
n i t i a l i z e a l l f i e l d s to default values ∗/
struct s t r i e n o d e ∗ pnode = ( struct s t
r i e n o de ∗) malloc (
sizeof ( struct s t r i e n o d e ) ) ;
int i ;
pnode−>tr an sl a ti on = NULL;
for ( i = 0 ; i < UCHAR MAX+1; i ++)
pnode−>children [ i ] = NULL;
return pnode;
}
/∗ del ete node and a l l i t s children input
: pointer to node to del ete
postcondition : node and children are freed ∗/
void delete node ( struct s t r i e n o d e ∗ pnode ) {
/∗ TODO: d e l e t e node and a l l i t s c h i l d r e n Be
s u r e to f r e e non−n u l l t r a n s l a t i o n s ! Hint :
use recursion
∗/
int i ;
Programming Homework Help
11. i f ( pnode−>t r a n s l a t i o n ) fr e e
( pnode−>tran sl a ti o n ) ;
for ( i = 0 ; i < UCHAR MAX+1; i ++)
if ( pnode−>children [ i ] )
delete node ( pnode−>chil dren [ i ] ) ;
fr e e ( pnode ) ;
}
/∗ add word to tri e , with t ra n sl at i o n
input : word and t r an s l ati on
output : non−zero i f new node added , zero otherwi
se postcondition : word e x i s t s in t r i e ∗/
int add word ( const char ∗ word , char ∗ tr an sl a ti on ) {
/∗ TODO: add word to t r i e structure
I f word exists , append tra n sl a ti o n to ex i st i n g
stri n g
Be sure to store a copy of translation , since
the str i ng i s reused by l oad di ctionary ()
∗/
struct s t r i e n o d e ∗ pnode = proot ; int i
, l e n = s t r l e n ( word ) , inew = 0 ;
unsigned char j;
for ( i = 0 ; i < l e n ; i ++) {
j = word [ i ] ;
if (( inew = ! pnode−>children [ j ] ) )
pnode−>children [ j ] = new node ( ) ;
pnode = pnode−>children [ j ] ;
}
if ( pnode−>tra nsl a t i on ) {
/∗ concatenate s t r i ng s ∗/
Programming Homework Help
12. char ∗ ol d t ra nsl a t i on = pnode−>tra n sl at i o n ;
int oldlen = st r l e n ( ol dt ra nsl at i o n ) ,
newlen = s tr l e n ( tr an sl a ti on ) ;
pnode−>tr an sl a ti on = malloc ( oldlen + newlen + 2
) ; strcpy ( pnode−>translation , ol dt ra nsl at i o n ) ;
strcpy ( pnode−>tra nsl at i o n+oldlen , ",") ;
strcpy ( pnode−>tra n sl a t i o n+oldlen +1, tr a n sl a ti
o n ) ; f r e e ( ol dt ra n sl a ti o n ) ;
} else
pnode−>t r a n s l a t i o n = s t r c p y ( malloc ( s
t r l e n ( tra n sl a ti on )+1) , t ra n sl a ti o n ) ;
return inew ;
}
/∗ search t r i e structure f or word and return t ra ns l a ti o
n s input : word to search
output : translation , or NULL i f not found ∗/
char ∗ lookup word ( const char ∗ word ) {
/∗ TODO: search t r i e structure for word r
e t u r n NULL i f word i s not found ∗/
struct s t r i e n o d e ∗ pnode = proot ;
int i , len = s t r l e n (word ) ;
unsigned char j;
for ( i = 0 ; i < l e n ; i ++) {
j = word [ i ] ;
if ( ! pnode−>children [ j ] )
return NULL;
pnode = pnode−>chil dren [ j ] ;
}
return pnode−>tra nsl at i o n ;
}
Programming Homework Help
13. /*
* prob1.c
*
* Created on:
* Author:
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* maximum length of input string (including newline character) */
#define INPUT_MAX 2048
/* enable (1) or disable (0) parentheses checking in parsing strings
*/
/* leave disabled for part (a); enable for part (b) */
#define PARSE_PARENS 0
/* type of token */
enum token_type {
OPERAND, /* number */
OPERATOR, /* operator: +, -, *, / */
#if PARSE_PARENS
LPARENS, /* left parentheses ( */
RPARENS /* right parentheses ) */
#endif
};
Programming Homework Help
14. /* operator identifiers (opcodes) */
enum op {
ADD, /* a+b */
SUBTRACT, /* a-b (binary) */
MULTIPLY, /* a*b */
DIVIDE, /* a/b */
NEGATE /* -a (unary) */
};
/* direction of evaluation (associativity) */
enum assoc {
LEFT, /* left-to-right (+, binary -, *, /) */
RIGHT /* right-to-left (unary -) */
};
/* number of operands for each operator type */
const unsigned int op_operands[] = {2, 2, 2, 2, 1};
/* order-of-operations (precedence) (0 = evaluated last) */
const unsigned int op_precedences[] = {0, 0, 1, 1, 2};
/* evaluation direction (associativity) for each precedence level */
const enum assoc op_associativity[] = {LEFT, LEFT, RIGHT};
/* contains value of token */
union token_value {
double operand; /* numeric value for operand */
enum op op_code; /* opcode for operators */
};
/* data structure for token */
typedef struct s_expr_token {
union token_value value; /* numeric value or opcode
*/
enum token_type type; /* type of token */
Programming Homework Help
15. struct s_expr_token * linked_token; /* linked token in stack/queue
*/
} * p_expr_token; /* p_expr_token is shorthand for "struct
s_expr_token *" */
/* data structure for queue */
struct token_queue {
p_expr_token front; /* front of queue, where tokens
are dequeued */
p_expr_token back; /* back of queue, where tokens
are added */
};
/* queue functions - enqueue and dequeue */
void enqueue(struct token_queue * pqueue, const p_expr_token
ptoken);
p_expr_token dequeue(struct token_queue * pqueue);
/* stack functions - push and pop */
void push(p_expr_token * ptop, const p_expr_token ptoken);
p_expr_token pop(p_expr_token * ptop);
/* creates a new token in dynamic memory (using malloc()) */
p_expr_token new_token(const enum token_type type, const
union token_value value);
/* constructs a queue of tokens in infix order from a space-
delimited string */
struct token_queue expr_to_infix(char * str);
Programming Homework Help
16. /* creates a queue of tokens in postfix order from a queue of
tokens in infix order */
/* postcondition: returned queue contains all the tokens, and
pqueue_infix should be
empty */
struct token_queue infix_to_postfix(struct token_queue *
pqueue_infix);
/* evalutes the postfix expression stored in the queue */
/* postcondition: returned value is final answer, and
pqueue_postfix should be empty */
double evaluate_postfix(struct token_queue * pqueue_postfix);
/* handles evaluation process (calls above functions) for
expression string str */
double evaluate(const char * str);
int main(void) {
char input[INPUT_MAX];
double ans;
unsigned int len;
do {
printf("Enter an expression to evaluate:
");
fflush(stdout);
if (!fgets(input, INPUT_MAX, stdin))
abort(); /* failed to read
stdin */
Programming Homework Help
17. len = strlen(input);
/* remove trailing newline character */
if (len > 0 && input[len-1] == 'n') {
input[len-1] = '0';
--len;
}
if (len == 0) /* empty expression signals
exit */
break;
/* call evaluation functions */
ans = evaluate(input);
/* write result to stdout */
printf("%s => %gn", input, ans);
} while (1);
return 0;
}
/* enqueue (add) token to end of queue
input: pqueue - pointer to queue
ptoken - token pointer to add
postcondition: token added to end of queue */
void enqueue(struct token_queue * pqueue, const p_expr_token
ptoken) {
ptoken->linked_token = NULL;
if (pqueue->back)
pqueue->back->linked_token = ptoken;
else /* empty */
pqueue->front = ptoken;
pqueue->back = ptoken;
Programming Homework Help
18. }
/* dequeue (remove) token from front of queue
input: pointer to queue
output: front token pointer (or NULL, if queue was empty)
postcondition: token removed from queue */
p_expr_token dequeue(struct token_queue * pqueue) {
p_expr_token ptoken = pqueue->front;
if (pqueue->front) {
pqueue->front = ptoken->linked_token;
if (ptoken == pqueue->back) /* at end */
pqueue->back = NULL;
ptoken->linked_token = NULL;
}
return ptoken;
}
/* push (add) token to top of stack
input: ptop - pointer to top token pointer of stack
ptoken - token pointer to add
postcondition: ptop points to the added token */
void push(p_expr_token * ptop, const p_expr_token ptoken) {
ptoken->linked_token = *ptop;
*ptop = ptoken;
}
/* pop (remove) token from top of stack
input: pointer to top token pointer of stack
output: top token pointer (or NULL, if stack was empty)
postcondition: ptop points to next token in stack */
p_expr_token pop(p_expr_token * ptop) {
p_expr_token ptoken;
if ( (ptoken = *ptop) ) {
*ptop = ptoken->linked_token;
ptoken->linked_token = NULL;
}
Programming Homework Help
19. return ptoken;
}
/* allocate new token on heap, with specified type and value; the
token is initially
un-linked (field "linked_token" == NULL)
note: token must be freed using free() after use */
p_expr_token new_token(const enum token_type type, const
union token_value value) {
p_expr_token ptoken =
(p_expr_token)malloc(sizeof(struct s_expr_token));
ptoken->type = type;
ptoken->value = value;
ptoken->linked_token = NULL;
return ptoken;
}
/* handles evaluation process (calls above functions) for
expression string str */
/* returns the final answer */
double evaluate(const char * str) {
char * strbuffer; /* mutable buffer for string (modified
in calls to strtok()) */
double ans; /* answer to return */
struct token_queue queue_infix, queue_postfix;
/* copy str into mutable buffer */
strbuffer = strcpy((char *)malloc(strlen(str)+1),str);
/* get queue of tokens in infix order from string buffer
*/
queue_infix = expr_to_infix(strbuffer);
Programming Homework Help
20. /* get queue of tokens in postfix order from infix-
ordered queue */
queue_postfix = infix_to_postfix(&queue_infix);
/* get answer from postfix-ordered queue */
ans = evaluate_postfix(&queue_postfix);
free(strbuffer); /* free memory from heap */
return ans;
}
/* constructs a queue of tokens in infix order from a space-
delimited string */
struct token_queue expr_to_infix(char * str) {
struct token_queue queue_infix; /* queue with infix
ordering */
enum token_type type = OPERATOR;
union token_value value;
/* initialize the queue to empty */
queue_infix.front = NULL;
queue_infix.back = NULL;
/* delimiter string for strtok() -- contains whitespace
characters */
#define DELIMS_STR " nrt"
for (str = strtok(str, DELIMS_STR); str; str =
strtok(NULL, DELIMS_STR)) {
/* parse token */
if (strlen(str) == 1) { /* operators are all 1
character */
Programming Homework Help
21. switch (str[0]) {
case '+':
type =
OPERATOR;
value.op_code =
ADD;
break;
case '-':
/* check
previous token to distinguish between
negate (unary)
and subtract (binary) */
if (type ==
OPERATOR)
value.op_code = NEGATE; /* unary */
#if PARSE_PARENS
else if (type ==
LPARENS)
value.op_code = NEGATE; /* unary */
#endif
else
value.op_code = SUBTRACT; /* binary */
type =
OPERATOR;
break;
case '*':
type =
OPERATOR;
value.op_code =
MULTIPLY;
break;
Programming Homework Help
22. case '/':
type =
OPERATOR;
value.op_code =
DIVIDE;
break;
#if PARSE_PARENS
case '(':
type = LPARENS;
break;
case ')':
type =
RPARENS;
break;
#endif
default:
/* not an
operator */
type =
OPERAND;
value.operand =
strtod(str, NULL);
}
} else {
type = OPERAND;
value.operand = strtod(str,
NULL);
}
/* add token with parsed type and value
to end of queue */
enqueue(&queue_infix, new_token(type,
value));
}
return queue_infix;
Programming Homework Help
23. }
/* creates a queue of tokens in postfix order from a queue of
tokens in infix order */
/* postcondition: returned queue contains all the tokens, and
pqueue_infix should be
empty */
struct token_queue infix_to_postfix(struct token_queue *
pqueue_infix) {
/* TODO: construct postfix-ordered queue from infix-
ordered queue;
all tokens from infix queue should be added to
postfix queue or freed */
}
/* evalutes the postfix expression stored in the queue */
/* postcondition: returned value is final answer, and
pqueue_postfix should be empty */
double evaluate_postfix(struct token_queue * pqueue_postfix) {
/* TODO: process postfix-ordered queue and return
final answer;
all tokens from postfix-ordered queue is freed */
}
Programming Homework Help