A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Aula 9 Matrizes clássicas e vectores em C++ Melhor alternativa!

Apresentações semelhantes


Apresentação em tema: "Aula 9 Matrizes clássicas e vectores em C++ Melhor alternativa!"— Transcrição da apresentação:

1 Aula 9 Matrizes clássicas e vectores em C++ Melhor alternativa!

2 2003/2004 Introdução à Programação 2 Ler três inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza três inteiros: "; int a, b, c; cin >> a >> b >> c; cout << c << endl << b << endl << a << endl; } Como generalizar para 100, por exemplo? Para simplificar ignoram-se possíveis erros de extracção!

3 2003/2004 Introdução à Programação 3 Adaptação para 100 inteiros Basta acrescentar 97 variáveis, obviamente…

4 2003/2004 Introdução à Programação 4 Ler 100 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 100 inteiros: "; int a1, a2, a3, …, a100; cin >> a1 >> a2 >> a3 >> … >> a100; cout << a100 << endl << a99 << endl … << a1 << endl; } Pouco prático…

5 2003/2004 Introdução à Programação 5 Ler 100 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 100 inteiros: "; int valores[100]; ? } Matriz de 100 inteiros

6 2003/2004 Introdução à Programação 6 Sintaxe double m[4]; m[2] = 2.2; double x = m[3]; Tipo dos elementos Nome da matriz Número de elementos Indexações Como uma variável

7 2003/2004 Introdução à Programação 7 Organização double m[4]; m [0]: ? m: double[4] m [1]: ? m [2]: ? m [3]: ? Índices: 1º elemento: índice 0 2º elemento: índice 1 … nº elemento: índice n-1

8 2003/2004 Introdução à Programação 8 Inicialização double m[4]; Com lixo! m [0]: ? m: double[4] m [1]: ? m [2]: ? m [3]: ?

9 2003/2004 Introdução à Programação 9 Inicialização explícita double m[4] = {0.0, 1.1, 2.2, 3.3}; m [0]: 0 m: double[4] m [1]: 1,1 m [2]: 2,2 m [3]: 3,3

10 2003/2004 Introdução à Programação 10 Inicialização implícita (I) double m[4] = {0.0, 1.1}; m [0]: 0 m: double[4] m [1]: 1,1 m [2]: 0 m [3]: 0

11 2003/2004 Introdução à Programação 11 Inicialização implícita (II) double m[4] = {}; m [0]: 0 m: double[4] m [1]: 0 m [2]: 0 m [3]: 0

12 2003/2004 Introdução à Programação 12 Problemas das matrizes (I) Inicializadas implicitamente com lixo Inicialização explícita exaustiva…

13 2003/2004 Introdução à Programação 13 Ler 100 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 100 inteiros: "; int valores[100]; cin >> valores[0]; cin >> valores[1]; cin >> valores[2]; … ? } Absurdo! Por extensão não se ganhou nada!

14 2003/2004 Introdução à Programação 14 Ler 100 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 100 inteiros: "; int valores[100]; for(int i = 0; i != 100; ++i) cin >> valores[i]; ? } Extracção dos 100 inteiros e armazenamento na matriz por compreensão

15 2003/2004 Introdução à Programação 15 Ler 100 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 100 inteiros: "; int valores[100]; for(int i = 0; i != 100; ++i) cin >> valores[i]; for(int i = 100; i != 0; --i) cout << valores[i - 1] << endl; } Inserção dos 100 inteiros por ordem inversa

16 2003/2004 Introdução à Programação 16 Ler 100 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 100 inteiros: "; int valores[100]; for(int i = 0; i != 100; ++i) cin >> valores[i]; for(int i = 99; i != -1; --i) cout << valores[i] << endl; } Preferível!

17 2003/2004 Introdução à Programação 17 Elementos fictícios double m[4]; m [0]: ? m : double [4] m [1]: ? m [2]: ? m [3]: ? Elemento inicial m [-1]: m [4]: ? Elemento final Primeiro elemento Último elemento

18 2003/2004 Introdução à Programação 18 Ciclos com matrizes Directo Do primeiro ao elemento final, exclusive Inverso Do último ao elemento inicial, exclusive

19 2003/2004 Introdução à Programação 19 Adaptação para 1000 inteiros Basta substituir 100 por 1000, obviamente…

20 2003/2004 Introdução à Programação 20 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << "Introduza 1000 inteiros: "; int valores[1000]; for(int i = 0; i != 1000; ++i) cin >> valores[i]; for(int i = 99; i != -1; --i) cout << valores[i] << endl; } Ops…

21 2003/2004 Introdução à Programação 21 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { int const número_de_valores = 1000; cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; for(int i = 0; i != número_de_valores; ++i) cin >> valores[i]; for(int i = número_de_valores - 1; i != -1; --i) cout << valores[i] << endl; } Constante!

22 2003/2004 Introdução à Programação 22 Generalização (I) E se se pretender generalizar a leitura para qualquer número de inteiros, dado pelo utilizador? Basta usar uma variável, obviamente…

23 2003/2004 Introdução à Programação 23 Ler inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << Introduza o número de valores a ler: ; int número_de_valores; cin >> número_de_valores; cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; … } Erro! Tem de ser constante!

24 2003/2004 Introdução à Programação 24 Ler inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { cout << Introduza o número de valores a ler: ; int n; cin >> n; int const número_de_valores = n; cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; … } Erro! Tem de ser constante conhecida pelo compilador!

25 2003/2004 Introdução à Programação 25 Problemas das matrizes (II) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador

26 2003/2004 Introdução à Programação 26 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; int main() { int const número_de_valores = 1000; cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; for(int i = 0; i != número_de_valores; ++i) cin >> valores[i]; for(int i = número_de_valores - 1; i != -1; --i) cout << valores[i] << endl; }

27 2003/2004 Introdução à Programação 27 Vamos modularizar Leitura dos valores do teclado Escrita invertida dos valores no ecrã

28 2003/2004 Introdução à Programação 28 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; … int main() { int const número_de_valores = 1000; cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; // Leitura… escreveInvertida( … ); }

29 2003/2004 Introdução à Programação 29 escreveInvertida() /** Escreve no ecrã os elementos da matriz passada como argumento começando no último. */ void escreveInvertida( … ) { … }

30 2003/2004 Introdução à Programação 30 E a leitura? Procedimento, que altera a matriz recebida, preenchendo-a… …ou função, que devolve uma matriz preenchida? C++ proíbe devolução de matrizes! Mas era má ideia devolver: Leitura afecta estado do programa ( cin ): procedimento Devolução de valor: função Rotina mista é má ideia!

31 2003/2004 Introdução à Programação 31 Problemas das matrizes (III) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador Não se podem devolver

32 2003/2004 Introdução à Programação 32 lêPara() /** Lê do teclado valores inteiros que coloca por ordem nos elementos da matriz passada como argumento. */ void lêPara( … ) { … }

33 2003/2004 Introdução à Programação 33 Passagem de matriz como argumento lêPara() : passagem por referência escreveInvertida() : passagem por valor

34 2003/2004 Introdução à Programação 34 escreveInvertida() /** Escreve no ecrã os elementos da matriz passada como argumento começando no cout. fail () cout sofreu inserções dos número_de_valores elementos da matriz valores pela sua ordem inversa. */ void escreveInvertida(int valores[número_de_valores]) { … }

35 2003/2004 Introdução à Programação 35 lêPara() /** Lê do teclado valores inteiros que coloca por ordem nos elementos da matriz passada como cin. good () cin permite extracção de número_de_valores inteiros cin. fail () cin já não contém os primeiros número_de_valores inteiros que continha inicialmente a matriz valores contém-nos pela mesma ordem. */ void lêPara(int valores[número_de_valores]) { … } Falta dizer que passagem é por referência!

36 2003/2004 Introdução à Programação 36 Passagem de matriz como argumento Sempre por referência! Necessário precaver alterações do argumento em escreveInvertida() ! Mentira piedosa… Explicação no 2º semestre… (tem a ver com ponteiros)

37 2003/2004 Introdução à Programação 37 Problemas das matrizes (IV) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador Não se podem devolver Passagem sempre por referência (mentirita…)

38 2003/2004 Introdução à Programação 38 escreveInvertida() /** Escreve no ecrã os elementos da matriz passada como argumento começando no cout. fail () cout sofreu inserções dos número_de_valores elementos da matriz valores pela sua ordem inversa. */ void escreveInvertida(int const valores[número_de_valores]) { … } Não é a matriz que é constante! São os seus elementos!

39 2003/2004 Introdução à Programação 39 Ler 1000 inteiros e escrevê-los por ordem inversa … /** … */ void lêPara(int valores[número_de_valores]) { … } /** … */ void escreveInvertida(int const valores[número_de_valores]) { … } int main() { int const número_de_valores = 1000; … } Invisível aqui!

40 2003/2004 Introdução à Programação 40 Ler 1000 inteiros e escrevê-los por ordem inversa … int const número_de_valores = 1000; /** … */ void lêPara(int valores[número_de_valores]) { … } /** … */ void escreveInvertida(int const valores[número_de_valores]) { … } int main() { … } Mas o C++ ignora dimensão de matrizes usadas como parâmetro! (mais uma vez, tem a ver com ponteiros) Mas o C++ ignora dimensão de matrizes usadas como parâmetro! (mais uma vez, tem a ver com ponteiros)

41 2003/2004 Introdução à Programação 41 Problemas das matrizes (V) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador Não se podem devolver Passagem sempre por referência (mentirita…) Dimensão ignorada em parâmetros

42 2003/2004 Introdução à Programação 42 Ler 1000 inteiros e escrevê-los por ordem inversa … int const número_de_valores = 1000; /** … */ void lêPara(int valores[]) { … } /** … */ void escreveInvertida(int const valores[]) { … } int main() { … } Dimensão arbitrária

43 2003/2004 Introdução à Programação 43 Em falta Invocar procedimentos em main() Corpo dos procedimentos

44 2003/2004 Introdução à Programação 44 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; int const número_de_valores = 1000; … int main() { cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; lêPara(valores); escreveInvertida(valores); }

45 2003/2004 Introdução à Programação 45 lêPara() /** Lê do teclado valores inteiros que coloca por ordem nos elementos da matriz passada como cin. good () cin permite extracção de número_de_valores inteiros cin. fail () cin já não contém os primeiros número_de_valores inteiros que continha inicialmente a matriz valores contém-nos pela mesma ordem. */ void lêPara(int valores[]) { assert(cin.good()); for(int i = 0; i != número_de_valores; ++i) cin >> valores[i]; }

46 2003/2004 Introdução à Programação 46 escreveInvertida() /** Escreve no ecrã os elementos da matriz passada como argumento começando no cout. fail () cout sofreu inserções dos número_de_valores elementos da matriz valores pela sua ordem inversa. */ void escreveInvertida(int const valores[]) { for(int i = número_de_valores - 1; i != -1; --i) cout << valores[i] << endl; } Ainda constante global!

47 2003/2004 Introdução à Programação 47 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; … int main() { int const número_de_valores = 1000; cout << "Introduza << número_de_valores << inteiros: "; int valores[número_de_valores]; lêPara(valores, número_de_valores); escreveInvertida(valores, número_de_valores); } Dimensão passada como argumento

48 2003/2004 Introdução à Programação 48 lêPara() /** Lê do teclado valores inteiros que coloca por ordem nos elementos da matriz passada como 0 número_de_valores número_de_valores dim( valores ) cin. good () cin permite extracção de número_de_valores inteiros cin. fail () cin já não contém os primeiros número_de_valores inteiros que continha inicialmente a matriz valores contém-nos pela mesma ordem. */ void lêPara(int valores[], int const número_de_valores) { assert(0 <= número_de_valores); assert(cin.good()); for(int i = 0; i != número_de_valores; ++i) cin >> valores[i]; } Não há forma de saber dimensão de matriz parâmetro!

49 2003/2004 Introdução à Programação 49 Problemas das matrizes (VI) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador Não se podem devolver Passagem sempre por referência (mentirita…) Dimensão ignorada em parâmetros Não há forma de saber dimensão de matriz parâmetro

50 2003/2004 Introdução à Programação 50 escreveInvertida() /** Escreve no ecrã os elementos da matriz passada como argumento começando no 0 número_de_valores número_de_valores dim( valores cout. fail () cout sofreu inserções dos número_de_valores elementos da matriz valores pela sua ordem inversa. */ void escreveInvertida(int const valores[], int const número_de_valores) { assert(0 <= número_de_valores); for(int i = número_de_valores - 1; i != -1; --i) cout << valores[i] << endl; }

51 2003/2004 Introdução à Programação 51 Finalmente uma vantagem! Procedimentos genéricos Funcionam com matrizes de dimensão arbitrária Número de valores passado pode ser diferente da dimensão das matrizes Mas… índices não verificados…

52 2003/2004 Introdução à Programação 52 Indexação fora dos limites (I) int a = 0; int m[3] = {0, 1, 2}; int b = 0; m[-1] = -1; m[3] = 3; cout << a << << b << endl;

53 2003/2004 Introdução à Programação 53 Indexação fora dos limites (II) Que sucede? Programa aborta Escreve 3 -1 Escreve -1 3 Escreve 0 -1 ou -1 0 ou 0 3 ou … Escreve 0 0 Sorte! Pior caso!

54 2003/2004 Introdução à Programação 54 Explicação (escreve 3 -1) m [0]: 0 m : double [3] m [1]: 1 m [2]: 2 b:b: ? a:a: ? … … Memória 3

55 2003/2004 Introdução à Programação 55 Problemas das matrizes (VII) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador Não se podem devolver Passagem sempre por referência (mentirita…) Dimensão ignorada em parâmetros Não há forma de saber dimensão de matriz parâmetro Índices não verificados

56 2003/2004 Introdução à Programação 56 Mais problemas… double valores1[2] = {1.1, 2.2}; double valores2[2] = {3.3, 4.4}; if(valores1 != valores2) valores1 = valores2; Impossível!

57 2003/2004 Introdução à Programação 57 Problemas das matrizes (VIII) Inicializadas implicitamente com lixo Inicialização explícita exaustiva… De dimensão fixa De dimensão conhecida pelo compilador Não se podem devolver Passagem sempre por referência (mentirita…) Dimensão ignorada em parâmetros Não há forma de saber dimensão de matriz parâmetro Índices não verificados Atribuições inválidas Comparações inválidas

58 2003/2004 Introdução à Programação 58 Matrizes n-dimensionais (I) double m[2][3] = { {1, 2, 3}, {4, 5, 6} }; Duas linhas e três colunas Matriz de matrizes Indexável: m[1][2] = 12.0;

59 2003/2004 Introdução à Programação 59 Matrizes n-dimensionais (II) double (m[2])[3] = { … }; m[0][0]: 1 m[0]: double[3] m[0][1]: 2 m[0][2]: 3 m [1][0]: 4 m[1]: double[3] m [1][1]: 5 m [1][2]: 6 m: double[2][3]

60 2003/2004 Introdução à Programação 60 Vectores: A solução #include std::vector v(10); std::vector v(10, 13.0); std::vector v; Tipo dos itens Nome do vector Número de itens Inicializado com 10 itens de valor zero Inicializado com 10 itens de valor 13 Inicializado com 0 itens! Classe genérica

61 2003/2004 Introdução à Programação 61 Acedendo à dimensão de vectores vector v(10, 13.0); cout << v.size() << endl; instância.operação(argumento, … ); Invocação da operação size (). Instância para a qual a operação é invocada Nome da operação a invocar Argumentos a passar à operação

62 2003/2004 Introdução à Programação 62 vector ::size() Devolve inteiro sem sinal Tipo não-especificado: unsigned short int ? unsigned int ? unsigned long int ? Tipo exacto é sinónimo de vector ::size_type

63 2003/2004 Introdução à Programação 63 Ler 1000 inteiros e escrevê-los por ordem inversa #include using namespace std; … int main() { int const número_de_valores = 1000; cout << "Introduza " << número_de_valores << " inteiros: "; vector valores(número_de_valores); lêPara(valores); escreveInvertido(valores); }

64 2003/2004 Introdução à Programação 64 lêPara() /** Lê do teclado valores inteiros que coloca por ordem nos itens do vector passado como cin. good () cin permite extracção de valores. size () inteiros cin. fail () cin já não contém os primeiros valores. size () inteiros que continha inicialmente o vector valores contém-nos pela mesma ordem. */ void lêPara(vector & valores) { assert(cin.good()); for(vector ::size_type i = 0; i != valores.size(); ++i) cin >> valores[i]; }

65 2003/2004 Introdução à Programação 65 escreveInvertida() /** Escreve no ecrã os elementos do vector passado como argumento começando no cout. fail () cout sofreu inserções dos valores. size () itens do vector valores pela sua ordem inversa. */ void escreveInvertido(vector const valores) { for(vector ::size_type i = valores.size() - 1; i != -1; --i) cout << valores[i] << endl; } i é de um tipo sem sinal. Nunca poderá chegar a -1. Guarda sempre verdadeira!

66 2003/2004 Introdução à Programação 66 escreveInvertida() /** Escreve no ecrã os elementos do vector passado como argumento começando no cout. fail () cout sofreu inserções dos valores. size () itens do vector valores pela sua ordem inversa. */ void escreveInvertido(vector valores) { for(vector ::size_type i = valores.size(); i != 0; --i) cout << valores[i - 1] << endl; }

67 2003/2004 Introdução à Programação 67 Leitura com devolução (I) vector vectorLido(int número_de_valores) { assert(cin.good()); vector valores(número_de_valores); for(vector ::size_type i = 0; i != valores.size(); ++i) cin >> valores[i]; return valores; } … int main() { … vector valores = vectorLido(número_de_valores); escreveInvertido(valores); } Não é função nem procedimento! Má ideia!

68 2003/2004 Introdução à Programação 68 Leitura com devolução (II) vector vectorLido(int número_de_valores) { assert(cin.good()); vector valores; for(int i = 0; i != número_de_valores; ++i) { int valor; cin >> valor; valores.push_back(valor); } return valores; } Não é função nem procedimento! Má ideia!

69 2003/2004 Introdução à Programação 69 Vectores por valor? Vectores podem-se passar por valor Implica cópia do vector Vectores podem ser grandes Passagem por referência não faz cópia Mas permite alterações no parâmetro… Ideal: vantagens de ambos

70 2003/2004 Introdução à Programação 70 Passagem por referência constante /** Escreve no ecrã os elementos do vector passado como argumento começando no cout. fail () cout sofreu inserções dos valores. size () itens do vector valores pela sua ordem inversa. */ void escreveInvertido(vector const& valores) { for(vector ::size_type i = valores.size(); i != 0; --i) cout << valores[i - 1] << endl; } Sinónimo que proíbe alterações Inútil para tipos básicos!

71 2003/2004 Introdução à Programação 71 Generalização … int main() { cout << "Quantos valores quer que sejam lidos? "; int número_de_valores; cin >> número_de_valores; cout << "Introduza " << número_de_valores << " inteiros: "; vector valores(número_de_valores); lêPara(valores); escreveInvertido(valores); }

72 2003/2004 Introdução à Programação 72 Redimensionando vector v(5, 1); v.resize(8); // Novos itens com zero. v.resize(9, 2); // Novos itens com 2. v.resize(2);

73 2003/2004 Introdução à Programação 73 Vantagens dos vectores Inicializados implicitamente com zero Inicialização explícita abreviada… Dimensão variável Podem-se devolver Podem-se passar por valor ou por referência Dimensão não é nunca ignorada Pode-se saber dimensão Atribuições válidas Comparações válidas

74 2003/2004 Introdução à Programação 74 Problemas dos vectores Índices não verificados Inicialização exaustiva impossível

75 2003/2004 Introdução à Programação 75 Solução recursiva /** Lê o número de inteiros passado como argumento e escreve-os pela ordem 0 numero_de_valores cin. good () cin permite extracção de numero_de_valores inteiros cout. fail () cout sofreu inserções dos numero_de_valores inteiros lidos pela sua ordem inversa. */ void leEInverteInteiros(int const numero_de_valores) { assert(0 <= numero_de_valores); if(numero_de_inteiros_a_ler != 0) { int valor; cin >> valor; leEInverteInteiros(numero_de_valores - 1); cout << valor << endl; } Onde ficam guardados os valores?

76 2003/2004 Introdução à Programação 76 Aula 9: Sumário Matrizes clássicas do C++: Agregado indexável de instâncias do mesmo tipo Sintaxe: definição e inicialização Particularidades: dimensão constante proibidas atribuições, comparações e devoluções passagens sempre por referência indexações fora dos limites não verificadas Indexação fora dos limites: sintomatologia Vectores: Vantagens face a matrizes Operações da classe genérica vector


Carregar ppt "Aula 9 Matrizes clássicas e vectores em C++ Melhor alternativa!"

Apresentações semelhantes


Anúncios Google