Vetores

Last updated: April 28th, 2018

Introdução

  • Em algumas aplicações podemos ter uma quantidade muito grande de dados do mesmo tipo para processar, e criar uma variável para cada dado seria muito complicado.

  • Em algumas aplicações temos sequências de algum tipo e o programa precisa funcionar para qualquer sequência, independente dos valores nela ou do tamanho da sequência.

  • Imagine que você precisa fazer um programa para calcular as médias finais dos alunos de APC.

  • Para cada aluno, você deve ler as notas de 3 provas. Deve então e calcular e mostrar a média de cada um.

  • Com o que aprendemos até agora, é possível resolver esse problema. No entanto, você precisaria de: 40 x 3 provas = 120 variáveis!!

  • Prev Next
  • E se fosse um programa para calcular as médias da UnB inteira?

  • E se você precisar adicionar uma nota? Ou fazer qualquer alteração no cálculo?

  • Para essas situações usamos vetores (também chamados arrays).

Estrutura de um Vetor

  • Vetores são sequências ordenadas e indexáveis de um mesmo tipo (int, float, double, char, … )

  • Vetores possuem:

    • Tipo
    • Nome.
    • Tamanho.
    int array[100]; // vetor “array” de tipo int com tamanho 100
    float nums[] = {3.14, 2.71, 1.44, 9.98}; // vetor “nums” de tipo float inicializado
  • Vetores podem ser inicializados na declaração, e somente nesse caso não é necessário indicar o tamanho

Índices & Seg Fault

    int array[3] = {1, 4 ,-8}           
  • Vetores são indexados de 0 até n-1, ou seja, a primeira posição do vetor se encontra no índice 0.

  • índice:    0   1   2
    valor:    [1] [4] [-8]                     
  • Os valores de um vetor podem ser acessados em tempo constante, para isso, basta indicar qual posição deseja acessar.

  • int array[3] = {1, 4 ,-8}  
    int a,b,c,x = 2;
    a = array[0]; // a = 1
    b = array[1]; // b = 4
    c = array[x]; // c = -8             
  • Deve-se atentar bastante para não acessar um índice que não existe. O acesso de um vetor por um índice inválido causa um erro chamado Segmentation Fault.

  • Índices negatios (-1, -2 … ) ou maiores ou iguais ao tamanho do vetor (n , n+1 …) causam falha de segmentação.

  • int n = 31230;
    int array[3] = {1, 4 ,-8};  
    printf("%d\n",array[n]); // Irá ocorrer falha de segmentação
    Download Code Code Execution

    Executando o programa no terminal

        $ gcc -Wall -ansi -o segfault segfault.c
        $ ./segfault
        Segmentation fault (core dumped)
        $         
  • Exemplos:

    • Funcionamento de um vetor
    int main(){
        int a[3] = {1, 4, -8};
        int b[3], i;
     
        for(i = 0; i < 3; i++){
            b[i] = a[i] * 2;
        }
        return 0;
    }                                                   
    Download Code Code Execution
    • Disputa de alunos:
    • Apos vários jantares a Luz de Veras, permitiu que Veras tivesse uma idéia que possibilitasse esquentar o clima entre duas turmas de programação, visando o aumento do rendimento das notas dos alunos. Ambas as turmas possuem N alunos, e cada aluno tirou uma nota Xi na prova (Xi representa a nota do iésimo aluno). A disputa seria feita da seguinte forma: se o aluno i da turma A, tirou uma nota maior que o aluno i da turma B, então a turma A ganha um ponto, caso contrário a turma B ganha 1 ponto. Sua tarefa é ajudar Veras a descobrir quantos pontos cada turma fez, sabendo que ambas as turmas possuem a mesma quantidade de alunos.

    int n,i, resp = 0;
    scanf("%d", &n);
     
    double turmaA[n], turmaB[n];
     
    for(i = 0; i < n; i++)
        scanf("%lf", &turmaA[i]);
     
    for(i = 0; i < n; i++)
        scanf("%lf", &turmaB[i]);
     
    for(i = 0; i < n; i++){
        if(turmaA[i] > turmaB[i]){
            resp++;
        }
    }
     
    printf("A turma A possui %d pontos\n",resp);    
    printf("A turma B possui %d pontos\n",n-resp);
    Download Code

Vetores como parâmetros de função

  • Vetores são muito utilizados como parâmetros de funções. Eles são passados por referência, entao qualquer alteração no vetor feita dentro da função afeta o vetor original.
  • Em geral, ao passar o vetor para uma função também precisamos passar o tamanho dele.
/* returns the max between two numbers */
int Max(int a, int b){
    return a > b ? a : b;
}
/* returns the biggest element in array */
int maxElement(int* array, int n){
    int i;
    int max = array[0];
    for(i = 1; i < n; i++){
        max = Max(array[i], max);
    }
    return max;
}
 
int main(){
    int array[] = {0, -1, 3, -10, 4, 22, -5, 2};
    int maior = maxElement(array, 8);
    printf("O maior elemento é %d\n", maior);
}
Download Code Code Execution
  • Existem duas maneiras diferentes de passar vetores como parâmetros de função. Não faz diferença qual você usa, pode ser a da sua preferência.
  • Não é necessário especificar o tamanho do array na segunda maneira
int Max(int* array, int n); /* cabeçalho 1 */
int Max(int array[], int n); /* cabeçalho 2 */

Exercícios Recomendados

Materiais Extras

Malloc & Memset

  • A função Malloc é utilizada para alocar uma porção de memória.
  • A função Memset é utilizada para inicializar uma região de memória com um determinado valor.
  • Explicaremos como usar essas duas funções para criar vetores dinâmicos. Tudo bem se os conceitos não ficarem tão claros agora, mas tenha em mente que essas funções são muito utilizadas em Estruturas de Dados, e oferecem grande flexibilidade.
  • Os vetores que vimos até agora são estáticos, pois seu tamanho é definido em tempo de compilação. Os vetores dinâmicos, por outro lado, são definidos em tempo de execução.
  • A utilização dos vetores dinâmicos é exatamente igual a dos vetores estáticos, só um cuidado à mais é necessário: liberar o espaço de memória alocado.
  • Lembre-se também que ao alocar um espaço de memória sem inicializá-lo, aquele espaço terá lixo de memória. A função memset então pode ser utilizada para inicializar aquele espaço com um valor determinado. Ela pode ser usada em qualquer vetor.
  • A utilização envolve ponteiros, que é o retorno da função malloc.
  • Liberar o espaço de memória alocado é feito pela função free(). É importante fazer isso para evitar memory leaks Isto é, espaços de memória que não estão sendo utilizados mas estão ocupados por algum vetor dinâmico. Isso compromete a eficiência Da aplicação, e pode ter consequências catastróficas se uma quantidade meuito grande de memória for alocada e não liberada.
int k = 100; /* future size of array */
int* array = (int*) malloc(k * sizeof(int)); /* sizeof(int) returns size of int in bytes*/
memset(array, 0, sizeof(array));
free(array); /* array doesn't existe any more */