Conversor de unidades de memoria, repositório de código

Peter V5

Folding Member
Aqui está um programa que converte bytes ou megabyte para kilobytes ou gigabytes, por ai fora

/*
Nome: Conversor de unidades de memoria
Copyright: Copyleft
Autor: Pedro Melgueira AKA Peter V5
Data: 05-10-08 12:24
Descrição: Este programa converte bytes ou megabyte para kilobytes ou gigabytes, por ai fora
Contacto: [email protected]
*/
#include <stdio.h>

main()
{
float x;
int op1, op2;

printf("De:\n");
printf("1- b\n2- Kb\n3- Mb\n4- Gb\n\n");
scanf("%d", &op1);
printf("Para:\n");
printf("1- b\n2- Kb\n3- Mb\n4- Gb\n");
scanf("%d", &op2);

printf("Insira o valor\n");
scanf("%f", &x);

switch(op1)
{
case 1:
switch(op2)
{
case 1:
printf("%.2f\n", x);
break;
case 2:
printf("%.2f Kb\n", x/1024);
break;
case 3:
printf("%.2f Mb\n", x/1024/1024);
break;
case 4:
printf("%.2f Gb\n", x/1024/1024/1024);
break;
default:
printf("Erro.\n");
}
break;
case 2:
switch(op2)
{
case 1:
printf("%.2f B\n", x*1024);
break;
case 2:
printf("%.2f Kb\n", x);
break;
case 3:
printf("%.2f Mb\n", x/1024);
break;
case 4:
printf("%.2f Gb\n", x/1024/1024);
break;
default:
printf("Erro.\n");
}
break;
case 3:
switch(op2)
{
case 1:
printf("%.2f B\n", x*1024*1024);
break;
case 2:
printf("%.2f B\n", x*1024);
break;
case 3:
printf("%.2f Kb\n", x);
break;
case 4:
printf("%.2f Mb\n", x/1024);
break;
default:
printf("Erro.\n");
}
break;
case 4:
switch(op2)
{
case 1:
printf("%.2f B\n", x*1024*1024*1024);
break;
case 2:
printf("%.2f B\n", x*1024*1024);
break;
case 3:
printf("%.2f Kb\n", x*1024);
break;
case 4:
printf("%.2f Mb\n", x);
break;
default:
printf("Erro.\n");
}
break;
default:
printf("Erro.\n");
}
getchar();
getchar();
}
 
Ó pá, tava aqui a ver isto por acaso, e não me pude conter, tive de postar porque acho o teu código pouco elegante. Três coisas:

- Usas um switch, quando uma lookup table seria mais elegante
- Convertes tudo para bytes e depois voltas a converter, quando uma conversão só seria suficiente. Não é só mau por fazeres duas conversões, mas se se tratarem de números muito grandes podes ter um overflow desnecessário.
- Usas muitas multiplicações e divisões quando um único shiftezinho bastava
e permitia-te fazer código que também funcionava em inteiro

Eis uma versão em inteiro (sem os printfs):

Código:
#include <assert.h>

int converte(int de, int para, int quantos)
{
    static const int unidade[5] = { 0, 10, 20, 30, 40 };

    assert(de >= 1 && de <= 5 && para >= 1 && para <= 5);

    int expoente = unidade[para - 1] - unidade[de - 1];
    return quantos << expoente;
}

Agora a versão em vírgula flutuante:

Código:
#include <assert.h>
#include <math.h>

double converte(int de, int para, double quantos)
{
    static const int unidade[5] = { 0, 10, 20, 30, 40 };

    assert(de >= 1 && de <= 5 && para >= 1 && para <= 5);

    int expoente = unidade[para - 1] - unidade[de - 1];
    return ldexp(quantos, expoente);
}

Boas.
 
Foste desenterrar um tópico do repositório do código para dizer que tens uma maneira melhor de fazer as coisas de uma maneira que nem conheço, muito bem mas por isso mas dai a dizer que o meu codigo está pouco elegante é que já não..
 
... de uma maneira que nem conheço...

Agora já conheces. Isso se calhar quer dizer que o meu post pode ser mais instrutivo e útil para alguém. A técnica que sugeri tem vantagens objectivas: só usa somas e um único shift, evita overflow desnecessário, e é fácil estender para terabytes, petabytes e etc. A técnica que tu sugeriste tem um número de linhas de código proporcional ao quadrado do número de unidades a converter.
 
O assert não está lá a fazer nada, não tem qualquer efeito no código. Só meti o assert porque me sentia mal a indexar um array sem verificar que o índice estava dentro dos limites.

O header <assert.h> da biblioteca padrão do C define um macro, o assert, que serve para verificar se uma condição, que o programador pensa ser verdadeira naquele momento, é efectivamente verdadeira (as condições para as quais aquele código foi pensado). Na versão debug do código, a expressão assert(x) transforma-se em if (!(x)) abort(). Na versão release (ao definir o macro NDEBUG), a expressão assert(x) não geral qualquer código.

Por exemplo, o código inteiro pode ficar apenas (sem recurso a qualquer função de qualquer biblioteca):

Código:
int converte(int de, int para, int x)
{
    static const int unidade[5] = { 0, 10, 20, 30, 40 };
    int expoente = unidade[para - 1] - unidade[de - 1];
    return quantos << expoente;
}

A versão em vírgula flutuante utiliza, essa sim, uma função do C, o ldexp. Esta função existe porque os números são representados em sinal, expoente e mantissa, e os microprocessadores têm instruções para adicionar ao expoente. Esta função ldexp(x, y) adiciona y ao expoente de x, o que é equivalente a multiplicar x por 2 elevado a y.

Também na versão inteiro, o shift para a esquerda é equivalente a multiplicar "quantos" por 2 elevando a "expoente".

O código seguinte é mais fácil de entender:

Código:
double converte(int de, int para, double x)
{
    static const long unidade[4] = { 1L, 1024L, 1024L*1024L, 1024L*1024L*1024L };
    return quantos * unidade[para - 1] / unidade[de - 1];
}

Há uma única multiplicação pela razão entre as duas unidades. No entanto, a versão anterior, aproveita o facto das unidades serem potências de 2 para simplesmente adicionar ao expoente (ou fazer o shift no caso inteiro), em vez de fazer uma multiplicação, o que é mais rápido.
 
Foste desenterrar um tópico do repositório do código para dizer que tens uma maneira melhor de fazer as coisas de uma maneira que nem conheço, muito bem mas por isso mas dai a dizer que o meu codigo está pouco elegante é que já não..


Recebeste aqui uma critica bem construtiva...aprender a aceita-las irá ser-te bastante util para continuares a crescer como programador.

Gostei dos posts do bsd...tu tambem devias ter gostado.
 
Recebeste aqui uma critica bem construtiva...aprender a aceita-las irá ser-te bastante util para continuares a crescer como programador.

Gostei dos posts do bsd...tu tambem devias ter gostado.

Peço desculpa, quando vi ver isto estava um bocado irritado com uma coisa. até foi um post porreiro.

bsd, esplicação porreira, percebes bem disto, lol
 
Última edição:
Back
Topo