读书人

小型计算器程序解决办法

发布时间: 2012-05-04 12:36:09 作者: rapoo

小型计算器程序
这是一段出现在课本《c程序设计语言》中的程序,请高手解释一下具体的实现原理:

#include<stdio.h>
#include<stdlib.h>

#define MAXOP 100
#define NUMBER '\0'

int getop(char []);
void push(double);
double pop(void);

/* 逆波兰计算器程序 比如: 当输入: 4 5 - 6 8 * + 时, 则输出: 47 */
main()
{
int type;
double op2;
char s[MAXOP];

while ((type = getop(s)) != EOF){
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;
}
}
getch();
return 0;
}



#define MAXVAL 100

int sp = 0;
double val[MAXVAL];

void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}


double pop()
{
if(sp > 0)
return val[--sp];
else{
printf("error: stack empty\n");
return 0.0;
}
}


#include<ctype.h>

int getch(void);
void ungetch(int);


/* 请解释此段代码的工作原理 */
int getop(char s[])
{
int i, c;

while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0'; /* 此语句的作用? */
if (!isdigit(c) && c != '.')
return c;
i = 0;
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

char buf[BUFSIZE];
int bufp = 0;

int getch(void) /* getch()函数在标准库里已定义, 这里再定义一次不会和标准库冲突吗?*/
{
return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}

不好意思代码有点长,但觉得此程序很经典,想彻底了解一下,请高手指教。先谢谢啦

[解决办法]
int getop(char s[])
{
int i, c;
/**获取第一个非空字符**/
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0'; /* 此语句的作用? */
/*******************
*答:这句没用。
*******************/
/**返回一个非数字,也非.的字符,也就是返回操作符(+-*/)**/
if (!isdigit(c) && c != '.')
return c;
/**下面获取一个数字**/
i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = getch())) /* 收集整数部分 */
;


if (c == '.')
while (isdigit(s[++i] = c = getch())) /* 收集小数部分 */

;
/**字符串结束符**/
s[i] = '\0';
/******************************************
*下面把最后一个字符放到缓冲区,
*下一个循环要从buf中读最后一个字符,
*如果buf为空则从stdin中读一个字符。
*其实BUFSIZE为1就够了。
******************************************/
if (c != EOF)
ungetch(c);
return NUMBER;
}


getch()不是标准函数,它是微软发明的函数。
你可以查一下《C参考大全》,或者直接看C99文档。

我这里没有微软的编译器,所以无法测试会不会冲突,
GCC上编译是没有问题的。
在微软编译器上是否会冲突就要看编译器是怎么做的了,
反正是微软自己发明的,微软想让它冲突就冲突,想不冲突也有办法。
[解决办法]

C/C++ code
/* * 如果输入的第一个字符不是数字也不是小数点,那么把它写进s并返回此字符 * 否则读取完整的数字写入s,并返回一个标志NUMBER */int getop(char s[]) {     int i, c;     while ((s[0] = c = getch()) == ' ' || c == '\t')         ;  // 忽略空格和TAB    s[1] = '\0';  // 使s成为一个有结束符的完整字符串    if (!isdigit(c) && c != '.')         return c;  // 如果第一个子符不是数字也不是小数点,那么就返回这个字符。这时候上面的s[1]=0就有用了,因为main里要把s当作字符串处理    i = 0;     if (isdigit(c))         while (isdigit(s[++i] = c = getch())) /* 收集整数部分 */             ; // 把输入的数字保存到s,直到输入一个非数字    if (c == '.')         while (isdigit(s[++i] = c = getch())) /* 收集小数部分 */             ; // 把输入的数字保存到s,直到输入一个非数字     s[i] = '\0';  //字符串结束符    if (c != EOF)         ungetch(c);  // 把一串数字后面紧跟着的第一个字符(很可能是运算符)保存到缓冲区,下次再读取    return NUMBER; }
[解决办法]
C/C++ code
//其实是把整个输入的表达式当成一个字符串来看待int getop(char s[]) {     int i, c;     while ((s[0] = c = getch()) == ' ' || c == '\t')         ;     s[1] = '\0';      //'0'字符表示字符串结束的标志,当条件不满足时,结束输入。    if (!isdigit(c) && c != '.')    //如果不是数字并且不是小数点则返回         return c;     i = 0;     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 char buf[BUFSIZE]; int bufp = 0; int getch(void)  //通过函数重载的方法就不会冲突! {     return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) {     if(bufp >= BUFSIZE)         printf("ungetch: too many characters\n");     else         buf[bufp++] = c; } 

读书人网 >C语言

热点推荐