Introdução aos vetores

Nesta seção examinaremos resumidamente como utilizar vetores tanto em C quanto em Python.

Vetores: sequência contígua de variáveis

Usualmente um vetor é um agregado de dados de um mesmo tipo básico ocupando posições consecutivas de memória. Isso significa que é possível pegar alternadamente o valor armazenado em qualquer das posições do vetor, Usualmente isso é implementado nas linguagens por uma indexamentos, ou seja, sendo vet o nome da variável agregada, pode-se pegar o primeiro elemento fazendo vet[0], o segundo com vet[1] e assim por diante.

Na figura acima representamos a memória do computador com um vetor (agregado) de variáveis (usando 8 bits apenas) e de tamanho 4, ou seja, um vetor para armazenar 4 valores do tipo dado.

Vetores em C

Como em C deve-se sempre declarar o tipo da variável, no caso de vetor deve-se declarar seu tipo e seu tamanho. No exemplo abaixo ilustramos declaração e uso de vetores dos tipos básicos int, char e float.

Vetores em C
Vetor de inteiros Vetor de caracteres Vetor de flutuantes
#include <stdio.h>
#define M 20 // usado para constante
int main (void) {
  int i; // auxiliar, para indexar os vetores
  int nI; // tamanho util dos vetores
  int  vetI[M]; // Vetor para inteiros (ate' M elementos)
  scanf("%d", &nI);
  for (i=0; i< nI; i++) // "Ler" nI inteiros
    scanf("%d", &vetI[i]);
  for (i=0; i< nI; i++) // "Imprimir" os elementos
    printf("%d\n", vetI[i]);
  return 0;
  }
#include <stdio.h>
#define M 20 // usado para constante
int main (void) {
  int i; // auxiliar, para indexar os vetores
  int nC; // tamanho util dos vetores
  char vetC[M]; // Vetor para caracteres
  scanf("%d", &nC);
  for (i=0; i< nC; i++) // ler nC caracteres
    scanf(" %c ", &vetC[i]); // USAR branco antes de %c
  for (i=0; i< nC; i++)
    printf("%c\n", vetC[i]);
  return 0;
  }
#include <stdio.h>
#define M 20 // usado para constante
int main (void) {
  int i; // Auxiliar, para indexar os vetores
  int iF; // Tamanho util dos vetores
  float vetF[M]; // Vetor para flutuantes
  scanf("%d", &nF);
  for (i=0; i< nF; i++) // "Ler" nF "floats"
    scanf("%f", &vetF[i]);
  for (i=0; i< nF; i++)
    printf("%f4.1\n", vetF[i]); // Usar 4 posicoes
  return 0;                     // e 1 para pto dec.
  }

Como citado na explicação sobre funções, uma grande vantagem de ter um algoritmo genericamente implementado como uma função separada é que o código do programa fica mais organizado e pode-se invocar a função em qualquer outro trecho do programa. Por isso, alguns funções muito úteis acabam sendo implementadas pelos desenvolvedores nos ambientes de programação. Por exemplo, em C existe a biblioteca stdio.h que tem as funções onipresente para entrada (scanf) e para saída (printf) de dados, mas existem outras bibliotecas, como a stdlib.h que dispõe, entre outras, da função qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) que implementa o método ordenador eficiente denominado Quick Sort (ou Ordenador Rápido). Veja um exemplo de código usando o qsort:

#include <stdio.h> // para funcao 'printf'
#include <stdlib.h> // para a funcao 'qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))'
int vetor[] = { 3, 9, 1, 7, 0, 4, 6, 5, 2, 8 }; // por simplicidade usar globais e manter fixo
int N = 10;

void imprime (int vet[], int n) { // funcao para imprimir em mesma linha
  int i;
  for (i=0; i<n; i++)
     printf(" %d", vet[i]);
  printf("\n");
  }

// Esta e' a funcao comparadora: pode-se comparar qualquer coisa, basta codificar seu comparador
int comparador (const void *a, const void *b) { // precisa de 2 parametros a serem depois comparados
  return ( *(int*)a - *(int*)b );
  }

int main (void) {
  printf("Testar 'qsort' da biblioteca 'stdlib'\n");
  printf("Antes: ");
  imprime(vetor, N);
  printf("Inicio: invocar 'qsort' da biblioteca 'stdlib'\n");
  // Parametros para 'qsort': vetor de dados, numero de elementos no vetor, tamanho em bytes de cada elemento, endereco da funcao comparadora
  qsort(vetor, N, sizeof(int), &comparador);
  printf("Ordenado: ");
  imprime(vetor, N);
  return 0;
  }

Atenção. No C padrão NÃO é possível declarar o vetor usando a variável que será usada para informar o número efetivo de posições a serem usadas, ou seja, não tente fazer algo como int n; float vetF[n];. A razão disso é que C é uma linguagem compilada e ao compilar deve-se reservar o espaço máximo a ser usado pelo vetor. Já a variável n só será conhecida durante a execução do programa.

Apesar de algumas implementações de compiladores C permitirem, NÃO usem sob pena de seu programa não funcionar em outros compiladores.

Vetores/listas em Python

Geralmente, na literatura de programação, o termo vetor refere-se a um agregado de dados, de mesmo tipo e em posições consecutivas de memória. Como em Python, pode-se misturar tipos, então usa-se o termo lista (ou tuple). Por exemplo, pode-se declarar lista = (1, 2, "tres", "VI"); ou tupla = [1, 2, "tres", "VI"]; e alterar ou imprimir um elemento, como em: lista[3] = 3; tupla[3] = 3; print("lista=%s, tupla=%s, lista[3]=%d" % (lista,tupla, lista[3]);.

Como citado na explicação sobre funções, uma grande vantagem de ter um algoritmo genericamente implementado como uma função separada é que o código do programa fica mais organizado e pode-se invocar a função em qualquer outro trecho do programa. Por isso, alguns funções muito úteis acabam sendo implementadas pelos desenvolvedores nos ambientes de programação.

Por exemplo, em Python existe a função sorted(.) que ordena listas (e tuplas), mas também existe um método sobre lista (não sobre tupla) que também ordena lista:

  lista = ["tres", "quatro", "um", "dois"];
  print("Ordenado via 'sorted': %s" % sorted(lista)); # ['dois', 'quatro', 'tres', 'um']
  lista.sort(); # nao tente imprimir direto "lista.sort()" senao aparece "None"
  print("Ordenado via 'lista.sort()': %s" % lista); # ['dois', 'quatro', 'tres', 'um']
Note que o resultado em lista será ['dois', 'quatro', 'tres', 'um'], pois a ordem é lexicográfica (do dicionário).

Outra observação importante, o método sort() não está definido para tuplas, ou seja, os comandos lista = ("tres", "quatro", "um", "dois"); lista.sort(); print(lista); resultaria erro (AttributeError: 'tuple' object has no attribute 'sort').

No exemplo abaixo ilustramos a declaração e uso de listas dos tipos básicos int, char e float. Nesses exemplos utilizamos uma técnica de pré-alocar todo o espaço para a lista, utilizando um valor máximo para o número de posições a serem utilizadas (o M = 20;). Depois solicitamos que o usuário digite o número de elementos que ele deseja inserir na lista (não fazemos um teste, mas nessa técnica esse valor tem que ser menor que M), então utilizamos um laço para solicitar a "entrada" de cada elemento, inserindo-o na posição adequada da lista.

Listas em Python com alocação inicial de todo o espaço à priori
Vetor de caracteres Vetor de inteiros Vetor de flutuantes
M = 20 # usado para dimensionar os vetores
def main () :
  vetC = list(range(0,M)); # L1: Vetor para inteiros (ate' M elementos)
  nC = int(input());       # L2: Pode inverter L1 e L2 e usar "range(0,nC)"
  for i in range(0, nC) : # ler nC caracteres
    vetI[i] = raw_input(); # no Python 3 usar 'input()'
  for i in range(0, nC) : # imprimir os elementos
    print(vetI[i]);
M = 20 # usado para dimensionar os vetores
def main () :
  vetI = list(range(0,M)); # L1: Vetor para inteiros (ate' M elementos)
  nI = int(input());       # L2: Pode inverter L1 e L2 e usar "range(0,nI)"
  for i in range(0, nI) : # ler nI inteiros
    vetI[i] = int(input())
  for i in range(0, nI) : # imprimir os elementos
    print(vetI[i]);
M = 20 # usado para dimensionar os vetores
def main () :
  vetF = list(range(0,M)); # L1: Vetor para inteiros (ate' M elementos)
  nF = int(input());       # L2: Pode inverter L1 e L2 e usar "range(0,nF)"
  for i in range(0, nF) : # ler nF inteiros
    vetI[i] = float(input());
  for i in range(0, nI) : # imprimir os elementos
    print(vetI[i]);

Vale notar que, como em Python o espaço para o vetor é reservado durante a execução, não é necessário pré-dimensionar o espaço para o "vetor" como nos 3 códigos acima, e pode-se usar como linhas 3 e 4: nI = int(input()); vetI = list(range(0,nI));.

Por fim, vale destacar um detalhe a respeito de como "digitar" os dados usando o comando input. No Python 2, Nos códigos acima, se o usuário digitar SyntaxError: invalid syntax.

Podemos adotar outra técnica para registro dos dados na lista, desta vez não usando alocação a priori de espaço e sim estendendo a lista a cada novo elemento digitado. Mas ainda usando a técnica que obriga o usuário a digitar um único valor por vez (que dizer, digitar um inteiro e teclar ENTER). Esse exemplo está à esquerda da tabela abaixo.

Na coluna da direita da tabela mostramos um exemplo distinto, no qual não é necessário digitar a priori o número de inteiros que comporão a lista. O usuário deverá digitar todos os dados em uma mesma linha, com um único ENTER ao final, e o código decompõe a "string" digitada, utilizando como separadores espaço em branco para deduzir quais são os inteiros.

Listas em Python com alocação dinâmica de espaço e tipos de digitação
Digitando um elemento por vez Digitando todos os elementos de uma vez
def alocacaodinamica1por_linha () :
  vetI = []; # Aloca um "vetor" vazio
  # nI = int(input());
  nI = M;
  for i in range(0, nI) : # ler nI inteiro
    vetI.append(int(input())); # le novo elemento e estende a lista
  print("Lista: ", end=""); # imprimir sem mudar de linha
  for i in range(0, nI) : # imprimir os elementos
    print("%d " % vetI[i], end=""); # imprimir sem mudar de linha
  print(); # quebrar a linha ao final
def alocacaodinamica_varios_por_linha () :
  # como leremos por linha, pode-se deduzir depois o tamanho da lista
  linha = raw_input(); # ler como caracteres para poder pegar uma linha inteira - no Python 3 usar 'input()'
  vetI = map(int, linha.split()); # decomponha a linha em itens e faz um mapeamento, passando cada item para inteiro
  nI = len(vetI); # pegar tamanho da lista digitada
  print("Lista: ", end=""); # imprimir sem mudar de linha  
  for i in range(0, nI) : # imprimir os elementos
    print("%d " % vetI[i], end=""); # imprimir sem mudar de linha
  print(); # quebrar a linha ao final

Leônidas de Oliveira Brandão
http://line.ime.usp.br