6.Vectores

6.1 Introdução

Supor, que se pretendia um programa para ler a média das notas de cada um dos alunos de uma escola, calcular a média das médias, e depois para cada aluno determinar o desvio da sua média relativamente à média das médias. Uma solução para guardar cada uma das médias, seria definir por exemplo 3000 variáveis (número hipotético de alunos), por exemplo :

float med_1,med_2,med_3,med_4,med_5,med_6,med_7,med_8, ... ;

até med_3000, mais as instruções para a leitura das médias:

printf (\n Introduza a média do aluno n.º1:);
scanf (%f,med_1);

3000 vezes, o que se revela completamente impraticável. Seria preferível a possibilidade de definir as 3000 variáveis de uma só vez, por exemplo da seguinte forma:

float media[3000];

em que media[0] guardaria a média do aluno 1, media [1] a do aluno 2, e assim sucessivamente fazendo variar o valor do indice até 2999. Para melhorar o processo seria conveniente definir uma variável para indice, por exemplo:

int num;

Deste modo, para a leitura das 3000 variáveis, poder-se-ia utilizar um ciclo, como a seguir se ilustra:

  for (num=0;num<3000;num++)
  {
    printf (\n Introduza a média do aluno n.º %d,num);
    scanf (%f,media[num]);
  }

o que representaria uma melhoria extraordinária relativamente à primeira solução. Felizmente a generalidade das linguagens de programação fornecem este tipo de dados, chamados vectores (neste texto é usado também o termo array para significar vector), os quais se explicam nas próximas secções.

6.2 Vectores na Linguagem C

A linguagem C permite definir novos tipos de dados a partir dos existentes. Os arrays, ou vectores, são um conjunto de elementos do mesmo tipo, agrupados com o mesmo nome, e diferenciados através de um índice entre parêntises rectos. Antes de mais, convém salientar que os arrays estão fortemente ligados aos apontadores, os quais não serão aqui abordados.

Em C existem apenas arrays unidimensionais e o tamanho de um array deve ser fixo e definido por uma constante na altura da compilação. No entanto, um elemento de um array pode ser um objecto de qualquer tipo, inclusivé outro array. Isto faz com que seja possível simular array multidimensionais.

A melhor forma de entender o modo de funcionamento dos arrays, é perceber a sua declaração. Por exemplo,

int a[4];

diz que a é uma variável do tipo array de 4 elementos do tipo int. A sua representação será:

___ | ___ | ___ | ___

a[0] | a[1] | a[2] | a[3]

em que cada posição quarda um inteiro.

Como se pode ver, os elementos do array ocupam posições de memória contíguas e o seu índice varia obrigatoriamente de 0 a 3. Ou seja, tem-se, para essas 4 posições os elementos

a[0], a[1], a[2], a[3]

que são tratados como se fossem quatro variáveis distintas.
Atribuindo os valores 1,2 e 3 repectivamente, aos três primeiros elementos,

a[0]=1;
a[1]=2;
a[2]=3;

virá:

_1_ | _2_ | _3_ | ___

a[0] | a[1] | a[2] | a[3]

Convém ainda saber que o nome array é uma constante e representa o endereço da 1.ª posição do array. Isto é:

a==&a[0] /* O operador & dá o endereço da variável. Neste caso dá o endereço de a[0]*/

Supondo que o vector se iniciava na posição de memória com o endereço 100, e que cada inteiro gasta 2 bytes, ter-se-ia:

a==100
&a[0]==100
&a[1]==102
&a[2]==104
&a[3]==106

Em virtude de ser uma constante, não é possível atribuir valores ao nome de array, como se ilustra no seguinte caso:

int a[4];
a=2

a[0]=2;
a[0]++;
a[1]=2*a[0];

A atribuição na segunda instrução é inválida. Também quando se passa um array como argumento de uma função, na realidade o que é passado para a função é o seu endereço, como se viu com a função scanf.

A dimensão de um vector é determinado pelo produto das suas linhas pelas suas colunas. A seguinte declaração:

int ecra[25][80];

diz que ecra é um array de 25 arrays de 80 elementos inteiros cada. Assim, sizeof(ecra) será 2000 (25*80).
A inicialização de um array pode ser feita no momento da sua definição:

int a[4]={1,2,3};

irá definir (criar) um vector de quatro inteiros e inicializar a[0] a 1, a[1] a 2, e a[2] a 3. No entanto a definição:

int a[]={1,2,3};

irá definir um vector de apenas três elementos e inicializa-los de forma idêntica ao anterior. O vector é criado com apenas 3 posições em virtude de não ser explicitado entre parêntises o número de elementos, e portanto este número será determinado pela lista de inicialização.
No caso de um array ser multidimensional a inicialização obedece às mesmas regras.
Por exemplo :

int m[][3]={1,2,3,11,22,33};

ou

int m[][3]={{1,2,3},{11,22,33}};

em que se obtém os seguintes valores para cada elemento:

m[0][0] é igual a 1
m[0][1] é igual a 2
m[0][2] é igual a 3
m[1][0] é igual a 11
m[1][1] é igual a 22
m[1][2] é igual a 33

1 | 2 | 3
11 | 22 | 33

Exemplo 1: O programa media.c lê 100 notas para um array, e calcula a média das notas.

/* Programa media.c*/

#include <stdio.h>

> main()
> {

> > int i;
> > float notas[100],soma;

> > /* Ciclo que lê 100 notas e armazena-as no vector notas.*/
> > for (i=0;i<100;i++)
> > {

> > > printf (Nota %d=?,i+1);
> > > scanf(%f,&notas[i]);

> > }

> > /* A variável acumuladora soma inicializada a zero.*/
> > soma=0;
> > /* Ciclo que soma as 100 notas. */
> > for (i=0;i<100;i++)

> > > soma=soma+notas[i];

> > printf (A média é = %f,soma/100);

> }

Como cada elemento do vector notas é um inteiro, há necessidade na função scanf de lhe aplicar o operador & como acontece com qualquer outro inteiro.

6.3 Vectores como Argumentos de Funções

Para melhor se compreender este assunto observe o seguinte exemplo:

O seguinte programa testa uma função que troca os dois primeiros elementos de um vector dado como argumento.

#include <stdio.h>
void troca(); /*Declara a função como não retornando qualquer valor*/
main()
{

> int v[2];
> v[0]=2;
> v[1]=3;
> troca (v);
> printf (v[0]=%d,v[1]=%d,v[0],v[1]);

}

void troca(int x[2])
{

> int t;
> t=x[0];
> x[0]=x[1];
> x[1]=t;

}

O resultado será v[0]=3 e v[1]=2. Neste exemplo é passado como argumento da função o nome do vector, que é o endereço da 1.ª posição do array. Assim x vai representar também um endereço, o de v[0] que é o mesmo de x[0], e portanto as alterações feitas na função terão repercussões nas variáveis da função chamadora.

Na definição da função também seria possível e com os mesmos resultados, ter int x[] em lugar de int x[2], sendo nesse caso x dimensionado automaticamente a 2.

Supôr que o endereço de v[0] é 200, então é porque v=200 como mostra a figura:

(Supondo uma máquina de inteiros com 2 bytes, v[1] virá 2 bytes à frente (202)).

v=200

Designação: | v[0] | v[1]
Conteúdo: | 2 | 3
Endereço: | 200 | 202

então a chamada da função

troca(v); <=> troca(200);

em que ao nome do array x corresponderá o valor de 200, ou seja, x será igual a 200

x=200

Designação: | x[0] | x[1]
Conteúdo : | 2 | 3
Endereço : | 200 | 202

o que implica que após as trocas ficará:

Conteúdo : | 3 | 2
Endereço : | 200 | 204

Estas posições de memória(endereços) correspondem também a v[0] e a v[1], respectivamente.

6.4 Strings

Em C, não existe o tipo de dado string. Pode no entanto ser simulado através de um array de caracteres. Por convenção, delimita-se a string com o caracter nulo (\0). Isto é, coloca-se o caracter nulo na primeira posição não preenchida do array. Assim quando se define o tamnho do array de caracteres para ser usado como string é necessário contar com mais uma posição.

A standard library fornace um conjunto de funções para a manipulação de strings. Estas funções pressupõem que as strings que lhes são passadas são terminadas com o caracter nulo.

> int strlen(char s[]);

devolve o comprimento da string s. Exemplo:

> char s[]=OLA;
> printf (Comprimento da String==%d,strlen(s));

A definição anterior além de inicializar o array com a string, também o dimensiona como um vector de quatro caracteres, como mostra a figura seguinte:

'O' | 'L' | 'Á' | '\0'

Quanto à saída de printf, ela seria: Comprimento da String == 3.

strcpy (char destino[], char origem[]);

Copia origem para destino. Exemplo:

> char destino[]=ADEUS,origem[]=OLA;
> strcpy(destino,origem);
> printf (%s,destino);

a saida é OLA.

strcat (char primeira[], char segunda[]);

concatena (acrescenta) a string segunda à string primeira.

int strcmp(char s1[],char s2[]);

Compara s1 com s2,e devolve 0 se s1 igual a s2, >0 se s1>s2 e <0 se s1<s2.

Uma lista completa destas funções pode ser encontrada nos manuais de qualquer compilador de C. Para a utilização destas funções, é requerida a linha

#include <string.h>

Estas funções podem ser facilmente construídas pelo programador.

Back | Up | Forward

To front page | Pages by Nuno Nunes. |