Esercizio su cancellazione elemento da una struttura

di il
6 risposte

Esercizio su cancellazione elemento da una struttura

Salve a tutti,sono nuovo nel forum,
mi sto scervellando con questo programma in C.

In Pratica:
-Legge dal file di testo una serie di produzioni per una Grammatica
-stampa a video ogni produzione
-ogni singola produzione è nel formato:
x > y

dove:
x e y possono essere stringhe o caratteri di lettere maiuscole o minuscole e y può essere vuoto.
ES:
Axcv >
Asd>S
fG> m
A>b
etc...
questa è la struttura dell'Header.

#include <stdio.h>
#include <stdlib.h>
#ifndef _GRAMMAR_H
#define _GRAMMAR_H
#define MAX_WORD_LENGTH 100
#define MAX_PRODUCTIONS 100


// Definizione dei tipi ------------------------------------------------------*/

typedef char Symbol;

typedef struct
{
        Symbol word [MAX_WORD_LENGTH];
        unsigned length;
} Word;

typedef struct
{
        Word left;
        Word right;
} Production;

typedef struct
{
        Production productions[MAX_PRODUCTIONS];
        unsigned numprod;
} Grammar;


#endif
mentre qui sono elencate le varie funzioni per la stampa della intera grammatica,della singola produzione,del riconoscimento singolo carattere e altre funzioni di appoggio:

#include "Grammar.h"

// Procedure di riconoscimento dei simboli -----------------------------------*/

int is_terminal(Symbol s)
{
    return (islower(s));
    //return (s >= 'a') && (s <= 'z');
}

int is_nonterminal(Symbol s)
{
    return (isupper(s));
    //return (s >= 'A') && (s <= 'Z');
}

int is_prodsym(Symbol s)
{
    return (s == '>');
}

int is_prodsep(Symbol s)
{
    return (s == '\n');
}

/* Lettura di simboli da file ------------------------------------------------*/

Symbol read_sym(FILE* file)
{
       Symbol s;
       
       // fscanf(file,"%c",&s); 
       
       //questo ciclo permette di saltare la lettura di spazi tra i simboli
       do 
          s = getc(file);
       while (s==' ');
       
       return s;
}

Production* add_new_production(Grammar *g)
{
  Production* p;
  p = &(g->productions[g->numprod++]);
  p->left.length = 0;
  p->right.length = 0;
  
  return p;
}
                       

void add_symbol(Word *w, Symbol s)
{
  w->word[w->length++] = s;  
}


// Procedura di acquisizione di una grammatica da un file --------------------*/
                       
Grammar* load_grammar(FILE* file, Grammar* g)
{
         enum States {START,LEFT,RIGHT,ERROR};
         /*   START  = Scansione di una nuova produzione [F]
              LEFT   = Scansione della parte sinistra
              RIGHT  = Scansione della parte destra [F]
              ERROR  = Errore di scansione
         */
         enum States current_state = START;  // Stato iniziale
         Symbol s;
         Production* p;
         
         g->numprod = 0; // Inizializza la grammatica
                  
         while (current_state != ERROR && !feof(file)) 
         {
               s = read_sym(file);
               if (feof(file)) break;
               switch(current_state)
               {
               case START:
                    if (is_terminal(s) || is_nonterminal(s))
                    {
                       current_state = LEFT;
                       
                       //p = &(g->productions[g->numprod++]);
                       //p->left.length = 0;
                       p = add_new_production(g);
                       add_symbol(&p->left,s);
                       //L'istruzione precedente corrisponde a p->left.word[p->left.length++] = s;
                    }
                    else if (is_prodsep(s))
                    {
                       current_state = START;
                    }
                    else 
                         current_state = ERROR;
                    break;
               case LEFT:
                    if (is_terminal(s) || is_nonterminal(s))
                    {
                       current_state = LEFT;
                       add_symbol(&p->left,s);
                    }
                    else if (is_prodsym(s))
                    {
                       current_state = RIGHT;
                    }
                    else
                        current_state = ERROR;
                    break;
               case RIGHT:
                    if (is_terminal(s) || is_nonterminal(s))
                    {
                       current_state = RIGHT;
                       add_symbol(&p->right,s);
                    }
                    else if (is_prodsep(s))
                    {
                       current_state = START;
                    }
                    else 
                         current_state = ERROR;
                    break;
               }
         }
         
         if (current_state == START || current_state == RIGHT)
            return g;
         else
             return NULL;

}       

// Procedure di stampa

void print_sym (Symbol s)
{
     printf("%c ",s);
}


void print_word (Word* w)
{
     int i;
     
     for (i=0; i<w->length; i++)
         print_sym(w->word[i]);
}

void print_production (Production* p) 
{
     print_word(&p->left);
     printf (" --> ");
     print_word(&p->right);
}

void print_grammar(Grammar* g)
{
     int i;
     
     if (g == NULL)
        printf ("\n\nErrore! Grammatica non valida! \n");
     else
     {
        printf ("\n\nNumero di produzioni: %d\n", g->numprod);
        for (i=0; i<g->numprod; i++)
        {
            print_production(&g->productions[i]);
            printf ("\n");
        }
     }
}
Questo invece è il main:

#include "Grammar.h"
// MAIN ------------------------------------------------------------------------

int main(int argc, char *argv[])
{
  char* filename = argv[1];
  FILE* gram_file;
  Grammar grammar;
  
  
  int del;
  // controlla se è stato inserito il nome del file
  
  if (filename == 0)
  {
     printf("nome file non specificato \n");
     return -1;
  }
  
  // apertura del file contenente la grammatica
  
  gram_file = fopen(filename,"r");
  if (gram_file == NULL)
  {
     printf("nome di file errato\n");
     return -1;
  }
 
 print_grammar(load_grammar(gram_file,&grammar)); 
  cancella_produzione( &grammar,&del);  
 print_grammar(load_grammar(gram_file,&grammar)); 
 
fclose(gram_file);
 
  
  system("PAUSE");	
  return 0;
} 
 



Adesso:
-Vorrei cancellare una produzione dalla struttura,non dal file passandogli,oltre alla struttura grammatica,anche l'indice che si desidera cancellare.

lo spiego in linguaggio lineare:
-creo una funzione canc_prod con parametri :
INPUT:
Grammar * g ( la struttura GRAMMATICA)
int del ( intero rappresentante l'indice della produzione da cancellare)

CORPO:
leggo ogni singola produzione
finchè non trovo che l'indice della produzione scansionata è uguale a quella dell'indice da cancellare
incremento indice.
se è uguale
scala di posizione le produzioni che stanno dopo.
ecco:
questo non riesco proprio a farlo...
Vi chiedo un aiutino
Grazie,scusate per il tema ma volevo essere il più chiaro possibile

6 Risposte

  • Re: Esercizio su cancellazione elemento da una struttura

    Così ho provato io.
    
    void cancella_produzione(Grammar *g,int  *canc )
    {
     int i ;
     
     Production *p;
     
     
    for (i=1; i<= g->numprod; i++) 
     {
      if ( i == *canc )
      {
       printf("Produzione cancellata\n");    
        p = &g->productions[i-1];
        
        p = NULL;
        g->numprod--;
       // print_production(p);
    
         for ( i = 1 ;i <= g->numprod; i++)
         {
          p = &g->productions[i-1];
           print_production(p);
           printf("\n");  
         }
        
      } 
      
     }
    }
    
    Ma mi cancella sempre l'ultima
  • Re: Esercizio su cancellazione elemento da una struttura

    
    void cancella_produzione(Grammar *g,int  canc )
    {
      int i;
      int size=sizeof(Production)*(g->numprod-canc);
      
      if (canc <0 || canc >g->numprod-1)
        return;
        
      memmove (&g->productions[canc],&g->productions[canc+1],size);
      g->numprod--;
      
      printf("Produzione %d cancellata\n",canc);
    
    }
    
    
  • Re: Esercizio su cancellazione elemento da una struttura

    Grazie infinite,davvero.
    Questa funzione memmove è fenomenale,non sapevo della sua esistenza.
    E' l'unico forum che mi abbia dato una risposta valida....
    Saluti.
  • Re: Esercizio su cancellazione elemento da una struttura

    Avrei un altro quesito da porvi:

    Per ogni produzione errata,visualizzare tipo di errore.
    Allora:
    ogni produzione deve essere sempre e solo nella forma:
    A > B

    con A carattere o stringa di lettere maiuscole(ossia NON TERMINALI) o minuscole (ossia TERMINALI)
    Un solo simbolo di separatore
    con B carattere o stringa di lettere maiuscole(ossia NON TERMINALI) o minuscole (ossia TERMINALI)

    Ecco come ho provato io (modificando la funzione load_grammar postata inizialmente):
    
    // Procedura di acquisizione di una grammatica da un file --------------------*/
                           
    Grammar* load_grammar(FILE* file, Grammar* g)
    {
    /*
    Stati:
          -SCAN:Scansione di una nuova produzione;
          -LEFT:Scansione parte sinistra di una produzione;
          -RIGHT:Scansione primo simbolo della parte destra della produzione;
                 (Caso in cui si legga 2 volte il separatore di produzione)
          -RIGHT2:Scansione secondo simbolo della parte destra di una produzione;
          -ERRORE1:Trovata parola vuota prima del simbolo di produzione:            --> w
          -ERRORE2:Trovato doppio simbolo di produzione prima della parte destra  v --> --> w         
          -ERRORE3:Trovato simbolo di produzione dopo la parte destra             v --> w -->
          -ERRORE4:Mancanza simbolo di produzione                                 v   w
    */         
     enum Stati { SCAN,LEFT,RIGHT,RIGHT2,ERRORE1,ERRORE2,ERRORE3,ERRORE4 };
     enum Stati stato = SCAN;
     
    int i;
    Symbol s;
    Production* p;
     
      g->numprod = 0;
       
       printf("\n\nVisualizza tipo errore accanto ad ogni eventuale produzione errata\n\n");
                       
       while (!feof(file))
          {
            s = read_sym(file);
            if (feof(file)) break;
            
          switch (stato)
           {
            
            case SCAN:
                 if(is_terminal(s) || is_nonterminal(s) ) 
                 {
                      stato = LEFT;
                      //p = &(g->productions[g->numprod++]);
                      //p->left.length = 0;
                      p = add_new_production(g);
                      add_symbol(&p->left,s);
                      //L'istruzione precedente corrisponde a p->left.word[p->left.length++] = s;
                 }
                 else if (is_prodsep(s)) 
                 {
                      stato = SCAN;
                 } 
                 else if (is_prodsym(s)) 
                 {
                      stato = ERRORE1;
                      //add_symbol(&p->left,s);
                      p->left.length = 0;
                      print_word(&p->left);
                      printf (" --> ");                                                              //Azzero parte destra
                      //print_word(&p->right);                                     //Stampo il separatore perchè la parte sinistra è vuota
                 }
                 break;
                  
            case LEFT:                                                     //Qui mi trovo quando ho letto  un terminale o non terminale
                 if(is_terminal(s) || is_nonterminal(s))
                 {
                      stato = LEFT;
                      add_symbol(&p->left,s);
                 }
                 else if(is_prodsym(s)) 
                 {
                      print_word(&p->left);                                
                      stato = RIGHT;                                       //Adesso leggo il simbolo di produzione
                      p->right.length = 0;                                 //Non devo più leggere dalla parte sinistra
                 }     
                 else if (is_prodsep(s)) 
                 {
                      stato = ERRORE4;
                      
                 } 
                 break;
                 
            case RIGHT:                                                     //Qui mi trovo quando ho lettp il simbolo di produzione
                 if(is_terminal(s) || is_nonterminal(s))
                 {                                                          
                      stato = RIGHT2;                                       //Se leggo un terminale o un non terminale passa a RIGHT2 
                      add_symbol(&p->right,s);
                 }
                 else if(is_prodsym(s)) 
                 {
                      stato = ERRORE2 ;                                     //ERRORE2 Se invece leggo di nuovo il simbolo di produzione prima della parte destra
                 }
                 else if(is_prodsep(s))
                 {
                      stato = SCAN;                                         //Produzione corretta se trovo separatore di produzione
                      printf("-->");
                      print_word(&p->right);
                      printf("\n");
                 } 
                 break;
              
            case RIGHT2:                                                    //Qui se ho letto prima il simbolo di produzione e poi un T o un NT
                 if(is_terminal(s) || is_nonterminal(s))
                 {   
                      stato = RIGHT2;
                      add_symbol(&p->right,s);
                 }
                 else if(is_prodsym(s)) 
                 {
                      stato = ERRORE3 ;                                     //ERRORE 3:Dopo la parte destra incontro di nuovo simbolo di produzione      
                 }
                 else if(is_prodsep(s))
                 {
                      stato = SCAN;
                      printf("-->");
                      print_word(&p->right);
                      printf("\n");
                 } 
                 break;
           
             case ERRORE1:
                 if(is_terminal(s) || is_nonterminal(s) ) 
                 {
                      stato = RIGHT;
                      add_symbol(&p->right,s);
                 }     
                 else if (is_prodsep(s)) 
                 {
                      stato = ERRORE1;
                      printf("-->");
                      print_word(&p->right);
                      printf("Errore!Trovata parola vuota prima del simbolo di produzione.\n\n");
                      printf("\n");
                      stato = SCAN;
                 }
                 break;
          
            case ERRORE2:
                 if(is_terminal(s) || is_nonterminal(s) ) 
                 {
                      stato = ERRORE2;
                      add_symbol(&p->right,s);
                 }     
                 if (is_prodsym(s))
                 { 
                      stato = ERRORE2;
                      printf("-->");
                      printf("Errore! Trovato doppio simbolo di produzione.\n\n");
                      stato = SCAN;
                 }
                 else  if (is_prodsep(s)) 
                 {
                      print_word(&p->left);
                      printf (" --> ");
                      printf (" --> ");
                      print_word(&p->right);
                      printf("Errore!Trovato doppio simbolo di produzione.\n\n");
                      stato = SCAN;
                 }     
                 break;
            
            case ERRORE3:
                 if(is_terminal(s) || is_nonterminal(s))
                 {   
                      stato = ERRORE3;
                      add_symbol(&p->right,s);      
                 }
                 else if(is_prodsym(s)) 
                 {                 
                      stato = ERRORE2 ;
                 }
                 else if(is_prodsep(s))
                 {
                      print_word(&p->left);
                      printf("--> ");
                      print_word(&p->right);
                      printf("--> ");   
                      printf("Errore!Trovato simbolo di produzione dopo la parte destra.\n\n");
                      stato = SCAN;
                 } 
                 break;
             case ERRORE4:
                 if (is_prodsep(s))
                 {
                      print_word(&p->left);                                 //ERRORE4:Dopo la parte sinistra c'è la nuova produzione.
                      printf("Errore!Manca simbolo di produzione.\n\n");
                      stato = SCAN;               
                 }    
           }      
       }
        if(stato == SCAN || stato == RIGHT )
               return g;
        else 
        return NULL;  
    }
    

    La grammatica ha le seguenti produzione nel file di testo: gr.txt

    A>bV
    C>aB
    D>b
    S>a
    S
    A>>xx
    A>gfg
    >df



    FAte conto che questa sia una finestra di PROMPT DI MSDOS:
    mando in esecuzione
    file sorgente + gr.tx(
    come argomenti del main appunto)
    ecco cosa mi visualizza:
    -------------------------------------------------------------------------------------------------------------------


    A -->b V
    C -->a B
    D -->b
    S -->a
    S Errore!Manca simbolo di produzione.

    A -->g f g
    --> -->g f g d f


    Numero di produzioni: 6
    A --> b V
    C --> a B
    D --> b
    S --> a
    S -->
    --> g f g d f


    1-Visualizza eventuali errori nelle produzioni

    2-Esci
    Inserisci la tua scelta:
    2

    Premere un tasto per continuare . . .
    --------------------------------------------------------------------------------------------------------------------
    In particolare:
    perchè legge S,non trova simbolo '>' mi visualizza l'errore,ma nella riscrizione dell'intera grammatica me lo fa visualizzare così?
    Grazie a chi mi risponderà.
  • Re: Esercizio su cancellazione elemento da una struttura

    Quando invece carico
    print_grammar(load_grammar(stdin,&grammar))

    man mano che inserisco da tastiera le singole produzioni,quando ne trova una non corretta,funziona.
    Perchè,dove è che sbaglio?
  • Re: Esercizio su cancellazione elemento da una struttura

    Ho risolto,cmq grazie lo stesso.
    non sono ancora molto pratico ma facendo molta pratica sto familiarizzando con questo
    linguaggio di programmazione.

    Saluti a tutti.
Devi accedere o registrarti per scrivere nel forum
6 risposte