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.
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):
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