Baixe o app para aproveitar ainda mais
Prévia do material em texto
Programação Estruturada II Autoria: Renato Cristiano Torres Tema 01 Ponteiros seç ões Tema 01 Ponteiros Como citar esse documento: TORRES, Renato Cristiano, Programação Es- truturada II. Valinhos: Anhanguera Educacional, 2014. p. 1-90. Disponível em: <http://www.anhanguera.com>. Acesso em: 03 fev. 2014. SeçõesSeções Tema 01 Ponteiros 5 Conteúdo Nessa aula você estudará: • A utilização Ponteiros. • Matrizes de Ponteiros. • Ponteiros para Funções. conteúdosEhabilidades Introdução ao Estudo da Disciplina Caro(a) aluno(a). Este Caderno de Atividades foi elaborado com base no livro C: Como Programar, dos autores Paul Deitel e Harvey Deitel, Editora Pearson, 2011. Roteiro de Estudo: Renato Cristiano TorresProgramação Estruturada II 6 Habilidades Ao final, você deverá ser capaz de responder as seguintes questões: • Como utilizar ponteiros em programação? • Como utilizar matrizes de ponteiros? • Como chamar funções utilizando ponteiros para funções? conteúdosEhabilidades Ponteiros Segundo Mizrahi (2008), ponteiro é um endereço de memória e um mecanismo para acessar uma variável sem se referir a ela diretamente, ou seja, ela é acessada não pelo seu nome, mas pelo seu endereço (Figura 1.1). Algumas razões para o uso dos ponteiros (MIZRAHI, 2008; DEITEL; DEITEL, 2011): • Manipular elementos de matrizes. • Receber argumentos de funções que necessitem de modificação. • Passar strings (cadeia de caracteres) de uma função para outras. • Criar estruturas de dados complexas. • Alocar e desalocar memória. • Passar para uma função o endereço de outra. A ideia do uso de ponteiros é que utilizemos posição de memória em vez de utilizarmos a passagem de estruturas em funções, visto que por ponteiros é bem mais eficiente (DEITEL; DEITEL, 2011). leituraobRIgATóRIA 7 leituraobRIgATóRIA Segundo Deitel e Deitel (2011), os ponteiros são variáveis que contêm valores que são endereços de memória. Ponteiros, assim como todas as variáveis, precisam ser definidos antes de serem utilizadas, exemplo: int *iPtr; // ponteiro para inteiro Isso quer dizer que a variável “iPtr” conterá o endereço de memória que apontará para uma variável do tipo int. Figura 1.1 Representação de Ponteiro. Erro Comum em Programação A notação * (asterisco), usada para declarar variáveis de ponteiro, não distribui para todos os nomes de variáveis em uma declaração. Cada ponteiro precisa ser declarado com o * prefixado ao nome. Exemplo: int *iPtr,iPtr2; //ERRADO! int *iPtr,*iPtr2; //CERTO! 8 Veja um exemplo: Exemplo 1 1) #include <stdio.h> 2) int main() 3) { 4) int i,j,k; 5) printf(“Endereço de i = %d”, &i); 6) // o símbolo & obtém o endereço onde está alocada a variável 7) printf(“Endereço de j = %d”,&j); 8) printf(“Endereço de k = %d”,&k); 9) system(“PAUSE”); 10) return 0; 11) } A saída da execução: Endereço de i = 0012FED4 // o endereço pode variar de um computador para outro Endereço de J = 0012FEC8 Endereço de K = 0012FEBC Os ponteiros são utilizados para permitir alocação de memória em tempo de execução, aumentam a eficiência de acesso a matrizes e permitem que funções modifiquem seus argumentos de chamada. leituraobRIgATóRIA 9 leituraobRIgATóRIA Veja um exemplo de alocação dinâmica: int *vetor; vetor = (int *)malloc(linhas*sizeof(int)); Neste trecho de código, vemos a criação de um vetor com tamanho definido pela variável “linhas”. Como o tamanho de cada célula é de um inteiro, ou seja, 8 bytes, é preciso multiplicar linhas por 8 ou sizeof(int) que pega o tamanho do inteiro da máquina, pois, como o tamanho de um inteiro pode variar de uma máquina para outra, multiplicamos esse tamanho pelo número de linhas do vetor; logo, se linhas igual a 5, precisaremos de 40 bytes de memória para alocar o vetor. Operadores de Ponteiros O operador de endereço é um operador unário que retorna o endereço do operando e é simbolizado por “&”. Exemplo: int y = 5; int *yPtr; //declaração de ponteiro para inteiro yPtr = &y; // atribuição ao ponteiro “yPtr” o endereço da variável “y” Erro Comum em Programação Um ponteiro não inicializado, ao ser acessado, gerará um erro e causará um erro fatal em tempo de execução. Garanta sempre que os ponteiros utilizados estejam inicializados corretamente para evitar efeitos colaterais indesejados. Passando Argumentos para Funções por Referência Segundo Deitel e Deitel (2011), existem duas maneiras de passar argumentos a uma função em C, chamada por valor ou por referência. A chamada por referência é utilizada quando há necessidade de alterar o valor do argumento passado, evitando overhead de passar o objeto por valor, pois isso leva à necessidade de a linguagem C fazer uma cópia do objeto todo. 10 Exemplo: 1) #include <stdio.h> 2) int cubo(int n); 3) int main() 4) { 5) int numero=5; 6) printf(“O valor original do número é %d”, numero); 7) numero = cubo(numero); 8) printf(“O novo valor do número é %d”, numero); 9) return 0; 10) } 11) int cubo(int n) 12) { 13) return n * n *n; // calcula o cubo da variável e retorna o resultado 14) } Resultado da Execução: O valor original da variável número é 5. O novo valor do número é 125. Aritmética de Ponteiros Um conjunto limitado de operações aritméticas pode ser realizado com ponteiros. Um ponteiro pode ser incrementado (++), decrementado (--), somado ou subtraído. Suponha um vetor de inteiros com 5 posições v[5]. Seu primeiro elemento está no endereço 1000h, ou seja, o valor do ponteiro vPtr é 1000h (Figura 1.2). int * vPtr vPtr = v; vPtr = &v[0]; Quando você incrementa um ponteiro de inteiro, por exemplo, vPtr += 2; // produzirá o valor 1008h. leituraobRIgATóRIA 11 O valor de 1008h é gerado, pois o ponteiro não é simplesmente incrementado em 2 inteiros, mas pelo inteiro multiplicado pelo tamanho do objeto ao qual se refere. Logo, neste caso, considerando um inteiro com 4 bytes, temos (1000 + 2*4) = 1008. Figura 1.2 Variável de ponteiro vPtr apontado para o primeiro endereço do vetor. Relação entre Ponteiros e Matrizes Deitel e Deitel (2011) afirmam que matrizes e ponteiros estão intimamente relacionados em C e normalmente são utilizados da mesma forma. Um nome de matriz pode ser considerado um ponteiro; desta forma, pode definir um ponteiro igual ao endereço do primeiro elemento na matriz mat. Por exemplo: mPtr = mat; // essa instrução é equivalente a: mPtr = &mat[0] Em outra forma, o elemento 4 da matriz mat[3] pode ser referenciado pela seguinte expressão: *(mPtr + 3). Matriz de Ponteiros Uma matriz pode conter inúmeros ponteiros em suas células. Um exemplo comum são as matrizes de caracteres, normalmente conhecidas como matriz de strings. Cada entrada em uma matriz de string é um ponteiro para o primeiro caractere de uma string. Suponha uma matriz de strings baralho (Figura 1.3). const char * baralho[4] = {“Copas”,”Ouros”,”Paus”,”Espadas”} A definição baralho[4] indica uma matriz de 4 elementos, e “const char” indica que as strings apontadas não serão modificadas. leituraobRIgATóRIA 12 Figura 1.3 Representação Gráfica da matriz ‘baralho’. Ponteiros para Funções Um ponteiro para uma função contém o endereço da função na memória. Você viu que um nome da matriz é na realidade um ponteiro para o primeiro elemento da matriz. De forma semelhante, um nome de função é o endereço inicial na memória do código que realiza a tarefa da função (DEITEL; DEITEL, 2011). Veja o fragmento de um programa que utiliza a chamada de função por ponteiro. 1) #include <stdio.h> 2) #define SIZE 10 3) void bubble(int work[], const int size, int (*compare)(int a, int b)); 4) int crescente(int a, int b); 5) int decrescente(inta, int b); 6) int main(void) 7) { 8) … // códigos iniciais 9) if ( order == 1){ 10) bubble(a,SIZE,crescente) 11) else leituraobRIgATóRIA 13 12) bubble(a,SIZE,decrescente) 13) } 14) int crescente(int a, int b) 15) { i. return b < a; 16) } 17) int decrescente(int a, int b) 18) { i. return b > a; 19) } 20) } O trecho do código int(*compare)(int a, int b) na linha 3 diz à função bubble que espera por um parâmetro, que é um ponteiro, para a função que recebe dois parâmetros inteiros e retorna um resultado inteiro. Podemos declarar um ponteiro para função da seguinte forma: void (*func)(); func é um ponteiro para uma função sem parâmetros e que retorna void. func = teste; teste é uma função declarada da seguinte forma: void teste() { printf(“Olá ! teste”); } Teste pode ser chamada por func da seguinte forma func(); // chama teste Veja outro exemplo interessante: 1) include <stdio.h> 2) #include <stdlib.h> 3) int aplicar_funcao( int ( * fptr ) ( int arg1, int arg2 ), 4) int arg1, int arg2 ) leituraobRIgATóRIA 14 5) { 6) int result = ( *fptr ) (arg1, arg2); 7) printf(“Resultado = %d\n”, result); 8) return result; 9) } 10) int adicionar( int arg1, int arg2 ) { return arg1 + arg2; } 11) int multiplicar( int arg1, int arg2 ) { return arg1 * arg2; 12) } 13) int main() { 14) aplicar_funcao(adicionar, 2, 3); 15) aplicar_funcao(multiplicar, 3, 4); 16) system(“pause”); 17) return 0; 18) } Note que a função aplicar_função na linha 3 recebe um ponteiro para a função que retorna um inteiro e recebe dois argumentos do tipo inteiro também. Nas linhas 10 e 11, são declaradas 2 funções no formato descrito com retorno de inteiro e recebem dois argumentos. Na linha 14, temos a primeira chamada da aplicar_função recebendo o nome da função desejada e valores como argumentos. Veja que, independentemente da função, como elas obedecem ao mesmo protótipo (formato), podemos chamar qualquer uma. Os ponteiros para função são comumente utilizados em sistemas baseados em textos e controlados por menus, pois permitem associar chamadas de funções às opções dos menus. Suponha que tenhamos a matriz de funções ptrMenu (Figura 1.4). Cada posição da matriz aponta para o endereço de outra matriz que contém 16 funções diferentes. Figura 1.4 Matriz de funções ptrMenu. leituraobRIgATóRIA 15 linksImPoRTAnTEs Quer saber mais sobre o assunto? Então: Sites Acesse o link: <http://linguagemc.com.br/matriz-em-c/>. Acesso em: 03/02/2014. Você encontrará um site dedicado à linguagem C. Acesse o link: <http://www.ime.usp.br/~pf/algoritmos/aulas/pont.html>. Acesso em: 03/02/2014. Encontre informações sobre ponteiros, com exercícios e exemplos. Acesse o link: <http://www.redes.unb.br/~udias/cpe/aulas18--.pdf>. Acesso em: 03/02/2014. Você encontrará um arquivo com exemplos e uma explicação detalhada sobre ponteiros. Vídeos Programar em C - Ponteiros / Vetores / Funções - Aula 73. Disponível em: <http://www. youtube.com/watch?v=OMwWqONMIQ4>. Acesso em: 03/02/2014. Aula demonstrativa utilizando Dev C++ sobre ponteiros, vetores e funções. UFRPE Linguagem C PONTEIRO aula 09 (chamando funções). Disponível em: <http:// www.youtube.com/watch?v=Fb46wYUvxSI>. Acesso em: 03/02/2014. Aula de 8 minutos específica de chamada de funções utilizando ponteiros. Ela o ajudará na compreensão do uso de ponteiros em C. Isso quer dizer que, se você quiser alterar o menu para que a Opção C execute a Func12, apenas precisa alterar o ponteiro ptrMenu[2] e atribuir o endereço da Func12. Isso permite criar um menu personalizável. leituraobRIgATóRIA 16 agoraéasuAvez Instruções: Chegou a hora de você exercitar seu aprendizado por meio das resoluções das questões deste Caderno de Atividades. Essas atividades auxiliarão você no preparo para a avaliação desta disciplina. Leia cuidadosamente os enunciados e atente-se para o que está sendo pedido e para o modo de resolução de cada questão. Lembre-se: você pode consultar o Livro-Texto e fazer outras pesquisas relacionadas ao tema. Questão 1: O que é um ponteiro em linguagem C? Questão 2: Suponha que nPtr seja um ponteiro para uma matriz de inteiros. Qual endereço é referenciado por nPtr após a atribuição? a) Endereço do primeiro elemento da matriz. b) Endereço do último elemento da matriz. c) Nenhum, nPtr referencia a um endereço específico da matriz. d) Endereço do segundo elemento da matriz. e) Nulo. Questão 3: A seguir, temos atribuição de endereços a um Ponteiro de inteiros (int *iPtr). Qual atribuição está correta? a) iPtr = 9; // 9 inteiro qualquer. b) iPtr = a; // a variável inteira qualquer, inicializa com zero. c) iPtr = &d; // d variável inteira qualquer, inicializa com zero. 17 d) iPtr = *m[5]; // m matriz de inteiros com 5 elementos. e) iPtr = 0. Questão 4: O que é do tipo int na instrução seguinte? int *p a) A variável p. b) O endereço de p. c) A variável apontada por p <- d) endereço da variável apontada por p. e) Obrigatoriamente, o conteúdo e endereço da variável p. Questão 5: Qual instrução a seguir declara um ponteiro para uma variável char? a) char *p; <- b) *char p; c) string * p; d) *p e) string=*p; Questão 6: Uma string é uma coleção de caracteres. Por que podemos dizer que uma string é uma matriz de caracteres? Questão 7: O que há de errado com essa declaração a seguir? const char * nomes[5] = {“Ana”,”Pedro”,”Ju lia”,”Maria”}; Questão 8: Um ponteiro para matriz sempre aponta para o primeiro elemento da matriz, então o trecho código a seguir está correto? int mx[10]; int* vPtr; vPtr = mx[3]; Questão 9: Qual a diferença entre escrever mx[4] e *(mx+3)? Questão 10: Dado o programa: void teste( ) int (*func)( ); agoraéasuAvez 18 int main(void) { func = teste; func( ); } void teste( ) { printf(“Olá ! teste”); } Qual o erro do programa? agoraéasuAvez Um ponteiro inicializado sempre conterá o endereço de outra variável que conte um valor. Os ponteiros podem ser definidos para apontar para objetos de qualquer tipo. Um nome de matriz pode ser considerado um ponteiro constante, matrizes podem conter ponteiros, e ponteiros para uma função podem ser armazenados em matrizes e atribuídos a outros ponteiros de funções. Neste tema, você aprendeu sobre o conceito de ponteiros, aprendeu a referenciar matrizes e seus elementos e a utilizar ponteiros e criar e chamar funções por meio de ponteiros. Caro aluno, agora que o conteúdo dessa aula foi concluído, não se esqueça de acessar sua ATPS e verificar a etapa que deverá ser realizada. Bons estudos! finalizando 19 MIZRAHI, Viviane V. Treinamento Linguagem C. São Paulo: Pearson, 2006. SCHILDT, H. C. Completo e Total. 3. ed. São Paulo: Makron Books, 1996. SEDGEWICK, R. Algorithms in C - Parts 1 – 4. Addison Wesley, 2003. referências glossário Bubble: método de ordenação simples, baseado em percorrer um vetor alvo de ordenação n2 vezes. Overhead: é considerado qualquer processamento ou armazenamento em excesso. 20 Questão 1 Resposta: Ponteiro é um tipo de variável que guarda o endereço de uma outra variável, matriz ou estrutura de dados. Questão 2 Resposta: Alternativa A. Questão 3 Resposta: Alternativa C. Questão 4 Resposta: Alternativa C. Questão 5 Resposta: Alternativa A. Questão 6 Resposta: Porque String é uma matriz unidimensional também chamada de vetor do tipo char, que armazena um texto formado de caracteres sempre terminado pelo caractere (‘0’). Questão 7 Resposta: Declara um vetor com 5 elementos e está tentando inicializar o vetor, porémhá apenas 4 elementos para inicialização. gabarito 21 gabarito Questão 8 Resposta: Não! vPtr = mx[3] não pode ser escrito dessa forma, pois vPtr é um ponteiro, e não uma variável inteira, e também não aponta para o primeiro elemento. O correto seria: vPtr = mx ou vPtr = &mx[0]; Questão 9 Resposta: Não há diferença, pois são formas equivalentes de acessar o vetor; o primeiro acessa o quarto elemento e o segundo acessa o terceiro elemento. Questão 10 Resposta: Foi declarado um ponteiro de função que retorna um inteiro, porém a função do programa não retorna inteiro, e isso causará um erro. Programação Estruturada II Autoria: Renato Cristiano Torres Tema 02 Recursividade seç ões Tema 02 Recursividade Como citar esse documento: TORRES, Renato Cristiano, Programação Es- truturada II. Valinhos: Anhanguera Educacional, 2014. p. 1-90. Disponível em: <http://www.anhanguera.com>. Acesso em: 03 fev. 2014. SeçõesSeções Tema 02 Recursividade 5 Conteúdo Nessa aula você estudará: • O que é Recursão. • Funções Recursivas. • Algoritmos Recursivos x Iterativos. conteúdosEhabilidades Introdução ao Estudo da Disciplina Caro(a) aluno(a). Este Caderno de Atividades foi elaborado com base no livro C: Como Programar, dos autores Paul Deitel e Harvey Deitel, Editora Pearson, 2011. Roteiro de Estudo: Renato Cristiano TorresProgramação Estruturada II 6 conteúdosEhabilidades leituraobRIgATóRIA Habilidades Ao final, você deverá ser capaz de responder as seguintes questões: • Quando utilizar a recursão? • Como escrever algoritmos ou funções recursivas? • Quais as implicações de utilizar a recursão? • Qual a diferença entre Recursão e Iteração? Recursividade Assim como em outras linguagens em C, uma função pode chamar a si própria quantas vezes for necessário. Uma função que chama a si própria é denominada função recursiva (DEITEL; DEITEL, 2011). Porém, existem cuidados que devem ser tomados ao se escrever funções recursivas. Um deles é determinar um critério de parada, que determinará quando a função deve encerrar a chamada para si própria, impedindo uma chamada ininterrupta ou infinita. Você verá um exemplo utilizando fatorial: O Fatorial de n (n é um número natural) é sempre o produto de todos seus antecessores, incluindo o próprio n e excluindo o zero. A representação do fatorial é expressa pelo número seguido de um ponto de exclamação: 5! = 120 -> 5*4*3*2*1 = 120 Aqui, temos um exemplo do cálculo do fatorial de um número inteiro iterativo, ou seja, que utilizará um looping: 7 leituraobRIgATóRIA 1) #include <stdio.h> 2) int fat(int n) 3) { 4) int fat=1; 5) for(i=1;i <= n; i++) a. fat = fat*i; 6) return fat; 7) } 8) int main(void) 9) { 10) int n,i; 11) scanf(“%d”,&n); 12) printf(“%\n”,fat(n); 13) } Agora, veremos o cálculo do fatorial de um número inteiro utilizando uma função recursiva, ou seja, a função chamará ela própria n vezes. 1) #include <stdio.h> 2) int fatorial(int n) 3) { 4) if (n) // se for zero retorna 1, para qualquer outro número entra em recursão return n*fat(n-1) 5) else 6) return 1; 7) } 8) int main() 9) { 10) int n; 11) printf(“\n\n Digite um valor :”); 12) scanf(“%d”,&n); 13) printf(“\n O fatorial de %d”, n, fat(n)); 14) return 0; 15) } 8 O critério de parada é quando n for menor ou igual a zero; enquanto n for maior que zero, a chamada continua. Analise como o fatorial de 5 é calculado: Para cada chamada, o programa coloca a chamada (expressão) em uma pilha até encontrar o critério de parada, depois desempilha resolvendo cada chamada. EMPILHANDO DESEMPILHANDO Passo 1 – 5! PASSO 6 = 1! = 1 Passo 2 – 5! = 5 * 4! PASSO 5 = 2! = 2*1! = 2 Passo 3 – 4! = 4 * 3! PASSO 4 = 3! = 3*2! = 6 Passo 4 – 3! = 3 * 2! PASSO 3 = 4! = 4*3! = 24 Passo 5 – 2! = 2 * 1! PASSO 2 = 5! = 5*4! = 120 Passo 6 – 1! = 1 PASSO 1 = 5! = 120 Apresentaremos outro exemplo utilizando a sequência de Fibonacci, que é uma sequência de números naturais, começando em 0 e 1, cuja propriedade estabelece que cada número de Fibonacci subsequente é a soma dos dois números de Fibonacci anteriores (DEITEL; DEITEL, 2011). Exemplo: a) 0 1º 2º 0 1 1 3º Número de Fibonacci somamos os 2 predecessores 0 e 1; = 0 +1 =1 b) 0 1º 2º 3º 0 1 1 2 4º Número de Fibonacci somamos os 2 predecessores 1 e 1; = 1 + 1 = 2 leituraobRIgATóRIA 9 leituraobRIgATóRIA c) 0 1º 2º 3º 4º 0 1 1 2 3 5º Número de Fibonacci somamos os 2 predecessores 1 e 2; = 1 + 2 = 2 Você verá como fica um programa iterativo para calcular a sequência no modo iterativo. 1) #include<stdio.h> 2) int main() 3) { 4) int n, primeiro = 0, segundo = 1, prox, c; 5) printf(“Entre com o número\n”); 6) scanf(“%d”,&n); 7) printf(“ A sequencia de Fibonacci para %d é :-\n”,n); 8) for ( c = 0 ; c < n ; c++ ) 9) { 10) if ( c <= 1 ) 11) prox = c; 12) else 13) { 14) prox = primeiro + segundo; 15) primeiro = segundo; 16) segundo = prox; 17) } 18) printf(“%d\n”,prox); 19) } 20) return 0; 21) } O programa executa o que foi mostrado para calcular a sequência de Fibonacci, utilizando as variáveis “primeiro” e “segundo” para somar os antecessores e “prox” para acumular a soma sucessivamente nas posições até encontrar o número que informamos de forma iterativa, ou seja, utilizando uma estrutura de laço. 10 Veja agora um exemplo recursivo: 1) #include<stdio.h> 2) int Fibonacci(int); 3) main() 4) { 5) int n, result; 6) scanf(“Digite um número inteiro : %ld”,&n); // número fornecido pelo usuário 7) printf(“Série Fibonacci\n”); 8) result = Fibonacci(i); // calcula o valor de fibonacci para o número fornecido pelo usuário 9) printf(“Fibonacci (%ld) = (%ld)\n”, number, result); 10) return 0; 11) } 12) int Fibonacci(int n) 13) { 14) if ( n == 0 ) | ( n == 1 ) 15) return n; 16) else 17) return ( Fibonacci(n-1) + Fibonacci(n-2) ); // Soma do antecessor do antecessor e o antecessor direto 18) } Resultado do Programa em execução: Digite um número inteiro: 4 Fibonacci(4) = 3 Digite um número inteiro: 6 Fibonacci(6) = 8 leituraobRIgATóRIA 11 Vamos testar: 0 1º 2º 3º 4º 5º 6º 0 1 1 2 3 5 8 = o quarto número da sequência é 3 – Certo! 0 1º 2º 3º 4º 5º 6º 0 1 1 2 3 5 8 = o sexto número da sequência é 8 – Certo! linksImPoRTAnTEs Quer saber mais sobre o assunto? Então: Sites Acesse o link: <http://www.matematicadidatica.com.br/Fatorial.aspx>. Acesso em: 03/02/2014. Você encontrará uma explicação detalhada sobre fatorial. Para entender melhor as diferenças entre recursão e iteração, acesse: <http://programando- ads.blogspot.com.br/2012/09/recursividade-entendendo-o-conceito.html>. Acesso em: 03/02/2014. Acesse o link: <http://www.ic.unicamp.br/~vanini/mc202/apresentacoes/aula3.pdf>. Acesso em: 03/02/2014. Você encontrará exemplos de recursão. leituraobRIgATóRIA 12 Instruções: Chegou a hora de você exercitar seu aprendizado por meio das resoluções das questões deste Caderno de Atividades. Essas atividades auxiliarão você no preparo para a avaliação desta disciplina. Leia cuidadosamente os enunciados e atente-se para o que está sendo pedido e para o modo de resolução de cada questão. Lembre-se: você pode consultar o Livro-Texto e fazer outras pesquisas relacionadas ao tema. agoraéasuAvez Vídeos Para você que deseja conhecer um pouco mais sobre sequência de Fibonacci, veja a aula Sequência Fibonacci e Número de Ouro. Disponível em: <http://www.youtube.com/watch?v =NIkJFjaWgi8&noredirect=1>. Acesso em: 03/02/2014. Questão 1: Qual a diferença entre recursão e iteração? Questão 2: As funções recursivas utilizam uma estrutura de dados interna do compiladordenominada: a) Lista de Ponteiros. b) pilha <- c) Matriz. d) Lista Encadeada. e) Lista Ligada. Questão 3: Uma recursão é baseada em? a) Laço de Controle. 13 b) Laço de Repetição. c) Funções que chamam a si própria n vezes. d) Chamada de funções externas. e) Execução de comandos externos. Questão 4: Qual a desvantagem do uso da recursão? a) Consome pouca memória. b) Pode consumir muita memória. c) Consome muito disco. d) É eficiente. e) Há limites para as funções chamarem a si próprias. Questão 5: Uma função interativa baseia-se em: a) Uma estrutura de repetição < b) Uma estrutura recursiva. c) Funções que chamam a si próprias. d) Bibliotecas. e) Estruturas recursivas de repetição. Questão 6: Escreva o código de um programa que calcule a potência de um número inteiro de forma recursiva. Questão 7: Escreva o código de um programa que tenha duas funções para o cálculo da multiplicação de 2 números de forma recursiva e interativa. Questão 8: Há uma preocupação especial com o critério de parada em programas que utilizam funções recursivas. Qual o motivo dessa atenção? Questão 9: Demonstre como fica a tabela de empilhamento/desempilhamento do cálculo recursivo da multiplicação dos números 4 e 5 utilizado na Questão 7. Questão 10: Demonstre como fica a tabela de empilhamento/desempilhamento de uma função recursiva que calcula o fatorial do número 6. agoraéasuAvez 14 Segundo Deitel e Deitel (2011), tanto a iteração quanto a recursão se fundamentam em uma estrutura de controle. A interação utiliza uma estrutura de repetição, enquanto a recursão utiliza uma estrutura de seleção. As duas envolvem critérios e testes para término. Porém, a recursão tem alguns pontos negativos que algumas vezes tornam um programa custoso computacionalmente, ou seja, consome muita memória por utilizar pilha e também por esse fato não é tão eficiente quanto o modelo iterativo. Logo, chegamos à conclusão de que a escolha de uma solução iterativa é utilizada quando uma recursiva não é tão clara. Caro aluno, agora que o conteúdo dessa aula foi concluído, não se esqueça de acessar sua ATPS e verificar a etapa que deverá ser realizada. Bons estudos! finalizando referências MIZRAHI, Viviane V. Treinamento Linguagem C. São Paulo: Pearson, 2008. SEDGEWICK, R. Algorithms in C - Parts 1 – 4. Addison Wesley, 2003. SCHILDT, H. C. Completo e Total. 3. ed. São Paulo: Makron Books, 1996. 15 glossário Iterativa: processo que se repete várias vezes. Fibonacci: Leonardo Fibonacci, matemático italiano criador da sequência de Fibonacci. gabarito Questão 1 Resposta: A interação utiliza uma estrutura de repetição. Logo, normalmente terá while/ for envolvido na solução, e a recursão utiliza uma estrutura de seleção. As duas envolvem critérios e testes para término, porém, a recursão utiliza-se do mecanismo de chamar a si própria várias vezes. Questão 2 Resposta: Alternativa C. Questão 3 Resposta: Alternativa D. Questão 4 Resposta: Alternativa B. 16 Questão 5 Resposta: Alternativa A. Questão 6 Resposta: 1) #include <stdio.h> 2) int potencia(int base, int expoente){ 3) if(expoente == 0) 4) return 1; 5) else 6) return (base * potencia(base, expoente-1)); 7) } 8) int main(){ 9) int base = 2, expoente = 8, resultado; 10) resultado = potencia(base,expoente); 11) printf(“%d elevado a %d = %d”, base, expoente,resultado); 12) return 0; 13) } Na linha 2, temos declarada a função recursiva potência que receberá a base e o expoente; ao chama-lá, ela fará sucessivas multiplicações. EMPILHANDO DESEMPILHANDO Passo 1 – 23 PASSO 6 = 21 = 2 * 20 = 2 Passo 2 – 23= 2 * 22 PASSO 5 = 22 = 2 * 21 = 4 Passo 3 – 22= 2 * 21 PASSO 4 = 23 = 2 * 22 = 8 gabarito 17 gabarito Questão 7 Resposta: Forma Iterativa 1) #include <stdio.h> 2) long int multiplicação(int a, int b){ 3) long int res=0; 4) while( b != 0){ 5) r += a; 6) b--; 7) } 8) return(r); 9) } Note que a base da função é um laço While. A cada iteração, faz uma soma baseada nos argumentos recebidos. Um exemplo de execução seria: 4 * 5 = 4 + 4 + 4+ 4+ 4 cinco vezes a soma do número quatro Forma Recursiva 1) long int mult(int a, int b) 2) { 3) if (b == 1) // qualquer número multiplicador por 1 o resultado é ele mesmo 4) return(a); 5) else 6) if (b == 0) 7) return 0; 8) else 9) return(a + mult(a, b-1)); // sucessivas somas até b == 0 10) } 18 Questão 8 Resposta: As funções recursivas exigem memória para executar, e, em um programa defeituoso que fique infinitamente em looping, haverá o travamento da Sistema Operacional; por isso, o critério de parada é importante. Questão 9 Resposta: EMPILHANDO DESEMPILHANDO 4 + mult(4 4) 4 + (4 + (4+(4+(4+(0)))) 4 + (4 + mult(4 3)) 4 + (4 + (4+(4+(4))) 4 + (4 + 4+(mult(4 2)) 4 + (4 + (4+(8)) 4 + (4 + (4+(4+(mult(4 1)))) 4 + (4 + (12)) 4 + (4 + (4+(4+(4+(mult(4 0))))) 4 + (16) = 20 Questão 10 Resposta: EMPILHANDO DESEMPILHANDO Passo 1 – 6! PASSO 7 = 1! = 1 Passo 2 – 6! = 6 * 5! PASSO 6 = 2! = 2*1! = 2 Passo 3 – 5! = 5 * 4! PASSO 5 = 3! = 3*2! = 6 Passo 4 – 4! = 4 * 3! PASSO 4 = 4! = 4*3! = 24 Passo 5 – 3! = 3 * 2! PASSO 3 = 5! = 5*4! = 120 Passo 6 – 2! = 2 * 1! PASSO 2 = 6! = 6*5! = 720 Passo 7 – 1! = 1 PASSO 1 = 6! = 720 gabarito Programação Estruturada II Autoria: Renato Cristiano Torres Tema 03 Arquivos seç ões Tema 03 Arquivos Como citar esse documento: TORRES, Renato Cristiano, Programação Es- truturada II. Valinhos: Anhanguera Educacional, 2014. p. 1-90. Disponível em: <http://www.anhanguera.com>. Acesso em: 03 fev. 2014. SeçõesSeções Tema 03 Arquivos 5 Conteúdo Nessa aula você estudará: • Manipulação de Arquivos em C. • Acesso a arquivos de Forma Aleatória e Sequencial. • Modos de Abertura de Arquivos. conteúdosEhabilidades Introdução ao Estudo da Disciplina Caro(a) aluno(a). Este Caderno de Atividades foi elaborado com base no livro C: Como Programar, dos autores Paul Deitel e Harvey Deitel, Editora Pearson, 2011. Roteiro de Estudo: Renato Cristiano TorresProgramação Estruturada II 6 conteúdosEhabilidades Habilidades Ao final, você deverá ser capaz de responder as seguintes questões: • Como ler e escrever em arquivos? • Qual a diferença entre acesso aleatório e sequencial? • Quais são os tipos de streams? conteúdosEhabilidades Arquivos O armazenamento de dados em variáveis, estruturas e matrizes é temporário. Esses dados são perdidos quando um programa é encerrado, e os arquivos são utilizados na conservação permanente de dados (DEITEL; DEITEL, 2011). Cada arquivo é uma sequência de bytes, em que cada linha termina com um marcador de fim de linha, e o arquivo contém outro marcador de fim de arquivo. Quando um arquivo é aberto, um objeto é criado e um stream é associado ao objeto. Os streams fornecem canais de comunicação entre arquivos e programas. Segundo Schildt (1996), existem dois tipos de streams: Stream de Texto – formado por sequência de caracteres; o padrão C ANSI permite que um stream de texto seja organizado em linhas terminadas por um caractere de nova linha. Stream Binário – formado por sequência de bytes, a quantidade de byte é a mesma do dispositivo, ou seja, não há tradução. leituraobRIgATóRIA 7 leituraobRIgATóRIAleituraobRIgATóRIA Criação de um Arquivo de Acesso Sequencial A linguagem C não impõe uma estrutura definida a um arquivo. Os conceitos de registro não fazem parte da linguagem. Isso quer dizer que você deve estruturar os dados da forma que satisfaçama necessidade da aplicação. Ao manipular um arquivo de forma sequencial, após a abertura do arquivo a posição corrente é o início do arquivo. Esse indicador é atualizado a todo momento enquanto se move pelo arquivo (Figura 3.1). Figura 3.1 Arquivo de acesso sequencial. 8 No modo sequencial, o indicador é posicionado no início do arquivo e faz uma varredura até o final de arquivo ser encontrado para realizar uma leitura total do arquivo. Caso haja a necessidade de ler parte do arquivo, você tem de avançar a partir do início do arquivo até o ponto desejado, sequencialmente. Veja no exemplo, a seguir, uma maneira simples de manipular registros em um arquivo: 1) #include <stdio.h> 2) int main(void) 3) { 4) int account; 5) char name[30]; 6) double balance 7) FILE *fptr; 8) if ((fptr = fopen(“clientes.dat”,”w”)) == NULL){ 9) printf(“O arquivo não pode ser aberto\n”); 10) } 11) else 12) { 13) printf(“Digite o número de conta, nome e saldo.\n”); 14) printf(“Digite fim de arquivo para terminar a entrada.\n”) 15) printf(“?”); 16) scanf(“%d%s%lf”,&account,name, balance); 17) while (!eof(stdin)){ i. fprintf(fptr,%d,%s,%2.f\n”,account,name,balance); ii. printf(“? ”) iii. scanf(“%d%s%lf”,&account,name, balance); 18) } 19) fclose(fptr); 20) return 0; 21) } leituraobRIgATóRIA 9 O comando fprintf funciona de forma similar ao printf. A diferença é que o fprint exige como parâmetro o ponteiro para arquivo, onde será escrito o dado no formato especificado no segundo argumento. Para ler dados do arquivo, podemos utilizar o comando fscanf, que também é similar ao scanf, da seguinte forma: fscanf(fptr,”%d”,&numero); O primeiro argumento da função é o ponteiro do arquivo, de onde será lido o dado; o segundo é a máscara de formato; e o terceiro é a referência da variável que receberá o dado lido. A combinação de teclas para informar fim de arquivo para Linux/Mac OS e Unix é <Ctrl>d, no Windows é <Ctrl>Z. Examinando o código na linha 7, você notará que o fptr é um ponteiro para uma estrutura FILE. Neste momento, você não precisa conhecer os detalhes para utilizar arquivos, porém, caso seja necessário, basta procurar o arquivo stdio.h na pasta padrão include do seu compilador. O ponteiro fptr será utilizado para referenciar o arquivo. Todo arquivo precisa de um ponteiro do tipo FILE associado. A função fopen na linha 8 retorna um ponteiro do tipo FILE e recebe como argumentos o nome do arquivo e o modo de abertura, “w” significa que o arquivo pode ser alterado, “r” será apenas leitura (Figura 3.2). Se fopen retornar NULL, logo o fptr será nulo. Desta forma, o arquivo não foi aberto, e um erro será retornado. Todo arquivo aberto deve ser fechado! Veja no nosso código a função fclose(fptr). Com isso, libera o arquivo para ser alterado por outro usuário. MODO DESCRIÇÃO r Abre um arquivo existente para leitura. w Criar um arquivo para gravação. Se o arquivo já existe, sobrescreve. a Abre ou Cria um arquivo para adicionar dados ao seu final. r+ Abre um arquivo para leitura e escrita; caso não exista, será criado. w+ Abre um arquivo para escrita; caso não exista, será criado. a+ Abre ou cria um arquivo para atualização; dados serão gravados no final do arquivo. leituraobRIgATóRIA 10 rb Abre um arquivo existente para leitura no mode binário. wb Abre um arquivo existente para escrita no mode binário. ab Abre ou cria um arquivo binário para adicionar dados ao seu final. rb+ Abre um arquivo binário para leitura e escrita; caso não exista, será criado. wb+ Abre um arquivo binário para escrita; caso não exista, será criado. ab+ Abre ou cria um arquivo binário para atualização; dados serão gravados no final do arquivo. Figura 3.2 Modos de abertura de arquivo. Arquivos de Acesso Aleatório O acesso a arquivos de forma aleatória possibilita fazer o acesso diretamente a registros, sem a necessidade de passar pelos registros anteriores. Logo, para acessar qualquer parte do arquivo, basta utilizar uma função de busca, por exemplo: fseek(fPtr,OffSet, SEEK_SET) A função fseek possui 3 argumentos. O primeiro é o ponteiro para arquivo; o segundo é a quantidade de bytes que o indicador precisará caminhar para chegar até o dado desejado a partir da origem especificada no terceiro argumento, que pode assumir 3 valores: ORIGEM VALOR Início do Arquivo SEEK_SET Posição Corrente SEEK_CUR Fim do Arquivo SEEK_END FILE *fp; char ch; if ((fp = fopen(“cliente.dat”, “rb”)) == NULL) { leituraobRIgATóRIA 11 leituraobRIgATóRIA puts(“Não posso abrir arquivo!”); exit(1); } fseek(fp, 44, SEEK_SET); ch = getc(fp); //lê um caractere na posição 45o A função fseek( ) retorna zero se houve sucesso ou um valor diferente de zero, se houve falha no posicionamento do indicador do arquivo. Normalmente, o arquivo terá comprimento de registro fixo, ou seja, as linhas do arquivo terão o mesmo número de bytes. Os registros criados com a função fprintf não têm necessariamente o mesmo tamanho. Registros individuais de um arquivo de acesso aleatório normalmente têm tamanhos fixos e podem ser acessados diretamente, rapidamente, sem pesquisa por outros registros. Isso torna os arquivos de acesso aleatório ideais para arquivos que precisam de acesso rápido a dados específicos, como arquivos de configuração, tabelas de dados em sistemas corporativos e outros. A função fwrite transfere para um arquivo um número especificado de bytes de um local da memória. A função fread transfere um número de bytes do arquivo para memória. Exemplo: fwrite(&numero, sizeof(int),1,fptr); Para ler e escrever tipos de dados maiores que um byte, C fornece duas funções fwrite e fread, que são capazes de ler e gravar qualquer tipo de informação. Exemplo: #include <stdio.h> #include <stdio.h> void main(void) { FILE *fp; double d=12.23; int i = 101; long l = 123023L; 12 if ((fp=fopen(“teste”,”wb+”)) == NUL{ printf(“O arquivo não pode ser aberto\n”); exit(1) } //Escrita de dados binário de vários tipos fwrite(&d,sizeof(double),1,fp); fwrite(&i,sizeof(int),1,fp); fwrite(&l,sizeof(long),1,fp); rewind(fp); // move o indicador para o inicio do arquivo //Leitura de dados binário de vários tipos fread(&d,sizeof(double),1,fp); fread (&i,sizeof(int),1,fp); fread (&l,sizeof(long),1,fp); prinff(“%f %d %ld, d ,i ,l); flclose(fp); } Nesse exemplo o programa escreve dados não caracteres em um arquivo e depois lê de volta. Esses dados não são visíveis em um editor de texto, caso você abra o arquivo. Uma das aplicações de fread() e fwrite() envolve ler e escrever estrutura de dados. Veja o exemplo: struct scruct_type{ float balanco; char nome[80]; }custo; leituraobRIgATóRIA 13 linksImPoRTAnTEs Quer saber mais sobre o assunto? Então: Sites Acesse o link: <http://linguagemc.com.br/matriz-em-c/>. Acesso em: 03/02/2014. Você encontrará um site dedicado à linguagem C. Vídeos Assista aos vídeos: Acesse o vídeo: Linguagem C Aula 12 Arquivos Escrever. Disponível em: <http://www. youtube.com/watch?v=gLAxAbv0KuY>. Acesso em: 03/02/2014. O vídeo apresenta uma aula sobre manipulação de arquivo, com a possibilidade de obter os arquivos fontes da aula no link informado pelo autor. Acesso o vídeo: Programar em C - Manipulação de Arquivos txt em C /Ler Dados. Disponível em: <http://www.youtube.com/watch?v=y_euDUgoND8>. Acesso em: 03/02/2014. Você encontrará um vídeo sobre manipulação de arquivos texto. Essa sentença escreve o conteúdo de custo no arquivo apontado por fp. fwrite(&custo, sizeof(struct struct_type),1,fp); Suponha que você precise guardar parâmetros da inicialização de um sistema. Você pode utilizar o fwrite para gravar a estrutura de dados e fread para ler as configurações. 14 Instruções: Chegou ahora de você exercitar seu aprendizado por meio das resoluções das questões deste Caderno de Atividades. Essas atividades auxiliarão você no preparo para a avaliação desta disciplina. Leia cuidadosamente os enunciados e atente-se para o que está sendo pedido e para o modo de resolução de cada questão. Lembre-se: você pode consultar o Livro-Texto e fazer outras pesquisas relacionadas ao tema. agoraéasuAvez Questão 1: Uma porta de comunicação do computador pode ser manipulada como arquivo? Questão 2: As funções fopen e fclose servem respectivamente para: a) Ler e escrever um arquivo. b) Abrir e fechar um arquivo. c) Fechar e abrir um arquivo. d) Escrever e ler um arquivo binário. e) Ler e escrever um arquivo texto. Questão 3: Quais dos seguintes parâmetros podem ser especificados pela função fopen( )? Acesso o vídeo: Manipulação de Arquivos em C. Disponível em: <http://www.youtube.com/ watch?v=Za93F-lhbRs>. Acesso em: 03/02/2014. Esse é outro vídeo que ensina como fazer manipulação de arquivos em C. linksImPoRTAnTEs 15 a) Que o arquivo será aberto para acrescentar dados ao seu final. b) Que o arquivo será aberto em modo hexadecimal. c) Que todos os números serão gravados em formato binário. d) Que todo o arquivo será lido caractere a caractere. e) Que o arquivo será lido linha a linha. Questão 4: Se um programador descuidado abrir um arquivo para inserir dados e não fechar esse arquivo, o que pode acontecer? a) Nada, o sistema operacional fecha o arquivo automaticamente durante a execução do programa. b) Enquanto o programa estiver sendo executado, nenhum usuário consegue escrever no arquivo. c) Enquanto o programa estiver sendo executado, nenhum usuário consegue ler o arquivo. d) Após encerrar o programa, o sistema operacional mantém o arquivo como somente leitura. e) Após encerrar o programa, o sistema operacional mantém o arquivo aberto. Questão 5: Para ler e escrever tipos de dados maiores que um byte, C fornece duas funções: a) read e write. b) fopen e fclose. c) fputs e fgets. d) fread e frwrite. e) fread e fget. Questão 6: O que há de errado com o programa a seguir? #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fptr; fptr = fopen(“Testestr.txt”,”w”); fptr = NULL; fputs(“Um grande antidote contra o egoísmo\n”,fptr); fputs(“é a generosidade.... Dê, mesmo que\n”,fptr); fputs(“isso requeira de você um esforço\n”,fptr); fputs(“consciente. Pelo fato de partilhar\n”,fptr); agoraéasuAvez 16 fputs(“tudo o que possui. Seu egosimo se\n”,fptr); fputs(“abrandará.\n”,fptr); fclose(fptr); return 0; } Questão 7: Qual a diferença entre acessar um arquivo de forma aleatória e sequencial? Questão 8: Qual o objetivo das funções fprintf e fscanf? Questão 9: Crie um programa que escreva 10 números inteiros em um arquivo e depois leia do ar- quivo e imprima os dados em tela. Questão 10: Explique o que faz a declaração a seguir: tfPtr = fopen(“dados.dat”,”r”); agoraéasuAvez 17 finalizando A linguagem C trata cada arquivo como uma sequência de bytes. Quando um arquivo é aberto, um stream é associado ao arquivo, indicado por ponteiro do tipo FILE. Esse ponteiro será o elo para a manipulação do arquivo. Os arquivos sequência devem obedecer à regra da estrutura para percorrerem seus registros, já, no modo aleatório, o percurso dentro do arquivo é realizado pelo reposicionamento do indicador de endereço dentro do arquivo. Caro aluno, agora que o conteúdo dessa aula foi concluído, não se esqueça de acessar sua ATPS e verificar a etapa que deverá ser realizada. Bons estudos! referências MIZRAHI, Viviane V. Treinamento Linguagem C. São Paulo: Pearson, 2008. SCHILDT, H. C. Completo e Total. 3. ed. São Paulo: Makron Books, 1996. SEDGEWICK, R. Algorithms in C - Parts 1 – 4. Addison Wesley, 2003. 18 glossário Bubble: método de ordenação simples, baseado em percorrer um vetor alvo de ordenação n2 vezes. Overhead: é considerado qualquer processamento ou armazenamento em excesso. gabarito Questão 1 Resposta: Sim, todo local que tem capacidade para receber bytes da memória do computador ou transferi-los pode ser manipulado como arquivo, por exemplo: teclado, vídeo, impressora, portas de comunicação etc. Desta forma, o conceito de arquivo é ampliado. Questão 2 Resposta: Alternativa B. Questão 3 Resposta: Alternativa A. Questão 4 Resposta: Alternativa B. 19 gabarito Questão 5 Resposta: Alternativa D. Questão 6 Resposta: Foi atribuído nulo ao ponteiro de arquivo. Com isso, ele não tem conexão com o arquivo aberto por fopen. Questão 7 Resposta: Na forma sequencial, quando abrimos o arquivo, o indicador do arquivo é posicionado no início do arquivo, e para ler os dados do arquivo temos de percorrer sequencialmente todos os bytes; no acesso aleatório, podemos utilizar a função seek para posicionar o indicador no registro ou posição desejada, iniciando a busca a partir do início do arquivo, posição corrente ou fim do arquivo. Questão 8 Resposta: Os comandos fprintf e scanf servem respectivamente para escrever e ler dados formatados. O fprintf funciona de forma similar ao printf, a diferença é que o fprint exige como parâmetro o ponteiro para arquivo, onde será escrito o dado no formato especificado no segundo argumento. O scanf, também de forma similar ao scanf, lê um dado formatado, porém do arquivo informado no primeiro argumento e com o formato informado no segundo argumento, e coloca o dado lido na variável informada no terceiro argumento. Questão 9 Resposta: 1) #include <stdio.h> 2) #include <stdlib.h> 3) main() 4) { 5) FILE *fp; 6) char nomeArquivo[25] = “DezNumeros.txt”; 7) int I,valor; // bloco de escrita do arquivo 20 8) 9) fp = fopen(nomeArquivo, “w”); 10) if (fp != NULL) 11) { 12) printf(“\n\n Arquivo Criado com Sucesso\n\n”); 13) for (i = 1; i <=10; i++) 14) fprintf(fp,”%d\n”,i); 15) } 16) else{ 17) printf(“Falha ao criar o Arquivo”); 18) exit(1); 19) } 20) fclose(fp); // bloco de leitura do arquivo 21) fp = fopen(nomeArquivo, “r”); 22) if (fp = fopen(nomeArquivo, “r”) != NULL) 23) { 24) printf(“\n\n Arquivo Criado com Sucesso\n\n”); 25) for (i = 1; i <=10; i++) 26) fscanf(fp,”%d\n”,&valor); 27) printf(“Dado Lido :%d”,valor); 28) } 29) else{ 30) printf(“Falha ao criar o Arquivo”); 31) exit(1); 32) } gabarito 21 33) fclose(fp); 34) system(“pause”); 35) } Questão 10 Resposta: Abre um arquivo chamado dados.dat como leitura e associa o ponteiro do arquivo à variável tfPtr. gabarito Programação Estruturada II Autoria: Renato Cristiano Torres Tema 04 Aprendendo a Depurar e Documentar o Código seç ões Tema 04 Aprendendo a Depurar e Documentar o Código Como citar esse documento: TORRES, Renato Cristiano, Programação Es- truturada II. Valinhos: Anhanguera Educacional, 2014. p. 1-90. Disponível em: <http://www.anhanguera.com>. Acesso em: 03 fev. 2014. SeçõesSeções Tema 04 Aprendendo a Depurar e Documentar o Código 5 Conteúdo Nessa aula você estudará: • Uso da Depuração. • Boas Práticas de Manutenção de Sistemas. • Documentação de Código-Fonte. • Versionamento. conteúdosEhabilidades Introdução ao Estudo da Disciplina Caro(a) aluno(a). Este Caderno de Atividades foi elaborado com base no livro C: Como Programar, dos autores Paul Deitel e Harvey Deitel, Editora Pearson, 2011. Roteiro de Estudo:Renato Cristiano TorresProgramação Estruturada II 6 Habilidades Ao final, você deverá ser capaz de responder as seguintes questões: • Como configurar a depuração no Dev C++? • Quando utilizar a depuração? • Por que documentar o código-fonte? • Para que serve a versão dos sistemas e programas? conteúdosEhabilidades Aprendendo a Depurar Depurar um programa é acompanhar sua execução linha a linha ou por meio de um ponto de interrupção, conhecido como breakpoint. O ponto de interrupção pausará a execução; será possível, utilizando uma ferramenta de depuração, avaliar conteúdo de variáveis, retorno de funções e outros. O objetivo é analisar o comportamento do programa durante sua execução. Normalmente, utilizamos o artifício de depuração quando buscamos entender algum erro que não esteja evidente e que se manifeste apenas durante a execução do programa. O exemplo utilizado será baseado no uso da IDE Dev C++. Configurando o Dev C++ O primeiro passo para utilizar o depurador do Dev C++ é configurar o compilador para incluir informações de depuração no código objeto gerado (Figura 4.1). leituraobRIgATóRIA 7 leituraobRIgATóRIA Vá em Ferramentas->Opções do Compilador Figura 4.1 Configuração do compilador. Na aba Compilador, marque a caixa de seleção “Adicionar os seguintes comandos quando chamar o compilador” e adicione o comando –O0. Esse comando instruirá o compilador para o modo de depuração (Figura 4.2). 8 Figura 4.2 Configuração do compilador – Opções. Depois, vá à aba Linker e modifique o parâmetro da opção “Gerar informação de depuração (–g3)”, coloque em YES (Figura 4.3). Isso fará com que o linkeditor se prepare para o modo de depuração. leituraobRIgATóRIA 9 leituraobRIgATóRIA Figura 4.3 Configuração do Linkeditor. Pronto! Agora o ambiente está pronto para depurar um programa! Depurando um Programa Click com o botão direito do mouse em cima dos números à esquerda do código, uma barra vermelha destacará a linha informando que é um ponto de interrupção, ou seja, o programa executará até esse momento e aguardará o comando de continuação (Figura 4.4). 10 Figura 4.4 Depurando um programa. Para executar o programa em modo de depuração, vá em Executar->Depurar ou utilize a tecla F5 (Figura 4.5). Figura 4.5 Executando um programa em modo de depuração. leituraobRIgATóRIA 11 Após a execução em modo de depuração, o ambiente irá executar e pausará a execução na linha marcada. Neste momento, a linha em destaque se torna azul e informa que a execução atingiu o ponto de interrupção (Figura 4.6). Figura 4.6 Depuração em tempo de execução. Neste momento, você tem disponível na parte inferior do ambiente diversas opções para continuar a execução linha a linha, continuar a execução ou parar (Figura 4.7). Figura 4.7 Opções de depuração. Com esses recursos, é possível observar o comportamento do programa em tempo de execução para detectar e corrigir erros. leituraobRIgATóRIA 12 Documentando o Código-Fonte do Programa Nas empresas que desenvolvem softwares profissionais, é comum que cada programador seja responsável por uma parte do código de um grande sistema, que pode ser um ERP, um sistema de BI ou e-commerce etc. Para que a leitura do código seja inteligível a todos, é fundamental utilizar algumas práticas e padrões, uma delas é a documentação do código. A documentação do código serve para explicar em forma de comentário o objetivo das funções, variáveis e até mesmo do programa ou da unidade do código, que pode ser um arquivo do tipo header (.h), biblioteca ou outros. Porém, para a documentação ser eficiente, o primeiro passo é pensar em quem vai ler aquele código, ou seja, quem for realizar uma manutenção ou precisar entender o código precisará saber facilmente o que ele faz, pois isso torna a manutenção e a compreensão eficiente e previne erros de interpretação. Veja o exemplo de documentação: Como deve ser feito: 1) #include <stdio.h> // dependente da biblioteca stdio 2) int fatorial(int n) // função que calcula fatorial de maneira recursiva 3) { 4) if (n) return n*fat(n-1) // recebe o número e chama a própria função novamente decrementando o número recebido. 5) else return 1; 6) } 7) int main() 8) { 9) int n; 10) printf(“\n\n Digite um valor :”); 11) scanf(“%d”,&n); // recebe o número para calcular o fatorial 12) printf(“\n O fatorial de %d”, n, fat(n)); // imprime o valor do fatorial do número digitado 13) return 0; 14) } leituraobRIgATóRIA 13 Como não deve ser feito: 1) #include <stdio.h> // adiciona o arquivo stdio.h 2) int fatorial(int n) // declara função fatorial 3) { 4) if (n) return n*fat(n-1) // calcula fatorial else return 1; // retorna 1 5) } 6) int main() 7) { 8) int n; 9) printf(“\n\n Digite um valor :”); // imprime a requisição de um valor 10) scanf(“%d”,&n); 11) printf(“\n O fatorial de %d”, n, fat(n)); // imprime o valor do fatorial do número digitado 12) return 0; 13) } Veja que no primeiro exemplo os comentários são dirigidos para a compreensão do código, já o segundo tenta explicar o que faz a linha de comando, o que é um erro, pois um programador sabe tecnicamente o que a linha de comando está fazendo, o que ele precisa entender é como aquela linha de comando contribui para o código todo. A documentação exige disciplina e também adota uma metodologia ou padrão. Vamos adotar, aqui, de forma didática, um padrão que terá as seguintes premissas: 1) O que precisa ser documentado Uma boa documentação começa com padrões de declaração de variável e funções, sempre utilizando por padrão letras minúsculas. Todas as funções devem possuir um cabeçalho detalhando sua finalidade e seus parâmetros. Variáveis importantes, ou seja, que não são somente auxiliares, devem ser comentadas. Laços devem ter seu escopo comentado e principalmente as condições de contorno. Se o programa recebe algum parâmetro para executar, devemos colocar esse comentário no cabeçalho da função main(). leituraobRIgATóRIA 14 2) Como documentar A documentação do nosso código terá o seguinte padrão: todo arquivo conterá uma marcação superior e um cabeçalho que conterá os seguintes dados: Objetivo: <Descrever aqui um resumo do “que” faz o código> Autor: <Nome de quem escreveu a primeira versão> Data da Ultima Alteração: <Data da última alteração realizada> Responsável Pela Última Alteração: <Nome de quem fez a última alteração> 3) Versionamento Quando temos várias pessoas alterando um sistema, ou seja, adicionando ou removendo funcionalidades, precisamos criar um mecanismo que controle tais alterações, informando quais alterações ou funcionalidades estão presentes nessa VERSÃO. Esse controle de mudanças é denominado versionamento e baseia-se no registro das mudanças, acompanhado de um código de versão. Exemplo de versionamento em um sistema de gestão de projetos: Versão Registro 1.0 Versão Inicial 2.0 Incluso a remoção de Atividades 2.1 Corrigido um erro ao alterar a data de conclusão de atividade Note que o código de versão apresentado segue o padrão: 2 Dígitos => O primeiro dígito informa que houve uma mudança significativa, inclusão ou remoção de funcionalidade. O segundo dígito informa pequenas mudanças ou correção de erros. As empresas podem empregar diferentes metodologias para versionamento. É comum ver a utilização de até 4 dígitos no código de versionamento. Porém, uma característica comum é o uso da data de liberação da versão. Veja como fica a tabela completa de versionamento: leituraobRIgATóRIA 15 Versão Registro Data de Liberação 1.0 Versão Inicial 01/10/2013 2.0 Incluso a remoção de Atividades 20/11/2013 2.1 Corrigido um erro ao alterar a data de conclusão deatividade 10/12/2013 Quando um sistema sofre alteração, é necessário realizar testes intensos para evitar erros pós-alteração; com isso, a data de liberação indica quando foi disponibilizada para o usuário aquela versão do sistema. Em sistemas comerciais, normalmente a liberação de versões segue uma política de períodos de distribuição que pode ser mensal, bimestral ou até semestral, exceto as liberações para correção de erros críticos. Durante muito tempo, o método comum de controle de versão era copiar os arquivos de um diretório para outro e renomeá-los com o código de versão manualmente. Essa técnica estava susceptível a erros, era fácil sobrescrever arquivos equivocadamente. Para apoiar esse controle, há sistemas específicos para o controle de versão. Os mais conhecidos e open source são: CVS e Subversion. Vamos conhecer o funcionamento básico de um sistema de controle de versão centralizado! (Figura 4.8) leituraobRIgATóRIA 16 Figura 4.8 Diagrama Padrão de um Sistema de Versionamento. Quando um programador quer obter a última versão do código-fonte, ele utiliza um comando chamado checkin; após esse comando, todos os arquivos selecionados são enviados para a máquina local. Após realizar as alterações, o programador utiliza o comando checkout para postar no servidor a nova versão alterada e, com isso, disponibilizar para todos os demais programadores. Quando o servidor de controle de versão recebe os arquivos, ele registra automaticamente o código de versão e grava também as modificações, sendo possível revertê-las ou, até mesmo, mesclá-las com outras versões. leituraobRIgATóRIA 17 linksImPoRTAnTEs Quer saber mais sobre o assunto? Então: Sites: Veja uma apresentação que demonstra a depuração passo a passo de um programa no DEV C++. Disponível em: <http://wiki.icmc.usp.br/images/1/18/Aula12-Arquivos-Parte1. pdf>. Acesso em: 03/02/2014. Vídeos: Assista aos vídeos: Para aprender como instalar subversion (software para controle de versão), acesse: <http:// www.youtube.com/watch?v=R59PzH79IN4>. Acesso em: 03/02/2014. Para aprender como instalar e utilizar o ambiente Dev C++, visite o endereço: <https://www. youtube.com/watch?v=SJqt7c6JuYs>. Acesso em: 03/02/2014. Você vai encontrar um tutorial bem prático que orientará a instalação e o uso do ambiente. Se você pretende iniciar o uso Dev C++, visite o endereço: <http://www.youtube.com/ watch?v=qHMXPIaHJrI>. Acesso em: 03/02/2014. Você encontrará uma videoaula que o auxiliará nos primeiros passos. Versionamento no desenvolvimento de aplicações: <http://www.youtube.com/ watch?v=Wb6RPV9peJ8>. Acesso em: 03/02/2014. Uma apresentação interessante sobre versionamento, explicando a motivação, as dificuldades e ferramentas para versionamento. 18 agoraéasuAvez Instruções: Chegou a hora de você exercitar seu aprendizado por meio das resoluções das questões deste Caderno de Atividades. Essas atividades auxiliarão você no preparo para a avaliação desta disciplina. Leia cuidadosamente os enunciados e atente-se para o que está sendo pedido e para o modo de resolução de cada questão. Lembre-se: você pode consultar o Livro-Texto e fazer outras pesquisas relacionadas ao tema. Questão 1: O que é Depuração ou Debug? Questão 2: A depuração serve para: a) Observar o comportamento do programa em tempo de execução. b) Encontrar erros de compilação. c) Encontrar erros de linkedição. d) Observar o comportamento do programa em tempo de compilação. e) Observar o comportamento do programa em tempo de linkedição. Questão 3: Qual a função do breakpoint ou ponto de interrupção? a) Informar o compilador onde deve parar a compilação. b) Informar o ponto de execução. c) Informar o depurador onde deve pausar a execução. d) Destacar a linha de execução. e) Destacar a linha de depuração. Questão 4: Para que serve a documentação do código- fonte? 19 agoraéasuAvez a) Serve para detalhar em forma de comentário o uso de argumentos de compilação e linkedição. b) Tem por objetivo declarar o tipo, a data e o autor do código. c) Tem por objetivo declarar o autor do código para rastrear o responsável pelos erros. d) Serve para explicar em forma de comentário o objetivo das funções, variáveis e até mesmo do programa ou da unidade do código. e) Serve para documentar o uso de bibliotecas e arquivos adicionar (.h). Questão 5: O versionamento de programa é baseado em: a) Parametrização do compilador para registrar alterações no programa. b) Registro das funções do programa, identificado por um código. Ex: f2.0, f2.1 e informações adicionais referentes a cada função. c) Registro de versões do programa, identificado por um código. Ex: 2.0, 2.1 e informações adicionais referentes a cada versão. d) Parametrização do linkeditor para registrar alterações nas bibliotecas. e) Registro do uso de arquivos do tipo header (.h). Questão 6: Utilizando o que você aprendeu sobre documentação de código, comente o código a seguir: 1) #include<stdio.h> 2) int main() 3) { 4) int n, primeiro = 0, segundo = 1, prox, c; 5) printf(“Entre com o número\n”); 6) scanf(“%d”,&n); 7) printf(“ A sequencia de Fibonacci para %d é :-\n”,n); 8) for ( c = 0 ; c < n ; c++ ) 9) { 10) if ( c <= 1 ) 11) prox = c; 12) else 13) { 14) prox = primeiro + segundo; 15) primeiro = segundo; 16) segundo = prox; 17) } 18) printf(“%d\n”,prox); 19) } 20) return 0; 21) } 20 agoraéasuAvez Questão 7: Qual o problema com os comentários do código a seguir? 1) #include <stdio.h> // adiciona o arquivo stdio.h 2) int fatorial(int n) // declara função fatorial 3) { 4) if (n) return n*fat(n-1) // calcula fatorial else return 1; // retorna 1 5) } 6) int main() 7) { 8) int n; 9) printf(“\n\n Digite um valor :”); // imprime a requisição de um valor 10) scanf(“%d”,&n); 11) printf(“\n O fatorial de %d”, n, fat(n)); // imprime o valor do fatorial do número digitado 12) return 0; 13) } Questão 8: Por que em sistemas profissionais há uma preocupação com documentação e versionamento? Questão 9: Imagine que você fará a manutenção de um programa que faz a gestão de proje- tos de uma empresa e que está na versão 3.6.1. Você fará alterações em duas fases. A primeira será uma grande alteração de inclusão da gestão de projetos por portfó- lio; a segunda será apenas um ajuste para corrigir um erro ao alterar a data de encer- ramento das tarefas. Apresente como fica- ria a tabela de versionamento. Questão 10: Como é o padrão de aquisição e postagem (checkin e checkout) de arquivos em um sistema de versionamento? 21 A evolução de uma área denominada engenharia de software trouxe inúmeras atividades e processos bem-estabelecidos como “boas práticas” para tornar eficiente a programação e o desenvolvimento de sistemas (SOMMERVILLE, 2003). A documentação do código e o versionamento são o resultado intenso da revisão dessas práticas, pois o grande objetivo é tornar um programa de fácil de leitura e compreensão por parte dos programadores e, por outro lado, garantir que a distribuição do programa esteja livre de erros e de acordo com a expectativa do usuário cliente, por meio de uma política de distribuição de versões. Caro aluno, agora que o conteúdo dessa aula foi concluído, não se esqueça de acessar sua ATPS e verificar a etapa que deverá ser realizada. Bons estudos! finalizando referências MIZRAHI, Viviane V. Treinamento Linguagem C. São Paulo: Pearson, 2008. SCHILDT, H. C. Completo e Total. 3. ed. São Paulo: Makron Books, 1996. SOMMERVILLE, IAN. Engenharia de Software. 6. ed. São Paulo: Pearson, 2003. 22glossário Código-fonte: código do programa em linguagem natural que será compilado e interpretado pelo computador. ERP: sistema integrado de gestão corporativa, normalmente possui módulos financeiro, vendas, faturamento, entre outros. e-Commerce: sistema de compras pela internet, cujo objetivo é possibilitar compras eletrônicas, sendo normalmente integrado ao ERP. BI (Business Intelligence): sistema que tem por objetivo construir análises de diversas bases de dados para apoiar a tomada de decisão; as análises podem ser baseadas em relatórios, gráficos ou indicadores. gabarito Questão 1 Resposta: Depurar e acompanhar a execução do programa linha a linha ou por meio de um ponto de interrupção, conhecido como breakpoint. O objetivo é analisar o comportamento do programa durante sua execução. Normalmente, utilizamos o artifício de depuração quando buscamos entender algum erro que não esteja evidente e que se manifeste apenas durante a execução do programa. 23 gabarito Questão 2 Resposta: Alternativa A. Questão 3 Resposta: Alternativa C. Questão 4 Resposta: Alternativa D. Questão 5 Resposta: Alternativa C. Questão 6 Resposta: // Autor: Estudante // Data Criação: 12/12/2013 //Objetivo: Cálculo do Número de Fibonacci 1) #include<stdio.h> 2) int main() 3) { 4) int n, primeiro = 0, segundo = 1, prox, c; 5) printf(“Entre com o número\n”); 6) scanf(“%d”,&n); // Obtém o número para calcular a sequencia de fibonacci 7) printf(“ A sequencia de Fibonacci para %d é :-\n”,n); // Apresenta sequencia de fibonacci até o número informado. 24 8) for ( c = 0 ; c < n ; c++ ) // Looping responsável pela interação de 0 até o número fornecido pelo usuário 9) { 10) if ( c <= 1 ) 11) prox = c; 12) else 13) { 14) //nesse ponto a variável prox armazena os 2 últimos antecessores do número atual apontado pela iteração 15) prox = primeiro + segundo; 16) primeiro = segundo; 17) segundo = prox; 18) } 19) printf(“%d\n”,prox); 20) } 21) return 0; 22) } Questão 7 Resposta: O problema do código é que os comentários dizem sobre os comandos de cada linha e não explicam como essas linhas cumprem sua função perante o objetivo do código. 1) #include <stdio.h> // adiciona o arquivo stdio.h 2) int fatorial(int n) // declara função fatorial 3) { 4) if (n) return n*fat(n-1) // calcula fatorial else return 1; // retorna 1 5) } gabarito 25 6) int main() 7) { 8) int n; 9) printf(“\n\n Digite um valor :”); // imprime a requisição de um valor 10) scanf(“%d”,&n); 11) printf(“\n O fatorial de %d”, n, fat(n)); // imprime o valor do fatorial do número digitado 12) return 0; 13) } Questão 8 Resposta: Como em sistemas grandes e profissionais vários programadores realizam alterações nos códigos, é importante registrar as alterações e as versões que consolidam essas alterações para que se controle quem, o que, quando foram feitas as alterações e quais funcionalidades contêm cada versão. Questão 9 Resposta: Versão Registro Data de Liberação 3.6.1 Versão Inicial 03/01/2014 4.0.0 Incluso Gestão de Projetos por Portfólio 10/01/2013 4.0.1 Corrigido um erro da data de encerramento das tarefas. 10/12/2013 Foi colocada a versão 3.6.1 como versão inicial para fins didáticos, a fim de notar como se altera a versão 3.6.1 para versão 4.0.0, visto que a mudança é grande; já a transição da versão 4.0.1 é uma mudança pequena, por isso alterou apenas o último dígito do código de versão. gabarito 26 Questão 10 Resposta: Quando um programador deseja obter a última versão do código–fonte, ele utiliza um comando chamado checkin. Após esse comando, todos os arquivos selecionados são enviados para a máquina local. Após realizar as alterações, o programador utiliza o comando checkout para postar no servidor a nova versão alterada e, com isso, disponibilizá- la para todos os demais programadores. Quando o servidor de controle de versão recebe os arquivos, ele registra automaticamente o código de versão e grava também as modificações, sendo possível revertê-las ou, até mesmo, mesclá-las com outras versões. gabarito 24/03/2014 1 Programação Estruturada II Tema: Revisão de Conteúdo Profª MSc. Edilene A. V. de Campos Objetivos desse encontro • Revisar conteúdo ponteiro; • Revisar conteúdo recursividade; • Revisar conteúdo arquivo; • Revisar conteúdo depuração e documentação O que é um Ponteiro? Indica um espaço de memória em particular. Referencia indiretamente um conteúdo. Resumindo, um ponteiro é uma variável que armazena um endereço de memória. 24/03/2014 2 Criação de ponteiro char a, *b; int *c; ... a M 000123A1 000123A2b 000423E1 000423E1 c 000223FB 000223FB ... Operadores de ponteiros Existem 2 operadores necessários relacionados com ponteiros: & → obtém o endereço de memória ocupado por qualquer variável * → possui duas funções: 1) criar um ponteiro e 2) fazer uma indireção Exemplo do uso dos operadores * e & #include <stdio.h> int main(void) { int *pt, n; pt = &n; *pt = 10; println(“valor de n = %d“, n); println(“o endereço de n = %p “, pt); return 0; } 24/03/2014 3 Passagem de parâmetros (ou argumentos) Existem 2 maneiras para realizar a passagem de parâmetros para uma função: por valor e por referência. A linguagem C permite apenas passagem por valor. Entretanto, pode-se usar ponteiro para simular uma passagem por referência. Passagem de parâmetros (ou argumentos) por valor A passagem de parâmetros por valor cria cópia de conteúdos para serem utilizados pela função. Quando a execução da função termina, tais cópias são destruídas e todas as mudanças que as cópias sofreram são perdidas. Passagem de parâmetros (ou argumentos) por referência A passagem de parâmetros por referência trabalha com o conteúdo original, sem criar cópias. Quando a execução da função termina, nada é destruído. C simula a passagem por referência usando ponteiros. Assim, são criadas cópias apenas dos endereços de memória. 24/03/2014 4 Usando qualificador const com ponteiros O qualificador const também pode ser utilizado com ponteiros, das seguintes maneiras: - ponteiro não constante referenciando dados constantes; - ponteiro constante referenciando dados não constantes; - ponteiro constante referenciando dados constantes. Operador sizeof O operador sizeof permite descobrir o tamanho em bytes de um tipo de dado. size_t y = sizeof(float); OU float a; double b[12]; size_t x = sizeof(a); size_t y = sizeof(b); Aritmética de ponteiros Exemplo: int *ptr, vet[5]; ptr = &vet[0]; *ptr = 6; ptr=ptr+2; *ptr = 8; ... 0 1 2 3 4 6 8 24/03/2014 5 Ponteiros e arrays Arrays são diretamente ligados a ponteiros na linguagem C. Utilizar o nome de um array sem um subscrito informa o endereço da primeira posição do array. Exemplo: int a[5], *pt1, *pt2; pt1 = a; //equivale a pt1 = &a[0]; O que é Recursividade? •Alguma coisa que é definida em termos dela própria. •É a possibilidade de representar um problema em função dele próprio, contudo, numa instância menor. •Diminuir o problema até chegar em uma solução trivial (óbvia ou de fácil cálculo). 24/03/2014 6 Exemplo de Recursividade 1) Cálculo da potência de um número: 24 é bem mais fácil de calcular que 2876. Entretanto, o problema é o mesmo, o que muda é a instância do problema (ou o tamanho do problema). Exemplo de Recursividade 24 = 2 * 23 23 = 2 * 22 22 = 2 * 21 21 = 2 Exemplo de Recursividade 2) Cálculo do fatorial de um número: 4! é bem mais fácil de calcular que 345! Entretanto, o problema é o mesmo,o que muda é a instância do problema (ou o tamanho do problema). 24/03/2014 7 Exemplo de Recursividade 5! = 5 * 4! 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 Características importantes para funções recursivas •Possuem uma função de recorrência; •Possuem uma condição que identifica o momento de interromper a recorrência; •Possuem sempre instância do problema para a qual a solução é facilmente obtida. Função recursiva para calcular uma potência 24 = 2 * 23 23 = 2 * 22 22 = 2 * 21 21 = 2 Suponto uma potência genericamente representada por be: - Função de recorrência: be = b * be-1 - Instância com solução conhecida: b1 = b - Condição de parada: se e=1 24/03/2014 8 Função recursiva da potência em C #include<stdio.h> int potencia(int b, int e); int main() { int base, exp, result; printf(“\nDigite valor da base: “); scanf(“%d”, &base); printf(“\nDigite valor do expoente: “); scanf(“%d”, &exp); result = potencia(base, exp); printf(“\nPotencia = %d“, result); getchar(); } Função recursiva da potência em C (continuação) int potencia(int b, int e) { int pot = 0; if (e == 1) { pot = b; } else { pot = b * potencia(b, -1); } return pot; } 23 2 * 22 2 * 21 2 E 1 E 2 E 3 2 4 8 pot(base=2, expoente=3) = 8 Analisando a execução ... 24/03/2014 9 O que é um Arquivo? É um recurso utilizado para armazenamento permanente de informações. Um arquivo é uma sequência de valores binários (0s ou 1s), agrupados em bytes. Manipulação de arquivo - abertura fopen → abre um arquivo (ou seja, cria uma stream para o arquivo). ptr = fopen(“arquivo”, “modo abertura”) Obs: Se não for possível abrir o arquivo, o ponteiro ptr assumirá o valor null e nenhuma operação de leitura ou escrita poderá ser realizada. 24/03/2014 10 Modos de abertura r→ Abre um arquivo existente para leitura. w→ Cria um arquivo para gravação. Se o arquivo já existe, sobrescreve. a→ Abre ou cria um arquivo para adicionar dados ao seu final. r+ → Abre um arquivo para leitura e escrita; caso não exista, arquivo será criado. w+ → Abre um arquivo para escrita; caso não exista, será criado. a+ → Abre ou cria um arquivo para atualização; dados serão gravados no final do arquivo. Modos de abertura rb→ Abre um arquivo para leitura no modo binário. wb → Cria um arquivo para gravação no modo binário; se o arquivo já existir, sobrescreve. ab→ Abre ou cria um arquivo para adicionar dados ao seu final, no modo binário . rb+ → Abre um arquivo para leitura e escrita no modo binário. wb+ → Cria um arquivo para escrita no modo binário; se o arquivo já existir, sobrescreve. ab+ → Abre ou cria um arquivo para atualização no modo binário; a gravação é feita no final do arquivo. Arquivo binário X Arquivo texto • Em algum arquivo texto todos os dados gravados são obrigatoriamente convertidos para caracteres. Assim, arquivos textos podem ser visualizados através de qualquer editor de texto. Com isso, cada caractere consome 8 bits. • Arquivos binários gravam os dados no formato original, sem conversões. A quantidade de memória depende do tipo de dado gravado. 24/03/2014 11 Manipulação de arquivo - fechamento fclose→ todo arquivo precisa ser fechado. Para tal, utiliza-se o ponteiro obtido no momento da abertura. fclose(ptr) Manipulação de arquivo – detectando fim do arquivo feof → a função feof retorna verdadeiro toda vez que o programa tenta acessar dados de um arquivo cujo ponteiro já chegou ao final (e, portanto, não tem mais dados para retornar). Normalmente feof é usada em uma condição. feof(ptr) Ler e Escrever em arquivo de acesso sequencial fprintf → escreve um conteúdo em um arquivo. fprintf(ptr, “%d”, idade); fscanf → lê um conteúdo de um arquivo. fscanf(ptr, “%d%s”, &idade, nome); 24/03/2014 12 Arquivo de acesso aleatório • Acessar aleatoriamente um arquivo significa que não é necessário percorrer todas as posições desde o início. • O acesso aleatório permite realizar a operação de leitura ou de gravação na posição exata, usando deslocamentos. Leitura e Gravação em arquivo de acesso aleatório - gravação int ret= fwrite(&variável, sizeof(algum tipo), qtd_gravacoes, ponteiro_arquivo); - leitura int ret= fread(&variável, sizeof(algum tipo), qtd_leituras, ponteiro_arquivo); Reposicionando ponteiro de um arquivo de acesso aleatório fseek(ponteiro_arquivo, tamanho do deslocamento, posicao_origem); O valor de posicao_origem pode ser um valor definido dentre 3 possibilidades: SEEK_SET → a partir do início do arquivo SEEK_CUR → a partir da posição atual SEEK_END → a partir do fim do arquivo 24/03/2014 13 Depuração de programas Depurar programas é: Acompanhar a execução de um programa, tentando encontrar falhas ou tentando melhorar o seu desempenho. Teste de mesa • Estratégia utilizada pelo programador para, manualmente, acompanhar a as linhas escritas em um programa, simulando a sua execução. • Além de acompanhar as linhas, também ocorre o monitoramento do conteúdo das variáveis de memória. 24/03/2014 14 Depuração automática de programas •Quando o programa (ou trecho de código) a ser analisado é muito extenso ou muito complexo, pode-se fazer uso da depuração automática. •Grande parte das IDEs (como o DEV C++) traz este recurso através do Debug. Objetivos da depuração automática •Verificar a execução de todas as linhas do programa; •Acompanhar a utilização das variáveis de memória e seus respectivos valores ao longo da execução. •Todo programa de computador passa por manutenção durante sua vida útil. •Essa evolução requer manutenção pode ser corretiva ou evolutiva. •A documentação do código-fonte tem como objetivo facilitar as manutenções futuras. Documentação de código 24/03/2014 15 •Documentação começa pela escolha de nomes de variáveis, constantes e funções. •Os nomes escolhidos devem refletir o conteúdo de uma variável ou constante ou a ação realizada por uma função. Boas práticas na documentação de código • Existem 2 tipos de comentários usados em C: � Comentário de uma linha, iniciando com os símbolos // terminado ao final da linha; � Comentário de múltiplas linhas, iniciando com os símbolos /* e terminando com os símbolos */. Comentar o código • Comentários de uma linha são indicados para apresentar uma explicação rápida sobre o significado de um comando, feito na respectiva linha. • Comentários de múltiplas linhas são indicados para explicar o que é feito em um bloco de comandos, como uma função ou um laço, por exemplo. Comentar o código 24/03/2014 16 •É importante adotar controle de versões dos programas para que seja possível registrar a sua evolução e, também, permitir o trabalho de várias pessoas em um mesmo código. •Existe um padrão para determinar o número de uma versão. Controlando versionamento Padrão de versionamento Nº versão Registro Data liberação 1.0 Versão inicial 10/02/2013 2.0 Acrescimo função XXX 20/08/2013 2.1 Correção cálculo valor a pagar 15/12/2013 Fonte: Adaptado de TORRES, Renato Cristiano, Programação Estruturada II. Valinhos: Anhanguera Educacional, 2014. p. 1-90. Disponível em: <http://www.anhanguera.com>. Acesso em: 03 fev. 2014. Fonte: TORRES, Renato Cristiano, Programação Estruturada II. Valinhos: Anhanguera Educacional, 2014. p. 1-90. Disponível em: <http://www.anhanguera.com>. Acesso em: 03 fev. 2014. Como versionar?
Compartilhar