Dato che i mezzi a disposizione sono limitati,ovvero da quel che ho capito non si possono usare le liste ma solamente i vettori,il codice diventa un pelo lungo e leggermente piu complesso.
Ho volontariamente usato caratteri per i connettivi (!&|>-) al posto dei numeri solo per darvi un pò di lavoro anche a voi.
Ho cercato anche di non comprimere troppo il codice e non l'ho ottimizzato,questo per aiutarvi nel comprenderlo e nel modificarlo.
Ecco la pappa
///LOGICA PROPOSIZIONALE CALCULATOR
/// Grammatica elementare:
/// word : "abcdefghijklmnopqrstuvwxyz"
/// operator:
/// negazione : "!" : operator word
/// congiunzione : "&" : word operatoror word
/// disgiunzione : "|" : word operatorand word
/// implicazione : ">" : word operatorand word
/// doppiaimplicazione : "-" : word operatorand word
/// precedenza : negazione,congiunzione,disgiunzione,implicazione,doppiaimplicazione
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUT_MAX 100
#define CONNETTIVI_MAX 3
#define PROPOSIZIONI_MAX 4
#define SYNTAX_PROPOSIZIONE 0
#define SYNTAX_CONNETTIVO 1
#define SYNTAX_ERR_LASTCHAR -99
#define SYNTAX_ERR_MAXPROPOSIZIONE -100
#define SYNTAX_ERR_MAXCONNETTIVO -101
typedef enum {ERR = -1 , F , V} PROPOSIZIONE;
typedef enum {NONCONNETTIVO,NEGAZIONE,CONGIUNZIONE,DISGIUNZIONE,IMPLICAZIONE,DOPPIAIMPLICAZIONE,COUNTCONNETTIVO} CONNETTIVO;
///SUPPORT
int isword(char c)
{
if ( (c >= 'a' && c <= 'z') )
return 1;
return 0;
}
CONNETTIVO ctocon(char c)
{
switch (c)
{
case '!':
return NEGAZIONE;
case '&':
return CONGIUNZIONE;
case '|':
return DISGIUNZIONE;
case '>':
return IMPLICAZIONE;
case '-':
return DOPPIAIMPLICAZIONE;
}
return NONCONNETTIVO;
}
int isoperator(char c)
{
switch (c)
{
case '!':case '&':case '|':case '>':case '-':return 1;
}
return 0;
}
PROPOSIZIONE eval(PROPOSIZIONE lval,CONNETTIVO op,PROPOSIZIONE rval)
{
switch (op)
{
case NEGAZIONE:
return !rval;
case CONGIUNZIONE:
return lval && rval;
case DISGIUNZIONE:
return lval || rval;
case IMPLICAZIONE:
return (lval && !rval) ? 0 : 1;
case DOPPIAIMPLICAZIONE:
return ( (lval && rval) || (!lval && !rval)) ? 1 : 0;
}
return -1;
}
void proset(PROPOSIZIONE* p,unsigned char lowbyte)
{
int i;
for (i = 0 ; i < 4 ; i++ , lowbyte >>= 1)
p[i] = lowbyte & 0x001;
}
void prorem(PROPOSIZIONE* s,PROPOSIZIONE* c)
{
int nc = PROPOSIZIONI_MAX - (c-s);
for ( ; nc > 0 ; nc-- , c++)
*c = *(c+1);
}
void conrem(CONNETTIVO* s,CONNETTIVO* c)
{
int nc = CONNETTIVI_MAX - (c-s);
for ( ; nc > 0 ; nc-- , c++)
*c = *(c+1);
}
PROPOSIZIONE equieval(PROPOSIZIONE* p1,int* np1,CONNETTIVO* c1,int* nc1,PROPOSIZIONE* p2,int* np2,CONNETTIVO* c2,int* nc2)
{
PROPOSIZIONE parser(PROPOSIZIONE*,int*,CONNETTIVO*,int*);
CONNETTIVO mem1[CONNETTIVI_MAX];
memcpy(mem1,c1,sizeof(CONNETTIVO) * CONNETTIVI_MAX);
int memnp1 = *np1;
int memnc1 = *nc1;
CONNETTIVO mem2[CONNETTIVI_MAX];
memcpy(mem2,c2,sizeof(CONNETTIVO) * CONNETTIVI_MAX);
int memnp2 = *np2;
int memnc2 = *nc2;
int easy = 0;
PROPOSIZIONE a,b;
for ( easy = 0 ; easy < 0x100 ; easy++ )
{
proset(p1,(unsigned char)easy);
proset(p2,(unsigned char)easy >> 4);
memcpy( c1 , mem1 , sizeof(CONNETTIVO) * CONNETTIVI_MAX);
memcpy( c2 , mem2 , sizeof(CONNETTIVO) * CONNETTIVI_MAX);
*np1 = memnp1;
*nc1 = memnc1;
*np2 = memnp2;
*nc2 = memnc2;
a = parser(p1,np1,c1,nc1);
b = parser(p2,np2,c2,nc2);
if ( a == ERR || b == ERR ) return ERR;
if ( a != b) return F;
}
return V;
}
///END SUPPORT
///SYNTAX
int syntax(PROPOSIZIONE* p,int* np,CONNETTIVO* c,int* nc,const char* buffer)
{
*np = 0;
*nc = 0;
const char* st = buffer;
while (*buffer && *buffer == ' ') ++buffer;
int step = (isword(*buffer)) ? SYNTAX_PROPOSIZIONE : SYNTAX_CONNETTIVO;
for ( ; *buffer ; buffer++)
{
if (*buffer == ' ') continue;
if (step == SYNTAX_PROPOSIZIONE)
{
step = SYNTAX_CONNETTIVO;
if ( !isword(*buffer) )
{
if (*buffer != '!')
return (buffer - st) + 1;
}
else
{
if ( (*np)++ == PROPOSIZIONI_MAX) return SYNTAX_ERR_MAXPROPOSIZIONE;
*p++ = 0;
continue;
}
}
if ( step == SYNTAX_CONNETTIVO)
{
if ( (*nc)++ == CONNETTIVI_MAX) return SYNTAX_ERR_MAXCONNETTIVO;
if ( (*c = ctocon(*buffer)) == NONCONNETTIVO )
return (buffer - st) + 1;
++c;
step = SYNTAX_PROPOSIZIONE;
}
}
if (step == SYNTAX_PROPOSIZIONE) return SYNTAX_ERR_LASTCHAR;
return 0;
}
///END SYNTAX
///PARSER
int parser_single(PROPOSIZIONE* p,CONNETTIVO* c,int* nc,CONNETTIVO op)
{
CONNETTIVO* stc = c;
int ic;
int ex = 0;
for (ic = 0; ic < *nc ; ic++)
{
if (*c == op)
{
*p = eval(F,op,*p);
if (*p == -1 ) return -1;
conrem(stc,c);
++ex;
}
else
{
++c;
++p;
}
}
return 0;
}
int parser_double(PROPOSIZIONE* p,int* np,CONNETTIVO* c,int* nc,CONNETTIVO op)
{
PROPOSIZIONE* stp = p;
CONNETTIVO* stc = c;
int ic;
int ex = 0;
for (ic = 0 ; ic < *nc ; ic++)
{
if (*c == op)
{
*p = eval(*p,op,*(p+1));
if (*p == -1 ) return -1;
prorem(stp,p+1);
--*np;
conrem(stc,c);
++ex;
}
else
{
++c;
++p;
}
}
*nc -= ex;
return 0;
}
PROPOSIZIONE parser(PROPOSIZIONE* p,int* np,CONNETTIVO* c,int* nc)
{
if ( parser_single(p,c,nc,NEGAZIONE) ) return ERR;
if ( parser_double(p,np,c,nc,CONGIUNZIONE) ) return ERR;
if ( parser_double(p,np,c,nc,DISGIUNZIONE) ) return ERR;
if ( parser_double(p,np,c,nc,IMPLICAZIONE) ) return ERR;
if ( parser_double(p,np,c,nc,DOPPIAIMPLICAZIONE) ) return ERR;
return *p;
}
///END PARSER
int main ()
{
//Formula A
char f1[INPUT_MAX];
PROPOSIZIONE p1[PROPOSIZIONI_MAX];
CONNETTIVO c1[CONNETTIVI_MAX];
int np1,nc1;
printf("Insert formula A:");
gets(f1);
printf("Syntax...");
int erc = syntax(p1,&np1,c1,&nc1,f1);
switch (erc)
{
case 0:
printf("ok\n");
break;
case SYNTAX_ERR_LASTCHAR:
printf("errore ultimo carattere deve essere proposizione\n");
return erc;
case SYNTAX_ERR_MAXCONNETTIVO:
printf("errore inseriti troppi connettivi\n");
return erc;
case SYNTAX_ERR_MAXPROPOSIZIONE:
printf("errore inseriti troppe proposizioni\n");
return erc;
default:
printf("carattere non valido(%d) :%c\n",erc,f1[erc-1]);
return -1;
}
//Formula B
char f2[INPUT_MAX];
PROPOSIZIONE p2[PROPOSIZIONI_MAX];
CONNETTIVO c2[CONNETTIVI_MAX];
int np2,nc2;
printf("Insert formula B:");
gets(f2);
printf("Syntax...");
erc = syntax(p2,&np2,c2,&nc2,f2);
switch (erc)
{
case 0:
printf("ok\n");
break;
case SYNTAX_ERR_LASTCHAR:
printf("errore ultimo carattere deve essere proposizione\n");
return erc;
case SYNTAX_ERR_MAXCONNETTIVO:
printf("errore inseriti troppi connettivi\n");
return erc;
case SYNTAX_ERR_MAXPROPOSIZIONE:
printf("errore inseriti troppe proposizioni\n");
return erc;
default:
printf("carattere non valido(%d) :%c\n",erc,f2[erc-1]);
return -1;
}
printf("Le formule ");
PROPOSIZIONE ret = equieval(p1,&np1,c1,&nc1,p2,&np2,c2,&nc2);
switch (ret)
{
case ERR:
printf("errate secondo il parser\n");
return -1;
case V:
printf("sono equivalenti\n");
break;
case F:
printf("non sono equivalenti\n");
break;
}
return 0;
}
Sembra funzionare,almeno teoricamente,poi vedete voi se saltano fuori piccoli bug correggeteli o ditemelo.
Spero almeno vi sia di aiuto per capire il concetto.
Il problema fondamentale rimane l'uso esclusivo dei vettori.