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 (n) 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.
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 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 posições, (pois é 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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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 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 na posição do vetor. Antes veja que usaremos o break para finalizar a leitura quando ocorrer o fim de entrada (n e b 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 que começará com o valor 0. Vamos usar um for para olharmos todas as posições do vetor e, se em alguma delas o valor estiver negativo, significa que este banco terminou endividado e precisará de ajuda, logo receberá 1. Terminada a verificação, se o valor de 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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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 , 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 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, 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 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 c forem caracteres, escrever "%[abc]" fará a função ler todos os caracteres até o primeiro que não seja a, b ou 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 a e 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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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 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 b vier antes de a em ordem alfabética, ela retorna um valor positivo e retorna um negativo caso contrário. Exemplos: strcmp("casa","casa")=0, strcmp("casa", "arca")=1 e 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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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 representa vetores de 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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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.