Programação C/C++ Slide 5 Nielsen Castelo Damasceno Programação estruturada Programação estruturada Programação estruturada Programação estruturada Programação estruturada vetores vetores vetores vetores vetores vetores Vetores e constantes Vetores e constantes Vetores (Regras) Vetores (caracteres) Vetores (strings) Vetores (strings) Vetores (strings) Funções básicas (strings) Funções básicas (strings) Funções FUNÇÕES Função main Função Função Função Função Função FUNÇÕES (CMATH) Definindo uma função tipo_da_função nome_da_função (lista de parâmetros) { corpo da função } • A lista de parâmetros, também chamada de lista de argumentos, é opcional. A função pode não ter entrada (void). O comando return A instrução return expressão; tem os seguintes efeitos: 1) avaliação da expressão 2) conversão automática do resultado da expressão para o tipo da função 3) retorno do resultado 4) término da execução da função e retorno do controle para a instrução seguinte do código de chamada Sintaxe de um comando return: • return; • return expressão; • return (expressão); O comando return • No exemplo anterior, temos a definição das funções: Função com um comando return Função com mais de um comando return O comando return • Funções do tipo void podem ter um comando return sem expressão, servindo para terminar a execução da função • Em funções do tipo void, o comando return não é obrigatório • Uma função sem comando return termina quando encontra a chave de fechamento • O valor de retorno é obtido através de uma chamada à função, como no exemplo: Funções definidas pelo usuário Declaração e definição de funções • Em geral, o nome de uma função aparece em três lugares em um programa: 1) na declaração (protótipo/assinatura) 2) na definição 3) na chamada Exemplo Declaração de funções (protótipos) Chamadas de funções Definição de funções Declaração de uma função A declaração de uma função, dita protótipo da função, é uma instrução, geralmente colocada no início do programa, que estabelece o tipo da função e os argumentos que ela recebe. • Uma função não pode ser chamada sem antes ter sido declarada • No exemplo, temos a declaração das funções: • a função de nome le_numero() é do tipo int e não recebe argumentos • a função de nome max() é do tipo int e recebe como argumento dois valores do tipo int Observações 1) No protótipo de uma função, o seu tipo, o número e o tipo dos parâmetros devem corresponder àqueles do cabeçalho da definição. 2) O nome dos parâmetros podem ser omitidos na declaração. 3) Se uma função não tem parâmetros, pode-se declarar a lista de parâmetros como (void) ou simplesmente () Outras observações 1) Se uma função é definida antes da sua primeira chamada, esta não precisa ser declarada. 2) O comando return pode retornar somente um único valor. 3) Se uma função não tem valor de retorno, deve-se indicar o tipo de retorno como void 4) Não se pode definir funções dentro de uma outra função. Escopo de variáveis O escopo de uma variável é o bloco de código onde esta variável é válida • As variáveis podem ser declaradas em três lugares: 1)dentro de funções variáveis locais 2)como parâmetros de funções parâmetros formais 3)fora de todas as funções variáveis globais Variáveis locais void funcao1(void) { int x; x = -10; } void funcao2(void) { int x, y; x = 2; y = 18; } • São visíveis apenas dentro de seu próprio bloco de código. Um bloco de código é delimitado por { }. • O espaço de memória usado pela variável é liberado na saída do bloco de código. Variáveis globais • São visíveis no programa inteiro. • O espaço de memória fica reservado durante toda a execução do programa. Variáveis globais São úteis quando o mesmo dado é usado em muitas funções Ocupam espaço de memória mesmo quando desnecessárias Podem levar a erros no programa Variáveis globais x locais Qual a diferença entre as funções? int produto(int x, int y) { return (x * y); } int x, y; int produto(void) { return (x * y); } Variáveis globais x locais Qual a diferença entre as funções? int produto(int x, int y) { return (x * y); } int x, y; int produto(void) { return (x * y); } Parâmetros de uma função Variáveis locais que são inicializadas pelos valores passados na chamada da função. • São visíveis apenas dentro da função: são criadas na entrada e destruídas na saída da função • No momento da chamada de uma função, o número e o tipo dos parâmetros devem corresponder à declaração da função • Os parâmetros são convertidos automaticamente para os tipos da declaração antes de serem passados à função Passagem de parâmetros • Em geral, pode-se passar parâmetros para funções de duas maneiras: 1) Por valor: o valor do argumento é copiado para o parâmetro e as alterações feitas no parâmetro não tem efeito sobre a variável usada na chamada da função 2) Por referência: o endereço de uma variável copiado para o parâmetro, assim as mudanças feitas no parâmetro afetam a variável usada na chamada da função Passagem de parâmetros por valor o valor de n é copiado para o parâmetro x da função quadrado() a variável n, usada para chamar quadrado(), ainda tem o valor 10 na atribuição, apenas a variável local x é modificada Passagem de parâmetros por referência Operador unário de referência & A referencia de n é passado para o parâmetro x da função quadrado() a variável n, usada para chamar quadrado(), teve seu valor modificado na atribuição, a variável referenciada por x é modificada Passagem de parâmetros por valor • Considere o seguinte programa: Exercício Faça um programa que calcula as raízes de uma equação do 2 segundo grau (ax bx c 0) , onde a, b e c são números reais fornecidos pelo usuário. Observação: use funções para calcular e imprimir o resultado. Exercício • Implemente duas funções uma que converte em Real para dólar e outra que faz a operação inversa. • Chame essa função através do main. • O programa deve ter uma boa interação com usuário. • Mostre a cotação do dólar utilizado. Problema 1 • Crie uma função para encontrar o maior entre 3 inteiros. O usuário entra com os inteiros e o programa imprime os 3 inteiros e mostrando o maior elemento. Local e global Uso do define Constantes Operador (?:) Problema 2 • Escreva um programa que calcula a soma dos quadrados de dois números fornecido pelo usuário. • Implemente 3 funções: Calcula a soma dos quadrados de dois números, calcula o quadrado de um número e calcula a soma de dois números. • A função main deve chamar somente a função que apresente todo o resultado. Funções e variáveis globais Funções e variáveis globais Funções e variáveis globais Passando array a função • Para passar um argumento array a uma função, especifique o nome do array sem colocar colchetes. Por exemplo, se o array temperaturaPorHora for declarado como Passando array a função Exercício • Crie um programa em que o usuário entre com o tamanho do vetor. • A função main deve chamar outra função que preenche os valores desse vetor aleatoriamente (passando como parâmetro o vetor e seu tamanho). • Crie uma função que imprima esse vetor (passando como parâmetro o vetor e seu tamanho). • A função deve ser chamada pelo main. • Pesquise na Internet a função rand. Argumento de defaults Setprecision Variável static Exemplo Exemplo Problema 3: Passeio do cavalo • Um dos problemas mais interessantes para os fãs do jogo de xadrez é o problema do Passeio do Cavalo, proposto originalmente pelo matemático Euler. • A questão é esta: a peça do jogo de dez chamada ao cavalo pode se mover ao longo de um tabuleiro vazio e passar uma única vez em cada uma 64 casas? Problema 3: Passeio do cavalo • O cavalo faz movimentos em formato de L (percorre duas casas em uma direção e uma no sentido perpendicular às duas primeiras). Dessa forma, de uma casa no meio do tabuleiro, o cavalo pode fazer movimentos diferentes (numerados de 0 a 7). Problema 3: Passeio do cavalo • Desenhe um tabuleiro de xadrez 8-por-8 em uma folha de papel e tente fazer o Passeio do Cavalo a mão, Coloque um 1 no primeira casa para a qual se mover, um 2 na segunda casa, um 3 na terceira etc. • Antes de começar os movimentos, imagine até onde você chegará, lembrando-se que um passeio completo consiste em 64 movimentos. • Até onde você chegou? Você chegou perto do quanto havia imaginado? Problema 3: Passeio do cavalo Problema 3: Passeio do cavalo • Escreva um programa para mover o cavalo pelo tabuleiro de xadrez. • Rode o programa. • Quantos movimentos o cavalo fez? • Depois de tentar escrever e rodar o programa do Passeio do Cavalo, provavelmente você adquiriu alguns conceitos valiosos. Problema 4: Puzzle15 Problema 4: Puzzle15 • 1.3 trilhões de estados alcançáveis • Instâncias aleatórias são resolvidas otimamente em alguns milissegundos pelos melhores algoritmos de busca • 24-puzzle (5 x 5): possui 10 estados. • Resolver através da busca em profundidade. Problema 4: Puzzle8 • A estratégia deve “tentar” uma regra e, se mais tarde descobrir que essa regra não era apropriada, “voltar atrás” e tentar outra regra. Essa estratégia é chamada Backtracking (Tentativa e erro). Problema 4: Puzzle8 Ponteiros • Os ponteiros são variáveis que contêm endereços de memória como valores. • Normalmente, uma variável faz uma referência direta a um valor específico. • Um ponteiro, por outro lado, contém um endereço de uma variável que contém um valor específico. Ponteiros contPtr é um ponteiro para int ou contPtr aponta para um objeto do tipo inteiro Ponteiros • Os ponteiros devem ser inicializados ao serem declarados. • Um ponteiro pode ser inicializado com 0, NULL ou um endereço. • Um ponteiro com o valor NULL não aponta para lugar algum. • Inicializar um ponteiro com 0 é equivalente a inicializar um ponteiro com NULL Operadores de Ponteiros • O & ou operador de ponteiro é um operador que retorna o endereço de seu operando. Por exemplo, admitindo as declarações a instrução Operadores de Ponteiros Operadores de Ponteiros Operadores de Ponteiros • O operador *, chamado frequentemente operador de referência indireta ou operador de desreferenciamento, retorna o valor do objeto ao qual seu operando (i.e., um ponteiro) aponta. Usar * dessa maneira é chamado desreferenciar um poteiro. Operadores de Ponteiros Chamando funções por referência • Há duas maneiras de passar argumentos a uma função — chamada por valor e chamada por referência. • Usar ponteiros e o operador de referência indireta para simular chamadas por referência. Chamando funções por referência Chamando funções por referência Passagem por referência • Funções que recebem argumentos por referencia utilizam o operador & somente na definição do tipo de argumento. • Pelo comando return só é possível retornar um valor. • Por referência podemos retornar mais de um valor. Passagem por referência Passagem por referência Exercício • Implemente um programa que ordene 3 números de forma ascendente fornecido pelo usuário. • Utiliza chamada por referência. • A função main deve chamar a função ordena que apresenta os resultados. Expressões e aritmética com ponteiro Expressões e aritmética com ponteiro • Quando um inteiro é adicionado ou subtraído de um ponteiro, este último não é simplesmente incrementado ou decrementado por tal inteiro, mas sim por tal inteiro vezes o tamanho do objeto ao qual o ponteiro se refere. • O número de bytes depende do tipo de dado do objeto. • vPtr += 2, produziria 3008 (3 000 + 2 * 4) admitindo que um inteiro está armazenado em 4 bytes de memória Expressões e aritmética com ponteiro • Se um ponteiro for incrementado ou decrementado de um, os operadores de incremento e decremento podem ser usados. Qualquer uma das instruções ++vPtr; vPtr++; • As variáveis de ponteiros podem ser subtraídas entre si. • Por exemplo, se vPtr possuir o local 3000 e v2Ptr possuir o endereço 3008, a instrução x = v2Ptr vPtr; • A Aritmética de ponteiros não tem significado algum se não for realizada em um array. Ponteiros e Arrays • bPtr = &b[0]; • O elemento b [ 3 ] do array pode ser referenciado alternativamente com a expressão de ponteiro *(bPtr + 3). • Notação ponteiro/offset • Os parênteses são necessários porque a precedência do * é maior do que a precedência do +. • O array em si pode ser tratado como um ponteiro e usado com a aritmética de ponteiros. Por exemplo, a expressão *(b + 3). Ponteiros e Arrays • Os arrays podem conter ponteiros. Um uso comum de tais estruturas de dados é para formar um array de strings. Ponteiros e Arrays • Embora pareça que essas strings estão sendo colocadas no array naipe, apenas os ponteiros são de fato colocados no array. Ponteiros e Arrays Ponteiros e Arrays Ponteiros e Arrays Ponteiros e Arrays Ponteiros e Arrays Ponteiros e Arrays Alocando memória • typeName * pointer_name = new typeName; • int * pn = new int; Alocando memória Liberando memória Operador new e delete • O operador new é utilizado para alocar um bloco de memória. • Primeiro o operador new solicita ao SO um bloco de memória, após alocar o bloco de memória, new retorna um ponteiro para o bloco alocado. • Se new falhar, retorna um bad_aloc. Operador new e delete • Para destruir o objeto e devolver a memória para o SO utiliza-se o operador delete. • Delete destrói o objeto e devolve o bloco de memória para o SO. • Observe que apenas o bloco de memória é destruído. O ponteiro continua existindo, e continua apontando para o bloco de memória que agora não existe mais. • Depois de usar delete, o ponteiro aponta para um monte de lixo e não deve mais ser utilizado. Operador new e delete Ponteiro para função Problema 5 Faça um programa na linguagem C++ que imprima os 50 primeiros números inteiros pares positivos. Utilize ponteiros e funções. Problema 6 Num frigorífico existem 90 bois. Cada boi traz preso no pescoço um cartão contendo seu número de identificação e seu peso. Fazer um programa na linguagem C++ que escreva o número e peso do boi mais gordo e do boi mais magro. Problema 7 Suponha que no ano N a população americana seja maior que a brasileira. Sabendo-se que os Estados Unidos possuem um crescimento anual de 2% na sua população e que o Brasil tem crescimento anual de 4%, determinar o ano em que as duas populações serão iguais (em quantidade). São dados os números de habitantes dos Estados Unidos e do Brasil no ano N.