Baixe o app para aproveitar ainda mais
Prévia do material em texto
APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.1 Segunda revisão / 2002 VV.. TTIIPPOOSS DDEERRIIVVAADDOOSS As linguagens C e C++ permitem que tipos intrínsecos sejam agrupados para formar tipos de dados derivados. As formas básicas de tipos de dados agrupados são ARRAYS e STRUCTURES. Estes tipos de dados podem ser formados por outros dados derivados. Ponteiros e Classes também são tipos derivados, mas devido a importância que os ponteiros assumem para o C e o C++ e a de classes para o C++, estes serão tratados em capítulos separados. V.A. Arrays (Vetores e matrizes) Um array é uma agrupamento contínuo de um ou mais elementos de um mesmo tipo (o que inclui tipos intrínsecos, structures (ou classes) ou ponteiros). Arrays (ou seja vetores e matrizes) podem ser estáticos (número de elementos determinado em tempo de compilação) ou dinâmicos (número de elementos determinado em tempo de execução). A forma de declaração e dimensionamento de vetores e matrizes dinâmicos será apresentada somente após a apresentação de ponteiros (no capítulo VI). V.A.1. Declaração de Arrays V.A.1 Sintaxe de declaração de arrays estáticos: tipo identificador_array [ n ] ; tipo identificador_ array [ n ] [ m ] ...[ k ]; onde tipo é qualquer tipo válido da linguagem (intrínseco ou derivado), n, m ..., k são expressões constantes que representam o número de elementos em cada dimensão (vetor é um array de uma dimensão e matriz é um array de duas dimensões). O primeiro índice indicado (o mais próximo ao identificador) especifica a maior dimensão do array. Isto não significa que o primeiro índice deve ser maior que os demais, mas sim que o armazenamento do array na memória é feito variando mais rapidamente o índice da direita e mais lentamente o da esquerda. Exemplos: short int a [ 5 ]; // declaração de um array de inteiros de dimensão 1 (vetor) com 5 componentes. float d [ 3 ] [ 2 ]; // declaração de um array de floats de dimensão 2 com 3x2 (6) componentes. char c [ 5 ] [ 3 ] [ 5 ]; // declaração de um array de chars de dimensão 3 com 5x3x5 componentes. V.A.2. Inicialização de Arrays V.A.2 Da mesma forma que identificadores de tipos intrínsecos podem ser declarados e definidos (inicializado com um valor), os arrays também podem ser inicializados na declaração (ou seja, o array é definido na declaração). Os valores de inicialização para cada dimensão podem ser especificados de duas maneiras : • dimensão a dimensão, com os valores dos elementos colocados entre chaves ( { } ), partindo da “maior dimensão”, ou seja a primeira dimensão especificada; dentro do par de chaves, cada valor é separado por uma vírgula; • considerando o array como sendo de uma única dimensão, com os valores dos elementos especificados em seqüência, variando mais rapidamente a dimensão menor e menos rapidamente a dimensão maior. Para exemplificar estas duas formas de inicializar um array, vamos utilizar as declarações da seção V.A.1. Exemplos: // o array a com cinco componentes do tipo short int são inicializados com os valores APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.2 Segunda revisão / 2002 // a[0] = 1000, a[1] = 1001, a[2] = 10002, a[3] = 1003 e a[4] = 10004 short int a [ 5 ] = { 1000, 1001, 1002, 10003, 10004 }; ou short int a [ ] = { 1000, 1001, 1002, 10003, 10004 }; // ou seja, neste caso não é necessário // especificar a maior dimensão do array. float d [ 3 ] [ 2 ] = { { 30, 31 }, { 20, 21 }, { 10, 11 } }; ou float d [ ] [ 2 ] = { { 30, 31 }, { 20, 21 }, { 10, 11 } }; // novamente, não é necessário especificar a // maior dimensão do array ou float d [ ] [ 2 ] = { 30, 31, 20, 21, 10, 11 }; // novamente, não é necessário especificar a // maior dimensão do array ou float d [ ] [ 2 ] = { 30, 31, // neste caso, a visualização da matriz de 20, 21, // 3 linhas x 2 colunas se torna mais clara. 10, 11 }; // fim da definição da matriz d ou, ainda, float d [ ] [ 2 ] = { {30, 31}, // neste caso, a visualização da matriz de {20, 21}, // 3 linhas x 2 colunas se torna mais clara. {10, 11} }; // fim da definição da matriz d char c [ 5 ] [ 3 ] [ 5 ] = { {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, } ; // fim da definição de c ou char c [ ] [ 3 ] [ 5 ] = { {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, {{0,1,2,3,4}, {5, 6,7,8,9}, {10,11,12,13,14}}, } ; // fim da definição de c ou char c [ 5 ] [ 3 ] [ 5 ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.3 Segunda revisão / 2002 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; // fim da definição de c ou char c [ ] [ 3 ] [ 5 ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; // fim da definição de c V.A.3. Acesso aos componentes de um array utilizando índices Os elementos individuais de um array podem ser endereçados por índices, os quais correspondem a posição do elemento desejado no array. O operador de subscrito ( [ ] ) é utilizado para o acesso a um determinado elemento do array. A posição de memória em que o elemento está armazenado é determinada automaticamente em função do índice do elemento e do número de bytes utilizados para o armazenamento do tipo dos elementos. Observação: Todos os índices de arrays em C e C++ começam a ser contados a partir (e inclusive) do zero. Assim, o primeiro componente de um array unidimensional cujo identificador é vet será vet [0]. Como exemplo, vamos inicializar (não na declaração, como feito na seção V.A.2) um vetor de inteiros com os 100 primeiros números naturais. Exemplo: int n_naturais [100]; // somente declaração for (int i = 0; i < 100; n_naturais[i] = i + 1, i++); Exercícios: 1. Faça a inicialização utilizando um laço while. 2. Faça a inicialização na própria declaração. 3. Implemente, com todos os detalhes, um programa que armazene os primeiros 1000 números naturais num vetor e faça a soma desses números. Implemente umasaída para apresentar a soma. 4. Implemente, com todos os detalhes, um programa que armazene os primeiros 50 números naturais num vetor e faça o produto desses números. (Atenção à declaração do tipo de variável que irá armazenar a produtória. Aproveite para verificar a necessidade de uso do operador cast). 5. Faça um programa que some duas matrizes (arrays bidimensionais) de dimensões 6x4. Fixe o valor dos elementos das duas matrizes na inicialização e faça a soma num laço for. ATENÇÃO à soma de matrizes : Os elementos da matriz soma são obtidos fazendo soma ij = aij + bij APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.4 Segunda revisão / 2002 V.A.4. O armazenamento de arrays na memória As linguagens C e C++ suportam, diretamente, somente arrays de dimensão 1. Para formar arrays de dimensão mais elevada (arrays multidimensionais) utilizam-se vetores de vetores (lembrem-se da definição de array no início da seção). Por outro lado, em C e C++, ao contrário do que ocorre com muitas outras linguagens, não existe um limite teórico para o número de dimensões de um array. Os arrays componentes em um array de arrays é denominado subarray. Arrays são armazenados por linha em C e C++. A figura V.1 representa a forma de armazenamento dos arrays declarados na seção V.A.1. Estude a figura com atenção. short int a [ 5 ] ; float d [ 3 ] [ 2 ] ; elemento 1 elemento 5elemento 4elemento 3elemento 2 a [ 0 ] a [ 1 ] a [ 2 ] a [ 3 ] a [ 4 ] 2 bytes 2 bytes 2 bytes 2 bytes 2 bytes elemento 1,1 elemento 3,1elemento 2,2elemento 2,1elemento 1,2 d [ 0 ] [ 0 ] 4 bytes elemento 3,2 d [ 2 ] [ 1 ]d [ 2 ] [ 0 ]d [ 1 ] [ 1 ]d [ 1 ] [ 0 ]d [ 0 ] [ 1 ] 4 bytes 4 bytes 4 bytes 4 bytes4 bytes subarray char c [ 5 ] [ 3 ] [ 5 ] ; elemento 1,1,1 elemento 1,1,2 c [ 0 ][ 0 ][ 0 ] 1 byte c [ 0 ][ 0 ][ 1 ] elemento 1,1,5 c [ 0 ][ 0 ][ 4 ] 1 byte elemento 1,2,1 c [ 0 ][ 1 ][ 0 ] 1 byte elemento 1,2,5 elemento 1,3,1 c [ 0 ][ 2 ][ 0 ]c [ 0 ][ 1 ][ 4 ] 1 byte 1 byte1 byte subarray ... ...... ... elemento 1,3,5 elemento 2,1,1 c [ 1 ][ 0 ][ 0 ]c [ 0 ][ 2 ][ 4 ] 1 byte 1 byte elemento 5,3,5 c [ 4 ][ 2 ][ 5 ] 1 byte Figura V.1 : Esquema do armazenamento de arrays na memória Os endereços de memória crescem do primeiro elemento para o último. Assim o endereço de memória em que está armazenado o primeiro elemento é menor que o do segundo, que por sua vez é menor que o do terceiro, e assim por diante. Para efeito de comparação, vamos imaginar que a posição de memória em que o primeiro elemento do vetor de inteiros a é armazenado seja representada pelo valor 100 (este é o endereço). O segundo elemento vai estar armazenado na posição 102 (lembrem-se que um short int ocupa dois bytes de memória (ou duas posições de memória). O terceiro elemento estará armazenado na posição 104 e assim por diante. Por outro lado, se declaramos um vetor de 5 posições de doubles (cada double ocupa 8 bytes de memória ou 8 posições de memória): double a[5]; e o primeiro elemento encontra-se na posição 100, então, o segundo elemento vai ser localizado na posição 108 e o terceiro na posição 116. Isto ocorre devido à diferença do número de bytes necessário para representar um número short int de um número double. O compilador se encarrega de alocar a memória corretamente no caso de arrays estáticos e o programa automaticamente identifica a posição de memória em que cada elemento pode ser encontrado pelo tipo de dados armazenados no vetor (o que é definido pela declaração, seção V.A.1). V.A.5. Strings como vetores de caracteres Um dos usos mais freqüentes de arrays é o armazenamento de seqüência de caracteres (ou “strings”). A linguagem C++ inclui, na biblioteca padrão, uma classe para strings. Uma seqüência de caracteres é formada por um array unidimensional de caracteres (char), terminadas por um caracter de seqüência de escape, \0. Como conseqüência, uma seqüência de caracteres deve sempre ser definida com um elemento a mais que o conjunto de caracteres da seqüência. APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.5 Segunda revisão / 2002 Uma seqüência de caracteres pode ser inicializada caracter a caracter, de forma análoga ao que foi apresentado na seção V.A.2. Neste caso, não se pode esquecer de incluir o caracter ‘\0’ no final da seqüência. Outra forma de inicializar uma seqüência de caracteres é utilizando uma constante literal (“string literal”). Neste caso, o caracter ‘\0’ é incluído automaticamente no final da seqüência. A biblioteca padrão da linguagem C incorpora um conjunto de funções que permitem manipular strings (strcpy(), strcmp(), strcat(), strchr(), dentre outras). Tais funções podem também ser utilizadas em C++. Exemplos: char mensagem[9] = { ‘m’, ‘e’, ‘n’, ‘s’, ‘a’, ‘g’, ‘e’, ‘m’, ‘\0’}; ou char mensagem[ ] = { ‘m’, ‘e’, ‘n’, ‘s’, ‘a’, ‘g’, ‘e’, ‘m’, ‘\0’}; ou char mensagem[9] = “mensagem”; ou char mensagem[ ] = “mensagem”; char mensagem[8] = “mensagem”; // ERRO! a string não é suficiente para armazenar o // caracter ‘\0’ V.B. Structures Uma structure é um agrupamento de um ou mais objetos (de tipos intrínsecos ou derivados). Ao contrário do que ocorre com arrays, que só permitem agrupar objetos do mesmo tipo, uma structure permite agrupar objetos de tipos diferentes. Os objetos individuais que compõem a structure recebem a denominação de membros. Structures são utilizadas para agrupar um conjunto de dados que, juntos, apresentam um significado (uma unidade) na aplicação (software). V.B.1. Declaração de structures V.B.1 Sintaxe: struct denominacao_estrutura {tipo_e_identificador_dos_membros} identificador; onde denominação_estrutura é uma espécie de rótulo pelo qual a structure pode ser identificada, tipo_e_idenficador_dos_membros é uma lista contendo o tipo e o identificador dos dados membros da structure. O identificador é opcional (neste caso, fica declarada a estrutura da struct, mas nenhuma variável desse tipo é declarada. Nos exemplos a seguir são declaradas as estruturas de 3 diferentes structures. Declarações de objetos do tipo structure são apresentadas nos exemplos da seção V.B.2. Exemplos: struct endereco { char rua [256]; // armazena o nome da rua unsigned int numero; char cidade [30]; unsigned long int cep; } ; // fim da declaração da struct endereco struct data { unsigned char dia, mes; APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.6 Segunda revisão / 2002 unsigned short int ano; }; // fim da declaração da struct data struct pessoa { char nome [128]; endereco residencia; // a struct endereço, cujo identificador é residência, armazena // o endereço residencial da pessoa endereco comercial; // a struct endereço, cujo identificador é comercial, armazena // o endereço comercial da pessoa data nascimento; // armazena a data de nascimento }; // fim da declaração da struct pessoa V.B.2. Inicialização de Structures V.B.2 Da mesma forma que identificadores de tipos intrínsecos e arrays podem ser declarados e definidos (inicializado com um valor), as structures também podem ser inicializadas na declaração (ou seja, a structureé definida na declaração). A inicialização ocorre na ordem de declaração dos membros. A seguir seguem alguns exemplos de inicialização de structures dos tipos declarados na seção V.B.1. Exemplos: // declarando e definindo struct endereco { char rua [256]; // armazena o nome da rua unsigned int numero; char cidade [30]; unsigned long int cep; } end = { “Rua Balalaica”, 12222, “São Paulo”, 12222000}; // definindo (supõe-se declarada a struct endereco) endereco novo_end = { “Av. BlaBla da Silva”, 000, “Seilá”, 00000000}; // definicao da data com identificador dia_formatura data dia_formatura = {30,2,2000}; // definição de uma pessoa com identificador Joao_da_Silva // note-se que o conteúdo das structs residencial e nascimento foram inicializados colocando // os dados membros das structs entre chaves (bloco). // Contudo, essas chaves não são necessárias, como mostrado na inicialização da struct comercial. pessoa Joao_da_Silva = { “João José da Silva”, { “Av. BlaBla da Silva”, 000, “Seilá”, 00000000}, “Rua 1”, 333, “Seilá”, 01000000, {28,02,1900}}; ou, pessoa Joao_da_Silva = { “João José da Silva”, “Av. BlaBla da Silva”, 000, “Seilá”, 00000000, “Rua 1”, 333, “Seilá”, 01000000, 28,02,1900}; APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.7 Segunda revisão / 2002 V.B.3. Acesso aos membros de uma structure O acesso aos dados membros de uma structure é feito utilizando o operador de membro de structure (., seção III.D.2). O operador é posicionado entre o identificador da structure e o identificador do membro, como apresentado a seguir. Sintaxe: identificador_struct . identificador_membro Para exemplificar o acesso a dados membros de structures, são utilizadas as declaração e inicializações apresentadas nas seções V.B.1 e V.B.2. Exemplos: // acessando os dados membros da struct data unsigned short int a; unsigned char d, m; d = dia_formatura . dia; m = dia_formatura . mes; a = dia_formatura . ano; // acessando os dados membros da struct endereço char r [500], cid [500]; unsigned int n; unsigned long int cep; n = novo_end . numero; cep = novo_end . cep; strcpy ( r, novo_end . rua); // note o uso da função strcpy para copiar o conteúdo da string // (ou melhor, array unidimensional de caracteres) rua, para // o array r strcpy ( cid, novo_end . cidade); // note, novamente, o uso da função strcpy para copiar o // conteúdo da string cidade para o array cid. // acessando os dados membros da struct pessoa char nom [500], rres [500], cidres [500], rcom[500], cidcom[500]; unsigned int nres, ncom; unsigned long int cep; unsigned short int a; // ATENÇÃO : nestes exemplos utilizamos identificadores curtos. unsigned char d, m; // Contudo, acostumem-se a usar identificadores que tenham algum // significado, como ocorreu na declaração das structs. strcpy ( nom, Joao_da_Silva.nome); // atribui o conteúdo do dado membro nome da struct // Joao_da_Silva ao array nom. nres = Joao_da_Silva.residencia.numero; // atribui a nres o valor armazenado em numero, que é // um dado membro da struct residencia, que por sua APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.8 Segunda revisão / 2002 // vez, é um dado membro de Joao_da_Silva. // Note o uso em cascata do operador de acesso. ncom = Joao_da_Silva.comercial.numero; // atribui a ncom o valor armazenado em numero, que // é um dado membro da struct comercial, que por sua // vez, é um dado membro de Joao_da_Silva. cep = Joao_da_Silva.comercial.cep; strcpy ( rcom, Joao_da_Silva.comercial.rua); strcpy ( rres, Joao_da_Silva.residencia.rua); strcpy ( cidres, Joao_da_Silva.residencia.cidade); // alteração dos dados membros da struct data unsigned short int a = 1998; unsigned char d = 13, m = 4; dia_formatura . dia = d; dia_formatura . mes = m; dia_formatura . ano = a; // alteração dos dados membros da struct endereço char r [500] = “Rua X”, cid [500] = “Mogi”; unsigned int n = 123; unsigned long int cep = 01000100; novo_end . numero = n; novo_end . cep = cep; strcpy ( novo_end . rua, r); // a função strcpy copia o conteúdo do array unidimensional //de caracteres r para o membro rua O acesso a dados membros do tipo ponteiro é feito utilizando o operador −>. Sintaxe: identificador_struct −>−>−>−> identificador_ponteiro_membro Exemplos de acesso a ponteiros membro serão apresentados no capítulo que trata de ponteiros. Exercícios 1. Considere as structures declaradas na seção V.B.1 (data, endereco e pessoa). Escreva um programa que permita criar um array unidimensional de structures pessoa, armazenando os dados fornecidos pelo usuário pelo teclado: a. declare um array unidimensional estático de 100 posições; APOSTILA: LINGUAGENS DE PROGRAMAÇÃO C E C++ Angelo Passaro Página V.9 Segunda revisão / 2002 b. faça um laço para a entrada de dados via teclado (utilize cin) instruindo o usuário sobre os dados a serem preenchidos; c. terminada a entrada de dados, faça um laço sem fim no qual é pedido um índice ao usuário e, em seguida apresentadas as informações armazenadas na structure correspondente (use cout); d. implemente um teste para verificar se existem dados armazenados na structure com o índice indicado.
Compartilhar