domingo, 2 de dezembro de 2012

Programando em Java - parte 12

Herança

Na programação orientada a objetos temos o recurso de herança, que nada mais é que abstrair uma classe o mais genericamente possível e escrever outras classes mais especificas aproveitando os comportamentos e atributos da classe genérica. A ideia da herença é aumentar a produtividade na escrita do código e também deixar o código mais limpo, evitando a redundancia de código entre as classes (código repetido).
Como todo conceito da POO não é explicitamente obrigatório o uso de herança em seu código também não, porém, não usá-lo significa quebra conceitual.

Uma classe que faz tudo!

Muitos programadores acham que é beneficio criar uma classe que faça completamente tudo em seu sistema. Não há problema algum em declarar todas as funcionalidades de um sistema dentro de uma classe. No entanto, seu código fica muito mais complexo e a dificuldade de manutenção aumenta muito. Vejamos como poderiamos resolver o mesmo problema primeiramente sem utilizar a herança, depois utilizando a herança de forma errada e por fim aplicando a herança corretamente.

Classe animal.java


Olá meu nome é Juca! 
Preciso de um sistema que cadastre meus bichos de estimação. Sabe senhor programador eu sou um cara muito versátil quando se fala de animais, eu gosto de: cachorros, gatos, lagartos, passáros, tartarugas .. Preciso de um sistema bom, barato e que me entregue o mais rápido possível OK?!

Bom, muitas vezes você vai se deparar com os Jucas da vida, e a pergunta é como os maus programadores fariam esse sistema? Será que eles usariam Herança? Vamos para o exemplo:

public class BichoEstimacao {
// geral
private Animal animal;
private String nome;
private Date aniversario;
// mamiferos
private String corPelo;
private int nroGlandulasMamaria;
// repteis
private float temperaturaCorporal;
private String corEscama;
// métodos
}

Bom apesar de resolver todos os nossos problemas quanto a modelagem do sistema, programar todas as funcionalidades em apenas uma classe pode dificultar o desenvolvimento. Supondo que dois ou mais desenvolvedores são responsáveis pela implementação dos bichos de estimação, provavelmente eles modificariam a mesma classe em paralelo. Além disso, os desenvolvedores ficariam  confusos ao abrirem o código dessa classe.

Uma classe para cada animal

Para modelar melhor os animais, evitando uma quantidade grande de atributos e métodos desnecessários, criaremos uma classe para cada Animal.

public class Gato {
    // geral
    private Animal animal;
    private String nome;
    private Date aniversario;
    // gato
    private String corPelo;
    private int nroGlandulasMamarias;
    private String raca;
}


public class Tiu {
    // geral
    private Animal animal;
    private String nome;
    private Date aniversario;
    // tiu
    private String corEscama;
    private float temperaturaCorpo;
    private boolean chocando;
}

Criar uma classe para cada animal torna o sistema mais flexível, pois qualquer alteração em um determinado serviço não causará efeitos colaterais nos outros. Porém, essas classes apresentam redundância de código e sabemos que a herança veio para abolir isso! E pior, qualquer alteração que seja comum a todos os animais deverá ser implementada classe por classe. Isso quer dizer que ainda estamos errando em alguma coisa.

Uma classe genérica e várias específicas

Na modelagem dos animais do sistema do Juca, podemos aplicar o conceito de Herança. A ideia consiste em reutilizar o código de uma classe em N classes.
Aplicando herança a esse sistema, vamos ter uma classe BichoEstimacao com todos os atributos e métodos comuns à um animal de estimação, e vamos ter uma classe mais específica detalhando as caracteristicas e comportamentos que cada animal possui.
As classes Gato e Tiu seriam "relacionadas" a classe BichoEstimacao para poder reaproveitar o seu código já definido. Veja a representação UML abaixo:


Os objetos das classes específicas Gato e Tiu possuirão tanto os atributos e métodos definidos em suas respectivas classes quanto os definidos na classe BichoEstimacao. Dizemos que BichoEstimacao é a classe pai, e a Gato e Tiu são suas classes filhas. 
Para "associar/ligar" uma classe especifica a uma classe genérica em Java, utilizamos o comando extends. Não é necessário redefinir o conteúdo já declarado na classe genérica.

public class BichoEstimacao {
    // geral 
    private Animal animal;
    private String nome;
    private Date aniversario;
}

public class Gato extends BichoEstimacao {
    // gato
    private corPelo;
    private nroGlandulasMamarias;
    private raca;
}

public class Tiu extends BichoEstimacao {
    // tiu
    private String corEscama;
    private float temperaturaCorpo;
    private boolean chocando;
}

As classes filhas podem acessar todos os métodos e atributos de seu pai. Java não dá suporte a herança multipla, ou seja, para a Java um Pai pode ter vários filhos já os filhos são de um único pai. Esse pensamento traduzido para vida real é muito lógico já que um filho tem um único pai biológico e esse pai pode ter vários filhos.

Gato mimo = new Gato();
//chamada a um método da classe BichoEstimacao
mimo.setNome = "Mimo";
//chamada a um método da classe Gato
mimo.setRaca = "Angora";

Calcular idade

Todos os animais possuim uma idade certo? Vamos considerar inicialmente que para todos animais o calculo de idade é o mesmo. Sendo assim poderiamos implementar um método na classe BichoEstimacao para calcular a idade dos animais. Este método será reaproveitado por todas as classes que herdam da classe BichoEstimacao.

public class BichoEstimacao {
// atributos public int calculaIdade(int anoNascimento, int anoAtual) { return anoAtual - anoNascimento; }  }

BichoEstimacao bicho = new BichoEstimacao();
Gato megui = new Gato();
System.out.println("Idade: ", + bicho.calculaIdade(2010,2012));
System.out.println("Idade: ", + megui.calculaIdade(2012,2012));

Reescrita de método

Como sabemos cada animal representa uma idade diferente ao calculo da idade humana, alguns animais possuem um envelhicimento mais tardio e outros mais recentes. Como essa lógica é específica de cada animal devemos implementar esse calculo na classe BichoEstimacao.

class Gato extends BichoEstimacao {
// atributos
public int calcIdadeGato(int anoNascimento, int anoAtual) {
return (anoAtual - anoNascimento) * 7 ;
}

Para os objetos da classe Gato devemos chamar o método calcIdadeGato. Para todos os outros animais devemos chamar o método calculaIdade.

Mesmo assim isso não impederia que o método calculaIdade fosse chamado de um objeto da classe Gato, pois este método é herdado da sua classe Pai BichoEstimacao. Deste modo existe o risco de acidentamente invocarmos o método errado.

O correto é substituir a implementação do método calculaIdade(int anoNascimento, int anoAtual) herdado da classe BichoEstimacao na classe Gato. Para isso, basta escrever o método calculaIdade(int anoNascimento, int anoAtual) também na classe Gato do mesmo jeito que ela foi definida na classe Pai (BichoEstimacao), ou seja, com a mesma assinatura.

class Gato extends BichoEstimacao {
// atributos
public int calculaIdade(int anoNascimento, int anoAtual) {
return (anoAtual - anoNascimento) * 7 ;
}

Os métodos das classes filhas tem prioridade sobre os métodos da classe pai. Se o método chamado existe na classe filha ele será chamado, caso contrário se ele não exister será procurado sua existencia na classe Pai.

sexta-feira, 16 de novembro de 2012

Exercício de C - Estrutura de dados - Lista 5

#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
/*
 *    Área de definição das estruturas
 **/
struct aluno
{
    int matricula;
    char nome[80];
    char endereco[120];
    char telefone[20];
};

// Criando o tipo Aluno que representa a estrutura aluno
typedef struct aluno Aluno;

/*
 *    Área dos protótipos da função
 **/
int show_menu ();
void initializer (Aluno*);
void select_action (int, int*, Aluno*);
void insert_register (int*, Aluno*);
void remove_register (int, Aluno*, int*);
void change_register (int, Aluno*, int*);
void sort_registers (Aluno*, int*);
void show_registers (Aluno*, int*);
void show_register (int, Aluno*, int*);

/*
 * Método principal, start do programa.
 **/
int
main (void)
{
    Aluno alunos[MAX];
    int index = 0; // Essa variável é responsável por controlar os índices do vetor que mantem os alunos

    initializer (alunos);

    while (1)
        select_action (show_menu(), &index, alunos);

    sort_registers (alunos, &index);
    show_registers (alunos, &index);

    return 0;
}

/*
 * Exibe o menu de funcionalidades
 **/
int
show_menu (void)
{
    int option;

    printf ("\n1 -\tInserir novo aluno");
    printf ("\n2 -\tApagar registro de aluno");
    printf ("\n3 -\tModfificar registro");
    printf ("\n4 -\tListar registros");
    printf ("\n5 -\tBuscar registro por matricula");
    printf ("\n0 -\tExit \n.: ");
    scanf("%d", &option);

    return option;
}

/*
 * Inicializa todas as matriculas com o número 9999
 **/
void
initializer (Aluno *a)
{
    int i;
    for (i = 0; i < MAX; i++)
        a[i].matricula = 9999;
}

/*
 * Esse método dita o comportamento do programa. É ele quem chama as funções que são exibidas pelo programa no menu.
 * Ele é a chave central, todas as chamadas principais, passam por ele.
 **/
void
select_action (int option, int *index, Aluno *a)
{
    int number; /* Variável number armazena o número de matricula do aluno que o usuário deseja excluir/alterar/buscar */

    int dialog_option; /* Variável dialog_option tem a função de armazenar a escolha do usuário quando o mesmo entra na tela de encerramento do programa, caso o valor armazenado pela variável seja 1 o encerramento do programa deve ser feito, caso seja 0 o encerramento do programa é abortado */

    int list_option = 0; /* Variável list_option tem a função de selecionar qual a ordem da exibição, caso seja 0 (default) os registros serão dispostos em ordem crescente. Caso contrário os registros serão dispostos em ordem decrescente */

    switch (option)
    {
        case 1:
            insert_register (index, a);
        break;
        case 2:
            printf ("\nInforme o número de matricula do aluno que deseja excluir.: ");
            scanf ("%d", &number);
            remove_register (number, a, index);
        break;
        case 3:
            printf ("\nInforme o número de matricula do aluno que deseja alterar.: ");
            scanf ("%d", &number);
            change_register (number, a, index);
        break;
        case 4:
            show_registers (a, index);
        break;
        case 5:
            printf ("\nInforme o número do registro que deseja buscar.: ");
            scanf ("%d", &number);
            show_register (number, a, index);
        break;
        case 0:
            system ("clear");
            printf ("\nDeseja encerrar o programa? \n[1]Sim \n[0]Não \n");
            scanf ("%d", &dialog_option);
            if (dialog_option == 1)
                exit (0);
        break;
    }
}

/*
 * Esse método é responsável pela inserção de registros existentes na persistencia.
 **/
void
insert_register (int *index, Aluno *a)
{
    int avaliable = 1;
    /* Essa variavel irá responder se o nro de matricula solicitado para novo registro já se encontra cadastrado na persistência de dados.
        Caso o valor de avaliable seja igual a 0 corresponde que o número solicitado já se encontra na persistência de dados, caso seja 1 corresponde que o número está disponível para identificar um novo registro.
     */
    int number; /* variável armazana o número da matricula do aluno depois que ela foi validada */
    do
    {
        int i;

        system("clear");
        printf ("\nInforme o número de matricula.: ");
        scanf ("%d", &number);

        for (i = 0; i < MAX; i++)
        {
            if (number < 0 || number == 9999)
            {
                printf ("\nEsse número não é válido!");
                avaliable = 0;
                break;
            }
            else if (number == a[i].matricula)
            {
                printf("\nEsse número já está cadastrado, informe um número válido!");
                avaliable = 0;
                break;
            }
            else
                avaliable = 1;
        }
    }
    while (avaliable == 0);

    a[*index].matricula = number;
    __fpurge (stdin);
    printf ("\nInforme o nome.: ");
    gets (a[*index].nome);
    __fpurge (stdin);
    printf ("\nInforme o endereço: ");
    gets (a[*index].endereco);
    __fpurge (stdin);
    printf ("\nInforme o telefone: ");
    gets (a[*index].telefone);

    // Incrementando a variável responsável pelo controle do vetor dos alunos
    *index = *index + 1;

    // Reordenando os registros que se encontram na persistencia, já que um novo aluno foi inserido
    sort_registers (a, index);

    printf ("\n\n \t\t -- Registro inserido com sucesso! -- \n");
}

/*
 * Esse método é responsável pela exclusão de registros existentes na persistencia.
 **/
void
remove_register (int number, Aluno *a, int *index)
{
    system ("clear");

    int i;
    int status = 0; /* Variável armazena se foi possível realizar a exclusão, se 0 não se 1 sim */

    for (i=0; i < *index; i++)
    {
        if (a[i].matricula == number)
        {

            /* Exibindo o registro de aluno que foi encontrado, e perguntando ao usuário se realmente deseja efetuar a exclusão */
            int dialog_option = 0; // Se o valor for 0 o registro não será removido, se o valor for igual a 1 o registro será removido

            show_register (number, a, index);

            printf ("\n Deseja realmente excluir o registro? [1] Sim [0] Não.: ");
            scanf ("%d", &dialog_option);

            // Sinalizando que foi encontrado registro com codigo de matricula equivalente
            status = 1;

            if (dialog_option == 1)
            {
                a[i].matricula = 9999;
                strcpy (a[i].nome, "");
                strcpy (a[i].endereco, "");
                strcpy (a[i].telefone, "");

                // Decrementando a variável responsável pelo controle do vetor dos alunos
                *index = *index - 1;

                // Reordenando os registros que se encontram na persistencia, já que um registro de aluno fio removido
                sort_registers (a, index);

                system ("clear");

                printf ("\n\t\t --Registro removido com sucesso!--\n");
                break;
            }
        }
    }
    if (status == 0)
        printf ("\n\t\t -- Nenhum registro foi encontrado!--\n");
}

/*
 * Esse método é responsável pela alteração de registros existentes na persistencia.
 **/
void
change_register (int number, Aluno *a, int *index)
{
    system ("clear");

    int i;
    int status = 0; /* Variável armazena se foi possível realizar a alteração, se 0 não se 1 sim */
    Aluno aux;

    for (i=0; i < *index; i++)
    {
        if (a[i].matricula == number)
        {
            __fpurge (stdin);
            printf ("\nNovo nome.: ");
            gets (aux.nome);
            printf ("\nNovo endereço.: ");
            gets (aux.endereco);
            printf ("\nNovo telefone.: ");
            gets (aux.telefone);

            strcpy (a[i].nome, aux.nome);
            strcpy (a[i].endereco, aux.endereco);
            strcpy (a[i].telefone, aux.telefone);

            // Modificando o valor de status, sinalizando que o registro foi localizado e removido com sucesso!
            status = 1;

            printf ("\n\t\t --Registro alterado com sucesso!--\n");
            break;
        }
    }
    if (status == 0)
        printf ("\n\t\t -- Nenhum registro foi encontrado!--\n");
}

/*
 * Esse método reorganiza a persistencia de dados (vetores) toda vez que o mesmo tem uma alteração, seja uma adição ou subtração de registros.
 **/
void
sort_registers (Aluno *a, int *index)
{
    int i, j;
    Aluno aux;

    for (i = 0; i < *index; i++)
    {
        for (j = 0; j < *index; j++)
        {
            if (a[i].matricula < a[j].matricula)
            {
                aux.matricula = a[i].matricula;
                strcpy (aux.nome, a[i].nome);
                strcpy (aux.endereco, a[i].endereco);
                strcpy (aux.telefone, a[i].telefone);

                a[i].matricula = a[j].matricula;
                strcpy (a[i].nome, a[j].nome);
                strcpy (a[i].endereco, a[j].endereco);
                strcpy (a[i].telefone, a[j].telefone);

                a[j].matricula = aux.matricula;
                strcpy (a[j].nome, aux.nome);
                strcpy (a[j].endereco, aux.endereco);
                strcpy (a[j].telefone, aux.telefone);
            }
        }
    }
}

/*
 * Esse método exibe todos os registros cadastrados na persistencia (vetores)
 **/
void
show_registers (Aluno *a, int *index)
{
    system ("clear");

    int i = 0;

    for (i = 0; i < *index; i++)
    {
        if (a[i].matricula != 9999)
        {
            printf ("\n \t\t -- Registro número %d --", a[i].matricula);
            printf ("\n Nome.: %s", a[i].nome);
            printf ("\n Endereço.: %s", a[i].endereco);
            printf ("\n Telefone.: %s", a[i].telefone);
            puts("");
        }
    }

    if (*index == 0)
        printf ("\n\t\t -- Nenhum registro cadastrado -- \n");
}

/*
 * O método show_register tem um funcionamento parecido com o método show_registers.
 * A diferença é que esse método busca um único registro e caso encontre o exibe.
 **/
void
show_register (int number, Aluno *a, int *index)
{
    system ("clear");

    int i;
    int status = 0;

    for (i = 0; i < *index; i++)
    {
        if (a[i].matricula == number)
        {
            status = 1;
            break;
        }
    }

    if (status == 1)
    {
        printf ("\n \t\t -- Registro número %d", a[i].matricula);
        printf ("\n Nome.: %s", a[i].nome);
        printf ("\n Endereço.: %s", a[i].endereco);
        printf ("\n Telefone.: %s", a[i].telefone);
        puts("");
    }
    else
        printf ("\n\t\t -- Nenhum registro foi encontrado!--\n");
}

sexta-feira, 19 de outubro de 2012

Resolução do exercício do curso de Python - Urna

Exercício

Desenvolva uma urna eletrônica utilizando a linguagem de programação Python. O programa deve possuir tupla, dicionário de dados, comandos condicionais e de iteração. O sistema deve computar os votos de todos os candidatos assim como os votos em branco e nulos.
Ao final programa deve informar qual candidato venceu as eleições e mostrar um gráfico semelhante a esse:

Candidato x: ||||||||||||||||||||||||||
Candidato y: |||||||||||||||||||||||||||||||||||||||
Candidato c: |||||||||||||||||||
Candidato b: ||||||||||||||||||||||||||||||||||
Candidato a: ||||

O numero de barras  na frente dos nomes são definidas peçla quantidade de votos que o candidato obteve. Considere que a cidade tenha 200 eleitores.


# -*- coding: utf-8 -*-

t = ('Marcelo ', 'Marcia  ', 'Vermelho', 'Valter  ', 'Branco  ', 'Nulo    ')
d = {t[0]: 0, t[1]: 0, t[2]: 0, t[3]: 0, t[4]: 0, t[5]: 0}

print """
        \nMarcelo    15
        \nMarcia     13
        \nValter     55
        \nVermelho   21
        \nBranco     00
        \nNulo       99
        \n
"""
for i in range(50):
    voto = int(raw_input('Informe o número do seu candidato: '))
   
    if voto == 15:  d[t[0]] += 1
    elif voto == 13: d[t[1]] += 1
    elif voto == 21: d[t[2]] += 1
    elif voto == 55: d[t[3]] += 1
    elif voto == 0: d[t[4]] += 1
    else: d[t[5]] += 1

maior = -1
prefeito = ''

for candidato in d.keys():
    grafico = ''
    for i in range(d[candidato]):
        grafico += '|'
       
    if d[candidato] > maior:
        maior = d[candidato]
        prefeito = candidato
   
    print candidato, ':', grafico
   
print 'O candidato ', prefeito, ' é o novo prefeito de Araraquara!'

sábado, 29 de setembro de 2012

2ª lista de recursividade

Exercício 1:
#include <stdio.h>

float calc_tarifa(int, int, int, int, int *);

int main(void)
{
    int h1,h2,m1,m2, tempo;

    printf("\nInforme a hr de entrada: ");
    scanf("%d", &h1);
    printf("\nInforme a min de entrada: ");
    scanf("%d", &m1);
    printf("\nInforme a hr de saída: ");
    scanf("%d", &h2);
    printf("\nInforme a min de saída: ");
    scanf("%d", &m2);

    printf("Valor a ser pago = R$ %2.2f", calc_tarifa(h1, m1, h2, m2, &tempo));
    return 0;
}

float calc_tarifa(int h1, int m1, int h2, int m2, int *tempo)
{
    int i;
    float total;

    if(m1 > 0) h1++;//se minutos forem maior que 0, serão arredondados
    if(m2 > 0) h2++;

    *tempo = h2-h1;

    for(i=1; i<=*tempo; i++)
    {
        switch(i)
        {
            case 1:
                total = 8.00;
                break;
            case 2:
                total += 6.00;
                break;
            case 3:
                total += 3.5;
                break;
            case 4:
                total += 3.0;
                break;
            case 5:
                total += 3.0;
                break;
            default:
                total += 2.0;
                break;
        }
    }
    printf("\nVocê permaneceu %d hrs no estacionamento! \n", *tempo);
    return total;
}

Exercício 2: #include <stdio.h>//biblioteca para entrada/saída
#include <string.h>//biblioteca para manipulação de cadeia de caracteres
#include <stdlib.h>//biblioteca para funções acessar algumas funções do sistema, neste seu uso é para alocação dinâmica de memória
#define MAX 100//constante define o tamanho máximo de caracteres que podem ser inseridos no vetor

char * mesclar(char *, char *);

int main(void)
{

    char original[MAX];//vetor original, ele quem armazena a palavra completa fornecida pelo usuário
    int i, v1=0, v2=0;//variaveis de controle
    char * pCp1, * pCp2;//ponteiros para a posição de memória dos vetores cp1, cp2[]
    pCp1=malloc(MAX*sizeof(char));//alocando MAX memória para garantir que todas as letras serão armazenadas com sucesso
    pCp2=malloc(MAX*sizeof(char));//alocando MAX memória para garantir que todas as letras serão armazenadas com sucesso
    if(!pCp1 || !pCp2) printf("\n** ERRO : MEMÓRIA INSUFFICIENTE **");//verifica se não houve erro ao alocar a memória por falta de espaço

    //exibindo msg na tela e capurando a entrada do usuário
    printf("\nEntre com a palavra : ");
    gets(original);//função própia para ler cadeia de caracters... gets armazena inclusive espaços em branco

    /*
        comando irá percorrer até o tamanho da palavra digitada (strlen), afim de dividir o vetor em outros
        dois vetores. O vetor pCp1 armazena todas as letras que se encontram em indices pares. Já o vetor
        pCp2 armazena todas as letras que se encontram em indices ímpares.
    */
    for(i=0; i<strlen(original); i++)
    {
        if(i%2==0)
        {
            pCp1[v1] = original[i];
            v1++;
        }
        else
        {
            pCp2[v2] = original[i];
            v2++;
        }
    }
    pCp1 = realloc(pCp1,v1*sizeof(char));//realocando a memória a fim de economizá-la
    pCp2 = realloc(pCp2,v2*sizeof(char));//realocando a memória a fim de economizá-la

    printf("%s", mesclar(pCp1, pCp2));//chamada da função para refazer as palavras

    return 0;
}

char * mesclar(char * cp1, char * cp2)
{
    int i, size, v1=0, v2=0;/* A variavel i, v1, v2 são controladoras... já a variavel size é responsável por indicar a soma
        entre os tamanhos das cadeias de caracteres passadas por parametro.
    */
    char * final;//Essa será a cadeia de caracteres final, ou seja, a mesma cadeia que foi digitada no inicia do programa
    size = strlen(cp1)+strlen(cp2);//somando os tamanhos das cadeias distintas
    final=malloc(size*sizeof(char));//alocando o espaço de memoria de acordo com o tamanho que a palavra possui
    if(!final)
    {
        printf("\n** ERRO : MEMÓRIA INSUFFICIENTE **");//verifica se não houve erro ao alocar a memória por falta de espaço
        return NULL;
    }
    else
    {
        for(i=0; i<size; i++)
        {
            if(i%2==0)
            {
                final[i] = cp1[v1];
                v1++;
            }
            else
            {
                final[i] = cp2[v2];
                v2++;
            }
        }
        return final;
    }
}

quinta-feira, 27 de setembro de 2012

Recursividade - entendendo o conceito recursivo

Olá pessoal, hoje vamos entender e aprender a montar funções recursivas, como estou trabalhando em um novo projeto de python onde vou montar um curso do básico ao avançado, todos os exemplos de hoje serão escritos na linguagem python.

O que é recursividade?

Recursividade pode ser definida como a capacidade que uma função ou subrotina tem de invocar a si mesma, ou seja, definimos uma função como recursiva se esta faz uma chamada a si mesmo. 

Recursividade x Iteração

Quando falamos de recursividade algumas duvidas surgem, como: "Porque não usar iteração ao invés de recursividade?"... bom é um estilo de programação e algumas vezes determinadas soluções não serão possíveis de ser realizadas apenas com iterações (loops). Abaixo os prós e contras da recursividade:

Prós:
  • Código elegante;
  • Código mais legivel;
Contras:
  • Necessidade de mais memória;
  • Consome mais processamento; 
Algumas perguntas que você deve estar se fazendo:
  • Recursividade só pode ser usanda com linguagem C/C++?
 Não, o conceito é independente da linguagem escolhida. Recursividade pode ser utilizada em qualquer linguagem estruturada ou OO. 
  •  Porque quando falamos de recursividade o pessoal só mostra exemplos aplicados em funções que calculam fatorial de um número ou série fibonnacci?
Porque é o jeito mais claro de se apresentar o conceito recursivo. Mais acalme-se pequeno gafanhoto eu vou dar um exemplo mais tranquilo e aplicado ao seu cotidiano.

Vamos aos ... Exemplos!

Vamos exemplificar o conceito programando alguns problemas utilizando-se da recursividade para solucioná-los. 
Abaixo temos o famoso exemplo fatorial utilizando recursividade:

def fatorial (valor):
    if valor == 1 or valor == 0:
        return 1
    else:
        return valor * fatorial(valor-1)

#vamos pedir um valor para o usuario
a = input('Informe um numero: ')
#chamando a funcao e imprimindo o valor que ela retorna
print fatorial(a)



Uma função só é liberada da memória quando ela chega ao seu final. No caso da função fatorial() enquanto o parâmetro valor não for igual a 1, ela não vai ser encerrada (não vai chegar ao seu final) com isso ela persiste com uma referencia ativa na memória e se reexecuta. Com isso uma pilha de valores vai sendo criada na memória e enquanto a função não terminar esse processor vai ser repetido até que haja um estouro de memória ou que a função seja encerrada.



Vamos fazer um exemplo mais tranquilo agora pequeno gafanhoto, vamos fazer um programa que irá imprimir a soma de todos os numeros presentes no intervalo de 1  até X:

# -*- coding: UTF-8 -*-
def soma (n):
    if n == 1:
        return 1
    else:
        return n + soma( n - 1)
      
n = input("Informe um número: ")
print soma(n)


Importante: Deve-se definir uma solução que implica em uma condição de terminação (solução trivial). Outro fator importante é provar que a função decresce a cada passo de repetição.

Dúvidas, sujestões comentem...

domingo, 23 de setembro de 2012

Programando em Java - parte 11

Encapsulamento

Encapsulamento é uma técnica usada no paradigma Orientado a Objetos afim de centralizar e facilitar a busca de eventuais erros contidos no código. 

Exemplo:

public class Gato {     String raca; }
No exemplo acima, o atributo raça pode ser acessado e modificado em qualquer classe que esteja no projeto em que a classe Gato foi criada. Quando isso ocorre dizemos que o controle é descentralizado.
Para identificarmos e corrigirmos possíveis erros relacionados a raça do gato teremos que analisar todo o projeto já que a raça é visível ao projeto todo.
Vamos nos deparar muito com essa palavra "visibilidade", isso quer dizer "quem tem permissão para realizar a manipulação daquele atributo".
Para resolvermos este problema e criarmos o chamado controle centralizado devemos tornar o atributo raca privado e implementar métodos publicos que implementem toda a lógica de manipulação necessária desse atributo.
Os atributos devem ser privados porque todo atributo privado só pode ser acessado ou alterado pela classe que ele está contido, ou seja, o atributo raca só pode ser alterado por código que esteja contido na classe Gato. E o contrário nunca poderá ser feito, se alguma outra classe que não seja a Gato tentar acessar o atributo raca, um erro de compilação será gerado.
Os métodos devem ser publicos para que as demais classes consigam acessá-los. Definir todos os atributos como privado e métodos publicos que implementem a lógica de manipulação dos atributos, é praticamente uma regra em Orientação a Objetos. Isso é feito para que o controle seja centralizado, facilitando a manutenção e detecção de erros.

Gato.java public class Gato {
    private raca;
   
    public void mudarRaca(String raca) {
        this.raca = raca;
    }
}

 

Métodos Privados

Nem sempre os métodos deveram ser visíveis a todas as classes do seu projeto, às vezes o método tem papel de auxiliar outros métodos que estejam na mesma classe. Nesse caso seria um erro chamar este método fora da classe em que ele foi escrito.
No exemplo abaixo o método atribuiIp() é um método auxiliar de entrarRede(), sairRede(). Sendo assim ele não deve ser chamado diretamente, pois a atribuição de ip só deve ocorrer quando ele entrar na rede.

Rede.java
public class Rede {
    void connectar() {
        //lógica para criar conexão
    }
   
    void desconectar() {
        //lógica para desconectar da rede
    }
   
    String atribuirIp() {
        //lógica para retornar um número IP válido na rede
    }
}

Para garantir que não será possível a chamada do método atribuirIP() fora da classe Rede, devemos adicionar o modificador private. 

public class Rede {
    void connectar() {
        //lógica para criar conexão
    }
   
    void desconectar() {
        //lógica para desconectar da rede
    }
   
    private String atribuirIp() {
        //lógica para retornar um número IP válido na rede
    }
}

Agora qualquer chamada ao método atribuirIP() que não seja feita pela classe Rede, acarretará um erro de compilação garantindo assim que nosso método só será chamado dentro da classe Rede.

Métodos Públicos

Todos os métodos que devem ser acessados fora da classe de origem devem conter o modificador de acesso public. O public diz ao compilador que o método pode ser acessado por qualquer objeto que esteja no projeto em que o método chamado se encontra.

public class Rede {
    public void connectar() {
        //lógica para criar conexão
    }
   
    public void desconectar() {
        //lógica para desconectar da rede
    }
   
    private String atribuirIp() {
        //lógica para retornar um número IP válido na rede
    }
}

Porque encapsular?

Encapsular é uma das principais funcionalidades da programação orientada a objetos. Encapsular seria esconder o código de implementação e apenas mostrar a interface de uso do método.
O encapsulamento de dados nos ajuda na manutenção e no desenvolvimento do sistema, uma vez que com ele as tarefas ficam melhores divididas entre as classes e quando devemos modificar o comportamento dos objetos basta alterar a classe do objeto.
Para que você entenda melhor vamos fazer uma simples analogia ao mundo real utilizando o conceito de POO.

Imagine o controle remoto de sua televisão, a interface de uso seria os botões de: aumentar volume, abaixar volume, trocar de canal .. etc. Quando você usa o controle podemos dizer que você está usando a interface, porém, você não sabe como o serviço é feito. Você simplesmente aperta o botão e algo acontece, pois a implementação do serviço não é interessante, não é necessária conhecermos apenas queremos executar o serviço. Trazendo para a programação agora, o botão seria a assinatura do método = public void aumentarVolume(), e o serviço é o corpo do método, ou seja, o código que está escrito dentro dele. O código não deve ser visível ao objetos que vão acessar o método mais a assinatura do método deve ser visível aos demais objetos. Entendeu?

Getters e Setters

Aplicando a ideia do encapsulamento os atributos deveriam ser todos privados, com isso não seriam acessiveis por código que estivesse fora da classe em que foram definidos.
Mas na maioria dos sistemas as informações contidas nos atributos precisam ser acessadas e modificadas em qualquer parte do sistema. Nesse caso, podemos disponibilizar métodos para consulta e alteração de valores dos atributos.
Na linguagem Java, há uma convenção de nomenclatura para os métodos que tem como finalidade acessar ou alterar as propriedades de um objeto. Os métodos que tem como finalidade consultar as propiedades do objeto devem possuir o prefixo get, já os métodos que permitem a alteração das propriedades do objeto devem possuir o prefixo set.
Lembre-se bons programadores Java seguem a convenção.

public class Aluno {
    private String nome;

    public String getNome() {
        return nome;
    }
   
    public void setNome(String nome) {
        this.nome = nome;
    }
}

É isso ai pessoal! Dúvidas, sugestões, comentem ai...

sábado, 22 de setembro de 2012

Programando em Java - parte 10

Atributos e Métodos de Classe

Em um sistema muitas vezes é necessário que uma váriavel seja compartilhada por todos os objetos que venham a ser criados. Em Java temos os atributos e métodos de classe. Para criarmos métodos e atributos de classe utilizamos a palavra reservada staticUm atributo de classe por definição é publico então é redundante colocar o modificador de acesso public, já que por definição static é public também.
Vejamos um problema em que poderiamos aplicar uma solução utilizando atributo de classe:

Problema:
Imagine que uma montadora de veículos precise armazenar o número de carros fabricados por dia. A cada novo carro criado o sistema deve contabilizar o carro para que no final do dia possa exibir a quantidade de veículos criados.

Solução:

Montadora.java
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.swing.JOptionPane;

public class Montadora {
    public static void main(String[] args) {
        Carro.numCarros = 0;//inicializando o valor da variável
       
        for(int i=0; i<10;i++)
            new Carro();
           
        JOptionPane.showMessageDialog(null, "Foram fabricados " + Carro.numCarros + " carros.");
        JOptionPane.showMessageDialog(null, "Data: " + new SimpleDateFormat("dd/MM/yyyy").format(new Date()));
    }
}

Carro.java
public class Carro {
    static int numCarros;
   
    public Carro() {
        numCarros++;
    }
}

Para acessar variáveis de classe utilizamso o nome da classe, em seguida o operador ponto final (.) e o nome da variável que queremos acessar.

O correto para manipular atributos de classe é criarmos métodos de classe com a finalidade de controlar os valores contidos nesses atributos. Como a variável é publica e visível por todas as classes do nosso projeto não é explicitamente obrigatória a criação dos métodos de classe para fazer o controle dos mesmos, porém, fazer o manusei dos atributos de classe sem o uso de métodos é uma má prática de programação e consiste em um erro conceitual.

Problema 2:
Os funcionários da empresa GTi sistemas recebem vale refeição, todos os meses o valor do vale pode ser reajustado.

Solução:

Funcionario.java public class Funcionario {
    private String nome;
    static float valeRefeicao;
   
    public Funcionario(String nome) {
        this.nome = nome;
    }
   
    static void reajusteValeRefeicao(float valor) {
        valeRefeicao = valor;
    }
}

EmpresaGTi.java public class EmpresaGTi {
    public static void main(String[] args) {
        Funcionario programador = new Funcionario("Guilherme");
        Funcionario rh = new Funcionario("Débora");
        Funcionario analista = new Funcionario("Luiz");
       
        Funcionario.reajusteValeRefeicao(20);//todas as instancias de funcionário compartilham da mesma variável valeRefeicao
       
        //ERRO...
        programador.valeRefeicao = 20;//é possivel, porém, é erro conceitual
    }
}

Dúvidas , sugestões comentem...

Programando em Java - parte 9

Arrays

Quando desejamos armazenar uma grande quantidade de valores de um determinado tipo, podemos utilizar arrays. Um array é um objeto que pode armazenar muitos valores de um determinado tipo.
Podemos imaginar um array como sendo um armário com um determinado número de gavetas. E cada gaveta possui um rótulo com um número de identificação.

Criando um Array

Em Java, os arrays são criados através do comando new.

int numeros = new int[100];

Podemos ter arrays de vários tipos. Assim como podemos instanciar de várias maneiras o array, acima mostrei uma das formas de se criar um array, veja como podemos declarar um array de formas diferentes em Java:

int numeros[]; //aqui declaro meu array, porém, não instancie. Se eu tentar usá-lo irá acontecer um erro

int numeros[] = new int[] {1,23,54,19};/*Esse tipo de declaração instancia meu array e já adiciona os valores que são passados entre as chaves. Esse tipo de declaração é usado quando o programador já sabe quais valores devem sem iniciados junto com o array*/

Utilizando as Classes Arrays e Collections

Uma das vantagens de se usar a linguagem Java é que já existem muitas coisas prontas, basta o programador pesquisar a API e conhece-lá conforme suas necessidades. Quando trabalhamos com arrays podemos contar com as Classes Arrays e Collections do pacote java.util. Essas classes possuem os seguintes métodos já definidos:
  • Método de pesquisa de elemento;
  • Método de ordenação;
  • Método de exibição de todos elementos;
  • Método de inversão de ordem dos elementos contidos no array;
Exemplo:
import java.util.Arrays;
import java.util.Collections;
import javax.swing.JOptionPane;

public class ArraysExemplo {
    public static void main(String[] args) {
        String profInf[] = new String[] {"Renata", "Luiz", "Edilson", "Ednilson", "Janaina", "Gislaine", "Fábio", "Eduardo", "Francisco", "José Arnaldo"};
       
        //método bynarySearch retorna um int que condiz com a posição do elemento buscado no array
        //método sort organiza o array em de forma crescente
        //método toString imprime o array converte o array em String e exibe o completo na tela
        //método reverse inverte a ordem do array
       
        JOptionPane.showMessageDialog(null,"Posição: " + Arrays.binarySearch(profInf, "Janaina"));
       
        Arrays.sort(profInf);
        JOptionPane.showMessageDialog(null, "Array de forma organizada crescente : " + Arrays.toString(profInf));
       
        Collections.reverse(Arrays.asList(profInf));
        JOptionPane.showMessageDialog(null, "Array de forma organizada invertida : " + Arrays.toString(profInf));
    }
}

PS = Todo bom programador deve conhecer os recursos que sua linguagem já oferece pronta, para que ele não fique "reinventando a roda". A API do completa e atualizado Java pode ser encontrada no site da Oracle.

Comparando a utilização de array em um programa Java

Abaixo temos 3 versões de um mesmo programa Java. A função desse programa é ler três valores informados pelo usuário referentes a peso. Ao termino da entrada de dados o programa deve exibir qual  o maior, menor e a lista de todos os pesos lidos.

Programadores que não sabem utilizar array, ou acha que é perda de tempo escreve códigos Java assim:

import javax.swing.JOptionPane;

public class ArraysExemplo1 {
    public static void main(String[] args) {
        float peso, x, y;
        /*
        * a variável peso irá armazenar o peso fornecedo pelo usuário durante a execução do programa
        * a variável x irá armazenar a pessoa mais pesada
        * a variável y irá armazenar a pessoa mais leve
        */
       
        //inicializando x e y com valores impossíveis... Lembrando que essa é uma técnica não aconselhável
        x = -1000;
        y = 10000;
       
        for(int i=0; i<3; i++) {
        //diferentemente de C, o comando for em Java pode conter a declaração e inicialização de variáveis em sua primeira parte
            peso = Float.parseFloat(JOptionPane.showInputDialog("Informe o peso"));
           
            if(peso > x)
                x = peso;
           
            if(peso < y)
                y = peso;
        }
       
        JOptionPane.showMessageDialog(null, "Mais pesado = " + x + "kg");
        JOptionPane.showMessageDialog(null, "Mais leve = " + y + "kg");
        //não tem como mostrar todos os pesos lidos   :(
    }
}


Programadores que sabem utilizar array, porém, não conhecem os recursos que a API os oferecem. Irá desenvolver um código Java semelhante a este:

import javax.swing.JOptionPane;

public class ArraysExemplo2 {
    public static void main(String[] args) {
        float peso[] = new float[3];
        float x, y;
        /*
        * a variável peso irá armazenar o peso fornecedo pelo usuário durante a execução do programa
        * a variável x irá armazenar a pessoa mais pesada
        * a variável y irá armazenar a pessoa mais leve
        */
        for(int i=0; i<3; i++) {
            peso[i] = Float.parseFloat(JOptionPane.showInputDialog("Informe o peso"));
        }
       
        //inicializando os valores de x e y, com o primeiro valor lido
        x = peso[0];
        y =  x;
       
        for(int i=1; i<3; i++) {
        //diferentemente de C, o comando for em Java pode conter a declaração e inicialização de variáveis em sua primeira parte
       
            if(peso[i] > x)
                x = peso[i];
               
            if(peso[i] < y)
            y = peso[i];
        }
       
        JOptionPane.showMessageDialog(null, "Mais pesado = " + x + "kg");
        JOptionPane.showMessageDialog(null, "Mais leve = " + y + "kg");
        JOptionPane.showMessageDialog(null, "Todos os pesos lidos = " + peso[0] + ", " + peso[1] + ", " + peso[2]);
    }
}


Bons programadores, escrevem códigos assim:

import javax.swing.JOptionPane;
import java.util.Arrays;

public class ArraysExemplo3 {
    public static void main(String[] args) {
        float peso[] = new float[3];

        for(int i=0; i<3; i++) {
            try {
                peso[i] = Float.parseFloat(JOptionPane.showInputDialog("Informe o peso"));
            } catch(NumberFormatException e) {
                JOptionPane.showMessageDialog(null, "Erro ao coverter o valor digitado!", "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
       
        Arrays.sort(peso);//ordena os valores digitados
       
        JOptionPane.showMessageDialog(null, "Mais pesado = " + peso[2] + "kg");
        JOptionPane.showMessageDialog(null, "Mais leve = " + peso[0] + "kg");
        JOptionPane.showMessageDialog(null, "Todos os pesos informados = " + Arrays.toString(peso));
    }
}


Bom pessoal, duvidas e sugestões comentem...

sexta-feira, 21 de setembro de 2012

1ª lista de exercícios EDA

Fala galera, acho que vcs já estavam com saudades ... ou não, mas enfim vamos ao que interessa, coma a volta das aulas na faculdade voltaram também as listas de exercicíos, e como muitos adoram verificar e corrigir exercicíos alheios deixo para vcs a resolução dos 29 exercicíos da lista de ETA.


 #include <stdio.h> int main() { printf("\nÉ preciso fazer todos os algoritmos para aprender!"); return 0; }


#include <stdio.h> int main() { printf("\nGuilherme Carvalho!"); return 0; }
#include <stdio.h> int main() { printf("%d", 28*43); return 0; }
#include <stdio.h> <stdio.h> int main() { printf("%d", (9+8+7)/3); return 0; }

#include <stdio.h> int main() { int i; printf("\nInforme um numero inteiro: "); scanf("%d", &i); printf("%d", i); return 0; }
#include <stdio.h> int main() { int i, ii; printf("\nInforme dois numeros inteiro: "); scanf("%d%d", &i, &ii); printf("%d \n%d", i,ii); return 0; } 


 #include <stdio.h>  int main() { int i, s, a; printf("\nInforme um numero: "); scanf("%d", &i); s = i + 1; a = i - 1; printf("Sucessor: %d \nAntecessor: %d", s, a); return 0; }


 #include <stdio.h>  int main() { char nome[80]; char endereco[80]; char telefone[20]; printf("\nInforme o nome: "); gets(nome); printf("\nInforme o endereço: "); gets(endereco); printf("\nInforme o telefone: "); gets(telefone); printf("\nNome: %s \nEndereço: %s \nTelefone: %s", nome, endereco, telefone); return 0; } 


#include <stdio.h>  int main() { int x, y; printf("\nInforme 2 numeros inteiros: "); scanf("%d%d", &x, &y); printf("Soma = %d", x+y); return 0; }


 #include <stdio.h> int main() { int x, y; printf("\nInforme 2 numeros inteiros: "); scanf("%d%d", &x, &y); printf("Produto = %d", x*y); return 0; }

#include <stdio.h> <stdio.h> int main() { int x; printf("\nInforme um numero: "); scanf("%d", &x); printf("Terça parte de %d = %d", x, x/3); return 0; }

#include <stdio.h>  int main() { int x, y; printf("\nInforme 2 numeros inteiros: "); scanf("%d%d", &x, &y); printf("Media = %d", (x+y)/2); return 0; }


#include <stdio.h> int main() { float v; printf("\nInforme valor: "); scanf("%f", &v); v *= 1.01; printf("\n%f", v); return 0; }


#include <stdio.h> int main() { int a, h; printf("\nárea: "); scanf("%d", &a); printf("\nbase: "); scanf("%d", &h); printf("\narea=%d \nperimetro=%d", h*a, (h*2)+(a*2)); return 0; }


#include <stdio.h> #define PI 3.1415 int main() { int r; printf("\nRaio: "); scanf("%d", &r); printf("\nPerimetro = %f, Area = %f", 2*PI*r, PI*r*r); return 0; }


#include <stdio.h> int main() { int a, h; printf("\nlado: "); scanf("%d", &a); printf("\narea=%d \nperimetro=%d", a*a, (a*2)+(a*2)); return 0; }


#include <stdio.h> int main() { int b, a; printf("\naltura: "); scanf("%d", &a); printf("\nbase: "); scanf("%d", &b); printf("\narea=%d ", (b*a)/2); return 0; }


#include <stdio.h> int main() { float x; printf("\nvalor: "); scanf("%f", &x); printf("\nnovo valor = %f", x*0.91); return 0; }


#include <stdio.h> int main() { int x; printf("\nnumero: "); scanf("%d", &x); if(x >= 20 && x <= 90) { printf("\nNro está compreendido entre o intervalo!"); } else { printf("\nNro não está compreendido entre o intervalo!"); } return 0; }


#include <stdio.h> int main() { char nome[100]; int idade; char sexo; printf("\nInforme o nome: "); gets(nome); printf("\nInforme a idade: "); scanf("%d", &idade); __fpurge(stdin); printf("\nInforme sexo [M/F]: "); scanf("%c", &sexo); sexo = toupper(sexo); if(sexo == 'F' && idade < 25) { printf("\nNome: %s \nAceito (a)", nome); } else { printf("\nNome: %s \nNão aceito (a)", nome); } return 0; }


#include <stdio.h> int main() { int x, y, z; printf("\nInforme 3 valores: "); scanf("%d%d%d", &x, &y, &z); if((x + y > z) && (x + z > y) && (y + z > x)) { printf ("É triangulo"); } else { printf("\nNão é triangulo"); } return 0; }


#include <stdio.h> int main() { int x, y, z; printf("\nInforme 3 valores: "); scanf("%d%d%d", &x, &y, &z); if((x + y > z) && (x + z > y) && (y + z > x)) { printf("\nTriângulo "); if((x == y) && (z == x) && (y == z)) printf("Equilátero"); else if((x != y) && (z != x) && (y != z)) printf("Escaleno"); else printf("Isóceles"); } else { printf("\nNão é triangulo"); } return 0; }


#include <stdio.h> int main() { int x; printf("\nInforme um numero: "); scanf("%d", &x); if(x % 4 == 0) { printf("\nMultiplo de 4!"); } else if(x % 7 == 0) { printf("\nMultiplo de 7!"); } else { printf("\nNão é multiplo de 4 nem de 7!"); } return 0; } 


#include <stdio.h> int main() { int x; printf("\nInforme um numero: "); scanf("%d", &x); if(x <= 1) { x = 1; } else if(x > 1 && x <= 2) { x = 2; } else if(x > 2 && x <= 3) { x = x*x; } else { x = x*x*x; } printf("\nValor de x = %d", x); return 0; }


#include <stdio.h> int main() { int i; for(i = 1; i <= 600; i++) { if(i % 2 == 0) { printf("%d\t", i); } } return 0; }


#include <stdio.h> int verificaPrimo(int n) { int i; for(i = 2; i < n; i++) { if(n % i == 0) { return 1;//não é primo break; } } return 0;//primo } int main() { int i; for(i = 1; i < 2001; i++) { if(!verificaPrimo(i))//nega condição printf("%d\t", i); } return 0; } 


#include <stdio.h> int main() { float v; printf("\nInforme o valor do produto: "); scanf("%f", &v); if(v < 20) v *= 1.45; else v *= 1.3; printf("\nValor de venda: %5.2f", v); return 0; } 


#include <stdio.h> int main() { int nBg, nBm;//número do boi gordo e boi magro respectivamente float pBg, pBm;//peso do boi gordo e boi magro respectivamente int i = 1; int n; float p; printf("\nInforme o numero do %dº boi: ", i); scanf("%d", &nBg); printf("\nInforme o peso do %dº boi: ", i); scanf("%f", &pBg); nBm = nBg; pBm = pBg; for(i = 2; i <= 90; i++) { printf("\nInforme o numero do %dº boi: ", i); scanf("%d", &n); printf("\nInforme o peso do %dº boi: ", i); scanf("%f", &p); if(p > pBg) { pBg = p; nBg = n; } else { pBm = p; nBm = n; } } printf("\nBoi + gordo = %dº %3.2f \nBoi + magro = %dº %3.2f", nBg, pBg, nBm, pBm); return 0; } 


#include <stdio.h> #include <stdio.h> <stdio.h> int main() { char sexo; char olhos[9]; char cabelos[9]; float porcentagem = 0; int idade, i, mIdade = -1; for(i = 1; i <= 200; i++) { __fpurge(stdin); printf("\nSexo [M/F]: "); scanf("%c", &sexo); sexo = toupper(sexo); __fpurge(stdin); printf("\nOlhos: "); gets(olhos); __fpurge(stdin); printf("\nCabelos: "); gets(cabelos); printf("\nIdade: "); scanf("%d", &idade); if(idade > mIdade) mIdade = idade; if(sexo == 'F') { if(idade > 17 && idade < 36) { if(strcasecmp("castanho", olhos) == 0 && strcasecmp("preto", cabelos) == 0) porcentagem++; } } } printf("\nMaior idade = %d", mIdade); printf("\nPorcentagem = %3.2f", porcentagem/2); return 0;}

Novidade!!! Agora vamos ter canal no Youtube =D

Fala pessoal tudo beleza, estou sumido a correria está forte por aqui. Estou querendo dar um start em um projeto antigo que vem desde o temp...