linguagem c funções e...
TRANSCRIPT
Linguagem C – funções e registros
IF61A/IF71A - Computação 1
Prof. Leonelo Almeida
Universidade Tecnológica Federal do Paraná
Até agora ...
• Introdução à linguagem C
▫ ...
▫ Operadores aritméticos, de comparação e lógicos
▫ Entrada e saída de dados
▫ Estruturas condicionais
▫ Estruturas de repetição
▫ Vetores
▫ Matrizes
▫ Funções
Aula de hoje
Crie uma função que recebe 100 variáveis inteiras e retorna a média de seus valores
Tentativa:
float media (int val1, int val2,
int val3, ..., int valn)
Funciona, mas cansativo, não?
Ainda hoje
• Declare uma (coleção de) variável(is) que contenha:
▫ Nome da pessoa
▫ Altura
▫ 3 cores preferidas
Ainda hoje
• Declare uma (coleção de) variável(is) que contenha:
▫ Nome da pessoa
▫ Altura
▫ 3 cores preferidas
Posso usar um vetor ou uma
matriz?
Aula de hoje
Vetores e matrizes como parâmetros em funções
Recursão
Coleções de variáveis heterogêneas
Passagem de vetores como parâmetros
de funções • Vetores unidimensionais
▫ Não precisa passar o tamanho do vetor na declaração da função
• É diferente da passagem de parâmetros de variáveis normais ▫ Quando uma variável simples é passada como
parâmetro, seu valor é atribuído para uma nova variável local da função
▫ No caso de vetores, não é criado um novo vetor!
▫ Os valores de um vetor são alterados dentro de uma função!
Declaração
tipo identificador (tipo vetor[],
tipo vetor2[TAM], ...) {
... }
• Exemplo: float funcVets (int veti[], float vetf[10]) {
... }
Exemplo - Passagem de vetores como
parâmetros de funções #include <stdio.h>
void fun1(int vet[], int tam){
int i;
for(i=0;i<tam;i++)
vet[i]=i+1;
}
int main(void){
int x[10];
int i;
for(i=0;i<10;i++)
x[i]=8;
fun1(x,10);
for(i=0;i<10;i++)
printf(“%d\n”, x[i]);
return;
}
O que será impresso?
Passagem de vetores
multidimensionais como parâmetros • Também são alterados pelas funções
• Somente a primeira dimensão pode ser omitida
• Declaração tipo identificador (tipo vetor[][TAM1][TAM2], ...)
• Exemplos int getDateCountry (int vet[][31][12][3000])
int getPotMat (int pot, float mat[2][3])
Retorno de funções
• Vetores não podem ser retornados por funções • No entanto, como eles são alterados pelas
funções o efeito é parecido
• Contraexemplo:
#include <stdio.h>
int[] leVet(void) {
int i, vet[100];
for (i = 0; i < 100; i++) {
printf("Digite um numero:");
scanf("%d", &vet[i]);
}
} ...
Esse código está incorreto!
Exemplo
#include <stdio.h>
void leVet(int vet[], int tam){
int i;
printf("Digite %d numeros: ",tam);
for(i=0; i<tam; i++)
scanf("%d",&vet[i]);
}
void escreveVet(int vet[], int tam){
int i;
for(i=0; i<tam; i++)
printf("vet[%d] = %d\n",i,vet[i]);
}
Exemplo - continuação
int main(){
int vet1[10], vet2[20];
leVet(vet1,10);
leVet(vet2,20);
escreveVet(vet1,10);
escreveVet(vet2,20);
return 0;
}
Exemplo – Operações em matrizes
• Faça um programa com operações básicas em matrizes quadradas. Onde o tamanho n é informado pelo usuário:
▫ Soma de 2 matrizes com dimensões nxn.
▫ Subtração de 2 matrizes com dimensões nxn.
▫ Calculo da transposta de uma matriz de dimensão nxn.
▫ Multiplicação de 2 matrizes com dimensões nxn.
Exemplo – Operações em matrizes
• Leitura da matriz
void leMatriz(double mat[][MAX], int n){
int i, j;
printf(“Lendo dados da matriz
(linha por linha)\n”);
for(i=0; i<n; i++){
for(j=0; j<n; j++){
scanf(“%lf”, &mat[i][j]);
}
}
}
Exemplo – Operações em matrizes
• Escrita da matriz
void imprimeMatriz(double mat[][MAX], int n){
int i, j;
printf(“dados da matriz
(linha por linha)\n”);
for(i=0; i<n; i++){
for(j=0; j<n; j++){
printf(“%.2lf”, mat[i][j]);
}
printf("\n");
}
}
Exemplo – Operações em matrizes
• Multiplicação de matrizes
void multiplica(double mat1[][MAX], double mat2[][MAX], double resp[][MAX], int n){
int i, j, k;
for(i=0; i<n; i++){
for(j=0; j<n; j++){
resp[i][j] = 0;
for(k=0; k<n; k++){
resp[i][j] = resp[i][j] + (mat1[i][k]*mat2[k][j]);
}
}
}
}
Exemplo – Operações em matrizes #include <stdio.h>
#define MAX 100
void leMatriz(double mat[][MAX], int n);
void imprimeMatriz(double mat[][MAX], int n);
void multiplica(double mat1[][MAX], double mat2[][MAX], double
resp[][MAX], int n);
int main() {
double mat1[MAX][MAX], mat2[MAX][MAX], mat3[MAX][MAX];
int n;
printf("Qual dimensão das matrizes: ");
scanf("%d", &n);
leMatriz(mat1, n);
leMatriz(mat2, n);
multiplica(mat1, mat2, mat3, n);
imprimeMatriz(mat1, n);
imprimeMatriz(mat2, n);
imprimeMatriz(mat3, n);
return 0;
}
Atividades
• Agora complete o programa de operações básicas sobre matrizes quadradas:
▫ Pergunte ao usuário que operação deseja realizar
▫ Crie funções para as demais operações
Atividades
• Crie uma função double media(int vet[], int tam) que recebe como parâmetros um vetor e
seu tamanho e devolve a media dos valores armazenados no vetor.
• Crie uma função char ordenado(int vet[], int tam) que recebe como parâmetros um vetor
e seu tamanho e devolve ‘C’ se os valores no vetor estão em ordem crescente, ‘D’ se decrescente, e ‘N’ caso esteja desordenado.
Atividades
• Crie uma função int verifica(int vet[], int tam, int C) que recebe como parâmetros um
vetor, seu tamanho e um inteiro C. A função deve retornar 1 caso existam dois elementos distintos do vetor tal que a multiplicação destes e C.
Recursão
Baseado no material: http://www.lis.ic.unicamp.br/~mc102/files/mc102jk-a18-4pp.pdf
Recursão
Para compreender o que é recursão ...
... é preciso compreender o que recursão.
Recursão
• Uma função é recursiva se ela chama a si mesma direta ou indiretamente
• Organização de uma recursão
▫ Processo de indução
Definir a solução para os caso(s) básico(s)
Definir as chamadas recursivas. O objeto define em termos de si mesmo.
Exemplo de recursão
• Soma dos n primeiros inteiros
▫ Se n = 1 então a soma é 1
▫ Se n > 1 então a soma é:
O próprio n + soma dos n-1 primeiros
Em outras palavras ...
• Já terminou o cálculo?
▫ Se sim então retorne o resultado
▫ Senão simplifique o problema. Para tanto, calcule o problema em termos mais simples e encaixe os resultados para compor a solução final.
• Sem a condição de parada, a recursão executaria infinitamente
Voltando ao exemplo
• Caso base: somar 1 elemento (resultado = 1)
• Chamada recursiva:
▫ Soma de n elementos: n + soma de n-1 elementos
▫ Soma de n-1 elementos: n -1 + soma de n-2 elementos
▫ Soma de n-2 elementos: n-2 + soma de n-3 elementos
▫ ...
▫ Soma de 2 elementos: 2 + soma de 1 elemento
▫ Soma de 1 elemento: 1 (caso base)
Exemplo
• Como seria o código dessa função?
int soma(int n) {
if (n <= 1)
return n;
else
return (n + soma(n-1));
}
Exemplo
• Como seria o código dessa função?
int soma(int n) {
if (n <= 1)
return n;
else
return (n + soma(n-1));
}
Caso base
Chamada recursiva
Como fica a execução? • Chamada para soma (4)
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3)
▫ Chamada para soma(3)
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3)
▫ Chamada para soma(3)
▫ n = 3
▫ resultado = 3 + soma(2)
Chamada para soma(2)
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3)
▫ Chamada para soma(3)
▫ n = 3
▫ resultado = 3 + soma(2)
Chamada para soma(2)
n = 2
resultado = 2 + soma(1)
Chamada para soma (1)
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3)
▫ Chamada para soma(3)
▫ n = 3
▫ resultado = 3 + soma(2)
Chamada para soma(2)
n = 2
resultado = 2 + soma(1)
Chamada para soma (1)
n = 1
resultado = 1
Chegamos ao caso base!
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3)
▫ Chamada para soma(3)
▫ n = 3
▫ resultado = 3 + soma(2)
Chamada para soma(2)
n = 2
resultado = 2 + soma(1) //2 + 1
Chamada para soma (1)
n = 1
resultado = 1
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3)
▫ Chamada para soma(3)
▫ n = 3
▫ resultado = 3 + soma(2) //3 + 3
Chamada para soma(2)
n = 2
resultado = 2 + soma(1)
Chamada para soma (1)
n = 1
resultado = 1
Como fica a execução? • Chamada para soma (4)
• n = 4
• resultado = 4 + soma (3) // 4 + 6 =
▫ Chamada para soma(3)
▫ n = 3
▫ resultado = 3 + soma(2)
Chamada para soma(2)
n = 2
resultado = 2 + soma(1)
Chamada para soma (1)
n = 1
resultado = 1
10
Exemplo 2
• Somar todos os inteiros no intervalo entre [m, n]
• Caso base: se n=m retorna m (ou n)
• Chamada recursiva:
▫ Se n > m, n + soma do intervalo [n-1, m]
▫ Senão n + soma do intervalo [n+1, m]
Exemplo 2
• Somar todos os inteiros no intervalo entre [m, n] int soma_mn (int m, int n) {
if (n == m)
return m;
else
if (m < n)
return n + soma_mn(m, n-1);
else
return n + soma_mn(m, n+1);
}
Caso base
Chamada recursiva
Exemplo 3 #include <stdio.h>
void imprime(int v[], int i, int n);
int main(){
int vet[] = {1,2,3,4,5,6,7,8,9,10};
imprime(vet, 0, 9);
printf("\n");
}
void imprime(int v[], int i, int n){
if(i==n)
printf("%d, ", v[i]);
else {
imprime(v,i+1,n);
printf("%d, ", v[i]);
}
}
O que será impresso após executar esse
programa?
Atividades
• Crie uma função recursiva que calcula o fatorial de um número n (n!)
• Crie uma função recursiva que calcula a potência p de um número n.
• A série de fibonacci é a seguinte:
▫ 1, 1, 2, 3, 5, 8, 13, 21, ...
• Qual é o n-ésimo (fibo(n)) número da série?
Coleções de variáveis heterogêneas
(Registros)
Coleções de variáveis heterogêneas
• Mais conhecidos como registros
• Agrupam várias variáveis que podem ser de tipos de dados diferentes, mas que compartilham um contexto comum
• Exemplo:
▫ Registro de alunos: nome, RA, notas das provas, etc
▫ Registro de veículos: modelo, ano, tamanho do tanque, cor, etc
Declaração de registros
struct identificador_do_tipo {
tipo_1 nome_1;
tipo_2 nome_2;
tipo_3 nome_3;
...
tipo_n nome_n;
};
• Exemplo: struct Aluno {
char nome[45];
int idade;
char genero;
}
Declaração de registros
#include <stdio.h>
struct Aluno {
char nome[45];
int idade;
char genero;
}
int main() {
struct Aluno a, b;
}
São variáveis do tipo “struct aluno”.
Usando uma struct
• Para acessar uma das variáveis de um registro basta: ▫ nome_registro.nome_variavel
• A partir daí o funcionamento de operações sobre as variáveis são os mesmos que de variáveis comuns do mesmo tipo.
Exemplo #include <stdio.h>
#include <string.h>
struct Aluno{
char nome[45];
int idade;
char genero;
};
int main(){
struct Aluno a, b;
strcpy(a.nome, “Helen”);
a.idade = 18;
a.genero = ‘F’;
strcpy(b.nome, “Dilbert”);
b.idade = 34;
b.genero = ‘M’;
printf(“A nome = %s, idade = %d, gênero = %c\n”, a.nome, a.idade, a.genero);
printf(“B nome = %s, idade = %d, gênero = %c\n”, b.nome, b.idade, b.genero);
}
Atribuição de registros
• É possível atribuir um registro ao outro.
• Exemplo: int main(){
struct Aluno a, b;
printf(“Digite o nome:”);
scanf(“%[^\n]”, a.nome);
printf(“Digite a idade:”);
scanf(“%d”, &a.idade);
printf(“Digite o gênero:”);
scanf(“%c”, &a.genero);
b = a;
printf(“B nome = %s, idade = %d, genero = %c\n”, b.nome, b.idade, b.genero);
}
Cada campo de “a” é copiado para “b”.
Mas os dois continuam
independentes.
Vetores de registros
• Para quando precisamos de várias instâncias do mesmo tipo de registro
• Exemplo:
▫ Declaração: struct Aluno turma[49];
▫ Para usar: turma[posicao].campo;
Atividade
• Encontre no projeto do curso e defina todos os registros que deverão ser criados.
Extras
Redefinição de tipos de dados
Tipos enumerados
Redefinição de tipo de dados
• Permite criar um tipo de dados, que se comporta da mesma maneira que um dos tipos de dados já existentes
• Na linguagem isso é feito com o comando typedef
• Declaração: typedef tipo_existente novo_tipo;
• Exemplo: typedef float nota;
nota n1, n2, n3, n4;
Typedef para registros
• Uso comum • Simplifica a declaração
• Exemplo: struct RegAluno {
int ra;
double nota;
};
typedef struct RegAluno Aluno;
Aluno turma[10];
turma[0].ra = 23456;
turma[0].nota = 5.4;
...
Tipos enumerados
• Quando queremos armazenar, por exemplo, o mês em uma variável, geralmente utilizamos um valor inteiro
• Exemplo:
▫ mes = 1;
• E se pudéssemos usar algo como:
▫ mes = janeiro;
• Não tornaria o código mais claro?
Tipos enumerados include <stdio.h>
//aqui criamos um novo tipo enumerado
//que pode ser usado por qualquer função
enum meses {jan = 1, fev, mar, abr, mai, jun, jul, ago, set,
out, nov, dec};
int main(){
//aqui criamos 2 variáveis do tipo "enum meses"
enum meses a, b;
a = jan;
b = jun;
if(a != b){
printf(“%d é um mês diferente de %d”, a, b);
}
}