Return 0

Maio 7, 2008

Instruções If e Else em C, C++ e Java

Arquivado em: C/C++, Java — Tags:, , , , — computeiro @ 7:45 pm

Bastante requisitada por programadores iniciantes e/ou programadores provenientes de outra linguagem, a maneira de se construir um bloco de instruções if/else é bastante trivial e exatamente igual em C, C++ e Java. Aqui vai um exemplo:

Em C:

# include <stdio.h>

int main(int argc, char** argv)
{
    int x = 0;
    int y = 1;

    if(x > y)
        printf("%d eh maior que %d\n", x, y);
    else
        printf("%d nao eh maior que %d\n", x, y);

    x = y--;

    if(x > y)
        printf("%d eh maior que %d\n", x, y);
    else
        printf("%d nao eh maior que %d\n", x, y);

    return 0;
}

Em C++:

# include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    int x = 0;
    int y = 1;

    if(x > y)
        cout << x << " eh maior que " << y << endl;
    else
        cout << x << " nao eh maior que " << y << endl;

    x = y--;

    if(x > y)
        cout << x << " eh maior que " << y << endl;
    else
        cout << x << " nao eh maior que " << y << endl;

    return 0;
}

Em Java:

public class IfElse
{
    public static void main(String args[])
    {
        int x = 0;
        int y = 1;

        if(x > y)
            System.out.println(x + " eh maior que " + y);
        else
            System.out.println(x + " nao eh maior que " + y);

        x = y--;

        if(x > y)
            System.out.println(x + " eh maior que " + y);
        else
            System.out.println(x + " nao eh maior que " + y);
    }
}

O velho problema das chaves nos if/else aninhados:

Sabemos que ao usar apenas uma instrução dentro de um if ou de um else, as chaves são opcionais. Mais de uma instrução, no entanto, torna obrigatório o uso das chaves. Vejamos um problema comum com o uso das chaves em if/else aninhados:

# include <stdio.h>

int main(int argc, char** argv)
{
    int x = 5;

    if(x == 5)
        x = 4;
        if(x == 3)
            x = 2;
    else
        x = 0;

    //imprima x

    if(x == 5)
        x = 4;
        if(x == 3)
            x = 2;
    else
        x = 1;

    //imprima x

    return 0;
}

O que ocorrerá com o valor de x neste código? Teste-o e tire suas conclusões. A dica que eu posso dar é que pode ser resolvido fazendo isto:

# include <stdio.h>

int main(int argc, char** argv)
{
    int x = 5;

    if(x == 5)
    {
        x = 4;
        if(x == 3)
            x = 2;
    }else
        x = 0;

    //imprima x

    if(x == 5)
    {
        x = 4;
        if(x == 3)
            x = 2;
    }else
        x = 1;

    //imprima x

    return 0;
}

Teste os dois códigos e perceba que uma instrução else sempre pertence a o último if, no caso deste if/else conter apenas uma instrução. Uma dica: para evitar problemas, sempre use chaves em if/else, não importa se ele tiverem mais de uma instrução ou apenas uma.

return 0

Abril 26, 2008

Write in C

Arquivado em: C/C++, Diversos — Tags:, , — computeiro @ 2:14 am

Tudo bem, vão falar que eu sou programador C, de tanto post que eu tenho sobre C. É que: 1. Não tô muito inspirado esses tempos; 2. C merece!

Quem não conhece este clássico da música clássica programística, que atire a primeira pedra.

WRITE IN C

When I find my code in tons of trouble,
Friends and colleagues come to me,
Speaking words of wisdom:
Write in C.”
As the deadline fast approaches,
And bugs are all that I can see,
Somewhere, someone whispers”
Write in C.”
Write in C, write in C,
Write in C, write in C.
LISP is dead and buried,
Write in C.
I used to write a lot of FORTRAN,
for science it worked flawlessly.
Try using it for graphics!
Write in C.
If you’ve just spent nearly 30 hours
Debugging some assembly,
Soon you will be glad to
Write in C.
Write in C, write in C,
Write In C, yeah, write in C.
Only wimps use BASIC.
Write in C.
Write in C, write in C,
Write in C, oh, write in C.
Pascal won’t quite cut it.
Write in C.
Guitar Solo
Write in C, write in C,
Write in C, yeah, write in C.
Don’t even mention COBOL.
Write in C.
And when the screen is fuzzy,
And the edior is bugging me.
I’m sick of ones and zeroes.
Write in C.
A thousand people people swear that T.P.
Seven is the one for me.
I hate the word PROCEDURE,
Write in C.
Write in C, write in C,
Write in C, yeah, write in C.
PL1 is 80’s,
Write in C.
Write in C, write in C,
Write in C, yeah, write in C.
The government loves ADA,
Write in C.

A letra tem alguns trechos errados, mas com esse cara cantando afinadamente desse jeito é bem difícil de entender. Se puderem me ajudar a consertar a letra, comentem.

return 0

Abril 23, 2008

Obfuscated C

Arquivado em: C/C++ — Tags:, , — computeiro @ 11:57 pm

A Competição Internacional de Código Ofuscado em C (International Obfuscated C Code Contest, ou IOCCC) é uma comptetição anual que ocorre desde 1984. O vencedor é aquele que produzir o código em C mais criativo, bizarro e difícil de ler, mas que rode. Os programas vencedores geralmente são engraçados, magníficas obras de arte, na maioria das vezes, ótimos exemplos de como não programar em C.

Um exemplo famoso e que já venceu é este, que imprime todos os números primos menores que 100. Vamos conferir os resultados de simples transformações no código do programa:

void primes(int cap) {
  int i, j, composite;
  for(i = 2; i < cap; i++) {
    composite = 0;
    for(j = 2; j < i; j++) 
      composite += !(i % j);
    if(!composite)
      printf("%d\t", i);
  }
}
 
int main() { 
  primes(100);
}

A primeira fase de transformações reduz a função primes: (1) O for é retirado e reescrito como um simples while contendo uma sequência de if-else; (2) O while é então escrito como recursão; (3) Os if-else em cascata são reescritos como um condicional apenas. Estas transformações já tornam o código consideravelmente obfuscated. O restante das transformações tem o objetivo de omitir detalhes da função: (4) remoção de variáveis intermediárias; (5) renomeação de variáveis para _, ___, etc; e, finalmente, (6) remoção de quaisquer espaços em branco e parênteses desnecessários.

Após esta primeira transformação:

void primes(int cap) { 
  int i, j, composite, t = 0;
  while(t < cap * cap) {
    i = t / cap;
    j = t++ % cap;
    if(i <= 1);
    else if(j == 0)
      composite = 0;
    else if(j == i && !composite)
      printf("%d\t",i);
    else if(j > 1 && j < i)
      composite += !(i % j);  
  }
}
 
int main() {
  primes(100);
}


O programa agora é transformado pela substituição do while por uma recursão. Isto requer a adição de dois parâmetros ao cabeçalho da função prime. Veja também que um bloco if-else adicional deve ser adicionado para que haja incremento na recursão quando nenhuma condição for obedecida:

void primes(int cap, int t, int composite) {
  int i,j;
  i = t / cap;
  j = t % cap;
  if(i <= 1)
    primes(cap,t+1,composite);
  else if(j == 0)
    primes(cap,t+1,0);
  else if(j == i && !composite)
    (printf("%d\t",i), primes(cap,t+1,0));
  else if(j > 1 && j < i)
    primes(cap,t+1, composite + !(i % j));
  else if(t < cap * cap)
    primes(cap,t+1,composite);
}
 
int main() {
  primes(100,0,0);
}

Agora os nomes das variáveis são mudados para apenas letras e substituição de if-else pelo operador condicional ternário (ex: if(A) B else if(C) D else E -> A ? B : C ? D : E):

void primes(int m, int t, int c) {
  int i,j;
  i = t / m;
  j = t % m;
  (i <= 1) ? primes(m,t+1,c) : (j == 0) ? primes(m,t+1,0) : (j == i && !c) ? 
  (printf("%d\t",i), primes(m,t+1,0)) : (j > 1 && j < i) ? 
  primes(m,t+1,c + !(i % j)) : (t < m * m) ? primes(m,t+1,c) : 0;
}
 
int main() {
  primes(100,0,0);
}

Agora o programa é transformado substituindo as variáveis i e j por (t / m) e (t % m), respectivamente:

void primes(int m, int t, int c) {
  ((t / m) <= 1) ? primes(m,t+1,c) : !(t % m) ? primes(m,t+1,0) : 
  ((t % m)==(t / m) && !c) ? (printf("%d\t",(t / m)), primes(m,t+1,0)) : 
  ((t % m)> 1 && (t % m) < (t / m)) ? primes(m,t+1,c + !((t / m) % (t % m))) : 
  (t < m * m) ? primes(m,t+1,c) : 0;
}
 
int main() {
  primes(100,0,0); 
}

Agora as variáveis m, t, e c são transformadas para _, __, ___, e ____, respectivamente:

void _(int __, int ___, int ____) {
  ((___ / __) <= 1) ? _(__,___+1,____) : !(___ % __) ? _(__,___+1,0) : 
  ((___ % __)==(___ / __) && !____) ? (printf("%d\t",(___ / __)), 
  _(__,___+1,0)) : ((___ % __) > 1 && (___ % __) < (___ / __)) ? 
  _(__,___+1,____ + !((___ / __) % (___ % __))) : (___ < __ * __) ? 
  _(__,___+1,____) : 0;

 
int main() {
  _(100,0,0); 
}

Finalmente, espaços em branco, declaração de tipos, e parênteses não-ambíguos são removidos para se chegar à fully obfuscated version:

_(__,___,____){___/__<=1?_(__,___+1,____):!(___%__)?_(__,___+1,0):___%__==___/
__&&!____?(printf("%d\t",___/__),_(__,___+1,0)):___%__>1&&___%__<___/__?_(__,1+
___,____+!(___/__%(___%__))):___<__*__?_(__,___+1,____):0;}main(){_(100,0,0);}

Informações (em inglês) sobre o IOCCC podem ser vistas em http://www.ioccc.org/

Exemplo de Obfuscated Hello Word:

#include "stdio.h"
#define e 3
#define g (e/e)
#define h ((g+e)/2)
#define f (e-g-h)
#define j (e*e-g)
#define k (j-h)
#define l(x) tab2[x]/h
#define m(n,a) ((n&(a))==(a))

long tab1[]={ 989L,5L,26L,0L,88319L,123L,0L,9367L };
int tab2[]={ 4,6,10,14,22,26,34,38,46,58,62,74,82,86 };

main(m1,s) char *s; {
    int a,b,c,d,o[k],n=(int)s;
    if(m1==1){ char b[2*j+f-g]; main(l(h+e)+h+e,b); printf(b); }
    else switch(m1-=h){
        case f:
            a=(b=(c=(d=g)<<g)<<g)<<g;
            return(m(n,a|c)|m(n,b)|m(n,a|d)|m(n,c|d));
        case h:
            for(a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
        case g:
            if(n<h)return(g);
            if(n<j){n-=g;c='D';o[f]=h;o[g]=f;}
            else{c='\r'-'\b';n-=j-g;o[f]=o[g]=g;}
            if((b=n)>=e)for(b=g<<g;b<n;++b)o[b]=o[b-h]+o[b-g]+c;
            return(o[b-g]%n+k-h);
        default:
            if(m1-=e) main(m1-g+e+h,s+g); else *(s+g)=f;
            for(*s=a=f;a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
        }
}

Mais exemplos em: http://www.cise.ufl.edu/~manuel/obfuscate/obfuscate.html

return 0

Abril 20, 2008

Debug – Limpar a Tela em C

Arquivado em: C/C++ — Tags:, , , , — computeiro @ 11:37 pm

Pode-se usar também a opção system(). Não tinha publicado antes porque é uma função dependente do sistema.

No GNU/Linux:

# include <stdio.h>

int main(int argc, char** argv)
{
    int n = 0;

     while(n++ < 11)
    {
        printf("%s\n%s\n%s\n%s\n",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!");

           usleep(2000000); //funcao para dar uma pequena pausa

           system("clear"); //isto aqui limpa a tela
    }

     return 0;
}

No Windows:

# include <stdio.h>

int main(int argc, char** argv)
{
    int n = 0;

     while(n++ < 11)
    {
        printf("%s\n%s\n%s\n%s\n",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!");

           usleep(2000000); //funcao para dar uma pequena pausa

           system("cls"); //isto aqui limpa a tela
    }

     return 0;
}

No Mac OS: Não faço a mínima idéia. Por sua herança UNIX, acredito que seja da mesma forma da citada acima (GNU/Linux). Testar é sempre bom. Como não tenho um Mac… Se alguém souber, por favor comente.

return 1

Abril 18, 2008

Limpar a Tela em C

Arquivado em: C/C++ — Tags:, , , , — computeiro @ 12:57 am

Para quem está acostumado com o famoso “clrscr()” de Pascal e não sabe mas tem muita vontade de limpar a tela pra deixar seu programa bonitinho em C, aí vai um exemplo de código que mostra como limpar a tela em C, usando uma funcionalidade especial do printf:

# include <stdio.h>

int main(int argc, char** argv)
{
    int n = 0;

    while(n++ < 11)
    {
        printf("%s\n%s\n%s\n%s\n",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!",
               "Teste Limpa Tela!");

        usleep(2000000); //funcao para dar uma pequena pausa

        printf("\33[2J"); //isto aqui limpa a tela
    }

    return 0;
}

Há várias outras funcionalidades do printf, você pode conferi-las em:

http://br.geocities.com/sdiasneto/c_int/printf.htm

http://br.geocities.com/sdiasneto/c_int/index.htm

Ah, já ia esquecendo. Se você usa windows, pode importar a biblioteca conio ( # include <conio.h> ) e usar tranquilamente o clrscr().

return 0

Blog no WordPress.com.