An alternate organization uses getline to read an entire input line; this makes getch and ungetch unnecessary. Revise the calculator to use this approach.
An alternate organization uses getline to read an entire input line; this makes getch and ungetch unnecessary. Revise the calculator to use this approach.
Solution by Franz Fritsche.
/* K&R Exercise 4-10 */
/* Franz Fritsche */
#include <stdio.h>
#include <stdlib.h>
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
#define MAXLINE 1000
int getop(char []);
void push(double);
double pop(void);
int getline(char [], int);
char line[MAXLINE];
int line_i;
/* reverse Polish calculator */
int main(void)
{
int type;
double op2;
char s[MAXOP];
while (getline(line, MAXLINE) != 0)
{
line_i = 0;
while ((type = getop(s)) != '\0')
{
switch (type)
{
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command \'%s\'\n", s);
break;
}
}
}
return 0;
}
#define MAXVAL 100 /* maximum depth of val stack */
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
/* push: push f onto value stack */
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else
printf("error: stack empty\n");
return 0.0;
}
/* getline: get line into s, return length */
int getline(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
#include <ctype.h>
/* getop: get next character or numeric operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = line[line_i++]) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; /* not a number */
i = 0;
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = line[line_i++]))
;
if (c == '.') /* collect fraction part */
while (isdigit(s[++i] = c = line[line_i++]))
;
s[i] = '\0';
line_i--;
return NUMBER;
}
Category 0 Solution by Jesus Alvarez
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define MAXOP 100 /* Max size of operand or operator. */
#define NUMBER '0' /* Signal that a number was found. */
#define VARIABLE '1'
#define VARMAX 27
#define BUFSIZE 1000
int is_first_input = 0; /* Prevents the solution from being printed on first
input */
double var_array[VARMAX]; /* Contains user defined variables. */
int getop(char []);
void push(double);
double pop(void);
double top(void);
int clear(void);
int swap(void);
int elem(void);
int dup(void);
void sprnt(void);
void result(void);
void set_solution(void);
void print_help(void);
int mygetline(char [], int);
int main()
{
int type;
int i, j;
int op3;
double topd;
double op2;
char ic[MAXOP]; /* Input Char */
char tmp[MAXOP];
for (i = 0; i < VARMAX; i++) {
var_array[i] = 0;
}
print_help();
while ((type = getop(ic)) != EOF) {
op3 = elem();
if (op3 == 0) { /* Only one input completed. */
is_first_input = 1;
} else if (op3 > 1) {
is_first_input = 0;
}
i = j = 0;
switch (type) {
case NUMBER:
push(atof(ic));
break;
case VARIABLE:
for (i = 2; ic[i] != '\0'; i++){
tmp[j++] = ic[i];
tmp[j] = '\0';
}
var_array[ic[0] - 'A'] = atof(tmp);
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0){
push(pop() / op2);
} else {
printf("Error: Divide by zero.\n");
}
break;
case '%':
op3 = (int) pop();
push((int) pop() % op3);
break;
case 'c':
if (clear()) {
printf("Stack Cleared.\n");
}
break;
case 'p':
if ((topd = top()) != 0) {
printf("Top stack element: %g", topd);
printf(" of %d elements.\n", elem());
}
break;
case 's':
if (swap()) {
printf("Swap successful.\n");
}
break;
case 'd':
if (dup()) {
printf("Duplication is successful.\n");
} else {
printf("Error: Stack empty.\n");
}
break;
case 'r':
sprnt();
break;
case 'o':
if (elem() < 2) {
printf("Error: pow requires at least two ");
printf("items on the stack.\n");
break;
}
op2 = pop();
push(pow(op2, pop()));
break;
case 'i':
set_solution();
push(sin(pop()));
result();
break;
case 'y':
set_solution();
push(cos(pop()));
break;
case 't':
set_solution();
push(tan(pop()));
break;
case 'x':
set_solution();
push(exp(pop()));
break;
case 'q':
set_solution();
push(sqrt(pop()));
break;
case 'f':
set_solution();
push(floor(pop()));
break;
case 'l':
set_solution();
push(ceil(pop()));
break;
case 'v':
for (i = 0; i < VARMAX; i++) {
if (i < VARMAX-1) {
printf("%c: %10.10G\n", 'A' + i, var_array[i]);
} else {
printf("%c: %10.10G\n", '=', var_array[VARMAX]);
}
}
break;
case 'h':
print_help();
break;
case '\n':
result();
break;
default:
if ((type >= 'A' && type <= 'Z') || type == '=') {
if (type != '=') {
push(var_array[type - 'A']);
} else {
push(var_array[VARMAX]);
}
} else {
printf("Error: Unknown command \'%s\'\n", ic);
}
break;
}
}
return 0;
}
#define MAXVAL 100 /* Maximum depth of val stack. */
int sp = 0; /* Next free stack position. */
double val[MAXVAL]; /* Value stack. */
void push(double f)
{
if (sp < MAXVAL) {
val[sp++] = f;
} else {
printf("Error: Stack full, cannot push %g\n", f);
}
}
double pop(void)
{
if (sp > 0) {
return val[--sp];
} else {
printf("Error: Stack empty.\n");
return 0.0;
}
}
double top(void)
{
if (sp > 0) {
return val[sp-1];
} else {
printf("Error: Stack empty.\n");
return 0.0;
}
}
int clear(void)
{
if (sp > 0) {
while(val[--sp] != '\0');
sp = 0;
return 1;
} else {
printf("Error: Stack empty.\n");
return 0;
}
}
int swap(void)
{
double sbuf;
if (sp > 0) {
sbuf = val[sp-2];
val[sp-2] = val[sp-1];
val[sp-1] = sbuf;
return 1;
} else {
printf("Error: Stack empty.\n");
return 0;
}
}
int elem(void)
{
return sp;
}
int dup (void)
{
if (sp > 0) {
sp++;
val[sp] = val[sp-1];
return 1;
} else {
return 0;
}
}
void sprnt(void)
{
int count = 0;
while (count < sp) {
printf("%d:%10.12g\n", count+1, val[count]);
count++;
}
}
void result(void)
{
if (sp == 1 && is_first_input != 1) {
printf("Solution: %10.20g\n", val[0]);
var_array[VARMAX] = val[0];
is_first_input = 0;
clear();
}
}
/*
* Opens result() for execution.
* Primarily used with the math functions because they can be used with only
* one stack item. For ex, if "1 i" is entered as the first input, this
* function would allow for a result to be shown and the stack cleared.
*/
void set_solution(void)
{
if (elem() >= 1) {
is_first_input = 0;
}
}
int mygetline(char s[], int maxline)
{
int i = 0;
char c;
while ((c = getchar()) != EOF && c != '\n' && i < maxline) {
s[i++] = c;
}
if (c == '\n') {
s[i++] = c;
}
s[i++] = '\0';
return i;
}
char getopbuf[BUFSIZE]; /* A string buffer that holds the mygetline. */
int getopbufp = 0; /* Current position is the string buffer. */
int getopbuflen = 0;
int getop(char s[])
{
int i = 0, c;
s[0] = '\0';
if (getopbuflen == 0 || getopbufp == getopbuflen-2) {
getopbufp = 0;
/* Get a new line of input from the user. */
getopbuflen = mygetline(getopbuf, BUFSIZE);
}
if (getopbuf[getopbufp] == '\n') {
return '\n';
}
/* Jump over spaces at the begining of the string. */
while (isspace(c = getopbuf[getopbufp++]));
s[i++] = c;
if (isalpha(c) && c >= 'A' && c <= 'Z') {
/* Collect the variable. */
for (i = 1; getopbuf[getopbufp] != ' '
&& getopbuf[getopbufp] != '\n';
s[i++] = getopbuf[getopbufp++]);
s[i] = '\0';
if (i > 1) { /* A properly formed variable definition. */
return VARIABLE;
} else {
return c;
}
} else if (!isdigit(c) && c != '.' && c != '-') {
return c; /* Not a number. */
}
if (c == '-') {
if ((c = getopbuf[++getopbufp]) == ' ') {
/* If the next char is space, then c is a operator. */
return c;
} else if (isdigit(c)) {
s[++i] = c;
}
}
if (isdigit(c)) { /* Collect integer part. */
for ( ; isdigit(c = getopbuf[getopbufp]); i++, getopbufp++) {
s[i] = c;
}
}
if (c == '.') { /* Collect fraction part. */
while (isdigit(s[i++] = c = getopbuf[getopbufp++]));
}
s[i] = '\0';
return NUMBER;
}
void print_help(void)
{
printf("The Polish Calculator\n");
printf("-----------------------------------------------\n");
printf("-> Enter equations in the form: \"1 1 + 2 5 + *\"\n");
printf("-> Use \"A=1 B=2 C=3\" to store variables.\n");
printf("-> Use \"A B C * *\" to use stored variables.\n");
printf("-----------------------------------------------\n");
printf(">>> Command Help:\n");
printf(">>> c: Clear memory.\n");
printf(">>> p: Print last character.\n");
printf(">>> s: Swap last two characters.\n");
printf(">>> d: Duplicate the last input.\n");
printf(">>> r: Print the entire stack.\n");
printf(">>> v: Print variable list.\n");
printf(">>> o: pow(x,y), x^y, x > 0.\n");
printf(">>> i: sin(x), sine of x.\n");
printf(">>> y: cos(x), cosine of x.\n");
printf(">>> t: tan(x), tangent of x.\n");
printf(">>> x: exp(x), e^x, exponential function.\n");
printf(">>> q: sqrt(x), x >= 0, square of x.\n");
printf(">>> f: floor(x), largest integer not greater than x.\n");
printf(">>> l: ceil(x), smallest integer not less than x.\n");
printf(">>> =: Access the last successful solution.\n");
printf(">>> h: Print this help text.\n");
}
'The C Programming Language' 카테고리의 다른 글
Chapter 4 - Functions and Program Structure 12 (0) | 2009.03.27 |
---|---|
Chapter 4 - Functions and Program Structure 11 (0) | 2009.03.27 |
Chapter 4 - Functions and Program Structure 9 (0) | 2009.03.27 |
Chapter 4 - Functions and Program Structure 8 (0) | 2009.03.27 |
Chapter 4 - Functions and Program Structure 7 (0) | 2009.03.27 |