C 如何正确解析算术表达式中的数字,区分正数和负数?
我在我的数据结构课程中有一个作业,我必须编写一个计算器,用4个基本运算和括号求解算术表达式,输入通过标准输入缓冲区完成,输出也一样 一开始很容易,老师给我们提供了算法(如何将表达式从中缀转换为后缀,以及如何计算),唯一的目标是我们实现自己的堆栈并使用它,但计算器本身工作不太好,我想这是因为我的解析器 ,以及我的代码,用于解析数字、运算符和括号,同时将它们放入数组中,以便于以后计算的方式存储表达式C 如何正确解析算术表达式中的数字,区分正数和负数?,c,string,parsing,calculator,arithmetic-expressions,C,String,Parsing,Calculator,Arithmetic Expressions,我在我的数据结构课程中有一个作业,我必须编写一个计算器,用4个基本运算和括号求解算术表达式,输入通过标准输入缓冲区完成,输出也一样 一开始很容易,老师给我们提供了算法(如何将表达式从中缀转换为后缀,以及如何计算),唯一的目标是我们实现自己的堆栈并使用它,但计算器本身工作不太好,我想这是因为我的解析器 ,以及我的代码,用于解析数字、运算符和括号,同时将它们放入数组中,以便于以后计算的方式存储表达式 // saida is an array of pairs of integers, the fir
// saida is an array of pairs of integers, the first value of the pair is the value of the info (the number itself or the ASCII value of the operator)
// The second value is an indicator of whether it is a number or a operator
for (i = 0; i < exp_size; i++) {
c = expression[i];
// If the current char is a digit, store it into a helper string and keep going until a non-digit is found
// Then atoi() is used to transform this string into an int and then store it.
if (c >= '0' && c <= '9') {
j = 1, k = i+1;
tempInt[0] = c;
while(expression[k] >= '0' && expression[k] <= '9') {
tempInt[j++] = expression[k];
k++;
}
tempInt[j] = '\0';
saida[saidaIndex][0] = atoi(tempInt);
saida[saidaIndex++][1] = 0;
i = k-1;
}
// If the character is an operator, the algorithm is followed.
else if (c == '+' || c == '-' || c == '*' || c == '/') {
while(pilha->size > 0 && isOpBigger( stack_top(pilha), c )) {
saida[saidaIndex][0] = stack_pop(pilha);
saida[saidaIndex++][1] = 1;
}
stack_push(c, pilha);
}
else if (c == '(') stack_push(c, pilha);
else if (c == ')') {
j = stack_pop(pilha);
while(j != '(') {
saida[saidaIndex][0] = j;
saida[saidaIndex++][1] = 1;
j = stack_pop(pilha);
}
}
}
//saida是一个整数对数组,该对的第一个值是info的值(数字本身或运算符的ASCII值)
//第二个值是数字还是运算符的指示器
对于(i=0;i='0'&&c='0'&&expression[k]size>0&&i更大(堆栈顶部(pilha),c)){
saida[saidaIndex][0]=堆栈(pilha);
saida[saidaIndex++][1]=1;
}
堆栈推送(c,pilha);
}
else如果(c=='(')堆栈推送(c,pilha);
如果(c=='),则为else){
j=堆叠(pilha);
而(j!='('){
saida[saidaIndex][0]=j;
saida[saidaIndex++][1]=1;
j=堆叠(pilha);
}
}
}
问题是,在这段代码中,我不知道减号是表示减法运算符还是负数(我知道减号运算符是负数的和,但它没有帮助我解决这个问题),我想到了以下几点,但都没有成功:
- 每次有负号时,存储一个加号,让下一个数字本身为*-1。如果下一个数字已经是负号,或者负号在带括号的表达式之前,如1+2-(3*4),则不起作用
- 如果减号后面有空格,它就是一个运算符,如果没有,它就是一个负数。这不起作用,因为输入中没有这些规则
谢谢您的帮助。这就是所谓的“一元负号”问题,在您的情况下(无变量)可以通过替换来解决 运算符
-
如果是一元负号,则为一元负号
- 前面有一个左括号
- 前面有另一个操作员
- 输入的第一个字符
-
,而是存储一个不同的字符,比如m
,并为其分配比其他运算符更高的优先级(或者与求幂运算符相同,如果有)
另一个提示:不要使用空格表示任何内容,算术表达式必须在没有空格的情况下工作,否则它是不正确的。而不是((i=0;i
。
(每次迭代只强制增量1
)尝试char*p=expression;而(*p){根据需要测试/增量}
允许您根据需要向前读取和使用表达式中的字符。例如,如果(*p='-'),而(isblank(*p))p++;
(或其他相关测试,例如,(
,0-9
等)这使您可以在表达式中向前读取以确定要处理的内容?我从未想过以这种方式遍历字符串,我会尝试一下,谢谢!解析任何字符串时,这会增加很大的灵活性。您知道每个字符串的末尾都有一个nul字节,因此只需在(*p)和根据需要进行读取/检查允许您执行各种操作,例如*(p+x)
以进行前(或后)读取。您甚至可以使用多个指针将子表达式括在字符串中,例如char*sp,*ep;
用于开始和结束指针,这允许您设置if(*p=='('))sp=p;
并持续到if(*p='))ep=p;
然后处理sp
和ep
之间的内容。这真的为我打开了新的视野,再次感谢你,我会记住这一点!谢谢,我要尝试一下。我应该用加号来实现它吗?不,通常不需要。@MikaelMello,因为你有一元负号操作符,你也有一元加号操作符它是不必要的,但是它可以作为+3
输入(在表达式的开头)或重复,如在++3
中。检查是否可以有++-++-++-++-++-++++-++3++-++-++-+5
等输入,并且它们是有效的。一元运算符的优先级应高于二进制算术运算符,以允许使用5*-3
或-5*+3
等表达式(被解释为5*-3
和-5*-5]*(+3)
)或者至少超过了添加运算符+
和-
(在这种情况下,de second-5*+3
是不正确的)您是对的,我添加了一个一元加号,以及对多个一元运算符的支持,如您的第二个和第三个示例。我使用了“布尔值”变量来指示一元运算符是否处于活动状态并且工作正常,但我选择将++3
指示为无效表达式,因为它似乎不正确。因此,如果这些示例是有效表达式,我将回到我第一次实现的方法