Conversor binário – ternário – binário

Esse é mais uma resolução comentada do livro Estrutura de Dados em C, ex 1.1.7, pg 33 e o enunciado segue abaixo:

Escreva um programa C para ler uma string de 0s e 1s representando um inteiro positivo em notação binária e imprima uma string de 0s, 1s e 2s representando o mesmo numero em notação ternária (veja o exercício anterior). Escreva outro programa C para ler um número ternário e imprimir o equivalente em notação binária.

Tenenbaum, Langsam e Augesnstein (2013)

Se você curtir esse artigo, não esqueça de dar uns cliques nos anúncios para ver o que os anunciantes tem para te oferecer. Vou ficar muito contente.

Esse exercício fala sobre fazer um programa para converter um número inteiro positivo da notação binária para a notação ternária e vice versa.

O valor máximo que é possível converter, corresponde ao valor 255 decimal que em binário é “11111111” e em ternário é “100110”.

O exercício foi resolvido com 3 arquivos, 7 no total se contar com os arquivos de programa e os do teste unitário.

O programa completo pode ser baixado direto da minha página do GitHub clicando aqui.

Para os testes unitários, devo lembrar que utilizei a suíte de testes Cutest, de código aberto, que pode ser baixada direto no site SouceForge, clicando aqui.

Sabe o que é bacana dessa implementação?

Se você não gostar da solução que eu dei, basta apagar, mantendo os testes unitários. Daí, ao executar os testes unitários, vão subir os erros e aí é só você ir montando um código, chamando as funções, resolvendo os erros e implementando a solução no seu estilo. Tem jeito melhor de estudar?

Descrição dos arquivos:

  • main.c – É o início do programa. Possui a lógica de controle se vai ou não vai rodar os testes unitários, chama as funções para executar as entradas de dados, depois as para fazer a conversão propriamente dita e finaliza apresentando os dados no console.
  • funcoes.h – Esse é o header descrevendo as funções implementadas no arquivo funcoes.c. Ele também tem o define dos termos BINARIO e TERNARIO.
  • funcoes.c – Esse é o coração do programa. Ele contém as funções que executam tarefas como leitura de dados, conversão binário para ternário e vice versa entre outras.
  • Testes_bin_3_bin.h – Esse é o arquivo contendo os protótipos dos testes.
  • Testes_bin_3_bin.c – Esse é o arquivo que tem a implementação das asserções que os testes unitários devem fazer.
  • Cutest.c e Cutest.h – É a suíte de testes open source Cutest, que utilizei para testar o programa.

Descrição das funções:

Aqui vou listar as funções principais, com sua finalidade. A maioria delas está no arquivo funcoes.c. Caso estejam em outro lugar, eu aviso.

int le_dado(char word[], int tipo);

Essa função é responsável por fazer a leitura dos dados inseridos pelo teclado. Ela recebe uma string e o tipo do dado que essa string deve ser preenchida: dado binário ou dado ternário. Se for binário, pode ter até 8 caracteres “0s” ou “1s” e se for um dado ternário, pode ter até 6 caracteres “0s”, “1s” ou “2s”.

void alinha_direita(char entrada[],int tipo)

Depois que o dado é digitado no teclado, é chamada essa função para fazer o alinhamento à direita da string, completando com zeros do lado esquerdo. Se for digitado o dado binário “11”, ele será formatado para “00000011” e se for um dado ternário “1201”, ele será formatado para “001201”. Para ela funcionar, a gente tem que mandar a string “entrada[]” e o tipo dela “BINARIO” ou “TERNARIO”, sem acento e conforme o caso.

void representaBinario(char entrada_ternario[],char result_binario[]);

Essa função é responsável por converter para binário um valor ternário que tenha sido digitado na entrada de dados. Ela recebe a string “entrada_ternario[]” com o valor ternário a ser convertido e o valor convertido é retornado na string “result_binario[]”.

void representaTernario(char entrada_binario[], char result_ternario[]);

Essa função é responsável por converter para ternário um valor binário que tenha sido digitado na entrada de dados. Ela recebe a string “entrada_binario” com o valor binário a ser convertido e o valor convertido é retornado na string “result_ternario[]”.

Alguns pontos do código:

Na conversão de um tipo para outro, sempre é feito primeiro a conversão para o sistema decimal. Entrou dado binário ou ternário, antes de tudo, ele é convertido para o valor decimal correspondente.

Para referência, seguem as tabelas de conversão de binário para decimal (8 bits) e de ternário para decimal (6bits):

Tabela binário para decimal
Tabela ternário para decimal

O programa converte corretamente para binário e vice versa os valores até 255 em decimal. Em ternário, o valor 255 corresponde a “100110” (243+9+3) e em binário 255 corresponde a “11111111”.

O programa não converte corretamente valores acima de 255 decimal, quando digitado em notação ternária. Isso é um bug conhecido e o tratamento dessa condição foi deixado para implementação futura.

O programa trabalha com strings representando os números “0”, “1” e “2” que correspondem aos caracteres ASCII “48”, “49” e “50”. Para a conversão de ternário para decimal, foi preciso converter o conteúdo do array que é do tipo string para inteiro. Isso foi realizado subtraindo o valor 48 do conteúdo dos elementos do array, conforme consta na linha 78 de funcoes.c:

decimal=decimal+(((entrada_ternario[controle])-48)*(pow(3,-1*controle+5)));

O programa completo:

Conforme dito, a versão mais atualizada dessa solução pode ser baixada direto do meu repositório no Git, Abaixo seguem os arquivos:

main.c

#include <stdio.h>
#include <stdlib.h>
#include "funcoes.h"
#include "Teste_unitario/CuTest.h"
#include "Teste_unitario/Testes_bin_3_bin.h"

/*
Escreva um programa C para ler uma string de 0s e 1s representando  um  inteiro
positivo em notacao binaria e imprima uma string de 0s, 1s e 2s representando o
mesmo numero em notacao ternaria (veja o exercicio anterior). Escreva outro pro
grama C para ler um numero ternario e imprimir o equivalente em notacao binaria

Fonte: Tenembaum, Estrutura de dados usando C, ex 1.1.7, pg33.
Autor da soulucao: Renato de Pierri - nets-nuts.com.br
*/

//Suite de testes
CuSuite* CuGetSuite();
CuSuite* CuStringGetSuite();
//Suite de testes

int main()
{
    int debug;
    int check1,check2=1;

    char entrada_binaria[9];
    char result_ternario[7];

    char entrada_ternaria[7];
    char result_binario[9];

//  debug = 0; //roda os testes unitarios
//  debug = 1; //operacao normal

    debug = 1;

    if (debug){
        do{
            printf("Entre com valor binario de ate 8 bits\n");
            check1 = 0;
            check1 = le_dado(entrada_binaria,BINARIO);
            alinha_direita(entrada_binaria,BINARIO);
            if(check1 == 0){
                printf("Dado binario ok: %s\n", entrada_binaria);

            }else{
                printf("Dado binario inconsistente\n\n");
            }

            printf("Entre com valor ternario de ate 6 ternos\n");
            check2 = 0;
            check2 = le_dado(entrada_ternaria,TERNARIO);
            alinha_direita(entrada_ternaria,TERNARIO);
            if(check2 == 0){
                printf("Dado ternario ok: %s\n\n", entrada_ternaria);
            }else{
                printf("Dado ternario inconsistente\n\n");
            }
            if((check1==1)|(check2==1)){
                printf("Dados inconsistentes.\n"
                       "Entrar com os dados novamente.\n\n");
            }else{
                representaTernario(entrada_binaria, result_ternario);
                printf("Conversao de binario %s para ternario: %s\n\n",
                       entrada_binaria, result_ternario);

                representaBinario(entrada_ternaria, result_binario);
                printf("Conversao de ternario: %s para binario: %s\n\n",
                       entrada_ternaria, result_binario);
            }
            system("pause");
            system("cls");

        }while ((check1==1)|(check2==1));
    }else{
        RunAllTests();
    }
    return 0;
}

funcoes.h

#ifndef FUNCOES_H_INCLUDED
#define FUNCOES_H_INCLUDED

#define BINARIO  0
#define TERNARIO 3

int le_dado(char word[], int tipo);
void representaBinario(char entrada_ternario[],char result_binario[]);
void representaTernario(char entrada_binario[], char result_ternario[]);
void alinha_direita(char entrada[],int tipo);

#endif // FUNCOES_H_INCLUDED

funcoes.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "funcoes.h"

int le_dado(char word[],int tipo){
    int controle, check, tamanho_string;
    controle = 0;

    //Verifica se tem apenas 0s, 1s e 2s conforme o caso
    if(tipo == BINARIO){
        check = 0;
        scanf("%8s",word);
        fflush(stdin);
        tamanho_string = strlen(word);
        while (controle < tamanho_string){
            if (word[controle]== '0'||word[controle] == '1'){
                check = 0;
                controle++;
            }else{
                check = 1;
                controle = tamanho_string;
            }
        }
    }else{
        check = 0;
        scanf("%6s",word);
        fflush(stdin);
        tamanho_string = strlen(word);
        while (controle < tamanho_string){
            if (word[controle]=='0'||word[controle]=='1'||word[controle]=='2'){
                check = 0;
                controle++;
            }else{
                check = 1;
                controle = tamanho_string;
            }
        }
    }
return check;
}

void representaTernario(char entrada_binario[], char result_ternario[]){
    int controle = 0;
    int decimal = 0;
    int v1 = 0;
    char temp1[7];
    int tamanhoString = strlen(entrada_binario);
    for(controle = 0; controle <= tamanhoString; controle++){
        if(entrada_binario[controle]=='1'){
           decimal=decimal+pow(2,-1*controle+7) ;
        }
    }
    controle = 5;
    while(decimal>0){
        v1 = decimal%3;
        temp1[controle]=v1+'0';
        controle --;
        decimal = (int)(decimal/3);
    }
    while(controle>=0){
        temp1[controle]='0';
        controle --;
    }
    strcpy(result_ternario,temp1);
return;
}

void representaBinario(char entrada_ternario[],char result_binario[]){
	int controle = 0;
    int decimal = 0;
    int v1 = 0;
    char temp1[9];
    int tamanhoString = strlen(entrada_ternario);
    for(controle = 0; controle <= tamanhoString; controle++){
        if((entrada_ternario[controle]=='1')||(entrada_ternario[controle]=='2')){
           decimal=decimal+(((entrada_ternario[controle])-48)*(pow(3,-1*controle+5)));
        }
    }
    controle = 7;
    while(decimal>0){
        v1 = decimal%2;
        temp1[controle]=v1+'0';
        controle --;
        decimal = (int)(decimal/2);
    }
    while(controle>=0){
        temp1[controle]='0';
        controle --;
    }
    strcpy(result_binario,temp1);
return;
}

void alinha_direita(char entrada[],int tipo){
    int tamanho_string;
    int controle;
    int desloca;
    char bin_direita[9]="00000000";
    char ter_direita[7]="000000";

    int des,ctrl;

    if(tipo == BINARIO){
        des = 8;
    }else{
        des = 6;
    }
    ctrl = des -1;

    tamanho_string = strlen(entrada);
    desloca = des - tamanho_string;

    if(tipo == BINARIO){
        for(controle = ctrl;controle>=0;controle--){
            if (controle < tamanho_string){
                bin_direita[controle+desloca] = entrada[controle];
            }
        }
        strcpy(entrada,bin_direita);
    }else{
        for(controle = ctrl;controle>=0;controle--){
            if (controle < tamanho_string){
                ter_direita[controle+desloca] = entrada[controle];
            }
        }
        strcpy(entrada,ter_direita);
    }

return;
}

Testes_bin_3_bin.h

CuSuite*StrUtilGetSuite();
void RunAllTests(void);

// Testes unitarios

void TesteBinarioParaTernario1(CuTest *tc);
void TesteBinarioParaTernario2(CuTest *tc);
void TesteBinarioParaTernario3(CuTest *tc);
void TesteBinarioParaTernario4(CuTest *tc);

//==================================================

void TesteTernarioParaBinario1(CuTest *tc);
void TesteTernarioParaBinario2(CuTest *tc);
void TesteTernarioParaBinario3(CuTest *tc);
void TesteTernarioParaBinario4(CuTest *tc);

//==================================================

void TesteAlinhaDireita1(CuTest *tc);
void TesteAlinhaDireita2(CuTest *tc);
void TesteAlinhaDireita3(CuTest *tc);
void TesteAlinhaDireita4(CuTest *tc);
void TesteAlinhaDireita5(CuTest *tc);
void TesteAlinhaDireita6(CuTest *tc);
void TesteAlinhaDireita7(CuTest *tc);

//==================================================

Testes_bin_3_bin.c

#include <stdio.h>
#include <stdlib.h>
#include "../funcoes.h"
#include "CuTest.h"

CuSuite* StrUtilGetSuite();

void RunAllTests(void){
    CuString* output = CuStringNew();
    CuSuite* suite = CuSuiteNew();
    CuSuiteAddSuite(suite, StrUtilGetSuite());
    CuSuiteRun(suite);
    CuSuiteSummary(suite, output);
    CuSuiteDetails(suite, output);
    printf ("%s\n\n", output->buffer);

}
// Testes unitarios


//==================================================

void TesteBinarioParaTernario1(CuTest *tc){
CuString* str = CuStringNew();
char  ter[7];
representaTernario("11111110", ter);
CuStringAppend(str,ter );
CuAssertStrEquals(tc, "100102", str->buffer);
}

void TesteBinarioParaTernario2(CuTest *tc){
CuString* str = CuStringNew();
char  ter[7];
representaTernario("01000010", ter);
CuStringAppend(str,ter );
CuAssertStrEquals(tc, "002110", str->buffer);
}

void TesteBinarioParaTernario3(CuTest *tc){
CuString* str = CuStringNew();
char  ter[7];
representaTernario("00000000", ter);
CuStringAppend(str,ter );
CuAssertStrEquals(tc, "000000", str->buffer);
}

void TesteBinarioParaTernario4(CuTest *tc){
CuString* str = CuStringNew();
char  ter[7];
representaTernario("00000010", ter);
CuStringAppend(str,ter );
CuAssertStrEquals(tc, "000002", str->buffer);
}

//==================================================

void TesteTernarioParaBinario1(CuTest *tc){
CuString* str = CuStringNew();
char  bin[9];
representaBinario("100110", bin);
CuStringAppend(str,bin );
CuAssertStrEquals(tc, "11111111", str->buffer);
}

void TesteTernarioParaBinario2(CuTest *tc){
CuString* str = CuStringNew();
char  bin[9];
representaBinario("002110", bin);
CuStringAppend(str,bin );
CuAssertStrEquals(tc, "01000010", str->buffer);
}

void TesteTernarioParaBinario3(CuTest *tc){
CuString* str = CuStringNew();
char  bin[9];
representaBinario("000000", bin);
CuStringAppend(str,bin );
CuAssertStrEquals(tc, "00000000", str->buffer);
}

void TesteTernarioParaBinario4(CuTest *tc){
CuString* str = CuStringNew();
char  bin[9];
representaBinario("000002", bin);
CuStringAppend(str,bin );
CuAssertStrEquals(tc, "00000010", str->buffer);
}

//==================================================

void TesteAlinhaDireita1(CuTest *tc){
CuString* str = CuStringNew();
char  input[9]="10";
alinha_direita(input,BINARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "00000010", str->buffer);
}

void TesteAlinhaDireita2(CuTest *tc){
CuString* str = CuStringNew();
char  input[9]="101010";
alinha_direita(input,BINARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "00101010", str->buffer);
}

void TesteAlinhaDireita3(CuTest *tc){
CuString* str = CuStringNew();
char  input[9]="10101010";
alinha_direita(input,BINARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "10101010", str->buffer);
}

void TesteAlinhaDireita4(CuTest *tc){
CuString* str = CuStringNew();
char  input[7]="22";
alinha_direita(input,TERNARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "000022", str->buffer);
}

void TesteAlinhaDireita5(CuTest *tc){
CuString* str = CuStringNew();
char  input[7]="012012";
alinha_direita(input,TERNARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "012012", str->buffer);
}

void TesteAlinhaDireita6(CuTest *tc){
CuString* str = CuStringNew();
char  input[7]="201";
alinha_direita(input,TERNARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "000201", str->buffer);
}

void TesteAlinhaDireita7(CuTest *tc){
CuString* str = CuStringNew();
char  input[9]="1000";
alinha_direita(input,BINARIO);
CuStringAppend(str,input );
CuAssertStrEquals(tc, "00001000", str->buffer);
}

//==================================================

CuSuite*StrUtilGetSuite(){
    CuSuite* suite = CuSuiteNew();

    SUITE_ADD_TEST(suite,TesteBinarioParaTernario1);
    SUITE_ADD_TEST(suite,TesteBinarioParaTernario2);
    SUITE_ADD_TEST(suite,TesteBinarioParaTernario3);
    SUITE_ADD_TEST(suite,TesteBinarioParaTernario4);

    SUITE_ADD_TEST(suite,TesteTernarioParaBinario1);
    SUITE_ADD_TEST(suite,TesteTernarioParaBinario2);
    SUITE_ADD_TEST(suite,TesteTernarioParaBinario3);
    SUITE_ADD_TEST(suite,TesteTernarioParaBinario4);

    SUITE_ADD_TEST(suite,TesteAlinhaDireita1);
    SUITE_ADD_TEST(suite,TesteAlinhaDireita2);
    SUITE_ADD_TEST(suite,TesteAlinhaDireita3);
    SUITE_ADD_TEST(suite,TesteAlinhaDireita4);
    SUITE_ADD_TEST(suite,TesteAlinhaDireita5);
    SUITE_ADD_TEST(suite,TesteAlinhaDireita6);
    SUITE_ADD_TEST(suite,TesteAlinhaDireita7);
}

Publicado por Renato de Pierri em 16/Janeiro/2023

Bibliografia:

TENENBAUM, Aaron M.; LANGSAM, Yedidyah; AUGESNSTEIN, Moshe J.. Estruturas de Dados Usando C. São Paulo: Pearson, 2013. 884 p. ISBN 13: 978-85-346-0348-5

Last updated by at .