[ create a new paste ] login | about

Link: http://codepad.org/QJgYS1lz    [ raw code | fork ]

ninwa - C, pasted on Sep 12:
/* RPN Calculator,
    My suggested soultions to the Exercises in
    "The C Programming Language" aka "K&R"

    Exercises 4-3 through 4-10

    Author (of code below): Joseph Bleau
    Date: September 12th, 2011
*/

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

#define STACKSIZE       128
#define LINESIZE        128
#define TOKENSIZE       32
#define SERRORSIZE      32
#define VARSTACKSIZE    25

#define _DEBUG_ 0
#define PDEBUGS(x) do{if(_DEBUG_)printf("%s",x);}while(0)
#define PDEBUGC(x) do{if(_DEBUG_)printf("%c",x);}while(0)
#define PDEBUGI(x) do{if(_DEBUG_)printf("%d",x);}while(0)

enum ERROR{ SUCCESS = 0, ALPHA_CHAR_FOUND,
            EXCEEDED_MAX_TOKENSIZE,
            EXCEEDED_MAX_STACKSIZE,
            DIVIDE_BY_ZERO} errorno;

int sgetline(char[], int);
int isoperator(char);
int isspace(char);
int isdigit(char);
void geterror(char[], int);
void view_stack(int*, int);
void print_vars(int[], int);
void show_commands();

int main(int argc, char* argv[])
{
    int i, j; /* loop counter */
    int val;  /* stores the outcome of an operation */

    /* Input buffer */
    char line[LINESIZE];
    int len = 0;

    /* Our operand stack. */
    int stack[STACKSIZE];
    int stack_ptr = -1;
    int tmp;
    int single = 0;

    /* Our Variable Stack */
    int varstack[VARSTACKSIZE];
    int varptr = 0;

    /* holds current token being worked with */
    char token[TOKENSIZE];

    /* holds ascii representation of error */
    char serror[SERRORSIZE];

    /* Clean errorno state */
    errorno = 0;

    for( i = 0; i < VARSTACKSIZE; i++)
        varstack[i] = 0xDEADBEEF;

    /* Take input until a newline is receieved, and when it is,
       attempt to parse the line. */
    while( errorno == SUCCESS &&
           ( printf("stack(%d): ", stack_ptr+1),
           len = sgetline(line, LINESIZE)) &&
           strcmp(line,"quit") != 0 )
    {
        /* Check for possible commands */
        if( strcmp(line, "view_stack") == 0){
            view_stack(stack, stack_ptr);
            continue;
        }

        if( strcmp(line, "swap_top") == 0){
            tmp = stack[stack_ptr-1];
            stack[stack_ptr-1] = stack[stack_ptr];
            stack[stack_ptr] = tmp;
            printf("top two items in stack were swapped\n");
            continue;
        }

        if (strcmp(line, "help") == 0){
            show_commands();
            continue;
        }

        if(strcmp(line, "empty") == 0){
            stack_ptr = -1;
            continue;
        }

        if(strcmp(line, "dupe_top") == 0){
            stack[++stack_ptr] = stack[stack_ptr-1];
            continue;
        }

        if(strcmp(line, "print_vars") == 0){
            print_vars(varstack, VARSTACKSIZE);
            continue;
        }

        if(len == STACKSIZE+1){
            show_commands();
            continue;
        }

        /* Greedy eater, munch up digits until a
           space or operator is found, and then place it on
           our stack */
        for (single = val = i = j = 0; i < len; ++i){
            if(!isdigit(line[i])   &&
               !isoperator(line[i]) &&
               !isspace(line[i])){
                if( line[i] >= 'a' && line[i] <= 'z'){
                    varptr = line[i] - 'a';
                    if( varstack[varptr] != 0xDEADBEEF ){
                        stack[++stack_ptr] = varstack[varptr];
                        j = 0;
                    }
                }
                else{
                    printf("Error: invalid command.\n");
                    break;
                }
            }
            else if(isspace(line[i]))
            {
                if(j == 0)
                    continue;
                token[j] = '\0';

                PDEBUGS("DEBUG: attempting to stack token: ");
                PDEBUGS(token);
                PDEBUGC('\n');

                if(stack_ptr + 1 >= STACKSIZE){
                    errorno = EXCEEDED_MAX_STACKSIZE;
                    break;
                }

                stack[++stack_ptr] = atoi(token);
                j = 0;
            }
            else if(isoperator(line[i]))
            {
                PDEBUGS("DEBUG: operator found, stack size: ");
                PDEBUGI(stack_ptr);
                PDEBUGC('\n');

                if(stack_ptr > 0 || line[i] == '=' ||
                   line[i] == '_' || line[i] == 's' || line[i] == ':' ){
                    switch(line[i]){
                        case 's':
                            if(stack_ptr > -1 && stack_ptr % 2 == 0){
                                stack[stack_ptr] = sin(stack[stack_ptr]);
                                single = 1;
                            }
                            else if(stack_ptr == -1){
                                printf("Error: Not enough operands\n");
                                single = 1;
                                break;
                            }
                            break;
                        case ':':
                            if(stack_ptr > -1 && stack_ptr % 2 == 0){
                                varstack[varptr] = stack[stack_ptr];
                                stack_ptr--;
                                single = 1;
                            }
                            else if(stack_ptr == -1){
                                printf("Error: Not enough operands\n");
                                single = 1;
                                break;
                            }
                            break;
                        case '%':
                            val = stack[stack_ptr] % stack[stack_ptr-1];
                            break;
                        case '+':
                            val = stack[stack_ptr] + stack[stack_ptr-1];
                            break;
                        case '-':
                                val = stack[stack_ptr] - stack[stack_ptr-1];
                                break;
                        case '_':
                            if(stack_ptr > -1 && stack_ptr % 2 == 0){
                                stack[stack_ptr] *= -1;
                                single = 1;
                            }
                            else if(stack_ptr == -1){
                                printf("Error: Not enough operands\n");
                                single = 1;
                                break;
                            }
                            break;
                        case '*':
                            val = stack[stack_ptr] * stack[stack_ptr-1];
                            break;
                        case '/':
                            if(stack[stack_ptr-1] == 0){
                                errorno = DIVIDE_BY_ZERO;
                                break;
                            }

                            val = stack[stack_ptr] / stack[stack_ptr-1];
                            break;
                        case '=':
                            if(stack_ptr == 0 && errorno == SUCCESS){
                                printf("Outcome: %d\n", stack[0]);
                                stack_ptr--;
                            }
                            else if(stack_ptr == -1)
                                printf("Error: no value to show\n");
                            else
                                printf("Error: excess items on stack, cannot apply '='\n");
                            break;

                    }

                    if(line[i] != '=' ){
                        if(!single)
                            stack[--stack_ptr] = val;
                    }
                }
                else{
                    printf("Error: Not enough operands\n");
                    break;
                }
            }
            else
            {
                if(j+1 > TOKENSIZE){
                    errorno = EXCEEDED_MAX_TOKENSIZE;
                    break;
                }

                token[j++] = line[i];
            }
        }

        if(j > 0){
            token[j] = '\0';

            if(stack_ptr + 1 >= STACKSIZE){
                errorno = EXCEEDED_MAX_STACKSIZE;
                break;
            }

            stack[++stack_ptr] = atoi(token);
            j = 0;
        }
    }

    geterror(serror,SERRORSIZE);
    printf("Exiting: %s", serror);

    return errorno;
}

int isoperator(char c){
    if(c == '+' || c == '-' || c == '*' ||
       c == '/' || c == '=' || c == '%' ||
       c == '_' || c == 's' || c == ':')
        return 1;

    return 0;
}

int isspace(char c){
    if( c == '\t' || c == ' ')
        return 1;

    return 0;
}

int sgetline(char line[], int bufsize)
{
    int i, c;

    i = 0;
    while( (c = getchar()) != '\n' && c != EOF ){
        if(i < bufsize)
            line[i++] = c;
        else
            break;
    }

    line[i] = '\0';

    if(i == 0)
        return STACKSIZE+1;

    return i;
}

void view_stack(int* stack, int stack_ptr)
{
    int i;

    printf("Our stack:\n");
    for (i = 0; i <= stack_ptr; i++)
        printf("\t%d\n", stack[i]);

    if(i == 0)
        printf("\t(empty)\n");
}

void print_vars(int varstack[], int bufsize)
{
    int i,c = 0;
    printf("variable list:\n");
    for( i = 0; i <  bufsize; i++)
        if( varstack[i] != 0xDEADBEEF){
            printf("\t%c: %d\n", i + 'a', varstack[i]);
            c++;
        }

    if(!c)
        printf("\t(empty)\n");
}

void show_commands()
{
    printf("Valid commands:\n");
    printf("\thelp\n\tview_stack\n\tswap_top\n");
    printf("\tdupe_top\n\tempty\n\tquit\n");
    printf("\n\noperators: +, -, *, /, _, %, s\n\n");
}

void geterror(char serror[], int bufsize)
{
    if(bufsize < 20)
        return;

    switch(errorno){
        case SUCCESS:
            strcpy(serror,"SUCCESS");
            break;
        case ALPHA_CHAR_FOUND:
            strcpy(serror,"ALPHA_CHAR_FOUND");
            break;
        case EXCEEDED_MAX_TOKENSIZE:
            strcpy(serror,"EXCEEDED_MAX_TOKENSIZE");
            break;
        case DIVIDE_BY_ZERO:
            strcpy(serror, "DIVIDE_BY_ZERO");
            break;
        case EXCEEDED_MAX_STACKSIZE:
            strcpy(serror, "EXCEEDED_MAX_STACKSIZE");
            break;
        default:
            strcpy(serror,"UNKOWN_ERROR");
            break;
    }
}


Create a new paste based on this one


Comments: