Aula Prática 3

Prazo de entrega: 1 semana (conferir no Moodle)

Exercício 1: Gerador de CPF

Números de CPF (Cadastro de Pessoa Física) possuem nove dígitos mais dois dígitos verificadores. As regras para cálculo dos digítos verificadores são as seguintes. Usaremos como exemplo o número 123456789:

  1. Calcule a soma dos produtos dos nove dígitos utilizando peso 2 para unidade, peso 3 para dezena, peso 4 para centena e assim sucessivamente. Exemplo: \(9 \times 2 + 8 \times 3 +\) \(+7 \times 4 + 6 \times 5 + 5 \times 6 + 4 \times 7 + 3 \times 8 + 2 \times 9 + 1 \times 10 = 210\).

  2. A dezena do número verificador é 0 caso o resto da divisão por 11 da soma dos produtos seja 0 ou 1. Caso contrário a dezena corresponde a subtrair de 11 o resto da divisão por 11 da soma dos produtos. Exemplo: o resto da divisão de 210 por 11 é 1, então a dezena do número verificador é 0.

  3. Calcule a soma dos produtos dos dez digitos, onde o digito menos significativo passa a ser a dezena dos digitos verificadores, utilizando os seguintes pesos: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11. Exemplo: \(2 \times 0 + 3 \times 9 + 4 \times 8 + 5 \times 7 + 6 \times 6 + 7 \times 5 + 8 \times 4 + 9 \times 3 +\) \(+ 10 \times 2 + 11 \times 1 = 255\).

  4. A unidade do número verificador é 0 caso o resto da divisão da soma dos produtos por 11 seja 0 ou 1. Caso contrário a unidade corresponde a 11 menos o resto da divisão por 11 da soma dos produtos. Exemplo: resto da divisão de 255 por 11 é 2, então a unidade do número verificador é \(11 - 2 = 9\).

Escreva um programa para calcular o dígito verificador de CPF dados os nove dígitos do CPF. Para calcular resto de dívisão em C use o operador de módulo:

int x = 5 % 2; /* x = 1 */
int y = 21 % 3; /* y = 0 */
int z = 43 % 5; /* z = 3 */

Exemplo de resposta: O CPF 123.456.789 com dígitos verificadores é 123.456.789-09.

Exercício 2: Manipulação de bits

Este exercício tem como objetivo praticar a operação de deslocamento de bits << e >>. Faça uma função que receberá um inteiro expoente , e retorna um unsigned long long contendo a potência de dois correspondente. Protótipo:

unsigned long long fast_pow_2(int expoente);

Exercício 3: Chamada otimizada

Este exercício tem como objetivo praticar as operações de bitwise & |. Você deverá fazer uma função auxiliar para um programa de lista de chamada. Sua função receberá um inteiro tipo unsigned long long (64 bits). Cada um dos 64 bits representa um aluno.

Desenvolva uma função que recebe um inteiro pos indicando que o aluno da posição pos na lista de chamada está presente e, por isso, o bit correspondente a ele deve ser 1. As posições estão númeradas de 0 a 63, da direita para a esquerda. Dessa forma, o bit menos significativo está na posição 0 e representa o primeiro aluno da lista de chamada, e o bit mais significativo está na posição 63. Para modificar o conteúdo da variável que grava quais alunos estão presentes, sua função receberá o valor por referência (através de um ponteiro). Protótipo:

void respondeu_chamada(unsigned long long alunos, int pos);

Teste: Teste seu programa chamando a função respondeu_chamada algumas vezes e verifique o resultado usando printf("%llx\n", lista).

Exercício 4: Biblioteca de funções

Todos os exercícios descritos abaixo pedem que uma função seja implementada. As funções implementadas devem ter, obrigatoriamente, o nome sugerido pelo exercício. Implementem todas as funções em um único arquivo .c, que também deverá ter o main para você testar suas funções. Um exemplo de arquivo que você pode utilizar para testar as funções se encontra no final deste exercício. Note que o código confere se as suas funções dão os resultados esperados através da função testaValores.

Exercícios

  1. Implementar uma função que recebe como parâmetro uma velocidade em km/h (quilômetros por hora) e retorne a mesma convertida para m/s (metros por segundo). A fórmula de conversão é \(M = K / 3.6\), sendo \(K\) a velocidade em km/h e \(M\) a velocidade em m/s. Protótipo:
float paraMetrosPorSegundo(float v);
  1. Implementar uma função que recebe como parâmetro o raio de um círculo e retorne a área do círculo correspondente. A área do círculo é \(A = \pi \times raio^2\), sendo que \(\pi = 3.141592\). Protótipo:
float areaCirculo(float raio);
  1. Implementar uma função que recebe como parâmetro um número inteiro \(n\) e retorne \(1\) se ele for par e \(0\) caso ele seja ímpar. Protótipo:
int ehPar(int n);
  1. Implementar uma função que recebe como parâmetro um número inteiro \(n\) e retorne a \(1\) se ele for divisível por \(3\) ou por \(5\), mas não simultaneamente pelos dois, ou \(0\) caso contrário (divisível por \(3\) e \(5\) ou por nenhum dos dois). Protótipo:
int ehDivisivelPor3ou5(int n);
  1. Implementar uma função que recebe como parâmetro a altura \(h\) em metros (exemplo: \(1.70\)) e o sexo 'M' para masculino e 'F' para feminino) de uma pessoa e retorne o seu peso ideal \(PI\), sendo que \(PI=(72.7\times h) - 58\) caso o sexo seja masculino e \(PI=(62.1\times h) - 44.7\) caso feminino. Protótipo:
float pesoIdeal(float h, char sexo);
  1. Implementar uma função que recebe como parâmetro três números inteiros maiores que zero (não precisa testar) \(x,y,z\) e uma operação numérica que pode assumir os valores \(1,2,3\) e \(4\). Caso a operação seja \(1\), a função deve calcular a média geométrica, caso seja \(2\), a média ponderada, caso seja \(3\), a média harmônica e, por fim, caso seja \(4\), a média aritmética. Olhar a Tabela abaixo para as fórmulas. Protótipo:
float calculaMedia(int x, int y, int z, int operacao);
Operação Média Fórmula
1 Geomética \(\sqrt[3]{x\times y\times z}\)
2 Ponderada \(\frac{x + 2y + 3z}{6}\)
3 Harmônica \(\frac{3}{1/x + 1/y + 1/z}\)
4 Aritmética \(\frac{x+y+z}{3}\)
  1. Implementar uma função que recebe como parâmetro um número inteiro \(N\) e retorne a soma dos números ímpares de 0 até \(N\) (incluindo \(N\), se \(N\) for ímpar). Protótipo:
int somaImpares(int N);
  1. Implementar uma função que recebe como parâmetro um número inteiro \(N\) e retorne o seu fatorial. Exemplo: o fatorial de 5 = \(5! = 5\times 4\times 3\times 2\times 1 = 120\). Protótipo:
double fatorial(int N);
  1. Implementar uma função que recebe como parâmetro um número inteiro \(N\) e retorne a soma de todos os números positivos menores ou iguais a \(N\) que são divisíveis por \(3\) ou por \(5\), mas não por ambos. Exemplo: para \(N==20\), a soma é \(3 + 5 + 6 + 9 + 10 + 12 +\) \(+ 18 + 20 = 83\). Protótipo:
int somaNumerosDiv3ou5(int N);
  1. Implementar uma função que recebe como parâmetro um número inteiro \(N\) e retorne o seu número de divisores. Exemplo: os divisores de \(66\) são \(8\): \(1, 2, 3, 6, 11, 22, 33, 66\). Protótipo:
int numeroDivisores(int N);
  1. Implementar uma função que recebe como parâmetro um número inteiro positivo \(N\) e retorne o enésimo termo da sequência de Fibonacci. Essa sequência começa no termo de ordem zero e, a partir do segundo termo, seu valor é dado pela soma dos dois termos anteriores. Exemplo: para \(N = 8\), o enésimo termo é \(13\), uma vez que a sequência de Fibonacci até o oitavo termo é: \(0, 1, 1, 2, 3, 5, 8, 13\). Protótipo:
int enesimoFibonacci(int N);

Extra

Coloca suas funções em um módulo separado e utilize seu módulo como uma biblioteca no programa de testes abaixo.

Programa de testes

#include <stdio.h>

// implementar funcoes aqui:

// exemplo:
float paraMetrosPorSegundo(float v) {
   return 0.0
}

// fim da implementacao das funcoes

int testaValores(float v1, float v2) {
   // Evitar comparacoes de igualdade entre floats. 
   // Converter para int e usar 2 casas decimais multiplicando por 100
   int t1 = (int)(v1*100); 
   int t2 = (int)(v2*100);
   if(t1 == t2) {
      printf("acertou! :)\n");
      return 1;
   }
   printf("errou! :(\n");
   return 0;
}

int main(int argc, char **argv) {
   int acertos = 0;
   printf("teste exercicio 1: ");
   acertos = acertos + testaValores(paraMetrosPorSegundo(100), 27.777);
   printf("teste exercicio 2: ");
   acertos = acertos + testaValores(areaCirculo(10), 314.159);
   printf("teste exercicio 3a: ");
   acertos = acertos + testaValores(ehPar(146), 1);
   printf("teste exercicio 3b: ");
   acertos = acertos + testaValores(ehPar(145), 0);
   printf("teste exercicio 4a: ");
   acertos = acertos + testaValores(ehDivisivelPor3ou5(15), 0);
   printf("teste exercicio 4b: ");
   acertos = acertos + testaValores(ehDivisivelPor3ou5(20), 1);
   printf("teste exercicio 4c: ");
   acertos = acertos + testaValores(ehDivisivelPor3ou5(27), 1);
   printf("teste exercicio 5a: ");
   acertos = acertos + testaValores(pesoIdeal(1.90, 'M'), 80.13);
   printf("teste exercicio 5b: ");
   acertos = acertos + testaValores(pesoIdeal(1.90, 'F'), 73.29);
   printf("teste exercicio 6a: ");
   acertos = acertos + testaValores(calculaMedia(10,20,30,1), 18.171);
   printf("teste exercicio 6b: ");
   acertos = acertos + testaValores(calculaMedia(10,20,30,2), 23.333);
   printf("teste exercicio 6c: ");
   acertos = acertos + testaValores(calculaMedia(10,20,30,3), 16.363);
   printf("teste exercicio 6d: ");
   acertos = acertos + testaValores(calculaMedia(10,20,30,4), 20);
   printf("teste exercicio 7: ");
   acertos = acertos + testaValores(somaImpares(21),121);
   printf("teste exercicio 8: ");
   acertos = acertos + testaValores(fatorial(5),120);
   printf("teste exercicio 9: ");
   acertos = acertos + testaValores(somaNumerosDiv3ou5(20),83);
   printf("teste exercicio 10: ");
   acertos = acertos + testaValores(numeroDivisores(66),8);
   printf("teste exercicio 11: ");
   acertos = acertos + testaValores(enesimoFibonacci(8),13);

   printf("\nVoce acertou %d de 18 testes!\n", acertos);
   getchar();
   return 0;
}

Profs. Pedro O. S. Vaz de Melo e Ítalo F. S. Cunha

vim: tw=68