如何计算一个字符串表示的计算式?比如,有字符串“1+2*3”,如何计算得到其值为7?

TouchStoneStudio 2013-01-31 03:24:06
如何计算一个字符串表示的计算式?比如,有字符串“1+2*3”,如何计算得到其值为7?
如题,请教各位
...全文
1522 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
jianglijun007 2014-11-12
  • 打赏
  • 举报
回复
你现在知道答案了吗?我只想简单的算数,不要括号和其他的,可以发一个吗?
TouchStoneStudio 2013-02-27
  • 打赏
  • 举报
回复
引用 33 楼 pw215712 的回复:
还没有学到栈,好多看不懂
可以用递归简单地实现
25K纯帅 2013-02-14
  • 打赏
  • 举报
回复
还没有学到栈,好多看不懂
zhaokai115 2013-02-03
  • 打赏
  • 举报
回复
为表歉意,贴个代码

// eval - 计算字符串表达式的值
//        表达式只由+-*/四种运算符及正整数组成,没有括号,没有空格
// @param s - 表达式字符串的起始位置
// @param e - 表达式字符串的结束位置(不算在表达式内)
//
int eval(const char *s, const char *e)
{
    const char *p;

    // 计算+-
    for (p = e - 1; p > s; --p) {
        switch (*p) {
        case '+':
            return eval(s, p) + eval(p + 1, e);
        case '-':
            return eval(s, p) - eval(p + 1, e);
        default:
            break;
        }
    }

    // 计算*/
    for (p = e - 1; p > s; --p) {
        switch (*p) {
        case '*':
            return eval(s, p) * eval(p + 1, e);
        case '/':
            return eval(s, p) / eval(p + 1, e);
        default:
            break;
        }
    }

    // 计算数值部分
    return atoi(s);
}

// 测试代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    static const char ops[] = "+-*/";
    char expr[] = "1+2-3*4/5";
    int i;

    srand(time(NULL));
    for (i = 0; i < N; ++i) {
        expr[0] = (rand() & 7) + '1';
        expr[1] = ops[rand() & 3];
        expr[2] = (rand() & 7) + '1';
        expr[3] = ops[rand() & 3];
        expr[4] = (rand() & 7) + '1';
        expr[5] = ops[rand() & 3];
        expr[6] = (rand() & 7) + '1';
        expr[7] = ops[rand() & 3];
        expr[8] = (rand() & 7) + '1';
        printf("%s = %d\n", expr, eval(expr, expr + 9));
    }
    return 0;
}

TouchStoneStudio 2013-02-03
  • 打赏
  • 举报
回复
引用 29 楼 zhaokai115 的回复:
为表歉意,贴个代码 C/C++ code?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263// eval - 计算字符串表达式的值// 表达式只由+-*/四种运算符及正整数……
谢谢你,我按照你的提供的思路,实现了一下 你看看我上面的实现,应该没有问题吧??? 另外,这里还有一篇文章介绍 http://chenlq.net/books/c-mate/learn-the-c-language-how-to-write-a-more-advanced-calculator-how-to-calculate-the-value-of-a-string-representation-formula-recursive-algorithm.html
TouchStoneStudio 2013-02-03
  • 打赏
  • 举报
回复
引用 23 楼 everax 的回复:
引用 19 楼 TouchStoneStudio 的回复:引用 10 楼 zhaokai115 的回复:递归调用,基本算法如下,自己加合法性检查,以及去掉多余空格等操作。C/C++ code?1234567891011121314int eval(const char *s){ int n; if (-1 != (n = find_first(s, '-')……
谢谢你 第一次我的实现确实有问题 修改之后的

// eval.c 计算字符串计算式的值

#include <string.h>
#include <stdio.h>

int find_last(const char* s,char a)
{
	int pos = strlen(s);
	// 从字符串末尾位置开始查找
	const char* p = s + pos;
	 
	// 如果没有到达字符串开始的前一个位置(s-1)
	while((s-1)!=p)
	{
		// 如果当前位置的字符就是要查找的字符
		if(*p == a)
		{
			break; // 结束查找哦啊
		}
		p--; // 变换到下一个位置
		pos--;
	}
	if((s-1)!=p) // 找到字符
	{
		return pos;
	}
	else // 未找到
	{
		return -1;
	}
}
// 取得字符串的左半部分
char* left_str(char* s,int pos)
{
	s[pos] = '\0';
	return s;
}
// 取得字符串的右半部分
char* right_str(char* s,int pos)
{
	return s + pos + 1;
}
// 计算字符串计算式s的值
int eval(char* s)
{
	int n = 0;
	// 找到最后一个加号
	n = find_last(s,'+');
	if(-1 != n)
	{
		// 以加号所在的位置,将字符串分为左右两部分分别计算
		// 然后将两部分的值加起来
		return eval(left_str(s,n)) + eval(right_str(s,n));
	}
	n = find_last(s,'-');
	if(-1 != n)
	{
		return eval(left_str(s,n)) - eval(right_str(s,n));
	}
	n = find_last(s,'*');
	if(-1 != n)
	{
		return eval(left_str(s,n)) * eval(right_str(s,n));
	}
	n = find_last(s,'/');
	if(-1 != n)
	{
		return eval(left_str(s,n)) / eval(right_str(s,n));
	}
	// 当字符串中不包含运算符时,返回这个数字本身
	return atoi(s);
}

int main(int argc,char* argv[])
{
	// 检查参数是否合法
	if(2 != argc)
	{
		puts("usage: eval 1+2+3");
		return 1;
	}
	// 复制从参数得到的计算式字符串
	char expr[32] = "";
	strcpy(expr,argv[1]); 
	 
	// 对计算式字符串进行计算,得到结果
	int res = eval(expr);

	// 输出结果
	printf("%s = %d",argv[1],res);
	
	return 0;
}

zhaokai115 2013-02-02
  • 打赏
  • 举报
回复
好吧,我承认误导楼主了,正确的应该是

 //找到最后一个低优先级的运算符,它将是最后被计算的
if (-1 != (n=find_last(s, "+-"))) {
    if ('+' == s[n])
        return eval(left(s,n)) + eval(right(s,n));
    else if ('-' == s[n])
        retur eval(left(s,n)) - eval(right(s,n));
} else if (-1 != (n=find_last(s, "*/"))) {
    // 现在只剩下高优先级的运算符了,最后一个是最后被计算的
    if ('*' == s[n])
        return eval(left(s,n)) * eval(right(s,n));
    else if ('/' == s[n])
        retur eval(left(s,n)) / eval(right(s,n));
} else {
} 
TouchStoneStudio 2013-02-02
  • 打赏
  • 举报
回复
引用 21 楼 AgedBOY 的回复:
楼主说的是很普通的“算符优先算法”。就是一个数值栈和一个算符栈,外加一张算符优先级表。算到最后算符栈应空,数值栈应该只有一个数,就是结果。这应该是大二编译原理课比较靠前的内容。你找本编译原理书看看吧,大部分都有讲到。
谢谢你的提示:)
TouchStoneStudio 2013-02-02
  • 打赏
  • 举报
回复
引用 24 楼 everax 的回复:
抱歉,上一条帖子例子举措了。。下面这个可以了 6 + 3 - 6 + 3 实际顺序 应该是 (((6 + 3) - 6) + 3) = 6 lz的顺序是 (6 + (3 - (6 + 3))) = 0
仔细分析了一下,我的计算顺序是 (6+((3-6)+3))=6 虽然结果碰巧对了,而我的计算过程还是有点问题
TouchStoneStudio 2013-02-02
  • 打赏
  • 举报
回复
引用 24 楼 everax 的回复:
抱歉,上一条帖子例子举措了。。下面这个可以了 6 + 3 - 6 + 3 实际顺序 应该是 (((6 + 3) - 6) + 3) = 6 lz的顺序是 (6 + (3 - (6 + 3))) = 0
没有啊,我算出来的结果也会是6啊? F:\code>a.exe 6+3-6+3 6+3-6+3 = 6
iEverX 2013-02-02
  • 打赏
  • 举报
回复
抱歉,上一条帖子例子举措了。。下面这个可以了 6 + 3 - 6 + 3 实际顺序 应该是 (((6 + 3) - 6) + 3) = 6 lz的顺序是 (6 + (3 - (6 + 3))) = 0
iEverX 2013-02-02
  • 打赏
  • 举报
回复
引用 19 楼 TouchStoneStudio 的回复:
引用 10 楼 zhaokai115 的回复:递归调用,基本算法如下,自己加合法性检查,以及去掉多余空格等操作。C/C++ code?1234567891011121314int eval(const char *s){ int n; if (-1 != (n = find_first(s, '-'))) return eval(left_st……
LZ的有问题吧。。 比如 6 - 3 + 6 - 2。。lz的计算顺序是 6 - ( 3 + (6 - 2)) 吧。。
iEverX 2013-02-02
  • 打赏
  • 举报
回复
引用 21 楼 AgedBOY 的回复:
楼主说的是很普通的“算符优先算法”。就是一个数值栈和一个算符栈,外加一张算符优先级表。算到最后算符栈应空,数值栈应该只有一个数,就是结果。这应该是大二编译原理课比较靠前的内容。你找本编译原理书看看吧,大部分都有讲到。
不用这么高深的算法吧。。 如果只有加减乘除,只需一个栈保存数字就行了
AgedBOY 2013-02-01
  • 打赏
  • 举报
回复
楼主说的是很普通的“算符优先算法”。就是一个数值栈和一个算符栈,外加一张算符优先级表。算到最后算符栈应空,数值栈应该只有一个数,就是结果。这应该是大二编译原理课比较靠前的内容。你找本编译原理书看看吧,大部分都有讲到。
line_us 2013-02-01
  • 打赏
  • 举报
回复
观摩各种解法。
兆帅 2013-02-01
  • 打赏
  • 举报
回复
引用 14 楼 happynesslele 的回复:
Python code?123str = "1+2*3"value = eval(str)print "%s=%d"%(str,value)
也可以
  • 打赏
  • 举报
回复

str = "1+2*3"
value = eval(str)
print "%s=%d"%(str,value)
DyanWang 2013-02-01
  • 打赏
  • 举报
回复
用栈,一个符号栈,一个值域栈,再将字符转化成数字就可以了
天涯洪七公 2013-02-01
  • 打赏
  • 举报
回复
引用 7 楼 TouchStoneStudio 的回复:
引用 4 楼 yh_1108 的回复:如果你只学过C语言你可以这样,先把这些字符串保存在一个数组里,然后把连续的数字变成数,然后读取这些字符串,发现有乘号或者除号就把前后两个数作运算,这样就消除了乘和除,然后再把加和减前后2个数作运算,然后就可以得到结果了,然后你就OK了…… 谢谢 这种方法是可行,但是好像稍微复杂了一点 如果我也学过C++,知道容器的用法呢? ……
如果那样你就可以像他们说的那样用栈了嘛
加载更多回复(15)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧