Pesquisar este blog

quinta-feira, 7 de novembro de 2013

Exercícios Vetor e Matriz C#

Abaixo a lista de exercícios passadas na última aula:

Lista de Exercícios – Vetores e Matrizes
Prof. Veras e Prof. Leminski

1.  Dada uma sequencia de n números, imprimi-la na ordem inversa à da leitura.

2.  Tentando descobrir se um dado era viciado, um dono de cassino honesto o lançou n vezes. Dados os n resultados dos lançamentos, determinar o número de ocorrências de cada face.

3.  Dados dois vetores x e y, ambos com n elementos, determinar o produto escalar desses vetores.
OBS.: o produto escalar é soma de todos os produtos dos números de mesma posição. Por exemplo, se n = 4:

Vetor X: 0, 3, 5, 6
Vetor Y: 2, 4, 9, 8
Produto escalar X · Y = (0 x 2) + (3 x 4) + (5 x 9) + (6 x 8) = 105

4. Faça um programa que leia um vetor de 10 posições e crie um segundo vetor substituindo os valores negativos por 1.
5. Faça um programa que leia uma matriz mat 3 x 4 de inteiros, substitua seus elementos negativos por 0 e imprima a matriz mat original e a modificada.

6. Ler um vetor que contenha as notas de uma turma de 10 alunos. Calcular a média da turma e contar quantos alunos obtiveram nota acima desta média calculada. Escrever a média da turma e o resultado da contagem.

7. Faça um programa que receba o nome de cinco produtos e seus respectivos preços, armazene-os em dois vetores separados, um para os produtos e outro para os preços. O programa deve calcular e mostrar:

  • A quantidade de produtos com preço inferior a R$ 50,00;
  • O nome dos produtos com preço entre R$ 50,00 e R$100,00;
  • A média dos preços dos produtos com preço superior a R$ 100,00.


8. Ler um vetor A de 6 elementos contendo o gabarito da Mega Sena. A seguir, ler um vetor B de 10 elementos contendo uma aposta. Escrever quantos pontos fez o apostador, e se ele fez a
sena (6 acertos), a quina (5 acertos) ou a quadra (4 acertos)

9. Seja A uma matriz de ordem M. Fazer um programa para:
  1. Determinar a soma dos elementos da diagonal principal de A.
  2. Colocar os elementos da diagonal principal de A em um vetor S.


10. Considere A e B duas matrizes N x M. Faça um programa para calcular a matriz C, resultante da soma da matriz A com a matriz B. Imprimir a matriz C.

11. Considere as matrizes A (M x N) e B (N x P). Obter a matriz P resultante do produto de A por B.


DESAFIOS

12.  (COMP 89) Dados dois strings (um contendo uma frase e outro contendo uma palavra), determine o número de vezes que a palavra ocorre na frase.
Exemplo:
Para a palavra ANA e a frase :
ANA E MARIANA GOSTAM DE BANANA
Temos que a palavra ocorre 4 vezes na frase.

13.  (MAT 88) Dada uma sequencia de n números reais, determinar os números que compõem a sequencia e o número de vezes que cada um deles ocorre na mesma.
Exemplo: n = 8
Sequencia: -1.7,  3.0,  0.0,  1.5,  0.0, -1.7,  2.3, -1,7
Saída:       -1.7 ocorre 3 vezes
                   3.0 ocorre 1 vez
                   0.0 ocorre 2 vezes
                  1.5 ocorre 1 vez
                   2.3 ocorre 1 vez

14.  Dadas duas sequencias com n números inteiros entre 0 e 9, interpretadas como dois números inteiros de n algarismos, calcular a sequencia de números que representa a soma dos dois inteiros.
Exemplo: n = 8,
1ª  sequencia
      8    2    4    3    4    2    5    1
2ª  sequencia
+    3    3    7    5    2    3    3    7

1    1    6    1    8    6    5    8    8

quarta-feira, 30 de outubro de 2013

Introdução a Programação: Vetor e Matriz em C#

Vetor e Matriz:

Arrays são um conjunto de elementos de um mesmo tipo, com uma quantidade limitada de posições.
Aqui vamos tratar destes importantes pontos de uma linguagem de programação.
Matrizes e Vetores são conjuntos de dados, uma variável onde podemos armazenar vários elementos de um mesmo tipo, por exemplo as informações de um arquivo.

Vetor:

Um vetor possui apenas uma dimensão, com isso, ele se comporta como uma linha de uma tabela, a linha possui várias colunas, e cada coluna possui o valor de um elemento. Considerando que esta linha só pode receber valores do mesmo tipo, por exemplo inteiro, teremos um vetor de inteiro.
Vale lembrar que para construirmos um vetor de inteiros, faremos:

string[] vetor = new string[10];

Os leitores mais atentos irão notar que colocamos um valor inteiro entre as chaves, mas o que é que significa isso?
Bom, será que estamos dizendo que termos um vetor que vai conter um elemento string com valor 10? Na verdade não, o que acontece é que os vetores são elementos com tamanho fixo e ao inicializarmos um vetor deveremos definir o seu tamanho, que é o que estamos fazendo ali, definimos um vetor de strings com 10 posições.
E para armazenar um valor na primeira coluna do vetor devemos fazer:

vetor[0] = "primeiro valor";

Com isso agora temos um vetor que contem um elemento inteiro com valor primeiro valor na sua primeira posição. Este nosso vetor possui dez posições, a podemos acessá-las da seguinte forma:

vetor[0] = "primeiro valor";
vetor[1] = "segundo valor";
vetor[2] = "terceiro valor";
vetor[3] = "quarto valor";
vetor[4] = "quinto valor";
vetor[5] = "sexto valor";
vetor[6] = "setimo valor";
vetor[7] = "oitavo valor";
vetor[8] = "nono valor";
vetor[9] = "decimo valor";

Repare que o valor que determina a posição de um valor no vetor é um pouco confuso, para acessarmos o decimo valor, usamos o algarismo de número 9, isso acontece pois o primeiro valor de um vetor tem a posição 0, com isso o último elemento do vetor será sempre o tamanho dele -1.

Matriz:

Como vimos até agora os vetores são arrays de apenas uma dimensão, já as matrizes são arrays multidimensionais. Por exemplo uma tabela contém linhas e colunas e isto é um bom exemplo de uma matriz bi dimensional.
Como fazemos pra criar uma matriz?
int[,] tabela = new int[2,3];
Com isso criamos uma pequena tabelinha com 2 linhas e três colunas.
Um vetor de três dimensões é um cubo e para criarmos um vetor de três dimensões devemos fazer:
int[,] cubo = new int[3,3,3];

 Exercícios:

  1. Faça uma função que recebe um vetor X(15) de inteiros , por parâmetro, e retorna a quantidade de valores pares em X.

  2. Resolução:
    static void Main(string[] args)
    {
       Console.WriteLine("Programa multiplicador de linhas e colunas de uma matriz");
       int[,] matriz = new int[,] {
          {1,2,3,4},
          {5,6,7,8},
          {010,11,12}
       };
       Console.WriteLine("Digite valor que deverá multiplicar a coluna");
       int multiplicadorColuna = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("Digite o numero da coluna a ser multiplcada");
       int numeroColuna = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("Os valores da coluna multiplicados sao");
       for (int linha = 0; linha <= matriz.GetUpperBound(0); linha++)
       {
          Console.WriteLine(matriz[linha, numeroColuna] * multiplicadorColuna);
       }
       Console.WriteLine("Digite valor que deverá multiplicar a linha");
       int multiplicadorLinha = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("Digite o numero da linha a ser multiplcada");
       int numeroLinha = Convert.ToInt32(Console.ReadLine());
       Console.WriteLine("Os valores da linha multiplicados sao");
       for (int coluna = 0; coluna <= matriz.GetUpperBound(1); coluna++)
       {
          Console.WriteLine(matriz[numeroLinha, coluna] * multiplicadorLinha);
       }
          Console.ReadLine();
    }
  3. Faça uma rotina que atribua à matriz 6x6 os seguintes números inteiros, 
    |345 | 24  | 456 | 2345 | 100 | 265 |
    |258| 963 |321 |120     | 98   |145  |
    |300| 256 |255 |024     | 324| 369  |
    |125| 564 |433 |132     | 233| 353  |
    |357| 464| 288 |999     | 40  |775   |
    |456| 213| 32   |234     | 271| 42    |
  4. Faça um programa que localize o número 300 e mostre em que posição ele se encontra.
  5. Resolução:
    static void Main(string[] args)
    {
       Console.WriteLine("Programa multiplicador de linhas e colunas de uma matriz");
       int[] vetor = new int[] {1,2,3,4,5,6,7,8,9,10};

          int minimo=0;
          int maximo=0;
       for (int indice = 0; indice <= vetor.Length; indice++)
       {
                
             if(minimo>vetor[indice]){
                  minimo=vetor[indice];
             }
             if(maximo<vetor[indice]){
                maximo=vetor[indice];
             }
          }
       
          Console.WriteLine("O valor do maior elemento é {0}, e o do menor elemento é                              {1}",maximo,minimo);
          Console.ReadLine();
    }
  6. Faça um programa que recebe um vetor com 10 elementos e calcule o maior e o menor valor deles.
  7. Faça um programa que receba um vetor de inteiros com 5 elementos e calcule a média deles.

quarta-feira, 11 de setembro de 2013

Estrutura de Repetição For no C#

Estrutura de repetição C#

A primeira estrutura de repetição que veremos aqui será o for, no for podemos executar uma parte do código repetidas vezes, de uma forma controlada, abaixo temos a estrutura do for:
 for(Inicialização;condição;passo){
   <codigo_a_ser_repetido>;
}
Nada melhor que um exemplo de código para começarmos a entender como funciona um for:

for(int contador=0;condador<10;contador++){
<código_a_ser_repetido>
}
Explicando o que acontece na definição do loop for, primeiro usamos a palavra chave for que define o loop, dentro do parênteses temos 3 definições de código, na primeira parte, que no exemplo é:
int contador=0;
Estamos definindo uma variável, e isso é o que geralmente fazemos em um for, porém devemos nos atentar que aqui podemos definir qualquer código e ele será executado apenas uma vez antes de qualquer passo do loop. Lembre-se que se uma variável for definida aqui, como fizemos com o contador, ela só poderá ser usada no contexto do for, ou seja, entre o início { e o fim } do for, após ele ela não será válida.
Na próxima definição, que no exemplo foi definido por:
contador < 10;
Temos uma condição booleana, esta parte do código será executada antes da execução de cada passo do loop, e ele o passo só será executado enquanto esta condição for verdadeira, quando ela for falsa o loop irá encerrar a execução.
Na última parte definida dentro do for, que foi definida por:
contador ++;
Temos uma parte do código que será executada ao final de cada passo do loop.
Neste exemplo do for, definimos uma variável inteira que começará com o valor de 0, este loop será válido para todos os valores de contador menores que 0, e a cada passo vamos acrescentar 1 ao valor de contador. Com isso, neste exemplo quando executado o contador terá os valores:
0
1
2
3
4
5
6
7
8
9
Lembre-se:
  1. Tanto a primeira, quanto a terceira parte do código dentro dos parênteses do for é opcional.
  2. A parte do código onde definimos a condicional é obrigatória.
  3. Não necessariamente devemos definir uma variável para o for, podemos usar uma que já existe.
  4. Podemos alterar a variável usando qualquer operação matemática, *, /, -, etc, e não necessariamente apenas o ++.
A primeira pergunta que nos vem a cabeça, quando pensamos em for é:
Ah, mas o for não é igual ao while?
Ainda não vimos o while, mas tudo o que fazemos no for, conseguimos fazer no while, porém no for é muito mais fácil e compacto.
Uma outra pergunta recorrente é:
Quem é mais eficiente o for ou o while?
Na verdade a eficiência dos dois é bem parecida, cabe ao programador escolher quando usar um ou outro.

Exercícios:

  1. Faça um programa  que receba um inteiro e imprima o quadrado de cada número entre 1 e o número passado pelo usuário.
  2. Faça um programa que receba um inteiro e imprima todos os números pares entre 0 e ele.
  3. Faça um programa que receba um inteiro e calcule o Fatorial daquele inteiro. (O fatorial de um número é determinado pela multiplicação do número n e seus inferiores, por exemplo o fatorial de 5 é 5 * 4 * 3 * 2 * 1 = 120).

Apresentação

Exemplo de código de um do while para o programa de médias:

  static void Main(string[] args)
        {
            double p1,p2,exame,media;
            string continua="N";
            Console.WriteLine("Olá, bem vindo ao program que calcula a média das matérias");
            do
            {
                Console.WriteLine("Digite a sua nota da P1:");
                p1 = Convert.ToDouble(Console.ReadLine());

                Console.WriteLine("Digite a sua nota da P2:");
                p2 = Convert.ToDouble(Console.ReadLine());

                media = (p1 + p2) / 2;
                if (media > 7)
                {
                    Console.WriteLine("Parabéns, você foi aprovado com uma média {0}, deseja continuar (S/N)",media);
                }
                else if (media > 3)
                {

                    Console.WriteLine("Digite a sua nota do Exame:");
                    exame = Convert.ToDouble(Console.ReadLine());
                    media = (media + exame) / 2;
                    if (media > 7)
                    {
                        Console.WriteLine("Parabéns, você foi aprovado com uma média {0}, deseja continuar (S/N)", media);
                    }
                    else
                    {
                        Console.WriteLine("Você foi reprovado com uma media {0}, deseja continuar (S/N)",media);
                    }
                }
                else
                {
                    Console.WriteLine("Você foi reprovado com uma media {0}, deseja continuar (S/N)",media);
                }
                continua = Console.ReadLine();
                Console.Clear();
            } while (continua.ToUpper().Equals("S"));


quarta-feira, 28 de agosto de 2013

Estrutura Condicional C#

Estrutura condicional:

As estruturas condicionais dos programas será a primeira condição lógica explorada neste curso. Existem dois tipos de estrutura condicional no C# o if else (se e senão) e o switch case (escolha caso).

Condições

As estruturas condicionais sempre avaliam se uma condição é verdadeira ou não, caso ela seja verdadeira o programa irá executar uma parte do código.

Comando Nome Definição
> Maior Retorna verdadeiro quando o atributo do lado esquerdo é maior do que o atributo do lado direito.
< Menor Retorna verdadeiro quando o atributo do lado esquerdo é menor do que o atributo do lado direito.
>= Maior igual Retorna verdadeiro quando o atributo do lado esquerdo é maior do que o atributo do lado direito ou se os atributos são iguais.
<= Menor igual Retorna verdadeiro quando o atributo do lado esquerdo é menor do que o atributo do lado direito ou se os atributos são iguais.
== Igual Retorna verdadeiro quando os dois lados da comparação são iguais
!= Diferente Retorna verdadeiro quando os dois lados da comparação são diferentes
| Ou lógico Retorna verdadeiro quando um dos dois lados é verdadeiro, executa os dois lados da condição.
|| Ou condicional Retorna verdadeiro quando um os dois lados da comparação é verdadeiro, mas não executa o segundo lado quando o primeiro for verdadeiro.
^ Ou exclusivo Retorna verdadeiro quando somente um os dois lados da comparação é verdadeiro.
& E lógico Retorna verdadeiro quando os dois lados da comparação é verdadeiro. Executa os dois lados da condição.
&& E condicional Retorna verdadeiro quando os dois lados da comparação é verdadeiro. Só executa o segundo lado da condiçao quando o primeo é verdadeiro.

IF ELSE

O if/else é usado quando precisamos testar uma condição em nosso programa, por exemplo, caso você queira fazer um programa que cumprimente o usuário, quando ele entre no seu programa. Se o horário for entre 06 e 12, o seu programa irá falar Bom dia <Nome do usuário>, caso o horário de entrada do usuário seja entre 12:01 e 18hs o sistema irá dizer: Boa tarde, <Nome do usuário>
e finalmente caso o horário seja entre 18:01 e 24h o sistema irá dizer, boa noite <Nome do usuário>
Este é um típico uso de if/else, no if definimos a condição para o programa executar uma parte do código e ele funciona da seguinte maneira:
if( condição booleana ) { // se ou caso a condição é verdadeira
código a ser executado quando a condição é verdadeira
} else { // senão
código a ser executado quando a condição booleana é falsa
Exemplo de código usando uma comparação:

int numero2 = 2;
int numero3 = 3;
if(numero2 % 2 == 0){
   Console.WriteLine("A variável número2 é par");
}else{
   Console.WriteLine("A variável número2 é impar");
}
if(numero3 % 2 == 0){
   Console.WriteLine("A variável número3 é par");
}else{
   Console.WriteLine("A variável número3 é impar");
}
Veja a comparação que estamos fazendo no primeiro if é, se o resultado do resto da divisão por 2 é 0, então significa que o número é par, senão o número é impar.
As mesmas comparações podem ser realizadas com todos os outros condicionais como o >, o <, etc.

Switch Case

Switch case é uma operação usada para testar uma condição em uma lista de possibilidades. Esta condição pode ser usada em variáveis do tipo inteiro ou string. O switch case só testa condições de igualdade, não há testes de maior,menor ou diferente. A declaração de switch funciona da seguinte maniera:
switch (<nome_da_variavel>)// Teste a variável.
{
case 1: // Caso o valor da variável seja 1
    <Código da condição>
    break// Final do case, quando o break é executado o programa finaliza o switch.
default// Código caso nenhum case tenha sido verdadeiro
    <Código da condição caso nenhum dos cases acima seja verdadeiro>
    break// Final do switch
}

Abaixo temos um exemplo de código de switch:
int variavelTestada = 1;
switch (variavelTestada)
{
case 1:
    Console.WriteLine("Caso variavelTestada seja 1");
    break;
case 2:
    Console.WriteLine("Caso variavelTestada seja 2");
    break;
default:
    Console.WriteLine("Caso variavelTestada não seja nem 1, nem 2");
    break;
}
No código acima, a condição a ser executada será o código dentro do case 1, já que o valor da variável variavelTestada é 1.
Este código só executaria o default, caso a variável variavelTestada não seja nem 1, nem 2.
Lembrando que toda vez que colocarmos qualquer código dentro do case, deveremos  inserir o comando break para demarcar o final daquele bloco de código.
switch (variavelTestada)
{
    // Este switch causará um erro.
    case 1:
        Console.WriteLine("Caso variavelTestada seja 1...");
        // Faltou adicionar o break aqui.
    case 2:
        Console.WriteLine("... e/ou Caso variavelTestada seja 2");
        break;
}
O caso acima não executa, pois o bloco do case 1 não tem uma marcação de finalização, faltou inserir o break.
Existe a possibilidade de fazermos um teste em uma variável caso ela tenha mais de um valor, como mostrado abaixo:
        int n = 2;
        switch(n) 
        {
            case 1:
            case 2: 
            case 3: 
                Console.WriteLine("Caso n seja 1, 2 ou 3.");
                break; 
            default: 
                Console.WriteLine("Caso n seja diferente de 1,2 ou 3.");
                break; 
        }


Como não há nenhuma linha de código entre os cases, o código executará caso o valor de n seja 1, 2 ou 3.

Exercícios:

  1. Construa um programa que receba o nome do usuário, o seu genero (M para masculino e F para Feminino) e a sua idade. Este programa deverá cumprimentar o usuário da seguinte forma. Para idade entre 0 e 3 anos, olá bebê, entre 4 e 8 anos olá criança, entre 9 e 12 olá garoto(a), entre 13 e 18 olá moça(o), entre 19 e 40 srta/rapaz, entre 40 e 60 sr(a) e finalmente maior que 61 anciã(ão).
  2. Faça um programa que receba o nome e o salário do usuário e aplique o dissídio conforme tabela do Sindiesp 2013, os valores do dissídio são:
    1. Para salários de até 2000,00, o reajuste será de 7,68%
    2. Para salários entre 2000,01 e 5000,00 será de 7,16%
    3. Para salários entre 5000,01 e 20000,00 será de 6,66%
    4. Para salários acima de 20000,01 o reajuste será fixo de 1000,00.
  3. Em 2013 o Governo Federal declarou como meta da inflação o valor de 4,5% com uma taxa de erro de 2% para cima ou para baixo, portanto a meta de inflação será entre 2,5% e 6,5%. Faça um programa que receba a taxa de inflação do ano, e determine se ela ficou exatamente na meta, se ela ficou dentro da faixa de erro mas abaixo da meta, se ela ficou acima da meta mas dentro da faixa de erro, se ela ficou fora da meta para baixo ou se ela ficou fora da meta para cima.

Apresentação

quarta-feira, 21 de agosto de 2013

Estrutura Sequencial e Comandos de Atribuição

 Estrutura Sequencial

Depois de termos visto variáveis e os princípios do C# vamos explicar alguns conceitos de programação.
As operações no C# seguem uma sequência de prioridade de execução, esta sequência segue a seguinte prioridade, da maior pra menor:
  • Funções pré definidas (Math.Pi, Math.Sqrt, ...)
  • Parenteses, do interno para o externo ( 2 (1) 2 )
  • ++x, --x, +x e  -x
  • *, / e %
  • + e -
  • =, *=, /=, %=, += e -=
  • x++ e x--
Onde x é mostrada como exemplo para o posicionamento dos operadores unários.
++x e x++ adiciona um ao valor de x
--x e x-- subtrai um do valor de x

Toda vez que declaramos uma variável, antes de usá-la devemos atribuir um valor a ela:
int numero;
Console.WriteLine(numero);
No código mostrado acima existe um erro de compilação, como não definimos um valor para a variável numero, não é possível usarmos ela, para corrigir este tipo de código podemos fazer como mostrado abaixo:
int numero =10;
Console.WriteLine(numero);
Como na primeira linha do código agora atribuímos um valor (10) a variável número agora podemos usar ela sem problemas.

Dica: Uma das coisas mais importantes a se pensar quando estamos desenvolvendo um software é na usabilidade. Quanto mais informações você dá para o usuário, melhor.
Exemplo de código com pouca usabilidade:
Console.WriteLine("Multiplicação");
double a = Convert.ToDouble(Console.ReadLine());
double b = Convert.ToDouble(Console.ReadLine());
 Console.WriteLine(a*b);
Qual é o resultado de executarmos o código acima?

Multiplicação:
3                  
5                  
15                   
 
Toda vez que você estiver fazendo um código, tente pensar com a cabeça de um usuário, imagina você como usuário, vendo uma tela preta com um texto branco, escrito: Multiplicação
Isso faz com que você pense que deve digitar dois números e que eles serão multiplicados e finalmente que o resultado será exposto na linha de baixo?
Certamente não, quanto melhor você informar o usuário do que você está fazendo e o que ele deve fazer para executar o seu programa, melhor. Veja o código refeito abaixo:
Console.WriteLine("Bem vindo ao programa de Multiplicação");
Console.WriteLine("Digite dois números para que eu lhe apresente o resultado da multiplicação entre eles.");
Console.WriteLine("Por favor, digite o primeiro número:");
double numero1 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Por favor, digite o segundo número:");
double numero2 = Convert.ToDouble(Console.ReadLine());
double resultado = numero1*numero2;
 Console.WriteLine("O resultado da multiplicação entre {0} e {1}, é: {2}",numero1,numero2,resultado);
 Vejamos agora qual é o resultado da execução do código acima:
Bem vindo ao programa de Multiplicação                                                  
Digite dois números para que eu lhe apresente o resultado da multiplicação entre eles.Por favor, digite o primeiro número:                                            
 3                                                                                                                
Por favor, digite o segundo número:                                                            
 5                                                                                                                  
O resultado da multiplicação entre 3 e 5, é: 15                                              
Bom, agora sim ficou bem claro o que o usuário deveria fazer e qual seria o resultado deste programa, tente sempre lembrar disto quando estiver fazendo um novo programa.

Conversão de valores:

Existe uma classe em c# que se chama Convert ela é usada para converter valores entre um tipo e outro, abaixo segue uma tabela dos métodos da classe Convert que são usados para converter valores:

Convert.ToBoolean() bool Convert.ToInt64() long
Convert.ToByte() byte Convert.ToSByte() sbyte
Convert.ToChar() char Convert.ToSingle() float
Convert.ToDecimal() decimal Convert.ToString() string
Convert.ToDouble() double Convert.ToUInt16() ushort
Convert.ToInt16() short Convert.ToUInt32() uint
Convert.ToInt32() int Convert.ToUInt64() ulong

Cada um dos métodos da classe Convert, executa a conversão para o tipo de variável declarada, por exemplo o ToBoolean converte qualquer tipo de variável para booleano, lembrando que por exemplo, ao usar uma string, se você passar um valor inválido de booleano, este método dispara uma exceção do tipo FormatException, o que indica um erro de execução do programa.

Funções matemáticas:

Na tabela abaixo mostramos as funções matemáticas disponíveis na classe Math

Nome do método

Descrição do Método

AbsValor absoluto de um número
CosValor do Cosseno
SinValor do Seno
TanValor da Tangente
ExpValor de e elevado ao expoente passado como parâmetro
RoundArredonda o valor do ponto flutuante
PowEleva o primeiro parâmetro a potência do segundo parâmetro
SqrtRaiz quadrada

Por exemplo para calcularmos a raiz quadrada de dois devemos fazer:
Math.Sqrt(2);
Para elevar 3 ao quadrado fazemos
Math.Pow(3,2); 

Exercícios:

1) Crie um programa que calcule a raiz quadrada de um valor passado pelo usuário.
2) Crie um programa que calcule um número elevado a potência fornecida pelo usuário.
3) Crie um programa que receba um valor numérico do usuário e converta ele para long.
4) Crie um programa que receba dois lados de um triângulo e calcule o terceiro lado usando o teorema de pitágoras.
5) A fórmula do cálculo da diagonal do quadrado é:
               d =\sqrt{2\,l^2}=l \sqrt{2}.
onde d é a diagonal do quadrado, e l é o lado do quadrado. Faça um programa que receba o valor do lado de um quadrado e calcule qual é o tamanho da diagonal do quadrado.
6)Sabendo que um carro popular, após um ano de uso é, 9,45%, que o valor médio do seguro deste carro é R$ 2.583,83,  o preço dele é R$ 21.415,00 e o IPVA do carro é 3% ao ano, calcule qual será o valor do carro após um ano de uso, inclua no cálculo os gastos com seguro e ipva para determinar qual será o valor real de venda do veículo após um ano de uso.

Referências:

sexta-feira, 16 de agosto de 2013

Conceito de Variável em C#

Conceito de variável

Em programação variável é um objeto ou um espaço na memória onde podemos armazenar um valor. Uma variável só existe em tempo de execução, ou seja, quando o programa está sendo executado, elas são associadas a nomes. Ao nomear uma variável devemos sempre ser o mais descritivos possível.
As variáveis são definidas por tipos, existem os tipos textuais, os tipos inteiros, os tipos de ponto flutuante que serão descritos na tabela abaixo:

Tipo C#

Valores possíveis

Tamanho na memória

Valor padrão

bool true (verdadeiro) ou false (falso) 1 bit false
byte 0 a 255 1 byte false
sbyte -128 a 127 1 byte false
char um caractere 2 bytes '\0'
decimal Valores decimais com 128 bits de precisão, 28~29 digitos significantes (-7,9 x 1028 a 7,9 x 1028) / 100 to 28 0.0M
double Valores decimais com 64 bits de precisão (+/-)5,0 x 10-324 a (+/-)1,7 x 10308 0.0D
float Valores decimais com 32 bits -3,4 x 1038 a + 3,4 x 1038 0.0F
int Inteiro com 32 bits -2.147.483.648 a 2.147.483.647 0
long Inteiro com 64 bits -923.372.036.854.775.808 a 9.223.372.036.854.775.807 0L
sbyte Inteiro de 8 bits -128 a 127 0
short Inteiro de 16 bits -32.768 a 32.767 0
uint Inteiro positivo de 32 bits 0 a 4.294.967.295 0
ulong Inteiro positivo 64 bits 0 a 18.446.744.073.709.551.615 0
ushort Inteiro positivo 16 bits 0 a 65.535 0
string Conjunto de caracteres, sendo 16 bits por caractere texto tamanho ilimitado ""

Quando criamos, ou declaramos, uma variável estamos reservando um espaço na memória para armazenar aquele valor. Por exemplo ao declarar uma variável do tipo long, estamos reservando 64 bits de memoria para esta variável.
Cada tipo de variável possui um determinado tamanho e a capacidade de armazenar uma certa quantidade de dados, conforme mostrado na tabela acima.
Um ponto importante e explicar qual e a diferenca entre o decimal, o double e o float. O double e o float são números binários de ponto flutuante, ou seja, eles representam um número desta forma:
100101,10101100
Já o decimal é um número decimal de ponto flutuante, ou seja eles representam um número desta forma:
1234,56
O importante de tudo isso é que nós estamos acostumados a representar números decimais da mesma forma que o decimal faz, e nós sempre esperamos ter o resultado exato deste número. Quando isso é feito por uma representação binária, por exemplo o 0,1 usando uma representação binária, nós teremos um valor aproximado de 0,1.
Portanto ao usar double e float nós temos uma aproximação do valor, já com decimal este valor sempre será exato.
Quando usar um e quando usar outro? Bom o exemplo mais comum que temos de uso do decimal são valores monetários, ao depositar 10,20 na sua conta do banco, você espera sempre ter este valor exatamente assim depositado em sua conta, sem arredondamentos.
Já o float e o decimal podem ser usados para cálculos de média, dados científicos, etc.

Operadores matemáticos:

Tipo do Operador

Como usar

Descrição

Multiplicador e divisão x * y
x / y
x % y
* define a multiplicação,
/ define a divisão
e % define o resto da divisão
Soma e subtração x + y
x - y
+ define a adição
- define a subtração
Shift x << y
x >> y
<< define um deslocamento binario a esquerda
>> define um deslocamento binário a direita

Todos os operadores mostrados na tabela acima estão em ordem de execução, portando o * é o operador que tem a máxima prioridade, se tivermos a seguinte expressão:

int valor = 1+ 2 * 3 
O resultado desta operação seria 7, já que * tem precedência ao + a operação que será realizada seria:
int valor = 1 + (2 * 3)
valor = 1 + 6
valor = 7
A precedencia dos operadores define quem é executado primeiro, e esta ordem se dá de cima para baixo na tabela mostrada acima.
Tirando os operadores matemáticos básicos, o que temos de novo aqui são os operadores de shift, que deslocam um bit pra esquerda ou pra direita. Na operação de deslocamento pra esquerda acontece uma multiplicação do valor da esquerda por 2 elevado a n, onde n é o valor que está a direita:
1 << 1   = 1 * 2 ^1 -> 1 * 2 = 2
res0: Int = 2
1 << 2  = 1 * 2 ^2 -> 1 * 4 = 4
res1: Int = 4
1 << 3 = 1 * 2 ^3 -> 1 * 8 = 8
res2: Int = 8
2 << 1 = 2 * 2 ^1 -> 2 * 2 = 4
res3: Int = 4
2 << 2 = 2 * 2 ^2 -> 2 * 4 = 8
res4: Int = 8
2 << 3 = 2 * 2 ^3 -> 2 * 8 = 16
res5: Int = 16
2 << 4 = 2 * 2 ^1 -> 2 * 2 = 4
res6: Int = 32
Já na operação de deslocamento pra direita acontece uma divisão do valor da esquerda por 2 elevado a n, onde n é o valor que está a direita:
scala> 16 >> 2 = 16 / 2 ^2 -> 16 / 4 =4
res22: Int = 4
scala> 16 >> 1  = 16 / 2 ^1 -> 16 / 2 =8
res23: Int = 8

Referências:

Apresentação 

sexta-feira, 9 de agosto de 2013

Princípios de programação com C#

Apresentação do C#

O que é C#?

C# é uma linguagem de programação Orientada o Objetos, fortemente tipada, robusta e multiplataforma que foi desenvolvida como parte do pacote .Net da Microsoft. Sua sintaxe foi baseada no C++ mas inclui também influencias de outras linguagens como Object Pascal e Java.
A criação da linguagem C# é atribuída a Anders Hejlsberg, que trabalhou como arquiteto na Borland nos projetos Turbo Pascal e Delphi.
A Microsoft submeteu o C# a entidade ECMA para uma padronização formal, que liberou esta especificação em Dezembro de 2001, em 2003 o C# tornou-se padrão ISO e existem algumas implementações em desenvolvimento como o Mono, o dotGNU, o Portable.NET e o BDS.
O C# é uma linguagem de programação visual dirigida por eventos e totalmente orientada a objetos, que permite intercâmbio entre linguagens. Com ela é possível interagir pela internet usando os padrões SOAP e XML.
Esta linguagem foi construída adaptando os melhores recursos disponíveis nas linguagens C, C++ e Java. Ela possui recursos como objetos, strings, componentes gráficos, tratamento de exceções, programação concorrente, multimídia, processamento de arquivos, banco de dados, redes e computação distribuída.

Visual Studio 

O Visual Studio é a ferramenta desenvolvida pela Microsoft para desenvolvermos o código do C#. Para baixar o Visual Studio vá até a página da microsoft para fazer o download  dos softwares necessários para programar em C#.
Lá você encontra todas as versões do Visual Studio disponíveis para baixar.
Aqui e aqui você encontra mais informações de como, sendo estudante, você pode conseguir acesso ao msdn  site da microsoft que possui todos os produtos dela disponíveis para download.
Para instalar o Visual Studio é só seguir os passos do instalador.
Após a instalação, o primeiro passo será criar um projeto, conforme mostrado na figura 1 abaixo

Figura 1 - Criando projeto.
 Ao clicar em novo projeto, aparecerá uma janela com as opções dos projetos disponíveis. Nós vamos trabalhar com projetos do tipo console application, que pode ser criados conforme mostrado na figura 2 abaixo.
Figura 2 - Criando um projeto do tipo Console application
 Ao criar um projeto do tipo console application, ele criará um programa básico, conforme mostrado abaixo na figura 3.
Figura 3 - Programa básico de um projeto console application.
A class Program define o nome do nosso primeiro programa, static void Main é o método que será executado. Cada { indica um início de escopo de código, toda linha deve ser terminada com ;
Esta imagem não mostra é a definição do namespace, namespace define um escopo de código que pode conter várias classes.
Alguns exemplos de código em C# podem ser encontrados aqui
Sites como o Submarino e muitas grandes empresas usam o C# para desenvolver seus produtos. Atualmente C# e Java polarizam o mercado de desenvolvimento no Brasil e somados ocupam quase que 80% das vagas disponíveis.


segunda-feira, 20 de maio de 2013

Paralelismo em Java com Callable

Paralelismo em Java com Callable

Pool de threads:

Na versão 5 do java, foram adicionadas classes para ajudar o desenvolvimento de threads e uma destas evoluções foram as pool d threads.
Uma pool de thread nada mais é do que uma maneira de administrar a execução das threads do seu programa. Caso você tenha 10000 threads para serem executadas, se você criar todas elas na mão e mandar executar fica difícil de administrar a execução de cada uma delas, colocando todas elas em um pool de threads, você pode controlar quantas serão executadas ao mesmo tempo e a máquina virtual é quem vai administrar a execução de todas as suas threads.
E como eu defino uma pool de threads?
ExecutorService executor = Executors.newFixedThreadPool(10);
No código acima, definimos uma pool de threads com tamanho fixo, existem várias outras maneiras de se definir uma pool de threads, mas aqui no nosso curso esta maneira é suficiente.
A grande vantagem de se usar pool de threads é que você pode determinar quantas threads serão executadas ao mesmo tempo no seu sistema, e a pool de threads é quem administra quem será executado e quando. Existe um cálculo que pode determinar qual é a quantidade ideal de threads de acordo com a sua máquina, mas para fazer este cálculo você tem que levar em conta o que o seu código faz. Porém, não adianta você colocar 10000 threads em uma máquina de 8 núcleos, que ela não vai conseguir executar todas as threads ao mesmo tempo, e isso provavelmente seja difícil de administrar. Já com as pool de threads, você cria, determina qual será a quantidade de threads executadas e pronto, ela administra pra você.
Estas pools, possuem métodos para receber as threads que serão executadas, como o método submit, este método retorna uma classe Future, que será explicada abaixo:
Future<Integer> futuro = executor.submit(new  ExemploCallable(i));
A classe future, possui um método chamado get, que quando executado, retorna o resultado do método de execução de uma thread, quando ele termina. Quando você chama o método get, ele fica esperando a thread acabar de executar. Como no nosso caso isso é imediato, não haverá nenhuma espera.
Múltiplas chamadas ao método get, não fará a thread executar várias vezes, só esperará o retorno do resultado da thread.
O método submit pode receber uma instancia de Runnable, ou de Callable. Quando passarmos uma instancia de runnable ele irá retornar nulo, ao final da execução do método, callable será explicada a seguir.
Até agora em nossos cursos trabalhamos apenas com a extensão da classe Thread ou a implementação da interface Runnable, mas e quando precisamos de um retorno do método da thread exectado, como faremos?

Interface Callable<T>

A interface Callable serve para resolver este problema, esta interface define um método call que possui um retorno e este retorno é definido pela classe T determinada na hora de implementar esta interface.

public class ExemploCallable implements Callable<Integer>{
A classe acima define que o ExemploCallable terá um método call retornando um Integer.
No exemplo abaixo definiremos uma maneira de implementar a soma de Fibonacci usando threads com a interface Callable<T>.
public class ExemploCallable implements Callable<Integer>{

    private Integer indice;

    public ExemploCallable(int indice) {
        this.indice=indice;
    }

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        Set<Future<Integer>> set = new HashSet<Future<Integer>>();
        Future<Integer> futuro =null;
        for(int i=0;i<20;i++){
            futuro = executor.submit(new  ExemploCallable(i));
            set.add(futuro);
        }
        int soma = 0;
        try {
            for (Future<Integer> resultadoFuturo : set) {
                soma += resultadoFuturo.get();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("A soma índices é "+ soma);
        System.exit(soma);
    }

    @Override
    public Integer call() throws Exception {
        return indice;
    }
}
 Repare que para construir a classe ExemploCallable passamos como argumento um inteiro, sendo este inteiro o índice do nosso loop for.
O método call simplesmente retorna este valor, com o retorno deste método iremos realizar a soma de todos os valores, o que nada mais é do que um Fibonacci.

domingo, 5 de maio de 2013

Programacao concorrente synchronized

Programacao concorrente synchronized

Sincronizando seus metodos

Algumas vezes, quando estamos programando com threads, necessitamos que um determinado metodo seja acessado apenas por uma thread de cada vez, por exemplo, no banco de dados, os geradores de ids para tabelas, so podem ser acessados por apenas uma thread, senao poderiamos ter um resultado de ids repetidos para duas chamadas diferentes, o que geraria um erro em nosso banco.
Para fazer com que um metodo, ou mesmo uma parte do codigo, seja acessada por apenas uma thread, fazemos o uso da palavra chave synchronized, como mostrado abaixo:

public synchronized int getId(String nomeTabela){
       // codigo para retornar o proximo id de uma tabela
}
ou mesmo:

public int getId(String nomeTabela){
     System.out.println("Pegando proximo id da tabela" +nomeTabela);
     synchronized {
     // codigo para retornar o proximo id de uma tabela
     }
}
Como vimos existem duas maneiras de se usar a palavra synchronized, a diferenca entre elas e que, quando usada na assinatura do metodo, o metodo inteiro so podera ser acessado por apenas uma thread, ja da outra forma, apenas o codigo dentro demarcado pela palavra synchronized, tera o acesso limitado.
Bom, a primeira vista, isso parece uma grande maravilha, mas veja, a palavra synchronized mistura duas coisas antagonicas. Um estamos trabalhando com programacao concorrente, e agora estamos forcando a programacao concorrente voltar a ser executada por apenas uma thread, e isso e bem perigoso.
O grande perigo do uso da palavra synchronized sao os dead locks, mas o que e um dead lock?

Dead Lock

Um dead lock, ou tranca mortal, acontece quando temos duas threads em execucao, e as duas estao esperando o metodo que esta sendo executado acabar de executar, mas para que isso aconteca, o ouatro metodo devera terminar. No texto parece meio complicado de entender, entao vamos pra um exemplo de codigo de quando isso acontece:

public class Deadlock {
    static class Amigo {
        private final String nome;
        public Amigo(String nome) {
            this.nome = nome;
        }
        public String getNome() {
            return this.nome;
        }
        public synchronized void passar(Amigo passador) {
            System.out.format("%s: %s"
                + "  me passou a bola!%n", 
                this.nome, passador.getNome());
            passador.passaDeVolta(this);
        }
        public synchronized void passaDeVolta(Amigo passador) {
            System.out.format("%s: %s"
                + " voltou a bola pra mim!%n",
                this.nome, passador.getNome());
        }
    }

    public static void main(String[] args) {
        final Amigo neymar =
            new Amigo("Neymar");
        final Amigo ganso =
            new Amigo("Ganso");
        new Thread(new Runnable() {
            public void run() { neymar.passar(ganso); }
        }).start();
        new Thread(new Runnable() {
            public void run() { ganso.passar(neymar); }
        }).start();
    } 
}

Bom analisando o codigo acima, podemos ver que, muito provavelmente, quando executarmos esta classe, ela nunca ira terminar, e por que?
Uma das threads estara executando o metodo passaDeVolta, e ao terminar, ela deveria voltar a execucao do metodo passar, porem a outra thread estara parada no metodo passar, esperando o metodo passarDeVolta completar, e ai temos um lock mortal, ou seja, a thread 1 esperando a thread2 completar, e a thread2 para completar, precisa aguardar a thread1 completar.
Com o codigo, acontece exatamente o que esta acontecendo no cruzamento abaixo:
Aqui e bem facil achar o problema do codigo, agora em um sistema mais complexo isso nao e tao facil, pois as chamadas podem vir de varios lugares diferentes.
Usar thread, com synchronized nao e uma boa opcao em java, sempre que voce precisar usar o synchronized, e bem provavel que voce tenha problemas.


quinta-feira, 25 de abril de 2013

Programação concorrente em Java (Threads)

Programacao concorrente:

Quando estamos usando o computador, muitas vezes estamos fazendo mais de uma coisa ao mesmo tempo, mas nem percebemos. Ouvimos musica, navegamos na internet e muitas vezes editamos documentos, tudo ao mesmo tempo.
Isso ja era possivel, mesmo na epoca dos processadores de um nucleo, coisa que so era possível devido as threads, ou programação concorrente.
Vamos comecar pelo o que e programação concorrente? 
Dizemos que um programa concorrente, e aquele que possui duas, ou mais partes do codigo, que podem ser executadas paralelamente.
Imagine que você esteja fazendo um programa e neste programa, você vai abrir um arquivo muito pesado. Leitura de arquivo e uma coisa bem lenta, e como você sabe que esta operação sera demorada, você quer mostrar uma barra de progresso, para o seu usuário.
Isto so e possivel devido a programação concorrente, que e realizada pelas threads. Cada thread é uma parte do programa que esta rodando, em java a maquina virtual é quem faz uma interface com o sistema operacional, que é quem realmente cuida de como e quando uma thread será executada.
Em java existem duas formas de conseguir rodar um código em paralelo:
  • Implementando a interface java.lang.Runnable
  • Extendendo a classe java.lang.Thread
A intereface Runnable define um método run, que e onde deveremos colocar o código que sera executado pela thread. A classe Thread implementa a interface Runnable.
Uma thread em java pode estar em um dos status mostrados a seguir:
  • NEW: thread criada mas ainda nao iniciada
  • RUNNABLE: quando a thread foi iniciada e pode ser executada pela maquina virtual
  • BLOCKED: quando a thread esta bloqueada esperando pela liberação de um lock para continuar a sua execução.
  • WAITING: Uma thread que esta esperando a execução de uma outra thread terminar para continuar a sua execução.
  • TIMED_WAITING: o mesmo que waiting, porem com um determinado tempo maximo de espera.
  • TERMINATED: uma thread que ja completou a sua execução.
Quando criamos uma thread ela esta no status new, para iniciarmos uma thread executamos o método start, com isso ela passa para o status de runnable.
Abaixo temos um exemplo de como criar uma thread:
public class ExemploConcorrencia implements Runnable{
     public void run{
            // Codigo a ser executado
    }
 Para executar o codigo acima faremos:
new ExemploConcorrencia().start();
 Na linha acima, construimos a thread e iniciamos a sua execução, a partir dai a maquina virtual vai executar o metodo run da thread.
O código colocado dentro do método run nem sempre sera executado por completo, do inicio ao fim. A máquina virtual java pode pausar a execução de uma Thread, para colocar outra Thread no lugar.
As threads tem um atributo chamado prioridade, este atributo influencia em como a máquina virtual vai escolher qual thread deve rodar, por exemplo uma thread com prioridade mínima só vai rodar, quando todas as threads com prioridade máxima estiverem pausadas por algum motivo.
O comportamento para prioridades das threads é diferente de plataforma para plataforma, por isso fique atento ao usar este atributo, pois ele pode ter um comportamento diferente de uma plataforma para outra. A máquina virtual é apenas uma interface para o verdadeiro controlador das threads, que é feito pelo sistema operacional.
Abaixo segue um exemplo de de um código usando Thread:
public class ExemploThread {
   // Mostra uma mensagem de acordo com o nome da thread atual   static void mensagemDaThread(String messagem) {
      String nomeDaThread =
      Thread.currentThread().getName();
      System.out.format("%s: %s%n",nomeDaThread,messagem);
   }
   private static class LoopDaMensagem implements Runnable {
      public void run() {
         String mensagens[] = {
           "Lpoo é a primeira matéria de java"            "Depois vem ALPOO",            "Finalmente quem sobrevive",            "Ai sim pode pegar o diploma"
         };
         try {
            for (int i = 0; i < mensagens.length; i++) {
            // Pause for 4 seconds
               Thread.sleep(4000);
             // Print a message
               mensagemDaThread(mensagens[i]);
            }
         } catch (InterruptedException e) {
            mensagemDaThread("Thread não finalizada!");         }
      }
   }
   public static void main(String args[])throws InterruptedException {
      mensagemDaThread("Iniciando a thread com o loop da mensagem");      long startTime = System.currentTimeMillis();
      Thread[] t = new Thread[5];
      for(int i=0;i<4;i++){
         t[i]= new Thread(new LoopDaMensagem()); 
         t[i].start();
      }
      mensagemDaThread("Esperando a thread terminar");      mensagemDaThread("Finalmente!");
   }
}

E o resultado de rodarmos ele em um ambiente Mac/Os:

main: Iniciando a thread com o loop da mensagem
main: Esperando a thread terminar
main: Finalmente!
main: Iniciando a thread com o loop da mensagem
main: Esperando a thread terminar
main: Finalmente!
Thread-1: Lpoo é a primeira matéria de java
Thread-2: Lpoo é a primeira matéria de java
Thread-4: Lpoo é a primeira matéria de java
Thread-3: Lpoo é a primeira matéria de java
Thread-1: Depois vem ALPOO
Thread-2: Depois vem ALPOO
Thread-4: Depois vem ALPOO
Thread-3: Depois vem ALPOO
Thread-1: Finalmente quem sobrevive
Thread-4: Finalmente quem sobrevive
Thread-3: Finalmente quem sobrevive
Thread-2: Finalmente quem sobrevive
Thread-1: Ai sim pode pegar o diploma
Thread-2: Ai sim pode pegar o diploma
Thread-3: Ai sim pode pegar o diploma
Thread-4: Ai sim pode pegar o diploma
Veja que a sequência de execução das Threads nem sempre é a mesma, e saiba que isso varia de sistema operacional para sistema operacional.

domingo, 21 de abril de 2013

Tratamento de Exceções no Java

Excecoes - Continuacao

Finally

E quando acontece uma excecao em nosso código e tratamos ela, mas mesmo assim ainda temos que fazer algo?

try{
   //Abrimos uma conexao com o banco
   //e vamos salvar um registro, mas e quando acontece uma excecao?
   //ponto 1
} catch(Exception e){
  //Quando a chave do banco e violada, uma exceção será disparada.
  //aqui tratamos a ela.
  //ponto 2

Tudo bem, mas e quando acontece uma exceção, como fica a conexão com o banco de dados?
Bom se fecharmos a conexão no ponto 1, ela nunca sera fechada quando acontecer uma excecao, voce ate pode pensar que a exceção pode ser fechada no ponto 2. 
Ok, mas neste caso, só passamos ali quando acontece uma exceção, e mais para fechar uma conexão com o banco devemos verificar se ela ainda está aberta, neste caso esta lógica ficaria em dois lugares, no ponto 1 e no ponto 2.
Mas e se temos que tratar mais de um tipo de excecao, vamos ter que tentar fechar a conexão com o banco a cada exceção tratada?
Isso nao faz muito sentido certo, bom pra isso e que serve o bloco finally, este bloco vem depois do catch e sempre sera executado, mesmo quando acontecer uma exceção
Aqui é o melhor lugar para colocarmos o código que finaliza a conexão com o banco de dados.

try{
   //Abrimos uma conexao com o banco
   //e vamos salvar um registro, mas e quando acontece uma exceção?
   //ponto 1
} catch(Exception e){
  //Quando a chave do banco e vialoda, uma exceção e disparada.
  //aqui tratamos a exceção.
  //ponto 2
}finally {
  //Aqui fechamos a conexão com o banco, pois esta parte sempre sera executada.
}

Até agora vimos duas maneiras de usar o try em nosso código, a primeira foi usando o try/catch e a segunda usando o try/catch/finally, mas existem três formas de usarmos o try.
A terceira maneira de usar o try é a seguinte:

try{
  //Código
} finally {
 // código que sempre será executado
}

Usando somente o try e o finally a sequência de execução é a mesma, ele executará o código do try, e mesmo quando acontecer uma exceção o código dentro do finally será executado.
O código é executado na mesma sequência que ele é disposto, primeiro o código do try e depois o código do finally.
A sequência de execução do código try é sempre a seguinte, primeiro o código do try é executado, logo após é a vez do código do catch, caso ele esteja presente, logo depois será a vez de executar o código do finally, caso ele esteja presente.

Exercícios:
1) Determine o que acontece com a execução de um código, quando uma exceção é disparada dentro de uma sequência contendo try e finally. Onde esta exceção deve ser tratada? Para onde vai a execução do código depois que uma exceção é disparada?

2) Dado os códigos abaixo, o que acontece quando uma exceção é disparada no ponto 1?


public void metodoExcecao(){
try{
Ponto 1
} finally {
Ponto 2
}
Ponto 3


public void metodoExcecao(){
try{
Ponto 1
} catch(Exception e){
Ponto 2
} finally {
Ponto 3
}

Ponto 4

Qual será a sequencia de execução dos códigos, onde ele passa e onde ele não passa?


segunda-feira, 8 de abril de 2013

Tratamento de erros e Exceções em Java


Exceções e Erros:

Throwable:

Em java temos uma interface chamada Throwable, esta interface é quem determina quais classes podem ser "lançadas" , através do uso da palavra chave throw, no código. Existem duas classes básicas que implementam Throwable, são elas Error (Erro) e Exception (Exceção).

Erros:

Um erro acontece quando há um sério problema com o nosso código, algo que a nossa aplicação não conseguirá tratar, por exemplo:
  • OutOfMemoryError => Erro que acontece quando os nossos programas tentam usar mais memória do que está disponível na máquina virtual
  • StackOverFlowError => acontece quando criamos um loop infinito.
A máquina virtual pode parar de executar por causa dos erros, um exemplo de como conseguir disparar um erro é mostrado a seguir:

//Exemplo de erro de loop infinitopublic boolean stackOverFlow(){   stackOverFlow();   return true;}//Exemplo de erro de estouro de memóriapublic void outOfMemory() {   List lista = new ArrayList();   while(true){      lista.add(new Professor());   }}

Exceções:

Exceções acontecem quando existe alguma coisa de errada no código, ou alguma parte do nosso sistema falha, como o acesso ao banco de dados ficou indisponível (servidor em manutenção), erro de conexão com algum serviço de rede, problemas com a interface de rede, etc.Quando estas falhas acontecem, o nosso sistema não pode parar, ele deve informar ao usuário que aconteceu um erro temporário, e este erro de ver tratado pelo nosso sistema, para mostrar uma mensagem que permita ao usuário entender o que está acontecendo.Toda vez que uma exceção é lançada pelo nosso código, a execução do método/construtor irá parar exatamente onde a exceção foi lançada.
Existem dois tipos de exceções as checáveis e as não checáveis. 


Exceções checáveis:

As exceções checáveis são aquelas onde nós temos que, obrigatoriamente tratá-las, quando um método/construtor as lança, estas exceções extendem Exception.

Exemplo de código com exceção checável:


public void conectaBanco(Connection conexao) throws IllegalArgumentException{
   if(conexao == null){
      throw new IllegalArgumentException("Conexao não pode ser nula");
   }
   //lógica omitida
}

No exemplo acima IllegalArgumentException é uma exceção checável, por isso obrigatoriamente temos que declarar ela na definição do método, usando a palavra throws. Com isso estamos dizendo que este método pode lançar uma exceção deste tipo.
Para acessar o método acima, temos que usar um try catch.

public void acessaConectaBanco() {   try{      conectaBanco(null);   } catch(IllegalArgumentException e) {      e.printStackTrace();   }}

Como IllegalArgumentException é uma exceção checável, obrigatoriamente temos que usar tratá-la no código que chama o método que a dispara e isso é feito através do try catch, que nada mais é do que uma expressão do tipo,
try{   ///tente executar este código}catch (IllegalArgumentException e){   //Caso aconteça uma exceção do tipo illegal argument exception, trate-a aqui.}

Voltando aos conceitos de orientação a objeto, o mesmo código poderia ter sido escrito assim:
public void acessaConectaBanco() {
   try{
      conectaBanco(null);
   } catch(Exception e) {
      e.printStackTrace();
   }
}

já que IllegalArgumentException extende Exception, que é a classe básica des exceções.

Exceções não checáveis:

As exeeções não checáveis, são as exceções que quando lançadas, não precisam ser declaradas no método/construtor, nem tratadas pelo código que executa o método/construtor, estas exceções extendem a classe RunTimeException.
Exceções não checadas:
public void conectaBancoRuntime(Connection conexao){
   if(conexao == null){
      throw new RuntimeException("Conexao nap pose set null");
   }
   //lógica omitida
}
Como estas exceções não precisam ser tratadas, nem declaradas, o mesmo código mostrado acima, poderia ter sido rescrito da seguinte maneira:

public void acessaConectaBancoRuntime() {
   conectaBancoRuntime(null);
}

Neste caso, quando chamarmos este método, a exceção será tratada pela classe que chamou o método acessaConexaoBancoRuntime.
Caso você queira tratar esta exceção lançada, você pode, usando um try catch, da seguinte forma:

public void acessaConectaBancoRuntime() {
   try{
      conectaBancoRuntime(null);
   } catch(RuntimeException e) {
      //tratamento de uma exceção
  }
}

PrintStackTrace:


A interface Throwable define um método chamado printStackTrace(); este método irá imprimir no console toda a lista de métodos que foi usada para chamar o método da exceção, no caso do método acessaConectaBanco, ele irá imprimir o seguinte:

Exception in thread "main" java.lang.IllegalArgumentException: Conexão não pode ser nula
at br.unip.erros.ExemploDeErros.conectaBanco(ExemploDeErros.java:39)
at br.unip.erros.ExemploDeErros.main(ExemploDeErros.java:48)
Acho podemos ver que a exceção aconteceu na thread main (thread principal do programa), foi uma exceção do tipo IllegalArgumentException. Aqui vemos também que a exceção foi lançada no método conectaBanco da classe ExemploDeErros na linha 39.

Exceções quando usar?

Visto os conceitos de exceções, ficamos tentados a extender a classe exception e criar um erro para cada atitude errada dos nossos usuários, ou para cada caso em que um método não retorne algo esperado, por exemplo, em uma tela de login, quando o usuário digita a senha errada, é muito mais fácil criarmos uma exceção SenhaInvalidaException e dispará-la, para depois tratarmos.
Na verdade, muitos dos exemplos encontrados na internet sobre exceções, incentivam este comportamento. A dica para usar é a seguinte:
Quando o seu cliente pode tomar alguma atitude que contornará a exceção, use exceção checada, já se o cliente não poderá fazer nada para contornar a exceção, use uma exceção não checada.
Dentre as principais desvantagens das exceções que podemos citar são:

  • Elas aumentam a quantidade de código escrita
  • Torna o código mais difícil de ler
  • Fragilizam a assinatura dos métodos
  • Não funcionam bem com interfaces
  • São pesadas demais
Carregar a stacktrace para mostrar no método printstacktrace não é uma operação nada fácil, isso requer várias operações na máquina virtual que são muito custosas, portanto a dica é evitar ao máximo.
Exceções devem ser usadas somente quando algo de extraordinário acontece, quando o resultado do método é algo esperado (é esperado que o usuário digite a senha errada, portanto o retorno deve ser algo que indique isso, e não uma exceção). Quando o comportamento do método for realmente algo que não de para tratar, ai sim devemos criar e disparar uma exceção.

Exercícios:

1) Determinar quais das exceções abaixo são do tipo checked, ou unchecked:
java.lang.NullPointerException
java.io.IOException
java.lang.NumberFormatException
java.lang.IllegalArgumentException

2) Altere a classe professor e faça com que ela dispare uma IllegalArgumentException quando ela receba um nome nulo ou vazio, um sobrenome nulo ou vazio.

3) Altere a classe matéria e faça com que ela dispare uma exceção IllegalArgumentException quando ela receba um Curso nulo.