Какой самый простой способ добавить режим плавания в этот калькулятор C? - PullRequest
1 голос
/ 06 февраля 2010

Каков наиболее эффективный способ создания режима с плавающей запятой, в котором пользователь может ввести 'f' или 'i' для переключения между целым числом и плавающей запятой? Я хотел бы сделать это без необходимости копировать весь код для поплавков. Я знаю, что типизация - это вариант, но я не совсем уверен, самый ли это безопасный способ.

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

Ответы [ 2 ]

2 голосов
/ 06 февраля 2010

Нет способа перегрузить функции в C, поэтому вам придется сделать две копии в любом случае. Однако вы можете обобщить push / popping, чтобы он работал на узлах с произвольными данными. Чтобы сделать это безопасно, вы можете использовать помеченный союз, как:

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

Это также позволяет в будущем легко распространяться на другие типы данных.

Или вы можете просто пойти с void* данными и использовать их небезопасно каждый раз, когда захотите работать с ними, высокомерно полагая, что вы всегда найдете то, что хотите (не рекомендуется).

0 голосов
/ 06 февраля 2010

Вы могли бы сделать немного магии с препроцессором макроса.

Выделение общих операций в заголовочный файл, предоставление некоторой макропеременной, например, TYPE. объединить TYPE с именами функций для создания отдельных имен, заменить явные типы на TYPE. в основной файл включите файл макроса / заголовка дважды, один раз с TYPE, определенным как int, в следующий раз с TYPE, определенным как double. вызывать специальные функции с их именами, добавленными с помощью TYPE.

Это как шаблон C ++ для бедняка

...