Improved version con automa a stati:
Codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#include <stdint.h>
typedef enum tagStates
{
S0,
S1,
S2,
S3
} States;
typedef struct tagPersona
{
unsigned char *Nome;
struct tagPersona *next;
struct tagPersona *last;
} Persona;
void Print(Persona *first)
{
Persona *n = first;
printf("\n");
while( n != NULL )
{
printf("%s\n", n->Nome);
n = n->next;
}
}
void FreeList(Persona *first)
{
Persona *n1 = first, *n2;
while ( n1 != NULL )
{
n2 = n1->next;
if ( n1->Nome )
free(n1->Nome);
free(n1);
n1 = n2;
}
}
Persona* NewNode(Persona *Pers)
{
Persona *n;
size_t len;
len = strlen(Pers->Nome);
n = (Persona *)malloc(sizeof(Persona));
if( n == NULL )
{
printf("\nNewNode 1: Impossibile allocare la memoria. LOL!!!\n");
return NULL;
}
n->Nome = (unsigned char*)malloc(sizeof(unsigned char) * len + 1);
if ( !n->Nome )
{
printf("\nNewNode 2: Impossibile allocare la memoria. LOL!!!\n");
free(n);
n = NULL;
return NULL;
}
strcpy(n->Nome, Pers->Nome);
n->next = NULL;
return n;
}
Persona* Append(Persona *Pers, Persona *first)
{
Persona *n = first, *nuovo;
if ( first == NULL )
{
nuovo = NewNode(Pers);
if ( !nuovo )
return first;
nuovo->last = nuovo;
return nuovo;
}
nuovo = NewNode(Pers);
if ( !nuovo )
return first;
n = first->last;
n->next = nuovo;
first->last = n->next;
return first;
}
uint64_t MakeBuffer(const char *szFileName, unsigned char **buffer)
{
long x;
uint64_t retSizeData = 0;
long numread;
FILE *fp;
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("\nLOL!!!\nErrore nell'apertura del file \"%s\". Addio!\n", szFileName);
return 0;
}
#if __linux__ || __APPLE__
fseeko(fp, 0, SEEK_END);
retSizeData = ftello(fp);
fseeko(fp, 0, SEEK_SET);
#else
_fseeki64(fp, 0, SEEK_END);
retSizeData = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
#endif
*buffer = (unsigned char *)malloc(sizeof(unsigned char) * retSizeData);
if ( !*buffer )
{
printf("\nLOL!!!\nMemoria insufficiente. Addio!\n");
fclose(fp);
return 0;
}
numread = fread(*buffer, 1, retSizeData, fp);
if ( numread < retSizeData )
{
fclose(fp);
free(*buffer);
*buffer = NULL;
printf("\nLOL!!!\nErrore nella lettura del file %s\n", szFileName);
return 0;
}
fclose(fp);
return retSizeData;
}
int DFA(unsigned char *buffer, uint64_t SizeData, Persona **pPers)
{
States state = S0;
char c;
long k;
long x;
Persona Pers;
Pers.Nome = (unsigned char*)malloc(sizeof(unsigned char) * 1024);
if ( !(Pers.Nome) )
{
printf("Impossibile allocare la memoria. LOL!!!\n");
return 0;
}
x = 0;
k = 0;
while ( k < SizeData )
{
c = *(buffer + k++);
while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' )
{
c = *(buffer + k++);
if ( k >= SizeData )
{
free(Pers.Nome);
return k;
}
}
switch( state )
{
case S0:
x = 0;
if ( c == '"' )
{
state = S1;
}
else
{
printf("\nS0 Errore: %c input malformato. Addio!\n", c);
free(Pers.Nome);
return 0;
}
break;
case S1:
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= 128 && c <= 154) || (c >= 224 && c <= 237) )
{
Pers.Nome[x++] = c;
if ( x >= 1024 )
{
printf("\nS1 LOOOOOOLLL!!! Ho trovato un nome piu' lungo di 1024 caratteri. LOOOOOOLLL!!! Addio!\n");
free(Pers.Nome);
return 0;
}
}
else
{
k--;
state = S2;
}
break;
case S2:
if ( c == '"' )
{
Pers.Nome[x] = '\0';
x = 0;
*pPers = Append(&Pers, *pPers);
state = S3;
}
else
{
printf("\nS2 Errore: %c input malformato. Addio!\n", c);
free(Pers.Nome);
return 0;
}
break;
case S3:
if ( c == ',' )
{
state = S0;
}
else
{
printf("\nS3 Errore: %c input malformato. Addio!\n", c);
free(Pers.Nome);
return 0;
}
break;
default:
printf("\nLOL! Errore: %c input malformato. Addio!\n", c);
free(Pers.Nome);
return 0;
}
}
if ( Pers.Nome )
free(Pers.Nome);
return k;
}
int main(int argc, char* argv[])
{
Persona *pPers = NULL;
unsigned char *buffer = NULL;
uint64_t sizeData = 0;
int ret;
if ( argc != 2 )
{
printf("\nDevi specificare il nome di un file!\n");
printf("\nUso: %s nomefile\n\n", argv[0]);
return -1;
}
sizeData = MakeBuffer(argv[1], &buffer);
if ( !sizeData )
{
printf("\nImpossibile allocare il buffer. Addio!\n");
return -1;
}
ret = DFA(buffer, sizeData, &pPers);
printf("\n");
if ( ret && pPers )
Print(pPers);
printf("\n");
if ( pPers)
FreeList(pPers);
if ( buffer )
free(buffer);
return 0;
}