鱼C论坛

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

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

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

这是一个可以连续计算的版本,跟我们平常用的计算器差不多。
效果如下:
效果.png
代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. float result=0;

  4. void calculate (float,char,float);
  5. void plus (float,float);
  6. void mutiply (float,float);


  7. int main(void)
  8. {
  9.     char c,ch;
  10.     float op1,op2;
  11.     start :
  12.     printf ("please input a formula:\n");
  13.     scanf ("%f%c%f",&op1,&c,&op2);
  14.     fflush(stdin);
  15.     calculate(op1,c,op2);
  16.     printf ("P for QUIT,R for restart...");
  17.     ch = getchar();
  18.     fflush(stdin);
  19.     while ((ch != 'p')&&(ch != 'P'))
  20.     {   
  21.         if ((ch=='r')||(ch=='R'))
  22.         {
  23.             goto start;
  24.         }
  25.         
  26.         printf ("please input:\n");
  27.         scanf ("%c%f",&c,&op2);
  28.         fflush(stdin);
  29.         op1 = result;
  30.         calculate(op1,c,op2);
  31.         printf ("P for QUIT,R for restart...");
  32.         ch = getchar();
  33.         fflush(stdin);
  34.     }
  35.     system ("pause");
  36.     return 0;
  37. }

  38. void calculate(float op1,char c,float op2)
  39. {
  40.     switch (c)
  41.     {
  42.     case '-':op2 = -op2;
  43.     case '+':plus(op1,op2);break;
  44.     case '/':
  45.     {
  46.         if (op2 == 0) {printf ("the formula is wrong!\n");break;}
  47.         else {op2 = 1/op2;}
  48.     }
  49.     case '*':mutiply(op1,op2);break;
  50.     default:break;
  51.     }
  52. }

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

  58. void mutiply(float op1,float op2)
  59. {
  60.     result = op1*op2;
  61.     printf ("the result is %.2f\n",result);
  62. }
复制代码

用了goto,有点愧疚

想请教一下大佬们,怎么实现这样的操作:输入一个四则运算的算式,直接按四则运算规定的顺序计算并且输出结果。
只用告诉我实现的方法就可以了。
最佳答案
2022-10-31 12:47:14
其实flex&bison更适合做这件事

  1. sh-5.1$ ls
  2. Makefile  parser.y  scanner.l
  3. sh-5.1$ cat scanner.l
  4. %option noyywrap
  5. /*%option debug*/
  6. %{
  7. #include "parser.h"
  8. %}
  9. %%
  10. "//".*              {}
  11. ([1-9]+[0-9]*)|0    {sscanf(yyget_text(), "%d", &yylval); return NUMBER;}
  12. [[:space:]]+        {}
  13. .                   {return yyget_text()[0];}
  14. %%
  15. sh-5.1$ cat parser.y
  16. %define parse.trace
  17. %define parse.lac full
  18. %define parse.error detailed
  19. %{
  20. #include <stdio.h>

  21. int yylex(void);

  22. void yyerror(const char *s) {
  23.     fprintf(stderr, "bc: %s\n", s);
  24. }
  25. %}
  26. %token NUMBER
  27. %left '+' '-'
  28. %left '*' '/'
  29. %nonassoc UMINUS
  30. %%
  31. line: %empty
  32.     | line ';'
  33.     | line exp ';'  {printf("= %d\n", $2);}
  34.     ;
  35. exp:  NUMBER
  36.     | exp '+' exp   {$$ = $1 + $3;}
  37.     | exp '-' exp   {$$ = $1 - $3;}
  38.     | exp '*' exp   {$$ = $1 * $3;}
  39.     | exp '/' exp   {$$ = $1 / $3;}
  40.     | '(' exp ')'   {$$ = $2;}
  41.     | '|' exp %prec UMINUS  {$$ = $2 < 0 ? -$2 : $2;}
  42.     | '-' exp %prec UMINUS  {$$ = -$2;}
  43.     ;
  44. %%
  45. int main(void) {
  46.     //yydebug = 1;
  47.     yyparse();
  48.     return 0;
  49. }
  50. sh-5.1$ cat Makefile
  51. CFLAGS = -g -Wall -Wextra -Wno-unused-function

  52. all: calc

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

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

  58. clean:
  59.         rm -f calc
  60.         rm -f scanner.o parser.o
  61.         rm -f scanner.c parser.c
  62.         rm -f parser.h
  63. sh-5.1$ make
  64. flex -o scanner.c scanner.l
  65. bison --header=parser.h -o parser.c parser.y
  66. cc -g -Wall -Wextra -Wno-unused-function   -c -o scanner.o scanner.c
  67. cc -g -Wall -Wextra -Wno-unused-function   -c -o parser.o parser.c
  68. cc -g -Wall -Wextra -Wno-unused-function -o calc scanner.o parser.o
  69. sh-5.1$ ls
  70. calc  Makefile        parser.c  parser.h  parser.o  parser.y        scanner.c  scanner.l  scanner.o
  71. sh-5.1$ ./calc
  72. 1+2*3-4/5;
  73. = 7
  74. sh-5.1$
复制代码

最佳答案

查看完整内容

其实flex&bison更适合做这件事
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 12:47:14 | 显示全部楼层    本楼为最佳答案   
其实flex&bison更适合做这件事

  1. sh-5.1$ ls
  2. Makefile  parser.y  scanner.l
  3. sh-5.1$ cat scanner.l
  4. %option noyywrap
  5. /*%option debug*/
  6. %{
  7. #include "parser.h"
  8. %}
  9. %%
  10. "//".*              {}
  11. ([1-9]+[0-9]*)|0    {sscanf(yyget_text(), "%d", &yylval); return NUMBER;}
  12. [[:space:]]+        {}
  13. .                   {return yyget_text()[0];}
  14. %%
  15. sh-5.1$ cat parser.y
  16. %define parse.trace
  17. %define parse.lac full
  18. %define parse.error detailed
  19. %{
  20. #include <stdio.h>

  21. int yylex(void);

  22. void yyerror(const char *s) {
  23.     fprintf(stderr, "bc: %s\n", s);
  24. }
  25. %}
  26. %token NUMBER
  27. %left '+' '-'
  28. %left '*' '/'
  29. %nonassoc UMINUS
  30. %%
  31. line: %empty
  32.     | line ';'
  33.     | line exp ';'  {printf("= %d\n", $2);}
  34.     ;
  35. exp:  NUMBER
  36.     | exp '+' exp   {$$ = $1 + $3;}
  37.     | exp '-' exp   {$$ = $1 - $3;}
  38.     | exp '*' exp   {$$ = $1 * $3;}
  39.     | exp '/' exp   {$$ = $1 / $3;}
  40.     | '(' exp ')'   {$$ = $2;}
  41.     | '|' exp %prec UMINUS  {$$ = $2 < 0 ? -$2 : $2;}
  42.     | '-' exp %prec UMINUS  {$$ = -$2;}
  43.     ;
  44. %%
  45. int main(void) {
  46.     //yydebug = 1;
  47.     yyparse();
  48.     return 0;
  49. }
  50. sh-5.1$ cat Makefile
  51. CFLAGS = -g -Wall -Wextra -Wno-unused-function

  52. all: calc

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

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

  58. clean:
  59.         rm -f calc
  60.         rm -f scanner.o parser.o
  61.         rm -f scanner.c parser.c
  62.         rm -f parser.h
  63. sh-5.1$ make
  64. flex -o scanner.c scanner.l
  65. bison --header=parser.h -o parser.c parser.y
  66. cc -g -Wall -Wextra -Wno-unused-function   -c -o scanner.o scanner.c
  67. cc -g -Wall -Wextra -Wno-unused-function   -c -o parser.o parser.c
  68. cc -g -Wall -Wextra -Wno-unused-function -o calc scanner.o parser.o
  69. sh-5.1$ ls
  70. calc  Makefile        parser.c  parser.h  parser.o  parser.y        scanner.c  scanner.l  scanner.o
  71. sh-5.1$ ./calc
  72. 1+2*3-4/5;
  73. = 7
  74. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 17:04:55 | 显示全部楼层
去了解一下逆波兰
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 18:21:05 | 显示全部楼层
用递归
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-31 18:32:46 | 显示全部楼层
这种题目其实算是基础题,可以用逆波兰或二叉树解决。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

使用道具 举报

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

使用道具 举报

发表于 2022-10-31 21:02:59 | 显示全部楼层
前缀表达式
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

好嘞还有很多要学习!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

好哩,我去学习一下
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

好的,我去研究!
小甲鱼最新课程 -> https://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个流程,从扫到一串字符开始,入处理,语法分析->语义分析,使用管理表,错误表,差不多就了解了这些了.

谢谢提供这好的学习资料.
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-23 06:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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