Até aqui, o programa já consegue interpretar dois dos oito comandos de brainfuck. Se o valor da célula selecionada for igual a 82, e for mandado para a tela, será exibido um “R”, pois 82 equivale a essa letra, de acordo com o ASCII.
Adicione novas condicionais para interpretar os outros quatro comandos, deixando os dois últimos para mais tarde. O comando “-” deve decrementar o valor da célula selecionada, “,” deve pegar um valor do usuário através do teclado e guardá-lo na célula selecionada, “>” deve selecionar a próxima célula e, “<” deve selecionar a célula anterior. Ficará assim:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int c;
FILE *arquivo; // Deve-se usar o asterisco aqui, por ser ponteiro
if (argc >= 2) // Se tiver 2 ou mais argumentos
{
arquivo = fopen(argv[1], "rb"); // Abre o arquivo especificado
if (arquivo == NULL) // Se não conseguir abrir o arquivo
{
puts("ERRO: Não foi possível abrir o arquivo!");
do { c = getchar(); } while ((c != '\n') && (c != EOF));
return 1; // Encerra o programa
}
}
else
{
return 0; // Encerra o programa
}
fseek(arquivo, 0, SEEK_END);
int tamanho = ftell(arquivo); // Offset do fim do arquivo, que equivale ao tamanho do arquivo
rewind(arquivo); // Rebobina o arquivo
// Aloca memória, com um byte adicional para o nulo (usado em strings em C)
char *fonte = (char *) malloc(tamanho + 1);
if (fonte == NULL) // Verifica se consegui alocar memoria
{
puts("ERRO: Não há memória o suficiente!");
do { c = getchar(); } while ((c != '\n') && (c != EOF));
return 1;
}
memset(fonte, 0, tamanho * sizeof(char)); // Preencherá a variável fonte com zeros (para "limpar")
size_t size = fread(fonte, 1, tamanho, arquivo);
fonte[tamanho] = 0; // Põe o sinal de fim (nulo)
if (size != tamanho * sizeof(char))
{
puts("ERRO: Não foi possível ler o arquivo!");
do { c = getchar(); } while ((c != '\n') && (c != EOF));
return 1;
}
int colchetes = 0, i;
for (i = 0; i < tamanho; i++)
{
if (fonte[i] == '[')
{
colchetes++;
}
else if (fonte[i] == ']')
{
if (colchetes == 0) // Se nenhuma estrutura '[' está aberta
{
puts("ERRO: A estrutura de repetição ']' não foi aberta!");
do { c = getchar(); } while ((c != '\n') && (c != EOF));
return 1;
}
else
{
colchetes--;
}
}
}
if (colchetes > 0) // Se alguma estrutura '[' não foi fechada
{
puts("ERRO: A estrutura de repetição '[' não foi fechada!");
do { c = getchar(); } while ((c != '\n') && (c != EOF));
return 1;
}
unsigned char pilha[30000]; // Equivalente a aproximadamente 30 KB
memset(pilha, 0, 30000 * sizeof(unsigned char));
int backup = 0, ptr = 0, pos[tamanho];
colchetes = 0;
for (i = 0; i < tamanho; i++)
{
if (fonte[i] == '[')
{
backup = i;
while (i < tamanho)
{
if (fonte[i] == '[')
{
colchetes++;
}
else if (fonte[i] == ']')
{
colchetes--;
}
if (colchetes == 0)
{
break;
}
i++;
}
pos[i] = backup;
pos[backup] = i;
i = backup;
}
}
for (i = 0; i < tamanho; i++)
{
switch (fonte[i])
{
case '+':
pilha[ptr]++;
break;
case '.':
putchar(pilha[ptr]);
break;
case '-':
pilha[ptr]--;
break;
case ',':
backup = getchar();
if (backup != -1)
{
pilha[ptr] = backup;
}
break;
case '>':
if (ptr == 30000 - 1) // Célula 30000
{
ptr = 0; // Célula 1
}
else
{
ptr++;
}
break;
case '<':
if (ptr == 0)
{
ptr = 30000 - 1; // Célula 30000
}
else
{
ptr--;
}
break;
}
}
free(fonte);
return 0;
}
Na verificação do comando “,”, eu usei uma condição para verificar o valor recebido. Isso porque por padrão, os interpretadores de brainfuck identificam a tecla Enter pelo valor ASCII 10, mas o Windows identifica como 13, causando incompatibilidade com a maioria dos códigos brainfuck espalhados pela internet. Se nosso programa receber o valor 13, guardará 10 e, se receber 10, guardará 13.
Um pouco mais a frente, eu usei uma condicional para verificar qual célula estava selecionada. Caso esteja na última célula (pilha[29999]
é a célula 30000), deverá pular para a primeira célula (pilha[0]
é a célula 1) e vice-e-versa. Se não houver a verificação, e o programa instruir selecionar a próxima célula, sendo que já estiver na última, houverá um problema e o programa encerrará de forma abrupta.
« parte anterior próxima parte »
0 comentários:
Postar um comentário