Арифметические операции на определенном скриптовом языке - PullRequest
2 голосов
/ 14 июля 2011

Я работаю над определенным языком сценариев.Значения, содержащие структуру

struct myvar
{
 char  name[NAMELEN];
 int   type;
 void* value;
}
type = 0  --> int* value
type = 1  --> char* value
type = 2  --> float* value

Я столкнулся с некоторой проблемой с арифметическими операциями.Кажется, что мне нужно совершать все виды преобразований типов для каждой отдельной операции, которая превращается в написание целой связки кода для каждой из них, например:

case 0:  // "="
 if(factor1.name)
 {
    if((factor1.type == 1) && (factor2.type==1))
    {
        free(factor1.value);
        int len = (strlen((STRING)factor2.value)+1)*sizeof(char);
        factor1.value = malloc(len);
        memcpy(factor1.value,factor2.value,len);
    }
    else if((factor1.type == 2) && (factor2.type==2))
    *(FLOAT*)factor1.value = *(FLOAT*)factor2.value;
    else if((factor1.type == 0) && (factor2.type==0))
    *(INTEGER*)factor1.value = *(INTEGER*)factor2.value;
    else if((factor1.type == 0) && (factor2.type==2))
    *(INTEGER*)factor1.value = *(FLOAT*)factor2.value;
    else if((factor1.type == 2) && (factor2.type==0))
    *(FLOAT*)factor1.value = *(INTEGER*)factor2.value;
    else
     GetNextWord("error");
 }
 break;

Есть ли способ избежать этогоутомительная процедура?В противном случае у меня нет выбора, кроме как скопировать и вставить этот фрагмент кода для каждого из "=", "~", "+", "-", "*", "/", "%", ">", "<», "> =", "<=", "==", "~ =", "И", "ИЛИ" </p>

Ответы [ 3 ]

3 голосов
/ 14 июля 2011

Используйте union вместо struct для значений:

struct myvar {
  enum {
    STRING, INT, FLOAT,
  } type;

  union {
    char  strval[NAMELEN];
    int   intval;
    float fltval;
  } val;
};

и затем при выполнении оператора присваивания на вашем языке сценариев вы просто делаете:

factor1 = factor2;

Чтобы получить правильное значение, основанное на типе, который вы сделали бы:

switch (operand.type) {
  case STRING:
    printf("%s", operand.val.strval);
    break;

  case INT:
    printf("%d", operand.val.intval);
    break;

  case FLOAT:
    printf("%f", operand.val.fltval);
    break;
}
2 голосов
/ 14 июля 2011

Как насчет написания 3 toType функций:

char* toType0(myvar* from)
{
   if (from->type == 0) return (char*)(from->value);
   else if (from->type == 1) return itoa((int*)from->value);
   else...
}
int toType1(myvar* from)
{
   //convert to int...
}

Тогда в ваших процедурах преобразования вы можете сделать:

 switch (factor1.type)
 {
    case 0:
     { char* other = toType0(&factor2);
     //assign or add or whatever....
     };
     break;
     case 1:
     { int other = toType1(&factor2);
     //assign or add or whatever....
     };
     break;
     ...
  }
2 голосов
/ 14 июля 2011

Я бы предложил следующее: при применении операции вы должны сначала привести типы операндов. Например, если ваши типы операндов int и float, вы должны привести значение int к плавающему и продолжить с плавающей версией операции. Принуждение одинаково (или почти одинаково) для всех операций. При таком подходе у вас гораздо меньше дел для рассмотрения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...