tags:

views:

65

answers:

2

What is the most efficient way to create a floating point mode where the user can enter 'f' or 'i' to switch between integer and floating point? I'd like to do this without having to copy the entire code for floats. I know typecasting is an option but I'm not completely sure if it's the safest way.

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

#define MAX 100

int *p;
int *tos;
int *bos;

void push(int i);
int pop(void);

int main (void)
{
    int a, b;
    char s[80];

    p = (int *) malloc(MAX*sizeof(int));    /* get stack memory */
    if (!p) {
        printf("Allocation Failure\n");
        exit(1);
    }

    tos = p;
    bos = p + MAX-1;

    printf("\nRPN Calculator\n");
    printf("Enter 'i' for integer mode\n");
    printf("Enter 'f' for floating point mode\n");
    printf("Enter 'q' to quit\n\n");
    char *endptr;

    do {        
        printf("> ");
        scanf("%s", s);
        int val = strtol(s, &endptr, 10);

        if (*endptr == '\0') {
            //printf("Got only the integer: %d\n", val);
        }
        else {  
            printf("operator: %s\n", endptr); 
            printf("integer: %d\n", val);
                if (val != 0){      /* don't push val on stack if 0 */
                push(val);
            }
        }

        switch(*endptr) {
            case 'i':
                printf("(Integer Mode)\n");
                break;
            case 'f':
                printf("(Floating Point Mode)\n");
                break;
            case '+':
                a = pop();
                b = pop();
            //  printf("%d\n",a);
            //  printf("%d\n",b);
            //  printf("%d\n",val);
                printf("%d\n", a+b);
                push(a+b);
                break;
            case '-':
                a = pop(); 
                b = pop(); 
                printf("%d\n", b-a); 
                push(b-a);
                break;  
            case '*':
                a = pop(); 
                b = pop(); 
                printf("%d\n", a*b); 
                push(a*b);
                break;
            case '/':
                a = pop(); 
                b = pop();
                if(a == 0){
                    printf("Cannot divide by zero\n");
                    break;
                }
                printf("%d\n", b/a);
                push(b/a);
                break;
            case '.':
                a = pop(); push(a);
                printf("Current value on top of stack: %d\n", a);

                break;  
            default:
            //  push(atoi(s));
                push(val);
        }
    } while (*s != 'q');    /* Do until 'q' is entered */

    return 0;
    }       

void push (int i)   /* Put an element on the stack */
{
    if (p > bos){
        printf("Stack Full\n");
        return;
    }
    *p = i;
    p++;
}

int pop (void)  /* Get the element from the top of the stack */
{
    p--;
    if(p < 0) {
        printf("Stack Underflow\n");
        return 0;
    }
    return *p;
}
+3  A: 

There's no way to overload functions in C, so you'll have to do two copies in any case. However, you can generalize the pushing/popping so that it operates on nodes with arbitrary data. To do it safely, you can use a tagged union like:

typedef struct {
  enum {INT, FLOAT} type;
  union {
    int i;
    float f;
  } data;
} Node;

This also allows you to easily extend to other data types in the future.

Or you could just go with a void* data and cast it unsafely each time you want to operate on it, arrogantly assuming that you'll always find what you want (not recommended).

Max Shawabkeh
How much code would this save me? So instead of using int i I could use Node.i or Node.f?
patrick
You would use `Node n; n.data.i = ...`. It would save you only the general pushing/popping parts.
Max Shawabkeh
A: 

you could do some magic with macro preprocessor.

Isolate common operations into header file, provide some macro variable, for example TYPE. concatenate TYPE to function names to create distinct names, replace explicit types with TYPE. in main file include macro/header file twice, one time with TYPE defined to int, next time with TYPE defined as double. call special functions with their names appended with TYPE.

This is like poor man C++ template

aaa