Thursday, March 13, 2008

RPN Calculator in C (R1 Command Line)

main.c
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "Stack.h"

#include "conversionController.h"


// Author: Devin Eldreth
/*
This program functions as a Reverse Polish Notation Calculator. It will accept integer input and push the values to the stack. As of now it is
only capable of performing the 4 main arithmetic functions (addition, subtraction, multiplication, and division). It is also capaable of converting between bases 2-16 much like
the *nix dc rpn calculator.

April 27th 2007
*/


void valueAdd(); // Add values from stack
void valueNeg(); // Subtract values from stack
void valuePro(); // Multiply values from stack
void valueDiv(); // Divide values from stack
Stack S;

int main(){
init(&S);

char value[100];
char allowedValues[20] = {'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F', '+', '-', '*', '/', 'p', 'P', 'i', 'o'};
int basein = 10;
int baseout = 10;

printf("RPN CALCULATOR (type L for command list)\n");

while(1){
fgets(value, 80, stdin);

if(index(allowedValues, value[0]) == value){
printf("Error\n");
}
else{
switch((int)value[0]){
case '+': // dc: + // Add the top most values and push the result to the stack
valueAdd();
break;

case '-': // dc: - // Subtract the top most values and push the result to the stack
valueNeg();
break;

case '*': // dc: * // Multiply the top most values and push the result to the stack
valuePro();
break;

case '/': // dc: / // Divide the top most values and push the result to the stack
valueDiv();
break;

case 'L': // Command: L // Displays a list of all available commands
printf("List of Commands:\n");
printf("+ : Addition (Adds the top two values on the stack and pushes the result)\n");
printf("- : Subtraction (Calculates the difference of the top two values on the stack and pushes the result)\n");
printf("* : Product (Calculates the product of the top two values on the stack and pushes the result)\n");
printf("/ : Quotient (Calculates the quotient of the top two values on the stack and pushes the integer result)\n");

// Stack based commands
printf("p : Peeks at the stack\n");
printf("P : Pops the stack\n");
printf("c : Clears the stack\n");

// Base control commands
printf("i : Uses the top value of the stack as the input of base n\n");
printf("o : Uses the top value of the stack as the output of base n\n");
break;

case 'p': // dc: p // Print top most value without alteration to stack
if(isEmpty(&S)){
printf("Stack is Empty\n");
}
else{
if(baseout != 10)
intToBase(peek(&S), baseout);
else
printf("%d\n", peek(&S));
}
break;

case 'P': // dc: P // Pops the value from the top of the stack
if(isEmpty(&S)){
printf("Stack is Empty\n");
}
else{
if(baseout != 10){
intToBase(pop(&S), baseout);
}
else{
printf("%d\n", pop(&S));
}
}
break;
case 'f': // dc: f // Prints the entire stack without alteration to the stack
displayStack(&S);
break;

case 'i': // dc: i // Sets the base conversion for 2 - 16
if(peek(&S) > 1 && peek(&S) < 17){
basein = pop(&S);
}
else{
printf("Error: The top most value of the stack is not within the range of bases (2 - 16).\n");
}
break;

case 'o': // dc: o // Sets the base output between 2 - 16
if(peek(&S) > 1 && peek(&S) < 17){
baseout = pop(&S);
}
else{
printf("Error: The top most value of the stack is not within the range of bases (2 - 16).\n");
}
break;

default: // For any alphanumberic character not specificed in the range of values, push those values onto the stack
if(basein != 10){
push(&S, baseToInt(value, basein));
}
else{
push(&S, atoi(value));
}
break;
}
}
}
}

void valueAdd(){
int added = pop(&S) + pop(&S);
push(&S, added);
}

void valueNeg(){
int neg = pop(&S) - pop(&S);
push(&S, neg);
}

void valuePro(){
int product = pop(&S) * pop(&S);
push(&S, product);
}

void valueDiv(){
if(topIs(&S) < 2 || isEmpty(&S) == 1){
printf("Div 0\n");
}
else{
int div = pop(&S) / pop(&S);
push(&S, div);
}
}



conversionController.h
/*
Author: Devin Eldreth

Header for conversionController.c
*/


// Convert a string value of a certain base n to a decimal number (base 10)
int baseToInt(char string[64], int base);

// This function accompanies baseToInt by returning values based on ASCII representations of A, B, C, D, E, F
int returnValue(char value);

// This function prints a string based on a passed integer value and a passed base n value
void intToBase(int pass, int base);



Stack.h
/*
Author: Devin Eldreth
April 17th 2007
*/


// Stuct declaration for Stack
// The only thing that really matters in this simple stack is the value, which implemented like this is also the max value
// and the top of the stack. Of course the name of the struct will be Stack.
// The type of the array 'value' will of course correspond to the type of the stack.

typedef struct{
int value[20];
int top;
}Stack;

// Initilize the stack. Just set the top value to 0
void init(Stack *S);

// Pop the last value pushed onto the stack and return it as an integer.
int pop(Stack *S);

// Push a value onto the stack and make sure that it is stored in whatever the top value is.
void push(Stack *S, int value);

// Print the first value of the stack without altering the stack
int peek(Stack *S);

// Display all of the values contained on the stack, top down, and if it is empty let someone know
void displayStack(Stack *S);

void displayStackOffset(Stack *S, int base);

// Check and see if the stack is full (return 1 for full. (i.e., the top is at 20).
int isFull(Stack *S);

// Check and see if the stack is empty
int isEmpty(Stack *S);

// Get the location of the top
int topIs(Stack *S);




conversionController.c
#include <stdio.h>

#include <string.h>

#include <math.h>

#include "conversionController.h"


/*
Author: Devin Eldreth
*/


int baseToInt(char input[64], int base){
int length = strlen(input) - 1; // The length of the input string
int value = 0; // Rolling sum for the values
int count = 0; // Counting variable

while(count < length){
// Sum up the base ^ current offset between the length of the string and the counting variable,
// multiplied by the getIndex return value for the value at count on the input string
value = value + pow(base, length - count - 1) * returnValue(input[count]);
count++;
}

return value;
}

int returnValue(char value){
switch(value){
case 'a':
case 'A':
return 10;
case 'b':
case 'B':
return 11;
case 'c':
case 'C':
return 12;
case 'd':
case 'D':
return 13;
case 'e':
case 'E':
return 14;
case 'f':
case 'F':
return 15;
default:
return (int)value - '0';
}
}

void intToBase(int pass, int passBase){
char basedig[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

int converted[64];
int next, index = 0;
int base = passBase;
long int value = pass;

while(value != 0){
converted[index] = value % base;
value = value / base;
++index;
}

--index;
for(; index >= 0; index--){
printf("%c", basedig[converted[index]]);
}

printf("\n");
}




Stack.c
#include <stdio.h>

#include "Stack.h"

#include "conversionController.h"


void init(Stack *S){
S->top = 0;
}

int pop(Stack *S){
(S->top)--;
return S->value[S->top];
}

void push(Stack *S, int value){
S->value[S->top] = value;
(S->top)++;
}

int peek(Stack *S){
int peeked;
(S->top)--;
peeked = S->value[S->top];
(S->top)++;
return peeked;
}

int isFull(Stack *S){
if(S->top >= 20){
return 1;
}
else{
return 0;
}
}

int isEmpty(Stack *S){
if(S->top == 0){
return 1;
}
else{
return 0;
}
}

void displayStack(Stack *S){
int counter;

if(S->top == 0){
printf("Stack is Empty\n\n");
}
else{
printf("Displaying contents of Stack:\n");

counter = S->top - 1;
while(counter >= 0){
printf("Stack[%d]: %d\n", counter, S->value[counter]);
counter--;
}
printf("\n");
}
}

void displayStackOffset(Stack *S, int base){
int counter;

if(S->top == 0){
printf("Stack is Empty\n\n");
}
else{
printf("Displaying contents of Stack:\n");

counter = S->top - 1;
while(counter >= 0){
printf("Stack[%d]: %s\n", counter, intToBase(S->value[counter], base));
counter--;
}
printf("\n");
}
}

int topIs(Stack *S){
return S->top;
}

No comments: