Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicitŗ e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
QuickBrainFuck - BrainFuck.cpp

BrainFuck.cpp

Caricato da: TheDarkJuster
Scarica il programma completo

  1. #include "BrainFuck.h"
  2.  
  3. BrainFuck::BrainFuck(char *program, Format output)
  4. {
  5.         //inizializzo l' oggetto:
  6.         this->formato = output;
  7.         this->valido = true;
  8.         this->numeroOperazioniAritmetiche = 0L;
  9.         this->esecuzioneTerminata = false;
  10.         this->totaleIstruzioniEseguite = 0L;
  11.         this->numeroIstruzioneAttuale = 0L;
  12.         this->numeroIstruzioniCaricate = 0L;
  13.         this->bytesUsati = 1L;
  14.         this->fileError = NO_ERRORS;
  15.        
  16.         //creo il primo byte nel nastro "infinito":
  17.         Nastro = new struct Byte;
  18.         Nastro->Next = (struct Byte*)NULL;
  19.         Nastro->Previous = (struct Byte*)NULL;
  20.         Nastro->Data = (unsigned char)0x00;
  21.        
  22.         //apro ed esamino il file
  23.         FILE *pFile = fopen(program, "r");
  24.         if (pFile != (FILE*)NULL)
  25.         {
  26.                 fseek (pFile, 0, SEEK_END);
  27.                 unsigned long programSize = ftell(pFile); //numero di caratteri nel file (1 byte = 1 char)
  28.                 fseek (pFile, 0, SEEK_SET);
  29.                 if (programSize != 0)
  30.                 {
  31.                         while (!feof(pFile)) //per ogni carattere nel file:
  32.                         {
  33.                                 char carattere = fgetc(pFile); //leggi il carattere
  34.                                 if ((carattere == '>') || (carattere == '<') || (carattere == '+') || (carattere == '-') || (carattere == '.') || (carattere == ',') || (carattere == '[') || (carattere == ']'))
  35.                                 { //e se il carattere √® una istruzione caricalo nella memoria istruzioni....
  36.                                         //trasformazione carattere ---> codice istruzione
  37.                                         unsigned short codiceIstruzione;
  38.                                         switch (carattere)
  39.                                         {
  40.                                                 case '>':
  41.                                                         codiceIstruzione = 0;
  42.                                                         break;
  43.                                                 case '<':
  44.                                                         codiceIstruzione = 1;
  45.                                                         break;
  46.                                                 case '+':
  47.                                                         codiceIstruzione = 2;
  48.                                                         break;
  49.                                                 case '-':
  50.                                                         codiceIstruzione = 3;
  51.                                                         break;
  52.                                                 case '.':
  53.                                                         codiceIstruzione = 4;
  54.                                                         break;
  55.                                                 case ',':
  56.                                                         codiceIstruzione = 5;
  57.                                                         break;
  58.                                                 case '[':
  59.                                                         codiceIstruzione = 6;
  60.                                                         break;
  61.                                                 case ']':
  62.                                                         codiceIstruzione = 7;
  63.                                                         break;
  64.                                                 default:
  65.                                                         break;
  66.                                         }
  67.                                         //carica la nuova istruzione
  68.                                         this->istruzioni.push_back(codiceIstruzione);
  69.                                         //aggiorna il contatore di istruzioni caricate
  70.                                         this->numeroIstruzioniCaricate++;
  71.                                 }
  72.                         }
  73.                        
  74.                         if (this->numeroIstruzioniCaricate != 0) //se il file contiene istruzioni
  75.                         { //controlla la corrispondenza fra [ e ]
  76.                                 long par = 0L, j;
  77.                                 bool errori = false;
  78.                                 for (j = 0L; j < this->numeroIstruzioniCaricate; j++)
  79.                                 {
  80.                                         if (this->istruzioni[j] == 6)
  81.                                                 par++;
  82.                                         else if (this->istruzioni[j] == 7)
  83.                                                 par--;
  84.                                         //se una parentesi √® stata chiusa senza essere aperta....
  85.                                         if (par < 0)
  86.                                         {
  87.                                                 errori = true; //memorizzo l' errore
  88.                                                 break; //ed esco dal ciclo
  89.                                         }
  90.                                 }
  91.                                 if (par != 0)
  92.                                         errori = true;
  93.  
  94.                                 if (errori) //se c' √® una mancata corrispondenza fra [ e ]
  95.                                 { //memorizza il tipo di errore e l' invalidit√† del programma
  96.                                         this->fileError = NOT_CORRESPONDING;
  97.                                         this->valido = false;
  98.                                 }
  99.                         } else { //il file non contiene istruzioni, memorizza il tipo di "errore" e l' invalidit√† del programma
  100.                                 this->fileError = NOINSTRUCTIONS;
  101.                                 this->valido = false;
  102.                         }
  103.                        
  104.                 } else {
  105.                         //il file non contiene caratteri
  106.                         this->fileError = FILE_EMPTY;
  107.                         this->valido = false;
  108.                 }
  109.                 fclose(pFile);
  110.         } else {
  111.                 //impossibile aprire il file
  112.                 this->fileError = FILE_UNAVAILABLE;
  113.                 this->valido = false;
  114.         }
  115.        
  116. }
  117.  
  118.  
  119. BrainFuck::~BrainFuck()
  120. {
  121.         if (this->Nastro != (struct Byte*)NULL)
  122.         {
  123.                 //mi porto al primo byte
  124.                 while (this->Nastro->Previous != (struct Byte*)NULL)
  125.                         this->Nastro = this->Nastro->Previous;
  126.                 //elimino ad uno ad uno gli elementi della lista
  127.                 while (this->Nastro->Next != (struct Byte*)NULL)
  128.                 {
  129.                         if (this->Nastro->Next != (struct Byte*)NULL) //se c' √® un byte dopo quello attuale
  130.                         {
  131.                                 //elimino quello attuale dopo essermi spostato sul successivo
  132.                                 this->Nastro = this->Nastro->Next;
  133.                                 delete this->Nastro->Previous;
  134.                         } else { //altrimenti sono arrivato alla fine della sequenza di byte e posso eliminare quello attuale
  135.                                 delete this->Nastro;
  136.                         }
  137.                 }
  138.         }
  139.         //se ci sono istruzioni caricate in memoria allora libera quella memoria
  140.         if (!this->istruzioni.empty())
  141.                 this->istruzioni.clear();
  142.         //se ci sono ancora dati nello stack utilizzato per i cicli libera la memoria dello stack (ovviamente se ci√≤ accade, l√® esecuzione del programma non √® terminata)
  143.         while (!this->Cicli.empty())
  144.                 this->Cicli.pop();
  145. }
  146.  
  147. unsigned long BrainFuck::Esegui()
  148. {
  149.         //in caso di validit√† del programma
  150.         if (this->valido)
  151.         {
  152.                 //mi preparo ad eseguire l' intero programma
  153.                 this->totaleIstruzioniEseguite = 0L;
  154.                 this->numeroIstruzioneAttuale = 0L;
  155.                 this->numeroOperazioniAritmetiche = 0L;
  156.                 this->esecuzioneTerminata = false;
  157.                 //eseguo il ciclo che provveder√† ad eseguire ogni istruzione in ordine fino alla fine del programma
  158.                 while (this->numeroIstruzioneAttuale < this->numeroIstruzioniCaricate)
  159.                 {
  160.                         if (this->EseguiIstruzione()) //se l' istruzione √® stata correttamente eseguita
  161.                                 this->totaleIstruzioniEseguite++; //aggiorno il numero totale di istruzioni eseguite
  162.                 }
  163.                 //memorizzo che l' esecuzione √® stata portata a termine
  164.                 this->esecuzioneTerminata = true;
  165.                 /* QUI GENERO IL REPORT */
  166.  
  167.         }
  168.         return this->totaleIstruzioniEseguite;
  169. }
  170.  
  171. bool BrainFuck::EseguiIstruzione()
  172. {
  173.         if ((this->valido) && (!this->esecuzioneTerminata))
  174.         {
  175.                 if (this->istruzioni[this->numeroIstruzioneAttuale] == 0)
  176.                 { //istruzione >
  177.                         if (this->Nastro->Next == (struct Byte*)NULL) //se non c' √® un byte successivo a quello attuale
  178.                         {
  179.                                 //crealo.....
  180.                                 struct Byte* nuovoByte = new struct Byte;
  181.                                 //collega il byte attuale a quello nuovo e vice versa
  182.                                 nuovoByte->Previous = this->Nastro;
  183.                                 nuovoByte->Next = (struct Byte*)NULL;
  184.                                 this->Nastro->Next = nuovoByte;
  185.                                 //inizializzane il valore a 0
  186.                                 nuovoByte->Data = (unsigned char)0x00;
  187.                                 //ed aggiorna il numero di byte richiesti dal programma
  188.                                 this->bytesUsati = this->bytesUsati + 1;
  189.                         }
  190.                         this->Nastro = this->Nastro->Next;
  191.                 }
  192.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 1)
  193.                 { //istruzione <
  194.                         if (this->Nastro->Previous == (struct Byte*)NULL) //se non c' √® un byte precendente a quello attuale
  195.                         {
  196.                                 //crealo.....
  197.                                 struct Byte* nuovoByte = new struct Byte;
  198.                                 //collega il byte attuale a quello nuovo e vice versa
  199.                                 nuovoByte->Next = this->Nastro;
  200.                                 nuovoByte->Previous = (struct Byte*)NULL;
  201.                                 this->Nastro->Previous = nuovoByte;
  202.                                 //inizializzane il valore a 0
  203.                                 nuovoByte->Data = (unsigned char)0x00;
  204.                                 //ed aggiorna il numero di byte richiesti dal programma
  205.                                 this->bytesUsati = this->bytesUsati + 1;
  206.                         }
  207.                         this->Nastro = this->Nastro->Previous;
  208.                 }
  209.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 2)
  210.                 { //istruzione +
  211.                         this->Nastro->Data = this->Nastro->Data + 1;
  212.                         //aggiorna il numero di istruzioni aritmetiche eseguite
  213.                         this->numeroOperazioniAritmetiche++;
  214.                 }
  215.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 3)
  216.                 { //istruzione -
  217.                         this->Nastro->Data = this->Nastro->Data - 1;
  218.                         //aggiorna il numero di istruzioni aritmetiche eseguite
  219.                         this->numeroOperazioniAritmetiche++;
  220.                 }
  221.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 4)
  222.                 { //istruzione .
  223.                         if (this->formato == Numbers)
  224.                                 printf("%u", this->Nastro->Data);
  225.                         else
  226.                                 printf("%c", this->Nastro->Data);
  227.                 } //istruzione ,
  228.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 5)
  229.                 {
  230.                         char lettura;
  231.                         fflush(stdin);
  232.                         //leggi il valore inserito da tastiera a seconda del formato specificato
  233.                         if (this->formato == Numbers)
  234.                                 scanf("%u", &lettura);
  235.                         else
  236.                                 scanf("%c", &lettura);
  237.                         //aggiorna il byte attuale
  238.                         this->Nastro->Data = lettura;
  239.                 }
  240.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 6)
  241.                 { //istruzione [
  242.                         if (this->Nastro->Data == (unsigned char)0x00)
  243.                         { //salta alla corrispondente ]
  244.                                 unsigned long par = 1;
  245.                                 while (par >= 1L)
  246.                                 {
  247.                                         this->numeroIstruzioneAttuale++;
  248.                                         if (this->istruzioni[this->numeroIstruzioneAttuale] == 7)
  249.                                                 par--;
  250.                                         else if (this->istruzioni[this->numeroIstruzioneAttuale] == 6)
  251.                                                 par++;
  252.                                 }
  253.                         } else { //memorizza nello stack la posizione attuale
  254.                                 this->Cicli.push(this->numeroIstruzioneAttuale);
  255.                         }
  256.                 }
  257.                 else if (this->istruzioni[this->numeroIstruzioneAttuale] == 7)
  258.                 { //istruzione ]
  259.                         if (this->Nastro->Data == (unsigned char)0x00) //se il byte attuale √® zero
  260.                         { //procedi con l' istruzione successiva alla ] attuale
  261.                                 this->Cicli.pop();     
  262.                         } else { //altrimenti torna alla corrispondente [
  263.                                 this->numeroIstruzioneAttuale = this->Cicli.top();
  264.                         }
  265.                 }
  266.                 //rendo la prossima istruzione da eseguire, quella successiva di quella appena eseguita
  267.                 this->numeroIstruzioneAttuale++;
  268.                 if (this->numeroIstruzioneAttuale == this->numeroIstruzioniCaricate)
  269.                         this->esecuzioneTerminata = true;
  270.                 return true;
  271.         }
  272.         return false;
  273. }
  274.  
  275. struct Report BrainFuck::GeneraReport()
  276. {
  277.         //genero il report a partire dalle informazioni memorizzate nell' oggetto
  278.         struct Report generato;
  279.         generato.byteUtilizzati = this->bytesUsati;
  280.         generato.istruzioniCaricate = this->numeroIstruzioniCaricate;
  281.         generato.istruzioniEseguite = this->totaleIstruzioniEseguite;
  282.         generato.opAritmetiche = this->numeroOperazioniAritmetiche;
  283.         generato.ultimoErrore = this->fileError;
  284.         generato.terminato = this->esecuzioneTerminata;
  285.         return generato;
  286. }