Programação Básica 03 - Vetores

Aula de Rogério Júnior

 

Imagine um problema bem simples: imprimir uma sequência de números de trás para frente. A entrada consiste de duas linha. Na primeira, haverá um inteiro n (1\leqn\leq 10^6) e, na segunda, um sequência de n números inteiros separados por um espaço em branco. A saída deve gerar uma única linha: Os n números da sequência lida, mas de trás para frente.

Você já deve ter percebido que vamos precisar salvar esses números, visto que não poderemos imprimí-los na ordem em que aparecem. Porém, como declarar n variáveis se não conheço o valor de n? A resposta é criando um vetor. Um vetor (ou um array, são sinônimos) é como uma sequência de variáveis em que posso acessá-las pelo índice.

vetor_image

 

Para criar um vetor, escrevo seu tipo, seu nome, e, em seguida, quantas variáveis ele vai guardar, entre colchetes "[]". Para declarar um vetor de inteiros com o nome sequencia para guardar 10 posições, por exemplo, escreveria o comando: "int sequencia[10];". Assim, o computador guarda, na sua memória, o espaço para guardar 10 inteiros. Para me referir ao elemento de índice 5 deste vetor, por exemplo imprimí-lo, eu o chamaria pelo índice, escrevendo "printf("%d", sequencia[5]);". Para ler um número na tela e guardá-lo no índice 5 do vetor, faria um comando análogo: "scanf("%d", &sequencia[5]);". Vale lembrar que, como mostrado na figura acima, se o vetor tem n posições, ele estará indexado de 0 a n-1, ou seja, o primeiro elemento será o sequencia[0], o segundo será o sequencia[1] e o último será o sequencia[n-1]. No caso, como declaramos um vetor de 10 posições, teremos os índices de 0 té 9. Para não marcar os elementos um por um, podemos dizer quais são os elementos de um vetor logo na sua declaração, através do comando "={}". Escrever, por exemplo, "int vetor[5]={0, 1, 4, 9, 16};" significa declarar um vetor de inteiros de 5 posições cujo nome é vetor e, onde a posição 0 do vetor receberá 0, a posição 1 receberá 1, a 2 receberá 4,  a 3 receberá 9 e a 4 receberá 16.

Geralmente usamos um for para percorrer todas as casas do vetor, fazendo um inteiro i ser o índice que quero acessar e fazendo-o variar entre as posições do vetor que desejo percorrer. Agora ficou fácil fazer o problema do início, não? Vamos declarar um vetor de 1000100 posições, (pois 10^6 é o valor máximo de n e sobra sempre é bom) e, usando um for que irá de 1 até n, vou salvar os números lidos na tela nas posições de 1 a n. Feito isso usaremos um for que vai de n até 1 para percorrer o vetor de trás para frente e imprimir os números nele salvo. Vamos ao código:


#include <cstdio> // scanf e printf
int main(){
int n; // declaro a variável n
int sequencia[1000100]; // declaro o vetor de inteiros "sequencia" de 1000100 posições
scanf("%d", &n); // leio o valor de n na tela
for(int i=1; i<=n; i++) scanf("%d", &sequencia[i]); // salvo cada número em uma posição do vetor, de 1 até n
for(int i=n; i>0; i--) printf("%d ", sequencia[i]); // percorro o vetor de trás para frente, imprimindo seus elementos
printf("\n"); // imprimo a quebra de linha ao fim do código
return 0;
}

view raw

array.cpp

hosted with ❤ by GitHub

Agora que você já sabe fazer o básico de vetores, tente fazer o problema Sub-Prime. Se  não conseguir, segue a solução comentada abaixo abaixo, mas realmente tente resolvê-lo antes de lê-la!

O uso de vetor neste caso será para guardarmos o fundo monetário que cada banco possui. No começo, vamos declarar um vetor de nome fundo de 30 posições, pois são no máximo 20 bancos e, no começo de cada caso de teste, salvaremos o fundo do banco de número i na posição i do vetor. Antes veja que usaremos o break para finalizar a leitura quando ocorrer o fim de entrada (nb forem zero). Agora que temos salvos os fundos de cada banco, vamos abrir um for que se repetirá n vezes e, a cada repetição, executará uma operação de debênture. No caso, essa operação consiste em ler os valores do banco devedor d, do credor c e do valor de transferência v, subtrair o valor de v do fundo do banco devedor ("fundo[d]-=v;") e adicionar este valor ao fundo do banco credor ("fundo[c]+=v;"). Após realizarmos todas as operações, vamos verificar se algum banco precisa de ajuda financeira. Vamos declarar uma variável ajuda que começará com o valor 0. Vamos usar um for para olharmos todas as posições do vetor fundo e, se em alguma delas o valor estiver negativo, significa que este banco terminou endividado e precisará de ajuda, logo ajuda receberá 1. Terminada a verificação, se o valor de ajuda ainda for zero, nenhum banco precisou de auxílio financeiro e então imprimiremos "S". Caso contrário, então algum banco está com fundo negativo e precisará de dinheiro, e imprimiremos "N". Segue o código:


#include <cstdio> // scanf e printf
int main(){
int b, n; // declaro as variáveis b e n
int fundo[30]; // declaro o vetor de inteiros "fundo" com 30 posições, que guardará o dinheiros dos bancos
while(true){ // repita o loop enquando "a verdade for verdade"
scanf("%d %d", &b, &n); // leia os valores de b e n
if(b==0 && n==0) break; // se b e n forem ambos zero, termine o loop
for(int i=1; i<=b; i++) scanf("%d", &fundo[i]); // leia o valor do fundo de cada banco
for(int i=1; i<=n; i++){ // para cada operação de debênture
int d, c, v; // declare as variáveis inteiras d, c e b
scanf("%d %d %d", &d, &c, &v); // leia os valores de "d", "c" e "v".
fundo[d]-=v; // tire do fundo do banco devedor o valor da transferência
fundo[c]+=v; // e adicione este valor ao fundo do banco credor
}
int ajuda=0; // declare a variável ajuda, inicializada com o valor zero
for(int i=1; i<=b; i++) if(fundo[i]<0) ajuda=1; // se algum banco tiver fundo negativo, ajuda receberá 1
if(ajuda==0) printf("S\n"); // se ajuda for zero, é possível tudo ser pago sem ajuda do governo
else printf("N\n"); // caso contrário, o banco central deverá ajudar algum banco
}
return 0;
}

view raw

sub-prime.cpp

hosted with ❤ by GitHub

Até agora, vimos um vetor de inteiros. Um tipo de vetor muito conhecido é o vetor de caracteres, que é uma frase. O vetor de variáveis do tipo char é declarado de maneira semelhante ao de inteiros. Ele tem um nome especial: string. Para escanearmos uma string com o scanf, usamos o indicador %s e não colocamos o "&" antes do nome da string, pois seu nome já é um ponteiro para o começo do vetor. Para ler uma frase e salvá-la em uma string de nome frase, escrevemos o comando: "scanf("%s", frase);". Vale lembrar que %s significa "leia até um espaço", ou seja, só será salva a frase até o primeiro espaço ou quebra de linha. Se na entrada estiver escrito "Alan Turing", ficaria salvo em frase apenas o nome "Alan", pois o scanf iria parar no espaço em branco entre as duas palavras. Além disso, é importante saber que o final de uma string é marcado pelo caractere '\0'. Ou seja, frase seria uma string de comprimento 4, mas teria 5 caracteres salvos: frase[0]='A', frase[1]='l', frase[2]='a', frase[3]='n' e frase[4]='\0'. A leitura já coloca o '\0' no fim da string automaticamente.

Assim como aspas simples representam caractere, aspas duplas representam string. Se quisermos fazer com que frase receba a frase "Alan Turing", escrevemos o comando "frase="Alan Turing;"; Um '\0' seria automaticamente adicionado na posição 12, no final da string.

Há algumas maneiras de explicar ao scanf o que queremos que ele leia para formar uma string, se quisermos algo diferente de simplesmente ler até o primeiro espaço. Se ao invés de %s escrevermos %[], podemos colocar entre os colchetes os tipos de caracteres que queremos. Seja c um caractere qualquer, se escrevemos "%[^c]" a função irá ler toda a entrada até que apareça o primeiro caractere igual ao char c e ignorar o resto da frase (ignoraria, inclusive, o caractere c). Para lermos uma linha toda até o fim e salvarmos na string frase, escrevemos o comando "scanf("%[^\n]", frase);", que irá ler até o caractere quebra de linha ('\n'). Se a, b e forem caracteres, escrever "%[abc]" fará a função ler todos os caracteres até o primeiro que não seja aou c. Podemos ligar caracteres através de "-" para indicar um conjunto, ou seja: "%[a-cek]" irá fazer a função ler até o primeiro caractere que não tenha código entre c (inclusive), ou e ou k. Exemplo: o comando  "scanf("%[a-z A-Z]", frase);" iria ler até o primeiro caractere que não esteja entre 'a' e 'z', ou entre 'A' e 'Z' ou não seja espaço em branco (pois ele aparece entre o z e o A), ou seja, iria ler letras minúsculas, maiúsculas e espaços em branco.

Segue o código de um programa que lê uma frase de até 29 caracteres até o primeiro caractere que não seja uma letra ou um espaço em branco e depois imprime esta frase seguida de um ponto e quebra de linha:


#include <cstdio> // scanf e printf
int main(){
char frase[30]; // declaro a string frase
scanf("%[a-z A-Z]", frase); // leio a frase, ate o primeiro caractere indsejado
printf("%s.\n", frase); // imprimo a frase
return 0;
}

view raw

scanf.cpp

hosted with ❤ by GitHub

Existem algumas funções próprias para uma string. Elas estão na biblioteca cstring ou string.h. Dentre várias, são mais importantes:

obs* saiba que o string nomeia um tipo que não é o vetor de char que estamos vendo, mas uma estrutura de C++ muito parecida que estudaremos depois. Para efeito didático, nesta página, vamos usar string para nomear o tipo "vetor de char" nas seguintes funções:

strlen(string x) - Retorna o tamanho de uma string ignorando o '\0'. O valor de strlen("casa") é 4, pois "casa" te 4 caracteres. Se frase ainda fosse "Alan Turing", então strlen(frase) seria 11, pois ela teria 11 caracteres.

strcmp(string a, string b) - Compara duas strings. Se elas forem iguais, a função retorna 0. Se vier antes de em ordem alfabética, ela retorna um valor positivo e retorna um negativo caso contrário. Exemplos: strcmp("casa","casa")=0strcmp("casa", "arca")=1 strcmp("arca", "casa")=-1.

Para que tudo fique mais claro, segue um programa que lê duas palavras de até 100 caracteres na tela e, se elas estiverem em ordem alfabética imprime "estao em ordem alfabetica" e, se não estiverem, imprime "nao estao em ordem alfabetica". Feito isso, se a primeira for menor ou igual que a segunda, imprime, em outra linha, "estao em ordem de tamanho", se não, imprime "nao estao em ordem de tamanho". Se as duas palavras forem iguais, deve imprimir, na saída, unicamente a frase "palavras iguais", e uma quebra de linha ao fim da saída, em qualquer caso:


#include <cstdio> // scanf e printf
#include <cstring> // strlen e strcmp
int main(){
char frase1[110], frase2[110]; // declaro as strings frase1 e frase2
scanf("%s %s", frase1, frase2); // salvo as duas palavras da entrada em frase1 e frase2
int compara=strcmp(frase1, frase2); // vou salvar o valor de strcmp(frase1, frase2) na variável inteira "compara"
if(compara==0) printf("palavras iguais\n"); // se ela for zero, as palavras são iguais
else{ // se não
if(compara<0) printf("estao em ordem alfabetica\n"); // se for negativo, estão em ordem alfabética
else printf("nao estao em ordem alfabetica\n"); // se não, não estão
if(strlen(frase1) <= strlen(frase2)) printf("estao em ordem de tamanho\n"); // checo se frase1 é mais curta que frase2
else printf("nao estao em ordem de tamanho\n"); // se não for, então elas estão em ordem de tamanho trocada
}
return 0;
}

view raw

string.cpp

hosted with ❤ by GitHub

Assim como podemos declarar um vetor de inteiros, por exemplo, podemos declarar um vetor de vetores de inteiros, o que chamamos de matriz de inteiros. Se declarássemos, por exemplo, o "int matriz[10][5];", teríamos 10 vetores, cada um com 5 inteiros. Para acessarmos o o vetor da posição 4 da matriz, usaríamos o comando "matriz[4];", e para acessarmos o elemento da posição 3 deste vetor, faríamos como em qualquer outro vetor e usaríamos o comando "matriz[4][3];". Note que os vetores também estão indexados de 0 a 9, e não de 1 a 10. Chamamos essa estrutura de matriz porque é fácil vê-la como uma matriz em que cada linha representa um vetor. Assim, uma matriz n \times m representa n vetores de m elementos.

Imagine o seguinte problema: você recebe n strings na entrada, e deve imprimí-las de trás para frente. Este é exatamente o primeiro problema da aula, mas agora, ao invés de guardarmos inteiros em um vetor, deveremos guardar vetores de char em um vetor. O nome dessa matriz de char será frase. Suponha que são no máximo 110 strings e cada uma tem no máximo 20 caracteres. Então devemos declarar, com sobra, uma matriz de char 110 x 30, com o comando "char frase[110][30];". Depois usamos um for para ler as n strings e salvar cada uma em um dos vetores de char da matriz, com o comando: "for(int i=1; i<=n; i++) scanf(" %s", frase[i]);". Feito isso, usaremos outro for, para percorrermos o vetor de vetores de trás para frente, imprimindo as strings, com o comando: "for(int i=n; i>0; i--) printf("%s\n", frase[i]);". A entrada deve ter, na primeira linha, o valor de n e, nas próximas n linhas, uma string apenas com letras minúsculas. A saída deve ter n linhas: as n strings de trás para frente. Segue o código:


#include <cstdio> // scanf e printf
int main(){
int n; // declaro a variável inteira n
char frase[110][30]; // declaro a matriz de char frase
scanf("%d", &n); // leio o valor de n
for(int i=1; i<=n; i++) scanf(" %s", frase[i]); // leio cada uma das strings
// percorro o vetor de strings de trás para frente, imprimindo-as
for(int i=n; i>0; i--) printf("%s\n", frase[i]);
return 0;
}

view raw

char_matrix.cpp

hosted with ❤ by GitHub

Agora que você já sabe de tudo isso, tente fazer os seguintes problemas do URI. Se ainda não tem uma conta neste site, clique aqui.

Problema 1 - Substituição em Vetor I

Problema 2 - Trova em Vetor I

Problema 3 - Menor e Posição

Problema 4 - Preenchimento de Vetor II

Problema 5 - Preenchimento de Vetor III

Problema 6 - Preenchimento de Vetor IV

Problema 7 - Sentença Dançante

Problema 8 - LED

Problema 9 - Avance as Letras

Problema 10 - Criptografia

Se tiver alguma dúvida em algum problema, vá na página inicial do curso e preencha o formulário para enviar sua pergunta.


 

As aulas do Curso Noic de Informática são propriedade do Noic e qualquer reprodução sem autorização prévia é terminantemente proibida. Se você tem interesse em reproduzir algum material do Curso Noic de Informática para poder ministrar aulas, você pode nos contatar por esta seção de contato para que possamos fornecer materiais específicos para reprodução.