四則演算するテスト
前書いたスタックを使って
前々から気になってた逆ポーランド記法に変換して処理する四則演算器書いた。
infix2postfix.h
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
enum Priority {NIL, LOW, MIDDLE, HIGH,};
static void check_argument(char **string, stack *st)
{
make_stack(for_string);
char *tmp;
tmp = (char *)malloc(sizeof(char));
if(tmp == NULL){
break_stack(*st);
return;
}
*tmp = ' ';
push_stack(st, tmp);
while(1){
tmp = (char *)malloc(sizeof(char));
if(tmp == NULL){
break_stack(*st);
return;
}
if(**string == '.' || **string == '_' || **string == '@' || ('A' <= **string && **string <= 'Z') || ('a' <= **string && **string <= 'z')){
*tmp = **string;
push_stack(&for_string, tmp);
++(*string);
}else if(**string == '('){
}else{
while(top_stack(&for_string) != NULL){
push_stack(st,top_stack(&for_string));
pop_stack(&for_string);
}
--(*string);
return;
}
}
}
static int check_constant(char **string, stack *st)
{
make_stack(for_string);
char *tmp;
tmp = (char *)malloc(sizeof(char));
if(tmp == NULL){
break_stack(*st);
return;
}
*tmp = ' ';
push_stack(st, tmp);
while(1){
tmp = (char *)malloc(sizeof(char));
if(tmp == NULL){
break_stack(*st);
return;
}
if('0' <= **string && **string <= '9'){
*tmp = **string;
push_stack(&for_string, tmp);
++(*string);
}else{
while(top_stack(&for_string) != NULL){
push_stack(st,top_stack(&for_string));
pop_stack(&for_string);
}
--(*string);
return;
}
}
}
static int ret_prio(char str)
{
enum Priority;
if(str == '(' || str == ')')return NIL;
if(str == '+' || str == '-')return LOW;
if(str == '*' || str == '/' || str == '%')return MIDDLE;
if( ('a' <= str && str <= 'z') || ('A' <= str && str <= 'Z') || str == ' ' || str == '_' || str == '@' || str == '.' || ('0' <= str && str <= '9'))return HIGH;
return -1;
}
char *convert(char *formula,char for_convert[])
{
int i = 0;
make_stack(st);
while(*formula != '\0'){
char *tmp;
while(*formula == ' ') ++formula;
if(*formula == '('){
tmp = (char *)malloc(sizeof(char));
*tmp = *formula;
push_stack(&st, (void *)tmp);
}else if(*formula == ')'){
while(*(char *)top_stack(&st) != '('){
if(top_stack(&st) != NULL){
*(for_convert+i) = *(char*)top_stack(&st);
++i;
free(top_stack(&st));
pop_stack(&st);
}else{
puts("error");
break_stack(st);
return NULL;
}
}
pop_stack(&st);
}else if( ('a' <= *formula && *formula <= 'z') || ('A' <= *formula && *formula <= 'Z') || *formula == '_' || *formula == '@' || *formula == '.'){
check_argument(&formula, &st);
}else if('0' <= *formula && *formula <= '9'){
check_constant(&formula, &st);
}else if(*formula == '+' || *formula == '-' || *formula == '*' || *formula == '/' || *formula == '%'){
while(top_stack(&st) != NULL && ret_prio(*formula) <= ret_prio(*(char *)top_stack(&st))){
*(for_convert+i) = *(char*)top_stack(&st);
++i;
free(top_stack(&st));
pop_stack(&st);
}
tmp = (char *)malloc(sizeof(char));
if(tmp == NULL){
break_stack(st);
return NULL;
}
*tmp = ' ';
push_stack(&st, (void *)tmp);
tmp = (char *)malloc(sizeof(char));
if(tmp == NULL){
break_stack(st);
return NULL;
}
*tmp = *formula;
push_stack(&st, (void *)tmp);
}else{
break_stack(st);
return NULL;
}
++formula;
}
while(top_stack(&st) != NULL){
if(*(char*)top_stack(&st) == '('){
int m;
puts("error");
break_stack(st);
for(m=0;m!=i;++m){
*(for_convert+m)='\0';
}
return NULL;
}
*(for_convert+i) = *(char*)top_stack(&st);
++i;
free(top_stack(&st));
pop_stack(&st);
}
break_stack(st);
return 0;
}
eval4rules.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include "stack.h"
double evaluation(char *formula,jmp_buf for_error){
make_stack(st);
double Ret;
char p[20]="";
while(*formula != '\0'){
const char *var_for_atoi;
if('0' <= *formula && *formula <= '9'){
double *num = (double*)malloc(sizeof(double));
if(num == NULL){
break_stack(st);
longjmp(for_error,-2);
}
while('0' <= *formula && *formula <= '9'){
char chr[2] = "";
chr[0] = *formula;
strcat(p,chr);
++formula;
}
var_for_atoi = p;
*num = atof(var_for_atoi);
push_stack(&st,num);
strcpy(p,"");
}else if(*formula == '+' || *formula == '-' || *formula == '*' || *formula == '/'){
double *num = (double*)malloc(sizeof(double));
if(num == NULL){
break_stack(st);
longjmp(for_error,-2);
}
double a,b;
if(top_stack(&st) == NULL){
break_stack(st);
longjmp(for_error,-1);
}else{
a = *(double*)top_stack(&st);
free(top_stack(&st));
pop_stack(&st);
}
if(top_stack(&st) == NULL){
break_stack(st);
longjmp(for_error,-1);
}else{
b = *(double*)top_stack(&st);
free(top_stack(&st));
pop_stack(&st);
}
switch(*formula){
case '+':
*num = a+b;
break;
case '-':
*num = b-a;
break;
case '*':
*num = a*b;
break;
case '/':
*num = b/a;
break;
}
push_stack(&st,num);
++formula;
}else if(*formula != ' '){
break_stack(st);
longjmp(for_error,-1);
}
++formula;
}
if(top_stack(&st) == NULL){
break_stack(st);
longjmp(for_error,-1);
}
Ret = *(double*)top_stack(&st);
free(top_stack(&st));
pop_stack(&st);
break_stack(st);
return Ret;
}
main.c
#include <stdio.h>
#include <setjmp.h>
#include "infix2postfix.h"
#include "eval4rules.h"
int main()
{
int i;
double n;
char formula[300];
char Result[10000] = "";
jmp_buf env;
i = setjmp(env);
if(i == 0){
scanf("%s",formula);
convert(formula,Result);
n = evaluation(Result,env);
printf("n:%f\n",n);
return 0;
}else if(i == -1){
puts("SyntaxError");
return -1;
}else if(i == -2){
puts("Stack memory limits");
return -1;
}
}
テストなので字句解析とかすっ飛ばしてるけど今ちゃんと書いてるので。
あと、エラー処理適当かなと。