| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4624 人关注过本帖, 1 人收藏
标题:c语言关于编四则运算的问题
只看楼主 加入收藏
nzxhust
Rank: 2
等 级:论坛游民
威 望:1
帖 子:99
专家分:28
注 册:2008-2-14
结帖率:85.71%
收藏(1)
 问题点数:0 回复次数:6 
c语言关于编四则运算的问题
#include <stdio.h>
#include <stdlib.h>

char token; /*全局标志变量*/

/*递归调用的函数原型*/
int exp( void );
int term( void );
int factor( void );

void error( void ) /*报告出错信息的函数*/
{
    fprintf( stderr, "错误\n");
    exit( 1 );
}

void match( char expectedToken ) /*对当前的标志进行匹配*/
{
    if( token == expectedToken ) token = getchar(); /*匹配成功,获取下一个标志*/
    else error(); /*匹配不成功,报告错误*/
}
void Message(void)
{
    printf("================================================================\n");
    printf("*               递归实现的四则运算表达式求值程序               *\n");
    printf("****************************************************************\n");
    printf("使用方法:请从键盘上直接输入表达式,以回车键结束.如45*(12-2)[回车]\n");
    printf("*****************************************************************\n\n");
}
main()
{
    int result;  /*运算的结果*/
    Message();
    printf(" >> 请输入表达式: ");
    token = getchar(); /*载入第一个符号*/
    
    result = exp(); /*进行计算*/
    if( token == '\n' ) /* 是否一行结束 */
        printf( " >> 表达式的计算结果为 : %d\n", result );
    else error(); /* 出现了例外的字符 */
    puts("\n\n                  请按任意键退出 ...\n");
    getch();
    return 0;
}

int exp( void )
{
    int temp = term(); /*计算比加减运算优先级别高的部分*/
    while(( token == '+' ) || ( token == '-' ))
        switch( token ) {
        case '+': match('+');     /*加法*/
              temp += term();
              break;
        case '-': match('-');
              temp -= term(); /*减法*/
              break;
        }
    return temp;
}

int term( void )
{
    int div; /*除数*/
    int temp = factor();   /*计算比乘除运算优先级别高的部分*/
    while(( token == '*' ) || ( token == '/' ))
        switch( token ) {
        case '*': match('*');  /*乘法*/
              temp *= factor();
              break;
        case '/': match('/');   /*除法*/
              div = factor();
              if( div == 0 ) /*需要判断除数是否为0*/
              {
                  fprintf( stderr, "除数为0.\n" );
                  exit(1);
              }
              temp /= div;
              break;
        }
    return temp;
}

int factor( void )
{
    int temp;
    if( token == '(' ) /*带有括号的运算*/
    {
        match( '(' );
        temp = exp();
        match(')');
    }
    else if ( isdigit( token )) /*实际的数字*/
    {
        ungetc( token, stdin ); /*将读入的字符退还给输入流*/
        scanf( "%d", &temp ); /*读出数字*/
        token = getchar();  /*读出当前的标志*/
    }
    else error(); /*不是括号也不是数字*/
    return temp;
}这是一个书上的例程,有些没明白他到底是怎么实现的,哪为好心的前辈能指导下.我需要详细的实现流程最好能一步步解释怎么算出来的,再此表示感谢!
搜索更多相关主题的帖子: c语言 运算 
2008-02-14 19:25
nzxhust
Rank: 2
等 级:论坛游民
威 望:1
帖 子:99
专家分:28
注 册:2008-2-14
收藏
得分:0 
怎么没人回答啊
2008-02-14 22:39
xianshizhe111
Rank: 1
等 级:新手上路
帖 子:1451
专家分:0
注 册:2007-12-8
收藏
得分:0 
兄弟别悲伤,说实在的你的程序让大家把详细的流程,一步步的详细写出来一般的都没有哪个时间.
如果:你的程序那里错了..乱了..或是想要个合理化建议什么的,大家尽可能帮你解决.
而且这已有不少的中文注释,在好好的理解,理解.
我说的是吧:兄弟
2008-02-15 00:08
真水无痕
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2006-5-12
收藏
得分:0 
我看代码就是一个简单的编译器代码,就是做了词法分析和语法分析,没生成任何目标代码.写了表达式,项,因子函数.楼主可以去看看编译原理.
2008-02-15 00:16
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 
我不知道LZ实在学习C语言还是在学习编译原理;
这个程序是使用递归下降的方法实现的表达式求解;也就是说语法分析时,将一个文本看作一个字符串流,通过扫描器每次取一个单词(token),与期望的文法中,产生式产生的单词是否匹配,将匹配点作为语法树的一个节点,当然在分析的同时可以进行语法树的修饰,也就是语义分析,为了以后正确得到这个字符串所需要告诉我们的信息。
最近我正好在写脚本编译器,举个简单的例子,关于如何获得token是扫描器事情,对于一种给定的语言如何识别,如何提取token,需要创建DFA之类的问题,希望LZ能去看看编译原理的书。
我这里个一个例子是如何获得一个实数,文法如下
DECIMAL --> SIGN UINT PRECISION EXPONENT
SIGN --> +|-|epsilon
UINT --> DIGIT DIGIT*
DIGIT --> [0-9]
PRECISION --> . UINT | epsilon
EXPONENT --> (e|E) SIGN UINT
epsilon表示空字(即什么都没有),其中符号|表示选择,比如SIGN --> +|-|epsilon,也就是说对于产生式SIGN可以生成+或-或者什么都不生成都是合法的,反之对产生式SIGN来说,其它符号都是不合法的,即语法错误;*是Kleene closure(闭包),DIGIT*表示可以重复从[0-9]这些字符中选择若干个,组成一个字符串,也就是说每一次循环选择一个字符,然后扩展字符串长度,重复这一过程;*的另一层涵义可以什么都不产生,即空字;
下面我们看看,对于-123.45e-6是怎样通过这个产生式产生的,并建立一棵语法书,首先无条件创建树根;
                                 DECIMAL
                            *     *     *           *
                         SIGN    UINT   PRECISION   EXPOENT
                          [-]      *     *    *       *     *       *
                                 DIGIT   [.]  UINT   [e]    SIGN   UINT
                                  [1]          *            [-]     *
                                  *            DIGIT               DIGIT
                                 DIGIT          [4]                 [6]
                                  [2]            *
                                  *             DIGIT
                                 DIGIT           [5]
                                  [3]
其中大写单词表示产生式,[]表示数据,这些数据挂在树的不同节点上,是根据产生式调用的次序获得的;而这些数据决定了这个树将得出什么结果,也就是说如何从叶结点逐级向上传递结果,使得根的结果是一个浮点数-123.45e-6而不是一个字符串。
这就牵涉到如何修饰语法树了,这里我不详细说明,因为这个不是一段两段文字能说得清楚的,详细请学习编译原理。

我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2008-02-15 19:03
nzxhust
Rank: 2
等 级:论坛游民
威 望:1
帖 子:99
专家分:28
注 册:2008-2-14
收藏
得分:0 
我从新具体说下哈
我是计算机系学生初学C语言的,主要是这个例程里面我有些看不懂,如那个函数参数是(void)是什么意思是无参数吗?
if( token == '\n' ) /* 是否一行结束 */
        printf( " >> 表达式的计算结果为 : %d\n", result );
    else error(); /* 出现了例外的字符 */
还有这个判断token=="\n"能推出例外字符是什么意思啊?还有getchar函数每次接受一个字符,那数字也算吗?
else if ( isdigit( token )) /*实际的数字*/
    {
        ungetc( token, stdin ); /*将读入的字符退还给输入流*/
        scanf( "%d", &temp ); /*读出数字*/
        token = getchar();  /*读出当前的标志*/
这一段里面的把读入的字符退还给输入流是什么意思,是相当于从新输入这个字符吗?
还有这个里面的getchar()是接受的前面第一次读入之后的字符吗?
现在我说下我的理解哈,我感觉程序是这样运做的,首先读第一个字符给token,然后调用factor()去判断是字符还是"(",
如果是数字就存入temp中,再次读入第二个字符,把先前的数字传到term()函数的temp中,判断第二个字符是*号还是/号,不是就返回到exp()中看是+号还是-号,假如是+号的话,就又调用term()函数,就又传到factor函数,factor函数就再次判断token我的问题就在这,这时的token还是第二个字符啊+号啊,那这里只有"("号和数字啊那不出错拉?
谁能看下我是哪出错了啊,帮我理清下思路哈!谢拉!
2008-02-15 20:30
nzxhust
Rank: 2
等 级:论坛游民
威 望:1
帖 子:99
专家分:28
注 册:2008-2-14
收藏
得分:0 
不好意思我没看清楚啊!
好象搞懂了,还有个match()函数也有个读入字符的,那这段程序就是这样的不?首先是main()函数中读入一个字符判断是数字还是"(",是"("号就重新循环,是数字就在读入第二个字符判断是什么符号,再当找到对应的符号后通过match()函数再读入第三个符号在调用在循环是这样的不?啊不过上个帖子中前面的几个问题还请各位帮下哈再次表示感谢哈
2008-02-15 20:38
快速回复:c语言关于编四则运算的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017475 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved