Baixe o app para aproveitar ainda mais
Prévia do material em texto
Escola Politécnica da Universidade de São PauloEscola Politécnica da Universidade de São Paulo Laboratório de Programação Orientada a Objetos para Engenharia Elétrica Aula 2: Ponteiros, Testes e Depuração PCS3111 Agenda 1. Arquitetura de von Neumann 2. Ponteiros • Ponteiros e arranjos • Passagem de parâmetro em C++ 3. Testes e depuração 4. Qualidade de código © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Arquitetura de von Neumann © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Computador Arquitetura de von Neumann Unidade Lógica-Aritmética (ULA) Unidade de Controle (UC) CPU Entrada: Teclado, mouse... Saída: Monitor, impressora ... E/SMemória © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Arquitetura de von Neumann A memória é uma sequência de bytes • 1 byte = 8 bits • Bytes são numerados sequencialmente • Dados e instruções (programa) ficam na memória Memória 0x000000 ... 0x000080 0x000084 0x000088 ... 0x000200 0x000204 ... CPU E/S Dados Instruções © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Arquitetura de von Neumann Exemplo: antes da execução Memória 0x000000 ... 0x000080 0x000084 5 i 0x000088 17 k ... 0x000200 i = i + k 0x000204 ... CPU E/S Dados Instruções © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Arquitetura de von Neumann Exemplo: depois da execução Memória 0x000000 ... 0x000080 0x000084 22 i 0x000088 17 k ... 0x000200 i = i + k 0x000204 ... CPU E/S Dados Instruções © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Ponteiros © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Ponteiros Variável especial que referencia um endereço da memória • Também chamado de apontador • “p” é um ponteiro que aponta para o valor de “i” int i = 100; 0x000000 ... i 100 0x000084 0x000088 p 0x000084 0x00008C ... © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Ponteiros Declaração • O ponteiro é específico para um tipo de variável Operador & • Obtêm o endereço de uma variável <Tipo> *p; 12 int *p1; 13 double *p2; 6 int i = 100; 7 double j = 5.5; 8 9 cout << &i << endl; 10 cout << &j << endl; 12 int *p1; 13 double *p2; 14 15 p1 = &i; 16 p2 = &j; 17 18 cout << p1 << endl; 19 cout << p2 << endl; Saída 0x6afef4 0x6afee8 0x6afef4 0x6afee8 p1 aponta para i EX01 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Ponteiros Operador * (desreferenciação) • Permite obter o valor apontado pelo ponteiro • É possível usá-lo para alterar o valor 6 int i = 5; 7 int *p = &i; 8 9 cout << i << endl; 10 cout << *p << endl; 12 *p = 10; 13 cout << *p << endl; 14 cout << i << endl; EX02 Saída 5 5 Saída 10 10 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Usando um ponteiro O valor inicial de um ponteiro é indefinido NULL • Representa que o ponteiro aponta para nenhum valor • NULL está definido em várias bibliotecas Em iostream, por exemplo 6 int *p1; // endereço indefinido 7 8 cout << *p1 << endl; // Ops… Problema! EX03 10 int *p2; // endereço indefinido 11 p2 = NULL; // nenhum valor 12 13 if (p2 == NULL) { É possível testar 14 cout << "Null" << endl; 15 } EX03 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Usando um ponteiro Na verdade, o ponteiro também está na memória • Então qual é o valor de: 0x000000 ... i 5 0x000084 0x000088 p 0x000084 0x00008C ... &i p *p &p *&i 6 int i = 5; 7 int *p = &i; EX02 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Usando um ponteiro Vários ponteiros podem apontar para o mesmo valor 6 char c = 'a'; 7 8 char *p1 = &c; 9 char *p2 = &c; 10 char *p3 = p1; 11 12 cout << *p3 << endl; 13 14 *p3 = 'b'; 15 16 cout << c << endl; EX04 Saída a b 0x000000 ... c ‘a’ 0x000084 ... p1 0x000084 0x000100 ... p2 0x000084 0x000200 p3 0x000084 0x000300 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Usando um ponteiro É possível ter ponteiros de ponteiros 0x000000 ... i 100 0x000084 0x000088 p1 0x000084 0x00008C ... p2 0x00008C 0x120060 6 int i = 100; 7 int *p1 = &i; 8 9 int **p2; 10 p2 = &p1; 11 12 cout << i << endl; 13 cout << *p1 << endl; 14 cout << **p2 << endl; EX05 Saída 100 100 100 p2 é um ponteiro para ponteiro de inteiros © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Ponteiros e arranjos Um arranjo é um ponteiro • A variável aponta para a primeira posição do arranjo • Um ponteiro para o arranjo pode ser usado como um arranjo 0x000000 ... 1 0x000084 2 0x000088 5 0x00008C a1 0x000084 6 int a1[] = {1, 2, 5}; Observação: em C++ não é possível retornar arranjos. É necessário retornar um ponteiro. 8 int *p = a1; 9 10 cout << p[0] << endl; 11 cout << p[2] << endl; Saída 1 5 EX06 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Ponteiros e arranjos É possível ter um arranjo de ponteiros • Ponteiro é um tipo • Observação: esse arranjo é um ponteiro de ponteiros! 15 int *a2[10]; 16 17 int i = 0; 18 a2[0] = &i; 19 20 *a2[0] = 10; EX06 Alternado o valor do inteiro em i para 10 Arranjo para 10 ponteiros de int Colocando o endereço de i na posição 0 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Passagem de parâmetro Como funciona a passagem de parâmetros? • Qual é a saída em tela? 5 void trocar(int a, int b) { 6 int temp = a; 7 a = b; 8 b = temp; 9 } ... 24 int main() { 25 int a = 1; 26 int b = 2; 27 28 trocar(a, b); 29 cout << "a: " << a << " b: " << b << endl; ... EX07 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Passagem de parâmetro O C++ passa argumentos por valor • Ou seja, é feita uma cópia do valor da variável 5 void trocar(int a, int b) { 6 int temp = a; 7 a = b; 8 b = temp; 9 } ... 24 int main() { 25 int a = 1; 26 int b = 2; 27 28 trocar(a, b); ... EX07 0x000000 ... a 1 0x000084 b 2 0x000088 ... 0x120060 0x120064 ... © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Passagem de parâmetro O C++ passa argumentos por valor • Ou seja, é feita uma cópia do valor da variável 5 void trocar(int a, int b) { 6 int temp = a; 7 a = b; 8 b = temp; 9 } ... 24 int main() { 25 int a = 1; 26 int b = 2; 27 28 trocar(a, b); ... EX07 0x000000 ... a 1 0x000084 b 2 0x000088 ... a' 1 0x120060 b' 2 0x120064 ... Cópia © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Passagem por referência C++ permite parâmetros por referência • Nesse caso a referência ao valor é passada como parâmetro • Usar o símbolo & na declaração do parâmetro 11 void trocar1(int& a, int& b) { 12 int temp = a; 13 a = b; 14 b = temp; 15 } ... 24 int main() { 25 int a = 1; 26 int b = 2; ... 33 trocar1(a, b); ... EX07 Por referência 0x000000 ... a 1 0x000084 b 2 0x000088 ... 0x120060 0x120064 ... © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Passagem usando ponteiros Uma outra forma é usar ponteiros 17 void trocar2(int* a, int* b) { 18 int temp = *a; 19 *a = *b; 20 *b = temp; 21 } ... 24 int main() { 25 int a = 1; 26 int b = 2; ... 38 trocar2(&a, &b); ... EX07 Ponteiro Endereço de a e de b 0x000000 ... a 1 0x000084 b 20x000088 ... 0x120060 0x120064 ... © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Passagem usando ponteiros Uma outra forma é usar ponteiros 17 void trocar2(int* a, int* b) { 18 int temp = *a; 19 *a = *b; 20 *b = temp; 21 } ... 24 int main() { 25 int a = 1; 26 int b = 2; ... 38 trocar2(&a, &b); ... EX07 Ponteiro Endereço de a e de b 0x000000 ... a 1 0x000084 b 2 0x000088 ... a' 0x000084 0x120060 b' 0x000088 0x120064 ... © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Testes e Depuração © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Testes e depuração Definições • Teste: processo de executar um programa com o objetivo de encontrar erros • Depuração: processo de localizar um suposto erro e corrigi-lo Saídas corretas em um teste não garantem que o software não tem erros • O teste pode não ter sido bom o suficiente! Existem abordagens de teste e de depuração • Engenharia de Software © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Exemplo: total de uma compra Se a soma dos preços dos produtos for maior que "limite" reais, o frete não deve ser cobrado • Como fazer testes? 11 double totalDaCompra (double produtos[], int quantidade, 12 double frete, double limite) { 13 double total = 0; 14 for (int i = 0; i < quantidade; i++) 15 total = total + produtos[i]; 16 if (total > limite) 17 total = total + frete; 18 return total; 19 } EX08 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Exemplo: total de uma compra Se a soma dos preços dos produtos for maior que "limite" reais, o frete não deve ser cobrado Saída Erro: 35.5 11 double totalDaCompra (double produtos[], int quantidade, 12 double frete, double limite) { 13 double total = 0; 14 for (int i = 0; i < quantidade; i++) 15 total = total + produtos[i]; 16 if (total > limite) 17 total = total + frete; 18 return total; 19 } EX08 21 int main() { 22 double produtos[] = {5, 10, 5, 10}; 23 double total = totalDaCompra (produtos, 4, 5.5, 25); 24 25 if (total != 30) cout << "Erro: " << total << endl; ... Teste © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Depuração Breakpoint • Ponto de parada no programa para depuração Inserir breakpoint na linha 23 usando botão direito ou 1 clique na linha 23 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Depuração Controle da depuração Executar até o próximo breakpoint Ir para a próxima linha Entrar na função existente na linha atual Janelas de depuração (a mais importante é a watches, que mostra os valores das variáveis) © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Observação Nunca compare double com == ou != • Pontos flutuantes tem problemas de precisão © PCS / EP / USP 2016 – PCS 3111 – Aula 2 1 #include <iostream> 2 #include <cmath> 3 4 using namespace std; .. 21 22 int main() { 23 double produtos[] = {5, 10, 5, 10}; 24 double total = totalDaCompra (produtos, 4, 5.5, 25); 25 26 if (abs(total - 30) > 0.01) cout << "Erro: " << total << endl; 27 return 0; 28 } Inclua cmath para usar o abs e faça using namespace std Se a diferença entre o valor esperado e o obtido for maior que um épsilon, há um erro EX08b Qualidade de Código © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Qualidade do código O que é um bom código? • Correto Faz o que se espera • Eficiente Não desperdiça recursos (memória e processador) • Elegante Simples, limpo, bonito e sem enfeites • Testável Fácil de procurar erros © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Qualidade do código O que esse código faz? 1 #include <iostream> 2 using namespace std; 3 4 int main() { 5 int i,J,k; 6 int l[10]; 7 cout << "Digite 10 numeros" << endl; 8 for (i=0;i<10; i++) 9 cin >>l[i]; k= 0; 10 for(J =0;J < 10;J++) { 11 if (l[J]> 0) k +=l[J];} 12 13 cout << "Valor: " << k; 14 return 0; 15 } Alguns problemas: • Nome das variáveis • Indentação • Espaçamento • Blocos não claros EX09 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Qualidade do código Uma outra versão do mesmo código 1 #include <iostream> 2 using namespace std; 3 4 int main() { 5 int entrada[10]; 6 cout << "Digite 10 numeros" << endl; 7 8 for (int i = 0; i < 10; i++) 9 cin >> entrada[i]; 10 11 int soma = 0; 12 13 for (int i = 0; i < 10; i++) { 14 if (entrada[i] > 0) 15 soma += entrada[i]; 16 } 17 18 cout << "Valor: " << soma; 19 return 0; 20 } EX10 © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Nome de variáveis Use nomes representativos • Cuidado com abreviações ou nomes longos • Dica: use “CTRL + ESPAÇO" para autocompletar Convenção: CamelCase • Variáveis e funções Primeira palavra com letra minúscula e as demais com só a 1ª letra em maiúscula Exemplo: i, peso, maiorNumero e pedidosAtrasados • Nomes de arquivos Cada palavra com a 1ª letra maiúscula e as demais minúsculas Exemplo: HelloWorld.cpp, Exemplo1.cpp, ListaLigada.cpp © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Organização geral Declaração de variável no início do bloco • Bloco real (if, for, etc.) ou lógico (organização do código) Declare somente a variável controladora do for no for • Exemplo: for (int i = 0, z; i < 10; i++) { int z; for (int i = 0; i < 10; i++) { ✓ ✕ © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Espaçamento Use um espaço para separar uma palavra da seguinte • =, <=, while, if, for etc. são palavras Deixe um espaço depois, mas não antes, de cada sinal de pontuação • Exemplo: int i, j; Parênteses • Deixe um espaço antes, mas não depois, de abrir um parêntese • Deixe um espaço depois, mas não antes, de fechar um parêntese • Exemplo: for (int i = 0; i < 5; i++) j++; © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Espaçamento Exceções • x[i] e não x [i] • x++ e não x ++ • "." não é sinal de pontuação em C++! © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Chaves (bloco) O { deve ficar na mesma linha do comando que define o bloco, com um espaço antes • Exemplo O } deve ficar em uma linha separada, mas alinhado com o comando que definiu o bloco • Exemplo if (x > 5) { if (x > 5){ if (x > 5) { if (x > 5) { if (x > 5) { // ... } ✓ ✕ ✕ ✕ ✓ © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Blocos O conteúdo de um bloco deve ficar tabulado (um “tab”, normalmente) • Deve ser possível diferenciar o que está dentro ou fora do bloco! • Exemplo for (int i = 0; i < 5; i++) { if (entrada[i] > 5) { cout << entrada[i] << endl; } } for (int i = 0; i < 5; i++) { if (entrada[i] > 5) { cout << entrada[i] << endl; }} ✓ ✕ © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Recomendações if, else e else if devem ficar alinhados As chaves podem ser omitidas se o bloco tiver apenas uma linha • Indente ou deixe na mesma linha o comando if (x == 0) { //... } else if (x > 0) { //... } else { //... } if (x > 5) i++;if (x > 5) i++; ✓ ✓ ✓ © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Outras recomendações Evite processamento desnecessário Evite excesso de otimização • Código ilegível, mas eficiente! Dificuldade de manutenção • (a menos que otimização seja fundamental) O fundamental é ser consistente © PCS / EP / USP 2016 – PCS 3111 – Aula 2 Bibliografia FEOFILOFF, P. Algoritmos em linguagem C. Editora Campus, 2009. Apêndices A e D. MYERS, G. J. The Art of Software Testing. John Wiley & Sons, 2ª edição, 2004. SAVITCH, W. C++ Absoluto. Pearson, 1st ed. 2003. Seção 10.1. © PCS / EP / USP 2016 – PCS 3111 – Aula 2
Compartilhar