Aula 4 - Vetores
Nesta aula veremos os vetores (também chamados de arrays): a primeira estrutura de dados propriamente dita da disciplina, capaz de guardar vários valores do mesmo tipo sob um único nome. Vetores e laços de repetição (Aula 3) andam sempre juntos — praticamente tudo que faremos com vetores envolve percorrê-los com um for.
1. Por que precisamos de vetores?
Imagine um programa que precisa guardar as notas de 5 alunos. Sem vetores, seríamos obrigados a criar uma variável para cada nota:
float nota1, nota2, nota3, nota4, nota5;
Isso já é incômodo para 5 alunos, e se torna inviável para 50, 500, ou uma quantidade de alunos que só será conhecida durante a execução do programa. Um vetor resolve esse problema, guardando várias posições do mesmo tipo sob um único nome, acessadas por um índice:
float notas[5]; // um único nome, cinco posições
2. Declaração e inicialização
Para declarar um vetor, indicamos o tipo dos elementos, o nome do vetor, e a quantidade de posições entre colchetes:
int idades[10]; // vetor de 10 inteiros, sem valores iniciais definidos
Também é possível já inicializar os valores no momento da declaração:
int primos[5] = {2, 3, 5, 7, 11};
Tamanho fixo. O tamanho de um vetor declarado dessa forma (notas[5]) é definido em tempo de compilação e não pode ser alterado durante a execução do programa — se você precisar de mais posições do que o vetor comporta, é preciso declará-lo com um tamanho maior desde o início.
|
3. Índices, acesso e modificação
Em C, os índices de um vetor sempre começam em 0 e vão até N - 1, onde N é o tamanho do vetor. Um vetor notas[5] possui as posições notas[0], notas[1], notas[2], notas[3] e notas[4] — nunca notas[5].
float notas[5]; notas[0] = 8.5; // atribui a primeira posição notas[1] = 7.0; printf("%.1f\n", notas[0]); // lê a primeira posição: imprime 8.5
Cuidado: C não verifica os limites! Diferente de outras linguagens, C não impede que você acesse um índice fora do vetor, como notas[5] em um vetor de 5 posições. Isso não gera um erro de compilação nem, necessariamente, um erro imediato na execução — o programa pode ler ou escrever em uma posição de memória que não pertence ao vetor, com resultados imprevisíveis (valores errados, ou até o encerramento abrupto do programa, conhecido como Segmentation Fault). É responsabilidade de quem programa garantir que os índices usados sejam sempre válidos.
|
4. Percorrendo um vetor com for
Por sabermos exatamente quantas posições um vetor possui, o for (Aula 3) é a estrutura natural para percorrê-lo, de 0 até tamanho - 1:
#include <stdio.h> int main() { int notas[5]; int i; // preenchendo o vetor for (i = 0; i < 5; i++) { printf("Digite a nota %d: ", i + 1); scanf("%d", ¬as[i]); } // exibindo o vetor for (i = 0; i < 5; i++) { printf("Nota %d: %d\n", i + 1, notas[i]); } return 0; }
Note o ¬as[i] dentro do scanf — assim como fazíamos com variáveis simples (Aula 1), o scanf precisa do endereço de onde guardar o valor lido, e ¬as[i] é o endereço da posição i do vetor.
5. Vetores na memória
Assim como vimos na Aula 1 para variáveis simples, os elementos de um vetor também ficam na memória, mas com uma característica especial: eles ficam sempre em posições contíguas (uma exatamente depois da outra).
Considere um vetor int primos[5] = {2, 3, 5, 7, 11};. Como cada int ocupa 4 bytes, e o vetor começa (por exemplo) no endereço E2000 (usando a mesma notação decimal de endereços da Aula 1 — a letra E seguida de um número, em vez do tradicional 0x em hexadecimal), seus elementos ficam assim organizados:
| Endereço | Identificador | Valor |
|---|---|---|
E2000 |
primos[0] |
2 |
E2004 |
primos[1] |
3 |
E2008 |
primos[2] |
5 |
E2012 |
primos[3] |
7 |
E2016 |
primos[4] |
11 |
É justamente por essa organização contígua que o acesso a qualquer posição do vetor é tão rápido: para acessar primos[i], o programa só precisa somar i * 4 bytes (o tamanho de um int) ao endereço inicial do vetor — não importa se i é 0 ou 4, o custo é sempre o mesmo.
6. Aplicações comuns com vetores
Soma e média dos elementos (acumulador)
int vetor[5] = {10, 20, 5, 8, 12}; int i, soma = 0; for (i = 0; i < 5; i++) { soma += vetor[i]; } printf("Soma: %d\n", soma); printf("Media: %.2f\n", soma / 5.0);
Maior e menor elemento
int vetor[5] = {10, 20, 5, 8, 12}; int i, maior, menor; maior = vetor[0]; // começa "otimista", assumindo o primeiro elemento menor = vetor[0]; for (i = 1; i < 5; i++) { // começa em 1: o índice 0 já foi usado acima if (vetor[i] > maior) { maior = vetor[i]; } if (vetor[i] < menor) { menor = vetor[i]; } } printf("Maior: %d\n", maior); printf("Menor: %d\n", menor);
Busca sequencial
Para descobrir se um valor está presente no vetor (e em qual posição), percorremos o vetor comparando cada elemento com o valor procurado — uma flag (ou a própria posição encontrada) guarda o resultado:
int vetor[5] = {10, 20, 5, 8, 12}; int i, procurado = 8; int posicaoEncontrada = -1; // -1 significa "ainda não encontrado" for (i = 0; i < 5; i++) { if (vetor[i] == procurado) { posicaoEncontrada = i; } } if (posicaoEncontrada != -1) { printf("Encontrado na posicao %d\n", posicaoEncontrada); } else { printf("Nao encontrado\n"); }
Essa técnica — percorrer os elementos um a um, comparando com o valor procurado — é chamada de busca sequencial, e será revisitada e aprofundada em uma aula futura, junto com técnicas de ordenação.
Resumo
|
Exercícios
Nível fácil
- Escreva um programa que declare um vetor de 5 inteiros, leia os 5 valores do usuário, e depois os imprima na ordem em que foram lidos.
- Escreva um programa que leia um vetor de 10 inteiros e imprima quantos deles são pares.
- Escreva um programa que leia um vetor de 5 números reais e imprima a soma e a média deles.
Nível médio
- Escreva um programa que leia um vetor de 10 inteiros e imprima o maior e o menor valor encontrado, e em quais posições (índices) eles estão.
-
Escreva um programa que leia um vetor de
ninteiros (comntambém lido do usuário) e um valor a ser procurado, e informe se o valor está presente no vetor e, em caso afirmativo, quantas vezes ele aparece. - Escreva um programa que leia um vetor de 10 inteiros e crie um segundo vetor, do mesmo tamanho, contendo apenas os valores do primeiro vetor multiplicados por 2. Imprima os dois vetores ao final.
Nível difícil
-
Escreva um programa que leia um vetor de
ninteiros e o inverta (o primeiro elemento passa a ser o último, e assim por diante), sem usar um segundo vetor — troque os elementos diretamente dentro do próprio vetor original. -
Escreva um programa que leia um vetor de
ninteiros e remova todas as ocorrências de um valorxinformado pelo usuário, deslocando os elementos seguintes para preencher os espaços abertos, e informando ao final quantos elementos restaram no vetor.
Sugestões de Respostas dos Exercícios
Exercício 1
#include <stdio.h> int main() { int vetor[5]; int i; for (i = 0; i < 5; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); } for (i = 0; i < 5; i++) { printf("%d\n", vetor[i]); } return 0; }
Exercício 2
#include <stdio.h> int main() { int vetor[10]; int i, contadorPares = 0; for (i = 0; i < 10; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); if (vetor[i] % 2 == 0) { contadorPares++; } } printf("Numeros pares: %d\n", contadorPares); return 0; }
Exercício 3
#include <stdio.h> int main() { float vetor[5]; float soma = 0; int i; for (i = 0; i < 5; i++) { printf("Digite o valor %d: ", i + 1); scanf("%f", &vetor[i]); soma += vetor[i]; } printf("Soma: %.2f\n", soma); printf("Media: %.2f\n", soma / 5); return 0; }
Exercício 4
#include <stdio.h> int main() { int vetor[10]; int i, maior, menor, posicaoMaior = 0, posicaoMenor = 0; for (i = 0; i < 10; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); } maior = vetor[0]; menor = vetor[0]; for (i = 1; i < 10; i++) { if (vetor[i] > maior) { maior = vetor[i]; posicaoMaior = i; } if (vetor[i] < menor) { menor = vetor[i]; posicaoMenor = i; } } printf("Maior: %d (posicao %d)\n", maior, posicaoMaior); printf("Menor: %d (posicao %d)\n", menor, posicaoMenor); return 0; }
Exercício 5
#include <stdio.h> int main() { int vetor[100]; // capacidade máxima; n informa quantas posições serão usadas int n, i, procurado, ocorrencias = 0; printf("Quantos elementos? "); scanf("%d", &n); for (i = 0; i < n; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); } printf("Qual valor procurar? "); scanf("%d", &procurado); for (i = 0; i < n; i++) { if (vetor[i] == procurado) { ocorrencias++; } } if (ocorrencias > 0) { printf("Encontrado %d vez(es)\n", ocorrencias); } else { printf("Nao encontrado\n"); } return 0; }
Como C exige que o tamanho de um vetor comum seja fixado na declaração, declaramos um vetor "grande o suficiente" (100 posições) e usamos apenas as primeiras n — uma limitação que será superada mais adiante na disciplina, quando estudarmos alocação dinâmica de memória.
Exercício 6
#include <stdio.h> int main() { int vetor[10]; int dobrado[10]; int i; for (i = 0; i < 10; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); dobrado[i] = vetor[i] * 2; } printf("Original: "); for (i = 0; i < 10; i++) { printf("%d ", vetor[i]); } printf("\n"); printf("Dobrado: "); for (i = 0; i < 10; i++) { printf("%d ", dobrado[i]); } printf("\n"); return 0; }
Exercício 7
#include <stdio.h> int main() { int vetor[100]; int n, i, inicio, fim, temp; printf("Quantos elementos? "); scanf("%d", &n); for (i = 0; i < n; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); } inicio = 0; fim = n - 1; while (inicio < fim) { // troca vetor[inicio] com vetor[fim] temp = vetor[inicio]; vetor[inicio] = vetor[fim]; vetor[fim] = temp; inicio++; fim--; } printf("Vetor invertido: "); for (i = 0; i < n; i++) { printf("%d ", vetor[i]); } printf("\n"); return 0; }
A ideia é usar dois índices que "andam um em direção ao outro": inicio começa no início do vetor e avança; fim começa no final e recua. A cada passo, trocamos os elementos dessas duas posições (usando uma variável temp auxiliar, para não perder um dos valores durante a troca) e continuamos até os dois índices se cruzarem no meio do vetor.
Exercício 8
#include <stdio.h> int main() { int vetor[100]; int n, i, j, x; int tamanhoFinal; printf("Quantos elementos? "); scanf("%d", &n); for (i = 0; i < n; i++) { printf("Digite o valor %d: ", i + 1); scanf("%d", &vetor[i]); } printf("Qual valor remover? "); scanf("%d", &x); tamanhoFinal = 0; // vai contar quantos elementos sobram for (i = 0; i < n; i++) { if (vetor[i] != x) { vetor[tamanhoFinal] = vetor[i]; // copia para a próxima posição livre tamanhoFinal++; } } printf("Restaram %d elementos: ", tamanhoFinal); for (j = 0; j < tamanhoFinal; j++) { printf("%d ", vetor[j]); } printf("\n"); return 0; }
Em vez de "abrir buracos" no vetor a cada remoção, usamos um segundo índice, tamanhoFinal, que só avança quando encontramos um elemento que deve permanecer — cada elemento mantido é copiado para a próxima posição livre à esquerda. Ao final, tamanhoFinal indica exatamente quantos elementos restaram, e todos eles estarão organizados nas primeiras posições do vetor.