Code Bye

C语言 计算器问题(请看一下)

123+213-67*34+345/23*45*(34+34-345+245+567)=359 183
可本人的程序等于-363067 代码如下
#include
#include
#include
#define MAXZISE 1000
struct oper
{
char name;
int priority;
int opnum;
};
typedef struct oper OPERATOR;
OPERATOR opStack[MAXZISE];
int OTop=-1;
int numStack[MAXZISE];
int NTop=-1;
int getPriority(char name)//获取一个字符所代表的运算符的优先级
{
if (name==”(“||name==”)”){
return 0;
}
if (name==”*”||name==”/”){
return 2;
}
if (name==”+”||name==”-“){
return 1;
}
}
int getOpNum(char name)//获取一个字符所代表的运算符的目数
{
if (name==”*”||name==”/”||name==”+”||name==”-“){
return 2;
}
if (name==”(“||name==”)”){
return 0;
}
}
void pushOp(OPERATOR op)//运算符压栈
{
if (OTop opStack[++OTop] = op;
}
}
OPERATOR popOp()//运算符出栈
{
if (OTop>= 0){
return opStack[OTop–];
}
}
void pushNum(int num)//操作数压栈
{
if (NTop numStack[++NTop] = num;
}
}
int popNum()//操作数出栈
{
if (NTop >= 0){
return numStack[NTop–];
}
}
int change(char s, int *i)//将数字从字符串转换到整型
{
int j = 0;
char str[MAXZISE];
while ((*s) >= “0” && *s <= “9”)
{
str[j++] = (*s);
s++;
}
(*i) = (*i) + j;
str[j] = “\0″;
return atoi(str);
}
int opertateNum(OPERATOR op)//从操作数栈中弹出两个操作数,完成一次双目运算
{
int num2=popNum();
int num1=popNum();
if (op.name==”+”){
return num1 + num2;
}
if (op.name==”-“){
return num1 – num2;
}
if (op.name==””){
return num1 * num2;
}
if (op.name==”/”){
return num1 / num2;
}
}
int main()
{
char S[MAXZISE];
int i,j;
OPERATOR op, topOp;
topOp.name = “#”;
topOp.priority = 0;
topOp.opnum = 0;
pushOp(topOp);
scanf(“%s”, S);
for(i=0;i if(S[i]!=” “)
S[j++]=S[i];
}
S[j]=”\0″;
for (i=0;S[i]!=”\0″&&S[i]!=”=”;){
if (S[i]>=”0″&&S[i]<=”9″){
pushNum(change(&S[i], &i));
}
else{
op.name = S[i];
op.priority = getPriority(S[i]);
op.opnum = getOpNum(S[i]);
topOp = popOp();
if (op.name == “(“){
//假如是”(“,将从栈顶弹出的运算符压回栈内,并将当前运算符则压栈
pushOp(topOp);
pushOp(op);
}
else if (op.name == “)”){
//假如是”)”,则进行运算,每次运算结果作为一个操作数压入操作数栈,直到将”(“弹出运算符栈
while (topOp.name != “(“){
pushNum(opertateNum(topOp));
topOp = popOp();
}
}
else{
if (topOp.name !=”#”&& op.priority<= topOp.priority){
pushNum(opertateNum(topOp));
}
else{
pushOp(topOp);
}
pushOp(op);
}
i++;
}
}
while ((topOp = popOp()).name!=”#”){
pushNum(opertateNum(topOp));
}
printf(“%d\n”, popNum());
return 0;
}
解决方案

40

帮题主调试了下发现
对于123+213-67*34+345/23*45*(34+34-345+245+567)相似这样的式子
它会计算成123+213-((67*34+345/23*45*(34+34-345+245+567)))=-363067
建议题主检查下逻辑,或单步调试看看
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。

20

代码功能归根结底不是别人帮本人看或讲解或注释出来的;而是被本人静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生本人领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
调试方法供参考:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <conio.h>
const int  DIGIT=1;
const int MAXLEN=16384;
char s[MAXLEN],*endss;
void show(int ST[10],int ist,char op[10],int iop,int last,char *expr,char *pp,int level) {
    int i;
    printf("level:%d\n",level);
    printf("last:%s\n",last==DIGIT?"DIGIT":"OPREATOR");
    printf("expr:%s\n",expr);
    printf("pp^ :%*s^\n",pp-expr,"");
    printf("ST:");
    for (i=0;i<ist;i++) printf(" %d",ST[i]);
    printf("\n");
    printf("op:");
    for (i=0;i<iop;i++) printf(" %c",op[i]);
    printf("\n");
    printf("\n");
    getch();
}
int calc(char *expr,char **addr,int level) {
    int ST[10]={0}; //数字栈
    char op[10]={"+"}; //运算符栈
    char c,*pp;
    int ist=1,iop=1,last;
    char cc;
    pp=expr;
    last = !DIGIT;
    printf("calc函数开始...\n");show(ST,ist,op,iop,last,expr,pp,level);
    if ((c=*pp)=="!") {
        printf("遇!,改栈底为!\n");
        op[0] = c;
        pp++;
        show(ST,ist,op,iop,last,expr,pp,level);
    }
    while (1) {
        c=*pp;
        if (c==0) break;
        if (c=="(") {
            printf("遇(,递归调用calc...\n");
            ST[ist++]=calc(++pp,addr,level+1);
            pp = *addr;
            last = DIGIT;
            show(ST,ist,op,iop,last,expr,pp,level);
        } else if (c==")") {
            pp++;
            show(ST,ist,op,iop,last,expr,pp,level);
            break;
        } else if (c=="+"||c=="*") {
            if (last != DIGIT) {
                printf("运算符粘连\n");exit(5);
            }
            pp++;
            if (c=="+") {
                printf("遇+,计算栈中保存的表达式...\n");
                show(ST,ist,op,iop,last,expr,pp,level);
                do {
                    cc = op[--iop];
                    --ist;
                    switch (cc) {
                    case "+":  ST[ist-1] |= ST[ist];break;
                    case "*":  ST[ist-1] &= ST[ist];break;
                    case "!":  ST[ist-1] =1-ST[ist];break;
                    }
                    show(ST,ist,op,iop,last,expr,pp,level);
                } while (iop);
                op[iop++] = c;
                printf("计算结果...\n");show(ST,ist,op,iop,last,expr,pp,level);
            } else if (c=="*") {
                cc = op[iop-1];
                if (cc=="+") {
                    printf("遇*,且栈顶是+,将*压栈...\n");
                    op[iop++] = c;
                    show(ST,ist,op,iop,last,expr,pp,level);
                } else {
                    printf("遇*,且栈顶是*或!,将旧栈顶两数*的结果或旧栈顶!的结果作为新栈顶...\n");
                    --ist;
                    op[iop-1] = c;
                    switch (cc) {
                    case "*":  ST[ist-1] &= ST[ist];break;
                    case "!":  ST[ist-1] =1-ST[ist];break;
                    }
                    show(ST,ist,op,iop,last,expr,pp,level);
                }
            }
            last = !DIGIT;
        } else if (c=="!") {
            printf("遇!,将!和0压栈\n");
            op[iop++] = c;
            ST[ist++] =0;
            pp++;
            show(ST,ist,op,iop,last,expr,pp,level);
        } else {
            if (last == DIGIT) {
                printf("两数字粘连\n");exit(7);
            }
            if (!(pp[0]=="0"||pp[0]=="1")) {
                printf("非法字符\n");exit(8);
            }
            printf("遇%c,压栈...\n",pp[0]);
            ST[ist++]=pp[0]-"0";
            pp++;
            last = DIGIT;
            show(ST,ist,op,iop,last,expr,pp,level);
        }
    }
    *addr=pp;
    if (iop>=ist) {
        printf("表达式有误\n");exit(9);
    }
    printf("calc函数结束前计算栈中保存的表达式...\n");show(ST,ist,op,iop,last,expr,pp,level);
    while (iop) {
        --ist;
        switch (op[--iop]) {
        case "+":  ST[ist-1] |= ST[ist];break;
        case "*":  ST[ist-1] &= ST[ist];break;
        case "!":  ST[ist-1] =1-ST[ist];break;
        }
        show(ST,ist,op,iop,last,expr,pp,level);
    }
    printf("返回计算结果...\n");show(ST,ist,op,iop,last,expr,pp,level);
    return ST[0];
}
int main() {
    setlocale(LC_ALL,"chs");
    while (1) {
        printf("请输入布尔表达式,例如!(1+1)*1:");fflush(stdout);
        rewind(stdin);
        gets(s);
        if (s[0]==0) break;//
        printf("%s的最终结果为%d\n",s,calc(s,&endss,1));
    }
    return 0;
}

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C语言 计算器问题(请看一下)