鱼C论坛

 找回密码
 立即注册
查看: 2217|回复: 12

[已解决]请教一下怎么用C语言实现计算算式的功能

[复制链接]
发表于 2022-10-31 12:47:13 | 显示全部楼层 |阅读模式
10鱼币
本帖最后由 水边的小姑娘 于 2022-10-31 12:48 编辑

这是一个可以连续计算的版本,跟我们平常用的计算器差不多。
效果如下:
效果.png
代码如下:
#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,有点愧疚

想请教一下大佬们,怎么实现这样的操作:输入一个四则运算的算式,直接按四则运算规定的顺序计算并且输出结果。
只用告诉我实现的方法就可以了。
最佳答案
2022-10-31 12:47:14
其实flex&bison更适合做这件事
sh-5.1$ ls
Makefile  parser.y  scanner.l
sh-5.1$ cat scanner.l
%option noyywrap
/*%option debug*/
%{
#include "parser.h"
%}
%%
"//".*              {}
([1-9]+[0-9]*)|0    {sscanf(yyget_text(), "%d", &yylval); return NUMBER;}
[[:space:]]+        {}
.                   {return yyget_text()[0];}
%%
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
calc  Makefile        parser.c  parser.h  parser.o  parser.y        scanner.c  scanner.l  scanner.o
sh-5.1$ ./calc
1+2*3-4/5;
= 7
sh-5.1$

最佳答案

查看完整内容

其实flex&bison更适合做这件事
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 12:47:14 | 显示全部楼层    本楼为最佳答案   
其实flex&bison更适合做这件事
sh-5.1$ ls
Makefile  parser.y  scanner.l
sh-5.1$ cat scanner.l
%option noyywrap
/*%option debug*/
%{
#include "parser.h"
%}
%%
"//".*              {}
([1-9]+[0-9]*)|0    {sscanf(yyget_text(), "%d", &yylval); return NUMBER;}
[[:space:]]+        {}
.                   {return yyget_text()[0];}
%%
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
calc  Makefile        parser.c  parser.h  parser.o  parser.y        scanner.c  scanner.l  scanner.o
sh-5.1$ ./calc
1+2*3-4/5;
= 7
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 17:04:55 | 显示全部楼层
去了解一下逆波兰
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 18:21:05 | 显示全部楼层
用递归
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 18:32:46 | 显示全部楼层
这种题目其实算是基础题,可以用逆波兰或二叉树解决。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 19:02:46 | 显示全部楼层
我还在想推荐这个方法是不是太重量级了,结果看到了人造人大佬的帖子……
如果想更深入的了解一下或者自己编写整个过程的话可以了解“文法制导翻译”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 19:44:27 From FishC Mobile | 显示全部楼层
程序写的已经完全不是任何一种学习算法的问题了,而是学习如何使用的问题了。人造人班主,你能不能就你的这个技术,开辟一个专用入门贴,指导一下我们新人能知道顺着哪些线索学习使用好这个工具。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

首先是编译原理,哈工大的
https://www.bilibili.com/video/B ... 7311a641effed03ee60

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

另外就是百度,其实我现在用的必应
https://cn.bing.com/?FORM=Z9FD1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 21:02:59 | 显示全部楼层
前缀表达式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-10-31 21:22:50 | 显示全部楼层
jhq999 发表于 2022-10-31 17:04
去了解一下逆波兰

好嘞还有很多要学习!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-10-31 21:24:54 | 显示全部楼层
傻眼貓咪 发表于 2022-10-31 18:32
这种题目其实算是基础题,可以用逆波兰或二叉树解决。

好哩,我去学习一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

好的,我去研究!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-11-1 22:47:01 | 显示全部楼层
人造人 发表于 2022-10-31 20:21
首先是编译原理,哈工大的
https://www.bilibili.com/video/BV1P4411e7gm/?vd_source=d7ab559fd4b017311 ...

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

谢谢提供这好的学习资料.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-20 14:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表