练习4-10 另一种方法是通过getline函数读入整个输入行,这种情况下可以不使用getch与ungetch函数。请运用这一方法修改计算机程序。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include<ctype.h>
#include<math.h>
#include<string.h>
#define NUMBER '0'
#define FUNCTION '1'
#define MAXLEN 100
#define MAXOP 100
#define MAXVAL 100
int sp = 0; //next free position in val;
double val[MAXVAL];
int getop(char to[], char in[],int* inp);
void push(double f);
double pop(void);
//int getch(void);
//void ungetch(int c);
void dealwithname(char s[]);
int getline(char s[],int maxlen);
void showtop(void); //#
void duplicate(void); //$
void swapitems(void); //?
void clearstack(void); //!
main() {
int type,len;
double op2;
char to[MAXOP];
char in[MAXLEN];
int inp;
while ((len = getline(in,MAXLEN)) > 0) {
inp =0;
while ((type = getop(to, in,&inp)) != '\0') {
switch (type) {
case NUMBER:
push(atof(to));
break;
case FUNCTION:
dealwithname(to);
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 '%':
op2 = pop();
if (op2 != 0.0) {
push(fmod(pop(), op2));
}
else
printf("error: zero divisor\n");
break;
case '#':
showtop();
break;
case '$':
duplicate();
break;
case '?':
swapitems();
break;
case '!':
clearstack();
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error:unknown command %s\n", to);
break;
}
}
}
return 0;
}
//这是采用getline的方案
int getline(char s[],int maxlen) {
int i;
char c;
for (i = 0; (c = getchar()) != EOF && c!='\n' && i < maxlen - 1; i++)
s[i] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
int getop(char to[],char in[],int* inp) {
int i = 0;
char c;
while ((to[0]=c=in[(*inp)++]) == '\40' || c == '\t')
;
to[1] = '\0';
if (isalpha(c)) {
while (isalpha(to[++i] = c = in[(*inp)++]))
;
to[i] = '\0';
if (c != EOF) --(*inp);
return FUNCTION;
}
if (!isdigit(c) && c != '-') {
return c;
}
if (c == '-') {
if (!isdigit(c = in[(*inp)++])) {
if (c != EOF) --(*inp);
return '-';
}
else {
to[++i] = c;
while (isdigit(to[++i] = c = in[(*inp)++]))
;
if (c == '.')
while (isdigit(to[++i] = c = in[(*inp)++]))
;
to[i] = '\0';
if (c != EOF) --(*inp);
return NUMBER;
}
}
if (isdigit(c))
while (isdigit(to[++i] = c = in[(*inp)++]))
;
if (c == '.')
while (isdigit(to[++i] = c = in[(*inp)++]))
;
to[i] = '\0';
if (c != EOF) --(*inp);
return NUMBER;
}
#define MAXVAL 100
int sp = 0; //next free position in val;
double val[MAXVAL];
void push(double f) {
if (sp > MAXVAL) printf("error:stack full,can't push %g\n", f);
else val[sp++] = f;
}
double pop() {
if (sp > 0) return val[--sp];
else {
printf("error:stack empty\n");
return 0.0;
}
}
void showtop(void) {
if (sp > 0) printf("the top of stack is %u\n", val[sp - 1]);
else printf("empty stack\n");
}
void duplicate(void) {
if (sp > 0) val[sp++] = val[sp - 1];
else printf("empty stack\n");
}
void swapitems(void) {
double temp;
if (sp > 1) {
temp = val[sp - 1];
val[sp - 1] = val[sp - 2];
val[sp - 2] = temp;
}
}
void clearstack(void) {
sp = 0;
}
//这是采用getch与ungetch的方案
/*int getop(char s[]) {
int c;
int i = 0;
while ((s[0] = c = getch()) == '\40' || c == '\t')
;
s[1] = '\0';
if (isalpha(c)) {
while (isalpha(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF) ungetch(c);
return FUNCTION;
}
if (!isdigit(c) && c != '-')
return c;
if (c == '-') {
if (!isdigit(c = getch())) {
if (c != EOF) ungetch(c);
return '-';
}
else {
s[++i] = c;
while (isdigit(s[++i] = c = getch()))
;
if (c == '.')
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
}
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
if (c == '.')
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
#define BUFSIZE 100
int buf[BUFSIZE];
int bufp = 0; //next free position in buf;
int getch(void) {
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) {
if (bufp > BUFSIZE) printf("error:too many characters\n");
else buf[bufp++] = c;
}*/
void dealwithname(char s[]) {
double op2;
if (!strcmp(s, "sin")) push(sin(pop()));
else if (!strcmp(s, "cos")) push(cos(pop()));
else if (!strcmp(s, "exp")) push(exp(pop()));
else if (!strcmp(s, "pow")) {
op2 = pop();
push(pow(pop(), op2));
}
else printf("%s is not a supported function.\n", s);
}