标题:科学计算器(可实现带括号的浮点数四则运算)
只看楼主
巧若拙
Rank: 4
来 自:宁波余姚
等 级:业余侠客
威 望:1
帖 子:159
专家分:273
注 册:2014-8-24
结帖率:46.15%
已结贴  问题点数:10 回复次数:5 
科学计算器(可实现带括号的浮点数四则运算)
/*
    Name: 科学计算器(可实现带括号的浮点数四则运算)
    Copyright:
    Author:
    Date: 15-09-14 21:49
    Description:
    对近阶段所学的一个小总结,综合了字符串与浮点数转换技术,利用逆波兰表达式,能顺利解决带括号的浮点数四则运算,
    并使用了文件操作,能够从文本文件中读入表达式并输出答案。
    算法思路:从文件读入计算表达式,将计算表达式转换为逆波兰表达式,然后计算出逆波兰表达式的值,最后输出答案。
*/

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>

#define MAXSIZE 200

void Translate(const char str[], char exp[]);//转换为逆波兰表达式
double CompValue(const char *exp); //求逆波兰表达式的值
double CharToDouble(const char *str); //将数字字符串转换为浮点数
void GetStr(char *str); //读取计算式
void ShowAnswer(const char *str, double answer); //输出答案

int main(void)
{
    char str[MAXSIZE], exp[MAXSIZE];
    double answer;
   
    GetStr(str);
    puts(str);
    Translate(str, exp);
    puts(exp);
    answer =  CompValue(exp);
    ShowAnswer(str, answer); //输出答案
     
    return 0;
}

void GetStr(char *str) //读取计算式
{
    FILE *fp;
    int i = 0;
   
    if ((fp=fopen("E:\\编程\\源代码基地\\c\\学习程序\\科学计算器计算式.txt", "rb")) == NULL)
    {
        fprintf(stderr, "Error opening file.");
        exit(1);
    }
   
    rewind(fp);
    while ((str[i] = fgetc(fp)) != EOF)
    {   
        if (str[i] == ' ')//去掉多余的空格
        {
            i--;
        }
        i++;
    }
   
    str[i++] = '#';
    str[i] = '\0';
   
    fclose(fp);
}

void ShowAnswer(const char *str, double answer) //输出答案
{
    FILE *fp;
   
    if ((fp=fopen("科学计算器计算式.txt", "a+b")) == NULL)
    {
        fprintf(stderr, "Error opening file.");
        exit(1);
    }
   
    fprintf(fp, " = %f ", answer);
    fprintf(stdout, "%s = %f\n", str, answer);
   
    fclose(fp);
}

void Translate(const char str[], char exp[]) //转换为逆波兰表达式
{
    char stack[MAXSIZE];
    int i = 0, k = 0, top = -1;
   
    while (str[i] != '#')
    {
        if (str[i] == '(') //直接将'('入栈
        {
            stack[++top] = str[i++];
        }
        else if (str[i] == ')')
        {
            while (top >= 0 && stack[top] != '(') //将'('之前的符号出栈,并存储到逆波兰表达式
            {
                exp[k++] = stack[top--];
            }
            
            if (top < 0) //'('不足,即有多余的')'
            {
                puts("'('不匹配\n");
                exp[k++] = '\0';
                return ;
            }
            top--;//去掉 '('
            i++;
        }
        else if (str[i] == '+' || str[i] == '-')
        {
            while (top >= 0 && stack[top] != '(') //如果有'(',将'('之前的符号出栈,否则所有符号出栈,并存储到逆波兰表达式
            {
                exp[k++] = stack[top--];
            }
            stack[++top] = str[i++]; //将新的运算符号入栈
        }
        else if (str[i] == '*' || str[i] == '/')
        {
            while (top >= 0 && (stack[top] == '*' || stack[top] == '/')) //将'*'和'/'之前的符号出栈,并存储到逆波兰表达式
            {
                exp[k++] = stack[top--];
            }
            stack[++top] = str[i++]; //将新的运算符号入栈
        }
        else
        {
            while ((str[i] >= '0' && str[i] <= '9') || str[i] == '.') //将浮点数直接存储到逆波兰表达式
            {
                exp[k++] = str[i++];
            }
            exp[k++] = '#'; //增加一个浮点数结束符号,以便正确提取浮点数
        }
    }
   
    while (top >= 0) //将栈中所有运算符号存储到逆波兰表达式
    {
        if (stack[top] == '(') //有多余的'('
        {
            puts("'('不匹配\n");
            exp[k++] = '\0';
            return ;
        }
        exp[k++] = stack[top--];
    }
   
    exp[k++] = '\0';
}

double CompValue(const char *exp) //求逆波兰表达式的值
{
    char tempStr[MAXSIZE];
    double stack[MAXSIZE];
    int i = 0, k = 0, top = -1;
   
    while (exp[i] != '\0')
    {
        if (exp[i] >= '0' && exp[i] <= '9')
        {
            k = 0;
            while (exp[i] != '#')
            {
                tempStr[k++] = exp[i++];
            }
            tempStr[k] = '\0';
            stack[++top] = CharToDouble(tempStr);
            i++; //跳过'#'
        }
        else
        {
            switch (exp[i++]) //将计算结果入栈,并退出多余的数字
            {
                case '+' : stack[top-1] += stack[top];
                           break;
                case '-' : stack[top-1] -= stack[top];
                           break;
                case '*' : stack[top-1] *= stack[top];
                           break;
                case '/' : if (stack[top] != 0)
                           {
                                  stack[top-1] /= stack[top];
                           }
                           else
                           {
                                  puts("除零错误\n");
                               return 0;      
                           }
                           break;                              
            }
            top--; //退出多余的数字
        }
    }
   
    return stack[top];
}

double CharToDouble(const char *str) //将数字字符串转换为浮点数
{
    double sumInt = 0, sumDec = 0, e = 1;
    int i = 0;
   
    while (str[i] >= '0' && str[i] <= '9')
    {
        sumInt = sumInt * 10 + str[i++] - '0';
    }
   
    if (str[i] == '.') //如果含小数,处理小数部分
    {
        while (str[++i] != '\0')
        {
            sumDec = sumDec * 10 + str[i] - '0';
            e *= 10;
        }
    }
   
    return sumInt + sumDec / e;
}
搜索更多相关主题的帖子: 计算器 Copyright 文本文件 include 表达式 
2014-09-15 21:51
随风而行lulu
Rank: 2
等 级:论坛游民
帖 子:59
专家分:60
注 册:2014-9-6
得分:4 
谢谢分享!第一次听说逆波兰表达式,是什么?
2014-09-15 22:05
魑魅魍魉!
Rank: 3Rank: 3
来 自:亲爱MM肚子里!
等 级:论坛游侠
威 望:1
帖 子:61
专家分:149
注 册:2014-5-3
得分:4 
亲。。。。。这是嘛情况 啊!!
看着都头晕哟
2014-09-15 22:59
随风而行lulu
Rank: 2
等 级:论坛游民
帖 子:59
专家分:60
注 册:2014-9-6
得分:0 
楼主能讲一下转换为逆波兰表达式的算法吗
2014-09-16 16:33
随风而行lulu
Rank: 2
等 级:论坛游民
帖 子:59
专家分:60
注 册:2014-9-6
得分:0 
楼主能讲一下转换为逆波兰表达式的算法吗
2014-09-16 18:38
龙牙
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:大汉
等 级:贵宾
威 望:17
帖 子:769
专家分:6207
注 册:2013-3-18
得分:4 
回复 5 楼 随风而行 lulu
呵呵,上百度查

只要心是晴朗的,人生就没有雨天。
2014-09-16 18:48



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-436126-1-1.html




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

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