Ir ao conteúdo
  • Cadastre-se

C Função Recursiva ,para mudança de Base binaria


lidy ane

Posts recomendados

você leu mesmo o que eu disse?

 

estava melhor antes. A função está ok, mas está confundindo os nomes todos. Antes faltava uma variável agora sobram 2

 

 

 

adicionado 5 minutos depois
	int ndecimal;
	scanf("%ld", &ndecimal);
	printf("Decimal: %ld Binario: %ld\n", ndecimal, n(ndecimal));

que tal algo assim mais simples?

 

No primeiro código você estava lendo uma variável com o nome da função

 

No segundo está lendo uma variável chamada decimal que você não declarou. 

 

Link para o comentário
Compartilhar em outros sites

agora, lidy ane disse:

im pois não tem como ler o que seria o decimal e binário ,entendi meu erro .Como nunca usei recursiva não consido dar a entrada e saída que quero

 

por exemplo, como a variável resposta vai printar o valor binário

 

Você entendeu que não tem nada errado com a função???

 

O que está errado é o programa.

 

image.png.f211b11b9ba7c7749e1e71d711215be4.png

 

Acima passou o endereço da função para scanf() e isso não funciona

 

image.png.7634e532df3ee08dd1df8bdab1c762f3.png


Aqui declarou DUAS variáveis e passou para scanf() o endereço de uma terceira que não declarou 

 

 

 

adicionado 0 minutos depois
3 minutos atrás, lidy ane disse:

como a variável resposta vai printar o valor binário ?? :

 pois é

 

Algo assim

 

adicionado 1 minuto depois

image.png.e26aad9694dbeb59d1d278674b6c6457.png

usando um printf() 

adicionado 1 minuto depois

Está lendo mesmo o que eu escrevo? ☹️

adicionado 12 minutos depois
11 minutos atrás, arfneto disse:

m pois não tem como ler o que seria o decimal e binário ,entendi meu erro .Como nunca usei recursiva não consido dar a entrada e saída que quero

 

Cada chama a n() vai retornar um int normal mas que vai ter a representação do argumento em binário. Sua lógica est;a correta. 

 

A saída da função vai ser um número e aí você faz o que precisar com ele.

Link para o comentário
Compartilhar em outros sites

 

5 horas atrás, lidy ane disse:

long int n

aM_yGGwAAYoY768Io2PUAMdY8D5fqk3mfQTZ7MdW

O que é long int n? long int n é o identificador da função!

Não, porque long int n é o seu parâmetro, o parâmetro da função.

 

 

QsjIPtwNokMoA5hK4H1HLkexABIAnl6inchdCciG

Identificador da função é o nome que lhe foi dado, parâmetro é variável de entrada, argumento é o valor no parâmetro.

 

 

UGpLS0WkgaXMV85oGVDyxat7ICr64dxIv-4qqfz3

Notei a confusão entre parâmetro e nome da função. A essa altura já entende como acontece a entrada, a saída e a impressão desse programa, nesse sentido só falta os detalhes; reforço que escolha nomes mais descritivos para as variáveis, principalmente um nome certo para a função.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Entenda que esse erro é da chamada a scanf()

 

7 minutos atrás, lidy ane disse:

int ndecimal;

scanf("%ld",&ndecimal);

.

Você declarou ndecimal um int mas na hora de ler usou o especificador %ld. Esse %ld espera um ponteiro para long int e por isso o erro --- warning, aviso no caso.

 

Mas está errado mesmo, porque sua função também espera um long int:

 

9 minutos atrás, lidy ane disse:

long int n(const int val)

 

Melhor corrigir a declaração de ndecimal para

long int ndecimal;

Não pode usar um compilador com mensagens em português?

 

adicionado 2 minutos depois
3 horas atrás, lidy ane disse:

Sim pois não tem como ler o que seria o decimal e binário ,entendi meu erro .Como nunca usei recursiva não consido dar a entrada e saída que quero

 

por exemplo, como a variável resposta vai printar o valor binário

 

Entendeu que não tinha entendido o seu erro?  🤔

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

8 horas atrás, lidy ane disse:

 

@arfneto

Agradeço a paciência e auxilio dos membros, me ajudou muito.

Fiz o seguinte declarei a função para conversão da base chamei de long int conversão para ficar mais claro.

Depois no int main declarei o numero  ,fiz a leitura e impressão da conversão do numero.

Deu certinho , obrigada pessoal !

 

long int conversao(const int val){

......

int main(){

long int numero;
   scanf("%ld",&numero);
   printf("%ld\n", conversao(numero));

return 0;
}

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Olá!

 

Bom que está rodando ok agora.

 

Entenda que o objetivo de responder a essas dúvidas em um forum público é que possa ajudar mais pessoas com dúvidas parecidas. E assim se você edita os tópicos iniciais faz com que seja impossível para quem eventualmente está lendo e interessado no problema entender o que está acontecendo. As respostas aos posts vão se referir a coisas que não estão mais lá...

 

Veja o tópico #2 por exemplo e não dá para entender nada... Você voltou ao tópico original e colocou o programa corrigido e com uma parte faltando...

 

 

Peço que não altere os posts mas apenas poste as correções e o resultado final para ter algo consistente registrado...

Link para o comentário
Compartilhar em outros sites

Em 27/05/2020 às 08:41, lidy ane disse:

long int conversao(const int val){

......

int main(){

long int numero;
   scanf("%ld",&numero);
   printf("%ld\n", conversao(numero));

return 0;
}

Ficou quase como gostaria que fosse
~//~

 

Code in C

I-ly8k3fPa48DJGR_dTcEOLk_9PldKOLcvfXwSiX

#include <stdio.h>
//


// Conversao de Base
// Converta um numero inteiro n positivo da base decimal para a base binaria
// função recursiva long int n:
//
// Entrada.: Havera um numero inteiro n na base decimal. 
// Saida...: Numero n convertido para a base binaria.
// Função Decimal para binario
//
long int decimal_binario (long int n){
	if (n) return (decimal_binario (n/2l)*10l + n%2l);
	return 0l;
}
//


int main (void){
// TESTE DA FUNCAO
	long int decimal = 0l;
	scanf (" %ld", &decimal);

	long int binario = 0l;
	binario = decimal_binario (decimal);

	printf ("%ld ---> 0b%ld \n", decimal, binario);
	return 0;
}
//


Link para o comentário
Compartilhar em outros sites

Nenhuma das funções apresentadas até agora funcionam para números negativos (números grandes também seria um problema).

 

Segue uma solução que funciona para números negativos:

 

#include <stdio.h>
#include <limits.h>

unsigned long long int binary(short a){
    unsigned short b = (unsigned short)a;
    if (b){
        return (unsigned long long int) binary(b >> 1) * 10LLU + (b & 1);
    }
    return 0LLU;
}

int main()
{
    short n = 12;
    printf("Decimal ->      Binario\n");
    printf(" %6hd -> %16llu\n", n, binary(n));
    n = -12;
    printf(" %6hd -> %16llu\n", n, binary(n));
    n = 1;
    printf(" %6hd -> %16llu\n", n, binary(n));
    n = -1;
    printf(" %6hd -> %16llu\n", n, binary(n));
    n = SHRT_MAX;
    printf(" %6hd -> %16llu\n", n, binary(n));
    n = SHRT_MIN;
    printf(" %6hd -> %16llu\n", n, binary(n));

    return 0;
}

 

Note que o parâmetro da função precisa ser do tipo short (para limitar a 16 bits) e que o retorno da função precisa ter tipo unsigned long long int para caber o número decimal com 16 casas que representa o número binário no valor retornado.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

9 horas atrás, Mauro Britivaldo disse:

aM_yGGwAAYoY768Io2PUAMdY8D5fqk3mfQTZ7MdW

O parâmetro enunciado é: long int n, n > 0 

 

Onde está o enunciado?

 

De qualquer maneira se é estritamente n > 0 então deveria ser unsigned long int n , mas ainda assim não dá pra retornar todos os valores possíveis de long int n para n > 0 como uma representação decimal do número binário, visto que mesmo para o tipo short só cabe no tipo long long int .

 

Nesse caso seria melhor fazer uma função que imprime o binário ao invés de retornar um número decimal que representa o binário, pois assim poderia converter corretamente qualquer tamanho de número binário, nesse caso a função ficaria assim (também fiz funcionar para números negativos):

#include <stdio.h>
#include <limits.h>

void printbinary(int a){
    unsigned int b = (unsigned int)a;
    static int notzero = 0;
    if (b){
        notzero = 1;
        printbinary(b >> 1);
        printf("%d", b & 1);
    }
    else if (notzero){
        notzero = 0;
    }
    else {
        printf("0");
    }
}

int main()
{
    long int n;
    printf("             Decimal -> Binario\n");
  
    n = 12;
    printf("%20ld -> ", n);
    printbinary(n);
  
    n = 1;
    printf("\n%20ld -> ", n);
    printbinary(n);
  
    n = LONG_MAX;
    printf("\n%20ld -> ", n);
    printbinary(n);

    return 0;
}

 

Ou então teria que fazer uma função que recebe um vetor de char como parâmetro e o preenche com uma string que compõe o número binário, mas aí teria que passar 2 parâmetros para a função recursiva: o vetor e o número a ser convertido.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

29 minutos atrás, isrnick disse:

uma função que recebe um vetor de char como parâmetro e o preenche com uma string que compõe o número binário, mas aí teria que passar 2 parâmetros para a função recursiva: o vetor e o número a ser convertido

 

algo assim seria mais de acordo com o enunciado, ainda usando recursão e ainda retornando o resultado como no problema original

    char*	em_binario(long long int val, char* vetor);

 

 

Link para o comentário
Compartilhar em outros sites

Algo assim serviria

char* em_binario_na_string(long long int val, char* p)
{
    static int bits = 0;
    if (val == 0)
    {   // pode ser ou nao a primeira vez
        if (bits == 0)
        {   // era 0 no inicio
            *p = '0';
            *(p + 1) = 0;
            return p;
        }
        else
        {   // acabaram os bits
            bits = 0; // reinicia porque pode chamar de novo
            return p;
        };  // if()
    };  // if()

    // desloca os bits pra direita
    for (int j = bits; j > 0; j = j - 1)
        *(p + j) = *(p + j - 1); // copia
    *p = '0' + (char)(val % 2); // '0' ou '1'
    *(p + bits + 1) = 0; // poe um '\0'
    bits = bits + 1; // a fila anda
    return em_binario_na_string(val / 2, p); // e continua
};

Um teste 


                                  0    *    1    *    2    *    3    *    4    *    5    *    6
                                  *1234*6789*1234*6789*1234*6789*1234*6789*1234*6789*1234*6789*123
00                   0  binario: '0'
01                   1  binario: '1'
02                 127  binario: '1111111'
03               32767  binario: '111111111111111'
04          2147483647  binario: '1111111111111111111111111111111'
05 9223372036854775807  binario: '111111111111111111111111111111111111111111111111111111111111111'

                                  0    *    1    *    2    *    3    *    4    *    5    *    6
                                  *1234*6789*1234*6789*1234*6789*1234*6789*1234*6789*1234*6789*123

Com esse programa

int main()
{
    char maior_valor[65];
    char* p = &maior_valor[0];

    long long int exemplo[6] = {
        [0] = 0, // limite
        [1] = 1,
        [2] = 0x7F, // char 1 byte
        [3] = 0x7FFF, // short 2 bytes
        [4] = 0x7FFFFFFF, // int 4 bytes
        [5] = LLONG_MAX // long 8 bytes
    };
    grade();
    long long int j = 1;
    for (int i = 0; i <= 5; i = i + 1)
    {   *p = 0;
        printf("%02d%20lld\tbinario: '%s'\n", i, exemplo[i],
            em_binario_na_string(exemplo[i],p));
    };
    grade();
    return 0;
};

O programa todo

#include <limits.h>
#include <stdint.h>
#include <stdio.h>

char* em_binario_na_string(long long int, char*);
void grade();

int main()
{
    char maior_valor[65];
    char* p = &maior_valor[0];

    long long int exemplo[6] = {
        [0] = 0, // limite
        [1] = 1,
        [2] = 0x7F, // char 1 byte
        [3] = 0x7FFF, // short 2 bytes
        [4] = 0x7FFFFFFF, // int 4 bytes
        [5] = LLONG_MAX // long 8 bytes
    };
    grade();
    long long int j = 1;
    for (int i = 0; i <= 5; i = i + 1)
    {   *p = 0;
        printf("%02d%20lld\tbinario: '%s'\n", i, exemplo[i],
            em_binario_na_string(exemplo[i],p));
    };
    grade();
    return 0;
};


char* em_binario_na_string(long long int val, char* p)
{
    static int bits = 0;
    if (val == 0)
    {   // pode ser ou nao a primeira vez
        if (bits == 0)
        {   // era 0 no inicio
            *p = '0';
            *(p + 1) = 0;
            return p;
        }
        else
        {   // acabaram os bits
            bits = 0; // reinicia porque pode chamar de novo
            return p;
        };  // if()
    };  // if()

    // desloca os bits pra direita
    for (int j = bits; j > 0; j = j - 1)
        *(p + j) = *(p + j - 1); // copia
    *p = '0' + (char)(val % 2); // '0' ou '1'
    *(p + bits + 1) = 0; // poe um '\0'
    bits = bits + 1; // a fila anda
    return em_binario_na_string(val / 2, p); // e continua
};


void    grade()
{   // mostra um grid para faciliar contar as letras
    printf("\n%34s0    *    1    *    2    *    3    *    4\
    *    5    *    6   \n", "");
    printf("%34s*1234*6789*1234*6789*1234*6789*1234*6789*\
1234*6789*1234*6789*123\n", "");
    return;
}

// fim

 

Link para o comentário
Compartilhar em outros sites

@Mauro Britivaldo Sua solução é meio complicada, atualizando uma variável static para saber onde está, e também fazendo várias cópias para mover os caracteres para a direita...

 

 

 

Segue minha solução para preencher um vetor de char com a string do número binário:

#include <string.h>

char *binarystr(char *bin, long long int n){
    unsigned long long int b = (unsigned long long int)n;
    static int notzero = 0;
    char c[] = {'\0','\0'};
    if (b){
        notzero = 1;
        c[0] = (b & 1) ? '1' : '0';
        binarystr(bin, b >> 1);
        strcat(bin, c);
    }
    else if(notzero) {
        *bin = '\0';
    }
    else {
        bin[0] = '0';
        bin[1] = '\0';
    }
    notzero = 0;
    return bin;
}

E um exemplo de programa utilizando a função:

#include <stdio.h>
#include <limits.h>
#include <string.h>

char *binarystr(char *bin, long long int n){
    unsigned long long int b = (unsigned long long int)n;
    static int notzero = 0;
    char c[] = {'\0','\0'};
    if (b){
        notzero = 1;
        c[0] = (b & 1) ? '1' : '0';
        binarystr(bin, b >> 1);
        strcat(bin, c);
    }
    else if(notzero) {
        *bin = '\0';
    }
    else {
        bin[0] = '0';
        bin[1] = '\0';
    }
    notzero = 0;
    return bin;
}

int main()
{
    long long int n;
    char s[1 + 8*sizeof n];
    
    printf("          Decimal -> Binario\n");

    n = 12;
    printf("%20lld -> %s\n", n, binarystr(s, n));
  
    n = 1;
    printf("%20lld -> %s\n", n, binarystr(s, n));
  
    n = -1;
    printf("%20lld -> %s\n", n, binarystr(s, n));

    n = LLONG_MAX;
    printf("%20lld -> %s\n", n, binarystr(s, n));

    n = LLONG_MIN;
    printf("%20lld -> %s\n", n, binarystr(s, n));

    return 0;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

37 minutos atrás, isrnick disse:

meio complicada, atualizando uma variável static para saber onde está, e também fazendo várias cópias para mover os caracteres para a direita...

 

@isrnick É bem mais eficiente um loop que movimenta bytes adjacentes -- menos de 63 --- do que esse exemplo que postou, que chama uma função dentro de uma função recursiva... Pense bem... E compare os tempos

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

2 horas atrás, arfneto disse:

 

@isrnick É bem mais eficiente um loop que movimenta bytes adjacentes -- menos de 63 --- do que esse exemplo que postou, que chama uma função dentro de uma função recursiva... Pense bem... E compare os tempos

 

Não entendi...

 

Esse strcat copia apenas 2 bytes toda vez. Seria o mesmo que fazer:

int i;
for(i=0; bin[i]; i++);
bin[i] = c[0]; //bin[i] = (b & 1) ? '1' : '0';
bin[i+1] = c[1]; //bin[i+1] = '\0';

 

adicionado 10 minutos depois

 

 

@arfneto Aqui deixa eu reescrever a função sem usar funções da biblioteca string.h para ficar mais claro:

char *binarystr(char *bin, long long int n){
    unsigned long long int b = (unsigned long long int)n;
    static int notzero = 0;
    if (b){
        notzero = 1;
        binarystr(bin, b >> 1);
        size_t i;
        for(i=0; bin[i]; i++);
        bin[i] = (b & 1) ? '1' : '0';
        bin[i+1] = '\0';
    }
    else if(notzero) {
        *bin = '\0';
    }
    else {
        bin[0] = '0';
        bin[1] = '\0';
    }
    notzero = 0;
    return bin;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Explicando:

 

Aquele loop "complicado" apenas desloca a string para a direita e abre lugar para o próximo caracter da string. Vou repetir aqui:

    for (int j = bits; j > 0; j = j - 1)
        *(p + j) = *(p + j - 1); // copia

Naturalmente o efeito é o mesmo de strcat(), porque a ideia é resolver o mesmo problema.

 

Declarar variáveis como static em uma função recursiva é absolutamente comum na prática porque é a maneira de passar contexto de uma execução para a outra. E tem custo zero. Ou até menor que zero já que elimina uma alocação a cada chamada recursiva.

 

Por outro lado chamar uma função dentro de uma função recursiva é algo que se evita a todo custo.

Chamar uma função envolve mudança de contexto, empilhar argumentos, um jump e um retorno no mínimo... strcat() tem dois argumentos e tem um código de preparação e um loop. E um retorno. Tipo o for que está aí acima. Mas sem overhead

 

14 minutos atrás, isrnick disse:

Esse strcat copia apenas 2 bytes toda vez

 

Pois é. Não tem sentido algum chamar uma função para mover dois bytes.

Para seu programa parecer menos complicado? Em duas linhas? Já leu uma implementação de strcat() na biblioteca padrão?  Já escreveu uma? É a mesma coisa que o loop, como eu disse.

 

Não comparei os tempos, na verdade confesso que sequer rodei seu programa, mas sua observação e esse exemplo chamaram minha atenção. 

 

Vou estimar que, apenas para o programa ter duas linhas "menos simples" numa função de 15 linhas, chamar uma função de biblioteca para mover dois bytes ou algo mais, vai fazer essa solução demorar umas 40 vezes mais.

 

Qualquer hora vou medir e isso e posto para vocês. O confinamento mudou minha agenda afinal. :( Semanas atrás eu retirei uma rotina dessas para acelerar um loop de um processo em uma simulação e foi algo assim a diferença, cerca de 50X, mas o processamento era muito  mais complexo.

 

De todo modo considere o que estou dizendo: um loop é sempre melhor que uma função, mas nesse caso é ingênuo demais usar uma função... E se for para mover dois bytes então nem sei o que dizer. Pense em como começa strcat(), como processa, e como retorna. E vai fazer isso dentro de cada recursão.

 

Espero que dê pra entender

 

 

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:

Declarar variáveis como static em uma função recursiva é absolutamente comum na prática porque é a maneira de passar contexto de uma execução para a outra. E tem custo zero. Ou até menor que zero já que elimina uma alocação a cada chamada recursiva.

 

Sim, eu não quis dizer que usar uma variável static em uma função recursiva seria um erro. Eu estava dizendo que se está acompanhando a posição numa variável estática deve ter um modo de sempre colocar o caractere na posição correta diretamente, e fazer a função sem ter que copiar várias vezes.

 

 

1 hora atrás, arfneto disse:

Por outro lado chamar uma função dentro de uma função recursiva é algo que se evita a todo custo.

Chamar uma função envolve mudança de contexto, empilhar argumentos, um jump e um retorno no mínimo... strcat() tem dois argumentos e tem um código de preparação e um loop. E um retorno. Tipo o for que está aí acima. Mas sem overhead

 

Entendi. 👍

 

 

 

Aqui está minha melhor versão até agora, usando uma variável static para contar o número de bits, e usa o retorno do ponteiro para ir avançando pelo vetor para mover para a posição correta para colocar o respectivo caractere 0 ou 1 do bit, e usa a variável contadora para saber quando deve parar de avançar. E mais importante não tem ciclos de repetição percorrendo o vetor várias vezes e nem faz cópias, cada posição da string só é atribuída um caractere uma vez.

 

char *binarystr(char *bin, long long int n){
    unsigned long long int b = (unsigned long long int)n;
    static int count = 0;
    char *p;
    if (b){
        count++;
        p = binarystr(bin, b >> 1);
        *p = (b & 1) ? '1' : '0';
        if(p-bin+1 < count)
            return p+1;
        else 
            count = 0;
    }
    else if (count == 0){
        bin[0] = '0';
        bin[1] = '\0';
    }
    else {
        bin[count] = '\0';
    }
    return bin;
}

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...