四則演算するテスト

前書いたスタックを使って

前々から気になってた逆ポーランド記法に変換して処理する四則演算器書いた。

 

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;
    }
}

 

テストなので字句解析とかすっ飛ばしてるけど今ちゃんと書いてるので。

あと、エラー処理適当かなと。