《C程序设计语言》练习题 5-10

编写程序 expr,计算从命令行输入的逆波兰表达式的值,其中每个运算符或操作数用一个单独的参数表示。例如,命令

expr 2 3 4 + *

计算表达式2x(3+4)的值

算法实现

getfloat.c:

// getfloat.c
#include<stdio.h>
#include<ctype.h>
int getfloat(char* str, double* store)
{
while (isspace(*str))
str++;
int ch, sign;
double power = 1.0;
ch = *str++;
sign = ch == '-' ? -1 : 1;
if (ch == '+' || ch == '-') {
ch == *str++;
}
for (*store == 0.0; isdigit(ch); ch = *str++) {
*store = *store*10.0 + ch - '0';
}
if (ch == '.') {
ch=*str++;
}
for (; isdigit(ch); ch = *str++) {
*store = *store*10.0 + ch - '0';
power *= 10.0;
}
if (ch == 0 || isspace(ch) || ch == EOF) {
//如果不能继续读取数字,那么跳出的原因必须是 ch==0 || isspace(ch) || ch==EOF
*store /= power;
*store *= sign;
return 1;
}
else {
return -1;
}
}

expr.c:

//expr.c
#include<stdio.h>
#include<ctype.h>
#define MAX_NUM 100
double stack[MAX_NUM];
extern int getfloat(char* str,double*);
int main(int argc, char* argv[])
{
if (argc < 2) {
printf("usage: expr num1 num2 operator ...\n");
return 1;
}
else {
int stackp = 0;
int ch = 0;
double num1, num2, ans;
while (--argc >= 1) {
ch = (*++argv)[0];
if (ch == '-'){
if (!isdigit(ch = (*argv)[1])) {
//是负号
if (stackp >= 2) {
num2 = stack[--stackp];
num1 = stack[--stackp];
stack[stackp++] = num1 - num2;
continue;
}
else {
printf("Error: at least two numbers are needed before operator '-'\n");
return -1;
}
}
}
if (isdigit(ch)) {
if (stackp < 0) {
printf("stack is underflowed!\n");
return -2;
}
else if (stackp >= MAX_NUM) {
printf("stack is overflowed!\n");
return -3;
}
else if (getfloat(*argv, &stack[stackp++]) == -1) {
printf("wrong argument to get number: %s\n", *argv);
return -4;
}
}
else if (ch == '+'||ch=='*'||ch=='/'||ch=='%') {
if (stackp >= 2) {
num2 = stack[--stackp];
num1 = stack[--stackp];
switch (ch) {
case '+':
ans = num1 + num2;
break;
case '*':
ans = num1*num2;
break;
case '/':
if (num2 == 0.0) {
printf("error zero divisor: %f / %f\n", num1, num2);
return -5;
}
ans = num1 / num2;
break;
case '%':
ans = (int)num1%(int)num2;
break;
}
stack[stackp++] = ans;
}
else {
printf("Error: at least two numbers are needed before operator '%c'\n",ch);
return -6;
}
}
else {
printf("wrong arguments for %c,usage: expr num1 num2 operator ...\n", ch);
return -7;
}
}
if (stackp == 1) {
printf("%.4f\n", stack[0]);
}
else {
printf("the format of input is wrong!\n");
}
}
return 0;
}

重温C语言(1)----计算算术表达式的值的更多相关文章

  1. 【算法】E.W.Dijkstra算术表达式求值

    算术表达式求值 我们要学习的一个栈的用例同时也是展示泛型的应用的一个经典例子,就是用来计算算术表达式的值,例如 ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ) 如果将4乘以5,把3 ...

  2. 栈的一个实例——Dijkstra的双栈算术表达式求值法

    Dijkstra的双栈算术表达式求值法,即是计算算术表达式的值,如表达式(1 + ( (2+3) * (4*5) ) ). 该方法是 使用两个栈分别存储算术表达式的运算符与操作数 忽略左括号 遇到右括 ...

  3. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  4. OpenJudge计算概论-简单算术表达式求值

    /*===================================== 简单算术表达式求值 总时间限制: 1000ms 内存限制: 65536kB 描述 2位正整数的简单算术运算(只考虑整数运 ...

  5. Dijkstra的双栈算术表达式求值算法

    这次来复习一下Dijkstra的双栈算术表达式求值算法,其实这就是一个计算器的实现,但是这里用到了不一样的算法,同时复习了栈. 主体思想就是将每次输入的字符和数字分别存储在两个栈中.每遇到一个单次结束 ...

  6. 算法手记(2)Dijkstra双栈算术表达式求值算法

    这两天看到的内容是关于栈和队列,在栈的模块发现了Dijkstra双栈算术表达式求值算法,可以用来实现计算器类型的app. 编程语言系统一般都内置了对算术表达式的处理,但是他们是如何在内部实现的呢?为了 ...

  7. 实现Linux下dc的功能,计算后缀表达式的值

    提交测试截图和码云练习项目链接,实现Linux下dc的功能,计算后缀表达式的值 -将运算符写在两个操作数之后的表达式称为"后缀表达式",如上面的中缀表达式可转换为后缀表达式1 2 ...

  8. [Java]算术表达式求值之三(中序表达式转二叉树方案 支持小数)

    Entry类 这个类对表达式的合法性进行了粗筛: package com.hy; import java.io.BufferedReader; import java.io.IOException; ...

  9. [Java]算术表达式求值之二(中序表达式转后序表达式方案,支持小数)

    Inlet类,入口类,这个类的主要用途是验证用户输入的算术表达式: package com.hy; import java.io.BufferedReader; import java.io.IOEx ...

随机推荐

  1. initializer_list

    initializer_list是一种模板类型,定义initializer_list对象是,必须说明列表中所含元素的类型: initializer_list<Type> lst{a, b, ...

  2. loj 6433 「PKUSC2018」最大前缀和 题解【DP】【枚举】【二进制】【排列组合】

    这是个什么集合DP啊- 想过枚举断点但是不会处理接下来的问题了- 我好菜啊 题目描述 小 C 是一个算法竞赛爱好者,有一天小 C 遇到了一个非常难的问题:求一个序列的最大子段和. 但是小 C 并不会做 ...

  3. Android手游2048核心功能

    private void swipeUp(){ //向上滑动函数 for (int x = 0; x < 4; x++) { //行从上到下 for (int y = 0; y < 4; ...

  4. 利用scrapy-client发布爬虫的远程服务器

    一.环境准备 远程服务器必须装有scapyd,我们使用的机器必须有scrapy-client(我这里是windows),并确保这两者正常安装并启动. 二.客户端准备上传 首先进入到爬虫项目的根文件夹: ...

  5. 第2章—装配Bean—自动化装配Bean

    自动化装配Bean 2.1.Spring配置可选方案 ​ 装配是依赖注入DI的本质,Spring提供了以下三种注入的装配机制: 在XMl中进行显式配置 在java中进行显式配置 隐式的Bean发现机制 ...

  6. ubuntu apache2 .htaccess 下配置 反向代理

    安装完apache2后, a2enmod rewrite //启用.htaccess规则 a2enmod proxy a2enmod proxy_http //启用反向代理支持 [P] 配置OK,就可 ...

  7. InterView之C/CPP

    CPP 引用 什么是"引用"?申明和使用"引用"要注意哪些问题? 答:引用就是某个目标变量的别名(alias),对应用的操作与对变量直接操作效果完全相同.申明一 ...

  8. 事务实现,redo,undo,锁

    事务(Transaction)是数据库区别于文件系统的重要特性之一.在文件系统中,如果你正在写文件,但是操作系统突然崩溃了,这个文件就很有可能被破坏.当然,有一些机制可以把文件恢复到某个时间点.不过, ...

  9. leetcode4:Permutation

    #include <utility> #include <iostream> #include <vector> #include <algorithm> ...

  10. 端口扫描工具nmap

    nmap 使用介绍 nmap是目前为止最广为使用的国外端口扫描工具之一.我们可以从[url]http://www.insecure.org/[/url]进行下载,可以很容易的安装到Windows和un ...