水边的小姑娘 发表于 2022-10-31 12:47:13

请教一下怎么用C语言实现计算算式的功能

本帖最后由 水边的小姑娘 于 2022-10-31 12:48 编辑

这是一个可以连续计算的版本,跟我们平常用的计算器差不多。
效果如下:

代码如下:
#include <stdio.h>
#include <stdlib.h>

float result=0;

void calculate (float,char,float);
void plus (float,float);
void mutiply (float,float);


int main(void)
{
    char c,ch;
    float op1,op2;
    start :
    printf ("please input a formula:\n");
    scanf ("%f%c%f",&op1,&c,&op2);
    fflush(stdin);
    calculate(op1,c,op2);
    printf ("P for QUIT,R for restart...");
    ch = getchar();
    fflush(stdin);
    while ((ch != 'p')&&(ch != 'P'))
    {   
      if ((ch=='r')||(ch=='R'))
      {
            goto start;
      }
      
      printf ("please input:\n");
      scanf ("%c%f",&c,&op2);
      fflush(stdin);
      op1 = result;
      calculate(op1,c,op2);
      printf ("P for QUIT,R for restart...");
      ch = getchar();
      fflush(stdin);
    }
    system ("pause");
    return 0;
}

void calculate(float op1,char c,float op2)
{
    switch (c)
    {
    case '-':op2 = -op2;
    case '+':plus(op1,op2);break;
    case '/':
    {
      if (op2 == 0) {printf ("the formula is wrong!\n");break;}
      else {op2 = 1/op2;}
    }
    case '*':mutiply(op1,op2);break;
    default:break;
    }
}

void plus(float op1,float op2)
{
    result = op1+op2;
    printf ("the result is %.2f\n",result);
}

void mutiply(float op1,float op2)
{
    result = op1*op2;
    printf ("the result is %.2f\n",result);
}
用了goto,有点愧疚{:9_220:}

想请教一下大佬们,怎么实现这样的操作:输入一个四则运算的算式,直接按四则运算规定的顺序计算并且输出结果。
只用告诉我实现的方法就可以了。{:9_228:}

人造人 发表于 2022-10-31 12:47:14

其实flex&bison更适合做这件事

sh-5.1$ ls
Makefileparser.yscanner.l
sh-5.1$ cat scanner.l
%option noyywrap
/*%option debug*/
%{
#include "parser.h"
%}
%%
"//".*            {}
(+*)|0    {sscanf(yyget_text(), "%d", &yylval); return NUMBER;}
[[:space:]]+      {}
.                   {return yyget_text();}
%%
sh-5.1$ cat parser.y
%define parse.trace
%define parse.lac full
%define parse.error detailed
%{
#include <stdio.h>

int yylex(void);

void yyerror(const char *s) {
    fprintf(stderr, "bc: %s\n", s);
}
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%%
line: %empty
    | line ';'
    | line exp ';'{printf("= %d\n", $2);}
    ;
exp:NUMBER
    | exp '+' exp   {$$ = $1 + $3;}
    | exp '-' exp   {$$ = $1 - $3;}
    | exp '*' exp   {$$ = $1 * $3;}
    | exp '/' exp   {$$ = $1 / $3;}
    | '(' exp ')'   {$$ = $2;}
    | '|' exp %prec UMINUS{$$ = $2 < 0 ? -$2 : $2;}
    | '-' exp %prec UMINUS{$$ = -$2;}
    ;
%%
int main(void) {
    //yydebug = 1;
    yyparse();
    return 0;
}
sh-5.1$ cat Makefile
CFLAGS = -g -Wall -Wextra -Wno-unused-function

all: calc

calc: scanner.o parser.o
        $(CC) $(CFLAGS) -o $@ $^

parser.c scanner.c: parser.y scanner.l
        flex -o scanner.c scanner.l
        bison --header=parser.h -o parser.c parser.y

clean:
        rm -f calc
        rm -f scanner.o parser.o
        rm -f scanner.c parser.c
        rm -f parser.h
sh-5.1$ make
flex -o scanner.c scanner.l
bison --header=parser.h -o parser.c parser.y
cc -g -Wall -Wextra -Wno-unused-function   -c -o scanner.o scanner.c
cc -g -Wall -Wextra -Wno-unused-function   -c -o parser.o parser.c
cc -g -Wall -Wextra -Wno-unused-function -o calc scanner.o parser.o
sh-5.1$ ls
calcMakefile        parser.cparser.hparser.oparser.y        scanner.cscanner.lscanner.o
sh-5.1$ ./calc
1+2*3-4/5;
= 7
sh-5.1$

jhq999 发表于 2022-10-31 17:04:55

去了解一下逆波兰

niuniu97 发表于 2022-10-31 18:21:05

用递归

傻眼貓咪 发表于 2022-10-31 18:32:46

这种题目其实算是基础题,可以用逆波兰或二叉树解决。{:10_327:}{:10_327:}

dolly_yos2 发表于 2022-10-31 19:02:46

我还在想推荐这个方法是不是太重量级了,结果看到了人造人大佬的帖子……
如果想更深入的了解一下或者自己编写整个过程的话可以了解“文法制导翻译”

howzyao 发表于 2022-10-31 19:44:27

程序写的已经完全不是任何一种学习算法的问题了,而是学习如何使用的问题了。人造人班主,你能不能就你的这个技术,开辟一个专用入门贴,指导一下我们新人能知道顺着哪些线索学习使用好这个工具。

人造人 发表于 2022-10-31 20:21:07

howzyao 发表于 2022-10-31 19:44
程序写的已经完全不是任何一种学习算法的问题了,而是学习如何使用的问题了。人造人班主,你能不能就你的这 ...

首先是编译原理,哈工大的
https://www.bilibili.com/video/BV1P4411e7gm/?vd_source=d7ab559fd4b017311a641effed03ee60

flex&bison的教程我看的
flex与bison+中文版.pdf
百度上下载的

另外就是百度,其实我现在用的必应
https://cn.bing.com/?FORM=Z9FD1

Yanyz 发表于 2022-10-31 21:02:59

前缀表达式

水边的小姑娘 发表于 2022-10-31 21:22:50

jhq999 发表于 2022-10-31 17:04
去了解一下逆波兰

好嘞{:9_238:}还有很多要学习!

水边的小姑娘 发表于 2022-10-31 21:24:54

傻眼貓咪 发表于 2022-10-31 18:32
这种题目其实算是基础题,可以用逆波兰或二叉树解决。

好哩,我去学习一下{:9_219:}

水边的小姑娘 发表于 2022-10-31 21:26:14

dolly_yos2 发表于 2022-10-31 19:02
我还在想推荐这个方法是不是太重量级了,结果看到了人造人大佬的帖子……
如果想更深入的了解一下或者自己 ...

{:9_222:}好的,我去研究!

howzyao 发表于 2022-11-1 22:47:01

人造人 发表于 2022-10-31 20:21
首先是编译原理,哈工大的
https://www.bilibili.com/video/BV1P4411e7gm/?vd_source=d7ab559fd4b017311 ...

谢谢了.太感谢了,一看就入迷了,一口气看到了2课,3,语义分析.老师讲的太生动了.6个流程,从扫到一串字符开始,入处理,语法分析->语义分析,使用管理表,错误表,差不多就了解了这些了.

谢谢提供这好的学习资料.
页: [1]
查看完整版本: 请教一下怎么用C语言实现计算算式的功能