Si può usare uno stack,ma data la semplicità dell'esercizio si può usare direttamente la stringa in ingresso come stack.
Si eseguirà un parser proprio come se lo facessimo su carta,prendiamo come definizione che i caratteri maiuscoli siano valori true e i caratteri minuscoli siano valori false.
Per una semplice logica booleana avremo dunque che
!a|b = A|b = A
!b&!c = B&C = B
!a&!b|!c&!d = A&B|C&D = A|C = A
Descriviamo quindi una grammatica,sviluppiamo alcune funzioni di supporto,allacciamo il tutto:
///BOOLEAN CALCULATOR
/// Grammatica elementare:
/// wordfalse : "abcdefghijklmnopqrstuvwxyz"
/// wordTRUE : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
/// word : wordtrue || wordfalse
/// operatornot : "!" : operatornot word
/// operatoror : "|" : word operatoror word
/// operatorand : "&" : word operatorand word
/// precedenza : operatornot,operatorand,operatoror
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
#define STEP_WORD 0
#define STEP_OPERATOR 1
int iswordfalse(char c)
{
if ( (c >= 'a' && c <= 'z') )
return 1;
return 0;
}
int iswordtrue(char c)
{
if ( (c >= 'A' && c <= 'Z') )
return 1;
return 0;
}
char setword(char c,int boo)
{
if (iswordfalse(c) && boo)
return c - ('a' - 'A');
else if (iswordtrue(c) && !boo)
return c + ('a' - 'A');
return c;
}
int isword(char c)
{
if ( iswordfalse(c) || iswordtrue(c) )
return 1;
return 0;
}
int isoperator(char c)
{
switch (c)
{
case '!':case '&':case '|':return 1;
}
return 0;
}
char operate(char lvalue,char ope, char rvalue)
{
switch (ope)
{
case '!':
if ( iswordfalse(rvalue) )
return setword(rvalue,1);
else
return setword(rvalue,0);
case '&':
if ( iswordtrue(lvalue) && iswordtrue(rvalue))
return setword(lvalue,1);
else
return setword(lvalue,0);
case '|':
if ( iswordtrue(lvalue) || iswordtrue(rvalue))
{
if (iswordtrue(lvalue))
return lvalue;
else
return rvalue;
}
else
return setword(lvalue,0);
}
return 0;
}
void strep(char* d,const char c,int str)
{
*d++ = c;
while ( *d != '\0' )
{
*d = *(d + str);
d++;
}
}
char* syntax(char* buffer)
{
//tolgo spazii e enter
//controllo che var sia 1 word e che sia alternato con operator
//formula non può finire con operator
char *rpb = buffer;
char *avb = buffer;
int step = STEP_WORD;
while ( *avb != '\0' && *avb != '\n')
{
if (*avb == ' ')
{
++avb;
continue;
}
if (step == STEP_WORD)
{
step = STEP_OPERATOR;
if ( !isword(*avb) )
{
if (*avb != '!') return avb;
}
else
{
*rpb++ = *avb++;
continue;
}
}
if ( step == STEP_OPERATOR)
{
if ( !isoperator(*avb) ) return avb;
step = STEP_WORD;
}
*rpb++ = *avb++;
}
if (step == STEP_WORD)
return avb;
*rpb = '\0';
return NULL;
}
int parser_not(char* buffer)
{
char* stop;
char rt;
for ( ; *buffer != '\0' ; buffer++)
{
if ( *buffer == '!')
{
stop = buffer;
++buffer;
rt = operate(0,'!',*buffer);
strep(stop,rt,1);
buffer = stop;
}
}//all char
return 0;
}
int parser_orand(char* buffer,char op)
{
char* stop;
char rt,lv;
for ( ; *buffer != '\0' ; buffer++)
{
if ( *buffer == op)
{
++buffer;
rt = operate(lv,op,*buffer);
strep(stop,rt,2);
buffer = stop - 1;
}
else
{
stop = buffer;
lv = *buffer;
}
}//all char
return 0;
}
char parser(char* buffer)
{
parser_not(buffer);
parser_orand(buffer,'&');
parser_orand(buffer,'|');
return *buffer;
}
int main ()
{
char buffer[MAX];
printf("Insert formula:");
gets(buffer);
printf("Syntax...");
char* erc = syntax(buffer);
if ( erc != NULL)
{
printf("error at char :%d\n",(erc - buffer) + 1);
return -1;
}
printf("ok\n");
printf("eval = %c\n", parser(buffer));
return 0;
}
Ora basta modificarlo per le proprie esigenze.