我尝试将我用C++编写的数学求值转换为C。当我试图循环通过表达式时,遇到了一个问题,并得到了分段错误。
我的树目录
├── main.c
├── math
│ ├── include.h
│ └── main.c
├── stack
│ ├── include.h
│ └── main.c
我的堆栈头文件和源文件
//HEADER
#ifndef STACK_H
#define STACK_H
#include <stdio.h>
typedef struct{
int top, max_height;
float data[];
}Stack;
void stack_push(Stack* st, float value);
Stack stack_init(int max);
void stack_replace_top(Stack* st, float value);
void stack_print(Stack* st);
float stack_pop(Stack* st);
int stack_full(Stack* st);
int stack_top(Stack* st);
int stack_height(Stack* st);
int stack_empty(Stack* st);
#endif
//SOURCE
#include <stdio.h>
#include <stdlib.h>
#include "include.h"
int stack_top(Stack* st){return st->top;}
int stack_height(Stack* st){return st->max_height;}
void stack_push(Stack* st, float value){
st->data[st->top] = value;
(st->top)++;
}
float stack_pop(Stack* st){
(st->top)--;
return (st->data[st->top]);
}
Stack stack_init(int max){
return (Stack){0,max};
}
int stack_full(Stack* st){return (st->top >= st->max_height);}
void stack_replace_top(Stack* st, float value){
st->data[st->top - 1] = value;
}
int stack_empty(Stack* st){return (st->top <= 0);}
void stack_print(Stack* st){
int i;
if(st->top == 0){
printf("Stack Is Empty.\n");
}else{
printf("Stack Contents:\n");
for(i=0;i<st->top;i++){
printf("%g\t",st->data[i]);
}
printf("\n\n");
}
}
我的数学源,标题没有任何重要的内容
#include <math.h>
#include <string.h>
#include "include.h"
#include "../stack/include.h"
#include "../utils/include.h"
static float precedence(char op){
switch(op){
case '+':case '-':return 1;
case '*':case '/':return 2;
case '^':case '%':return 3;
default: return 0;
}
return 0;
}
static float apply_op(float a,float b,char op){
switch(op){
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
case '^': return pow(a, b);
case '%': return fmod(a, b);
}
return 0;
}
float evaluate(char* text){
//evaluate a given expression for example (5+5)*7^2
char* token = strtok(text, " ");
//we will use two stacks one for numbers and one for operators
Stack values =stack_init(100);
Stack ops = stack_init(100);
int i=0,size = strlen(token);
printf("Eval: %s\n",token);
printf("4: %c\n",token[4]);
char c;
for(;i<size;i++){
printf("s %d\n",size);
printf("i %d\n",i);
printf("c %c\n",c);
c = token[i];
printf("passed\n");
//if the current character is a number, push it to stack for numbers
switch(c){
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':{
float val = 0;
//there may be more than one digits in number
while(i < size && c >= '0' && c <= '9'){
val = (val*10) + (c - '0');
c = token[i];
i++;
}
//push the number into stack for numbers
stack_push(&values,val);
//as we are also incrementing the i in above while loop we need to decrement it here
i--;
break;
}
case '(':{
//if current character is an opening brace, push it to 'ops'
stack_push(&ops,'(');
break;
}
case ')':{
while(!stack_empty(&ops) && stack_top(&ops) != '('){
float val2 = stack_pop(&values);
float val1 = stack_pop(&values);
char op = stack_pop(&ops);
stack_push(&values,apply_op(val1,val2,op));
}
//pop opening brace
stack_pop(&ops);
break;
}
case '+': case '-': case '*': case '/': case '^': case '%':{
while(!stack_empty(&ops) && precedence(stack_top(&ops)) >= precedence(c)){
float val2 = stack_pop(&values);
float val1 = stack_pop(&values);
char op = stack_pop(&ops);
stack_push(&values,apply_op(val1,val2,op));
}
//push current operator to 'ops'.
stack_push(&ops,c);
break;
}
}
}
// Entire expression has been parsed at this point, apply remaining ops to remaining values
while(!stack_empty(&ops)){
float val2 = stack_pop(&values);
float val1 = stack_pop(&values);
char op = stack_pop(&ops);
stack_push(&values,apply_op(val1,val2,op));
}
// Top of 'values' contains result, return it
return stack_pop(&values);
}
我的错误出现在数学源文件中for循环的“evaluation”函数中。当我的循环第二次运行时,我得到了错误。我真的很困惑,因为我传入的字符串是“20*2+1”,大小是6,但当我的循环第二次运行时,索引是4,所以它应该工作。我希望有人能帮助我解决我的错误。
1条答案
按热度按时间h79rfbju1#
问题似乎与索引无关。相反,您的堆栈实现是虚假的。这...
...声明了一个具有 flexible array member 的结构类型。所涉及的灵活性是,您可以使用为结构的任何给定示例分配的全部空间,就好像它的
data
成员是用维度声明的,该维度使它尽可能多地填充该空间。这只在与动态内存分配结合使用时才有用,而您目前没有使用动态内存分配。并且所产生的动态分配对象不能有效地通过值来传递或返回。您有两个主要选项:
1.如果你想继续使用FAM,那么
stack_init()
必须被修改为动态分配足够大的示例,并返回一个指向分配结果的指针。例如:需要进行其他更改以适应返回类型的更改,并在不再需要动态分配的堆栈对象时释放它们。
或
1.将
Stack.data
变更为指标,并动态配置堆栈空间。例如:当然,在这里,当不再需要分配的内存时,您需要再次提供释放。