Skip to content

Commit c7b0d71

Browse files
committed
Rewrite. Simplified code (WIP).
Fixed some issues but created others. See Issues section in source.
1 parent 27e0c22 commit c7b0d71

File tree

1 file changed

+99
-75
lines changed

1 file changed

+99
-75
lines changed

chapter04/4-6.c

Lines changed: 99 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
* Exercise 4-6. Add commands for handling variables. (it's easy to provide
33
* twenty-six variables with single-letter names). Add a variable for most
44
* recently printed value.
5+
* Issues:
6+
* 1. Variables are initialized to zero by default. Therefore, if a user
7+
* calls an unset variable, it will return a value 0. For example, the
8+
* result of "2 x$ *" is 0, if x is unset.
9+
* 2. If a variable is entered without the fetch operator "$", it will be
10+
* ignored. For example, "2 x *" is be evaluated as "2 *".
11+
* 3. If the call operator is used on an invalid variable, it will be ignored.
12+
* 4. Ambiguity, 4 x = and x 4 = will assign 4 to x. This makes 4 x 5 y = will
13+
* ambiguous becasue it assigns 5 to x and y.
514
* Faisal Saadatmand
615
*/
716

@@ -11,27 +20,28 @@
1120
#include <string.h> /* for strcmp() */
1221
#include <math.h> /* for math commands */
1322

14-
#define MAXOP 100 /* max size of operand or operator */
15-
#define NUMBER '0' /* signal that a number was found */
16-
#define MATH '1' /* signal that an operation was found */
17-
#define MAXVAL 100 /* maximum depth of val stack */
18-
#define BUFSIZE 100
19-
#define MAXVAR 26
20-
#define TOP val[sp - 1] /* top element in stack */
23+
#define MAXOP 100 /* max size of operand or operator */
24+
#define NUMBER '0' /* signal that a number was found */
25+
#define COMMAND '1' /* signal that a string command was found */
26+
#define VARIABLE '2' /* signal that variable was found */
27+
#define MAXVAL 100 /* maximum depth of val stack */
28+
#define BUFSIZE 100
29+
#define MAXVAR 26
30+
#define TOP val[sp - 1] /* top element in stack */
2131

2232
/* functions */
2333
int getop(char []);
2434
void push(double);
2535
double pop(void);
2636
int getch(void);
2737
void ungetch(int);
28-
void printTop(void);
38+
void printTOP(void);
2939
void duplicateTop(void);
3040
void swapTopTwo(void);
3141
void clearStack(void);
3242
int mathfunction(char []);
33-
void storeVariable(void);
34-
void fetchVariable(void);
43+
void storeValue(char);
44+
void fetchValue(char);
3545
void clearMemory(void);
3646

3747
/* globals */
@@ -40,9 +50,9 @@ double val[MAXVAL]; /* value stack */
4050
double mem[MAXVAR]; /* variables values */
4151
char buf[BUFSIZE]; /* buffer from ungetch */
4252
int bufp; /* next free position in buf */
43-
int stackcmd; /* stack commands flag */
44-
char variable; /* current input variable */
45-
double lastPrint; /* last printed value */
53+
int peak; /* flag: peak at top of the stack */
54+
int variable; /* current input variable */
55+
double printed; /* last printed value */
4656

4757
/* push: push f onto value stack */
4858
void push(double f)
@@ -74,27 +84,27 @@ int getop(char s[])
7484
s[1] = '\0';
7585

7686
i = 0;
77-
if (c == '-') /* check sign */
87+
if (c == '-') /* check sign */
7888
if (!isdigit(s[++i] = c = getch())) {
7989
ungetch(c);
80-
c = s[0]; /* not a sign */
90+
c = s[0]; /* not a sign */
8191
}
8292

83-
if (isalpha(c)) { /* math functions */
93+
if (isalpha(c)) { /* string command */
8494
while (isalpha(s[++i] = c = getch()))
8595
;
8696
s[i] = '\0';
8797
ungetch(c);
88-
return MATH;
98+
return (strlen(s) == 1) ? VARIABLE : COMMAND;
8999
}
90100

91101
if (!isdigit(c) && c != '.')
92-
return c; /* not a number */
102+
return c; /* not a number */
93103

94104
if (isdigit(c))
95105
while (isdigit(s[++i] = c = getch()))
96106
;
97-
if( c == '.') /* collect fraction part */
107+
if( c == '.') /* collect fraction part */
98108
while (isdigit(s[++i] = c = getch()))
99109
;
100110
s[i] = '\0';
@@ -119,98 +129,91 @@ void ungetch(int c)
119129
buf[bufp++] = c;
120130
}
121131

122-
/* printTop: prints the top element in the stack */
123-
void printTop(void)
132+
/* printTOP: print top of the stack without pop */
133+
void printTOP()
124134
{
125-
if (sp > 0) {
126-
printf("\t%.8g\n", TOP);
127-
stackcmd = 1;
128-
}
135+
if (sp < 1)
136+
printf("stack empty\n");
137+
printf("\t%.8g\n", TOP);
129138
}
130139

131-
/* deleteTop: deletes the top element in the stack */
140+
/* duplicateTop: duplicate the top element in the stack */
132141
void duplicateTop(void)
133142
{
134-
if (sp > 0) {
135-
push(TOP);
136-
printTop();
137-
}
143+
double top;
144+
145+
if (sp < 1)
146+
return;
147+
push(top = pop());
148+
push(top);
138149
}
139150

140151
/* swapTopTwo: swaps top two elements */
141152
void swapTopTwo(void)
142153
{
143154
double top1, top2;
144155

145-
if (sp > 1) {
146-
top1 = pop();
147-
top2 = pop();
148-
push(top1);
149-
push(top2);
150-
printTop();
156+
if (sp < 2) {
157+
if (sp == 1)
158+
printf("error: 1 element in stack\n");
159+
return;
151160
}
161+
top1 = pop();
162+
top2 = pop();
163+
push(top1);
164+
push(top2);
152165
}
153166

154167
/* clear: clears the entire stack */
155168
void clearStack(void)
156169
{
157-
while (sp > 0)
170+
while (sp > 1)
158171
pop();
159-
printTop();
160172
}
161173

162-
/* mathf: call the appropriate math function according to value of s */
174+
/* mathfunction: call the appropriate math function according to value of s,
175+
* return 1 on success 0 on failure. */
163176
int mathfunction(char s[])
164177
{
165178
double op2;
166179

167-
if (strcmp(s, "sin") == 0)
180+
if (!strcmp(s, "sin"))
168181
push(sin(pop()));
169-
else if (strcmp(s, "cos") == 0)
182+
else if (!strcmp(s, "cos"))
170183
push(cos(pop()));
171-
else if (strcmp(s, "exp") == 0)
184+
else if (!strcmp(s, "exp"))
172185
push(exp(pop()));
173-
else if (strcmp(s, "sqrt") == 0)
186+
else if (!strcmp(s, "sqrt"))
174187
push(sqrt(pop()));
175-
else if (strcmp(s, "pow") == 0) {
188+
else if (!strcmp(s, "pow")) {
176189
op2 = pop();
177190
push(pow(pop(), op2));
178191
} else
179192
return 0;
180193
return 1;
181194
}
182195

183-
/* storeVariable: stores the value of a variable (a to z) to the corrosponding
184-
* memory location in mem */
185-
void storeVariable(void)
196+
/* storeValue: store value of a var (a to z) to the corresponding
197+
* location in mem and push back to top of stack */
198+
void storeValue(char var)
186199
{
187-
pop(); /* pop stored value by fetchVariable */
188-
variable = tolower(variable);
189-
mem[variable - 'a'] = pop(); /* variable value - top of the stack */
190-
stackcmd = 1; /* skip pop print */
200+
push(mem[var - 'a'] = pop());
191201
}
192202

193-
/* fetchVariable: fetches variable value from memory and pushes to the top of
194-
* the stack */
195-
void fetchVariable(void)
203+
/* fetchValue: fetch value var from mem and push on to value stack */
204+
void fetchValue(char var)
196205
{
197-
if (variable == 'R')
198-
push(lastPrint);
199-
else {
200-
variable = tolower(variable);
201-
push(mem[variable - 'a']);
202-
}
206+
push(mem[var - 'a']);
203207
}
204208

205-
/* clearMemory: initializes values of mem to 0 */
209+
/* clearMemory: set values of mem to 0 */
206210
void clearMemory(void)
207211
{
208212
int i;
209213

210214
for (i = 0; i <= MAXVAR; ++i)
211215
mem[i] = 0;
212216
printf("memory cleared\n");
213-
stackcmd = 1; /* skip pop print */
214217
}
215218

216219
/* reverse Polish Calculator */
@@ -250,7 +253,7 @@ int main(void)
250253
printf("error: zero divisor\n");
251254
break;
252255
case '!':
253-
printTop();
256+
peak = 1;
254257
break;
255258
case '#':
256259
duplicateTop();
@@ -262,22 +265,43 @@ int main(void)
262265
clearStack();
263266
break;
264267
case '=':
265-
storeVariable();
268+
if (isalpha(variable)) /* check if variable is valid */
269+
storeValue(variable);
270+
variable = 0;
271+
break;
272+
case '$':
273+
if (isalpha(variable)) /* check if variable is valid */
274+
fetchValue(variable);
275+
variable = 0;
266276
break;
267277
case '\n':
268-
if (!stackcmd)
269-
printf("\t%.8g\n", lastPrint = pop());
270-
stackcmd = 0;
278+
if (peak) {
279+
printTOP();
280+
peak = 0;
281+
} else
282+
printf("\t%.8g\n", printed = pop());
283+
284+
if (variable) {
285+
printf("usage: %c$\n", variable);
286+
variable = 0;
287+
}
271288
break;
272-
case MATH:
273-
if (strlen(s) == 1) {
274-
variable = s[0];
275-
fetchVariable();
276-
} else if (strcmp(s, "mc") == 0)
277-
clearMemory();
278-
else if (!mathfunction(s))
279-
printf("error: unknown command %s\n", s);
289+
case VARIABLE:
290+
variable = tolower(s[0]);
280291
break;
292+
case COMMAND:
293+
if (!strcmp(s, "lp")) {
294+
push(printed);
295+
break;
296+
}
297+
if (!strcmp(s, "mc")) {
298+
clearMemory();
299+
peak = 1;
300+
break;
301+
}
302+
if (mathfunction(s))
303+
break;
304+
/* fall through */
281305
default:
282306
printf("error: unknown command %s\n", s);
283307
break;

0 commit comments

Comments
 (0)