PRG122804 2018 1 AULA09

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
A versão imprimível não é mais suportada e pode ter erros de renderização. Atualize os favoritos do seu navegador e use a função de impressão padrão do navegador.

Objetivos

O aluno deverá:

  • Compreender o conceito de vetores.
  • Definir e inicializar vetores do tipo int, float e double no C.
  • Passar vetores como parâmetro sem usar o conceito de ponteiros.

Arrays Unidimensionais (Vetores)

Um vetor pode ser visto como uma variável que pode ser indexada e onde em cada posição existe um elemento do vetor. Os elementos do vetor possuem um tipo único. Uma boa analogia é comparar o vetor com uma tabela de tamanho fixo onde em cada linha pode ser armazenado um elemento.

PROBLEMA: Ler 10 números inteiros para um vetor de inteiros. Computar um segundo vetor que é o resultado da multiplicação por um escalar inteiro 5.

DADO DE ENTRADA: Os 10 números armazenados em VET1

DADO DE SAÍDA: VET2, o vetor resultado da multiplicação de VET1 por 5.


ExplicacaoVetor1.jpg

EXERCÍCIO 1: Implementar um algoritmo (pseudo-código) para ler 10 números inteiros para um vetor e imprimir o número de números acima da média.
NOTE: Definir um contador, iniciado em zero. Calcular a média e fazer um loop sobre o vetor testando cada item para verificar se é maior que a média.

Exercício 1 - Programa em C
#include <stdio.h>
 
main()
{
	int i=0,am=0;
	int vet1[10];
	float media=0;

	for(i=0;i<10;i++) {
		printf("Entre com a nota %d => ",i+1);
		scanf("%d",&vet1[i]);
		media = media+vet1[i];
	}
	media = media/i;
	for( i=0;i<10;i++) {
		if (vet1[i]>media)
		   am++;
	}
	printf("Media=%0.1f. O número de notas acima da média é %d.\n",media,am);
}


EXERCÍCIO 2: Implementar um algoritmo (pseudo-código) para ler 10 números inteiros para um vetor e imprimir o maior e o menor número digitado.
NOTE: É possível implementar marcando a posição do vetor que possui o maior e o menor valor ou o próprio valor máximo e mínimo.

Exercício 2 - Programa em C
#include <stdio.h>
 
main()
{
	int i=0,am=0;
	int vet1[10];
	int max=0,min=0;
 
	for(i=0;i<10;i++) {
		printf("Entre com a nota %d => ",i+1);
		scanf("%d",&vet1[i]);
	}
	
	for( i=0;i<10;i++) {
		if (vet1[i]>vet1[max])
			max=i;
		if (vet1[i]<vet1[min])
			min=i;
	}
	printf("Menor número: %d. Maior número: %d.\n",vet1[min],vet1[max]);
}

Definindo e usando vetores no C

Um vetor pode ser facilmente definido no C da forma:

TipoVetor NomeDoVetor[dimensao];

O algoritmo do fluxograma implementado anteriormente ficaria da seguinte forma em C:

#include <stdio.h>

main()
{
  int vet1[5],vet2[5];
  int i;

  for(i=0;i<5;i++) {
     printf("Entre com vet[%d] => ",i);
     scanf("%d",&vet1[i]);
     vet2[i]=vet1[i]*5;
  }
  /* para conferir- vamos imprimir o conteúdo de vet2 */
  for(i=0;i<5;i++)
     printf("vet2[%d] => %d\n",i,vet2[i]);
}

Vamos a um exemplo que mostra as possibilidades de acesso a um vetor:

#include <stdio.h>
 
main()
{
  float x[10]; /* vetor com 10 floats */
  int i;
  x[0] = 22.5; /* colocando 22.5 na posição 0 do vetor */
  x[9] = x[0] + 2.5;
  printf("Entrar com o número na posição 5\n");
  scanf("%f",&x[5]);
  i=2;
  x[i*2]=i*1.5;        /* usando uma expressão como índice */
 
  while (i<8) {        /* usando loop para acessar o vetor */
     x[i]=0.0;
     i++;
  }
  for(i=0;i<10;i++)
  	printf("\nValor de x[%d]=%0.1f",i,x[i]);
  	
}

NOTA: Vetores na Linguagem C começam SEMPRE na posição 0.

Iniciando vetores em C

Pode-se iniciar um vetor da forma:

#include <stdio.h>

void main()
{
  int x[10] = {2,4,7,-5,3,2,3,4,9,10};

  printf("%d\n", x[2]);
}

Passando vetores como parâmetros

Vetores não são copiados na passagem por parâmetro. Eles são passados sempre como referência. Veja o exemplo a seguir:

#include <stdio.h>

void ler_vet(int aux[5])
{
  int i;

  for (i=0;i<5;i++) {
     printf("aux[%d] <== ",i);
     scanf("%d",&aux[i]);
  } 
}

main()
{
   int vet[5], i;

   ler_vet(vet);
   for (i=0;i<5;i++)
      printf("vet[%d]=%d\n",i,vet[i]);
}

Perceba como é realizada a declaração de parâmetros que são vetores. Observe no exemplo, que o vetor aux é na realidade o próprio vetor vet. Inicialmente dados são lidos para aux e depois vet é impresso.

Não é obrigatório definir o tamanho do vetor na declaração de parâmetros. Atenção! Na realidade o C não verifica o acesso indevido a um elemento fora do tamanho do vetor.

Exercícios

1. Implementar um programa em C para ler 10 números reais (float) para um vetor. Usar o comando while.

Resposta
#include <stdio.h>

main()
{
	float x[10];
	int i;

 	i=0;
 	while (i<10) {
		printf("Entre com x[%d] -> ", i);
		scanf("%f",&x[i]);
 		i++;
	}	
}

2. Modificar o exercício para computar a média dos 10 números que estão no vetor. 3. Modificar o exercício anterior para computar a quantidade de números do vetor que estão acima da média.

Resposta
#include <stdio.h>


main()
{
	float x[10];
	float soma = 0, media; 
	int i, cont;
 
	/* leitura do vetor */
 	i=0;
 	while (i<10) {
		printf("Entre com x[%d] -> ", i);
		scanf("%f",&x[i]);
		soma = soma + x[i];
 		i++;
	}	
   
	/* calculo da media */
	media = soma /10;

	/* computação de números acima da média */
	cont = 0;
 	i=0;
 	while (i<10) {
		if (x[i] > media) 
	           cont++;
		i++;
	}	
	printf ("Número de números acima da média = %d\n", cont);
}

4. Refazer os exercícios anteriores usando o comando for; 5. Considere um vetor global de floats chamado vetRnd de tamanho 100. Construa uma função que inicia este vetor com 100 números randômicos entre 1 e 6. 6. Sobre o exercício anterior, acrescente uma função para imprimir o número de 0s,1s,...6s do vetor. 7. Implementar uma função que recebe dois vetores de inteiros como parâmetro e o tamanho dos mesmos (suponha vetores de mesmo tamanho). A função deve retornar o número de elementos iguais comparados posição por posição. O esqueleto da função deve ser como:

Resposta
int compara_vetores(int ve1[],int vet2[], int tamanho)
{
  int num_elementos;

  return num_elementos;
}

Exemplo: Para os vetores x[]={1,1,3,4,5} e y[]={1,2,3,3,5} temos três elementos iguais (nas posições 0, 2 e 4).

Tipo Char

Em aulas anteriores viu-se que um caracter pode ser representado por uma sequência de bits. Utilizando um código é possível definir o significado da sequência. Um código amplamente usado é o ASCII. Com 8 bits (7 no Ascii original) tem-se então a possibilidade de representar qualquer letra, número, ou símbolo (vírgula, ponto-e-vírgula etc). Note que um número representado em ASCII NÃO serve para realizar operações aritméticas. Trata-se de representação textual, por exemplo, um dígito de um número telefone.

Em síntese, uma variável do tipo caracter é tratada como um número inteiro e declarada com o tipo char, que na prática é um número inteiro de byte.

Exemplo
#include <stdio.h>
 
main ()
{
  char x='A',y=65,w=0x41,z; /* três formas de representar a mesma coisa */
 
  scanf("%c",&z);
  printf("Caracter lido = %c\n",z);
  printf("Caracter lido = %d\n",z);
  printf("Caracter lido = %x\n",z);
  if (z==x)
      printf("Iguais 1\n");
  if (z==y)
      printf("Iguais 2\n");
  if (z==w)
      printf("Iguais 3\n");
}

Armazenamento de cadeias de caracteres em vetores

Uma cadeia de caracteres ou string nada mais é que uma sequência de caracteres ASCII. Para mantermos coerência com a linguagem C, vamos assumir que uma string bem comportada termina com um zero (0, não o caracter '0' que é o número 48 decimal em ASCII). Em inglês chama-se "string NULL terminated". Em algumas bibliografias e referências pode-se encontrar também: '\0'.

Exemplo: A string "IFSC" armazenada em um vetor CADEIA, na memória de um computador, teria a seguinte implementação:

ExplicacaoString1.jpg

Assumi-se que cada caracter é armazenado em um byte. Uma string terminada em 0 facilita o seu processamento pois se pode facilmente detectar o seu final. Note no exemplo acima, que a string está armazenada em um vetor CADEIA cujo tamanho excede ao da string. Os bytes que se seguem ao zero podem ser considerados lixo.

Processando cadeias de caracteres


Sabendo como uma string é armazenada na memória de um computador torna-se fácil processá-la. Por exemplo, vamos ver um algoritmo para contar o número de caracteres de uma string lida pelo teclado para dentro de um vetor CADEIA.

FluxogramaContadorCaracteresCadeia.jpg

EXERCÍCIO 1: Colocar o procedimento acima na forma de um subprograma (função) que recebe como parâmetro o vetor e retorna um número inteiro correspondente ao tamanho da cadeia.

EXERCÍCIO 2: Elaborar um fluxograma para computador o número de ocorrências do caracter 'b' em uma string lida pelo teclado. Apresentá-lo na forma de um subprograma que retorna o número de ocorrências.

EXERCÍCIO 3: Estude a tabela ASCII e elabore um fluxograma para capitalizar todos os caracteres minusculos de uma string lida pelo teclado. Apresentá-lo como subprograma.

Função gets()

Esta função é utilizada em substituição ao scanf().

Forma geral:

char s[];
gets(s);

O usuário entra com uma string, que ser armazenada no vetor char s[]. A função gets() não é segura, por quê? Simplesmente porque com gets() pode ocorrer um estouro da quantidade de posições que foi especificada na string. Veja o exemplo abaixo:

#include <stdio.h>
void main()
{
    char buffer[10];
    printf("Entre com o seu nome: ");
    gets(buffer);
    printf("O nome é: %s\n", buffer);
}

Se o usuário digitar como entrada:

Douglas de Souza

Ou seja, digitar um total de 16 caracteres: 17 posições (incluindo o '\0' ) serão utilizadas para armazenar a string. Como a string buffer[10] só tem 10 caracteres, os 7 caracteres adicionais serão colocados na área de memória subsequente, escrevendo em uma região de memória que não está reservada para string. Este efeito é conhecido como "estouro de buffer" e pode causar problemas imprevisíveis. Uma forma de se evitar este problema é usar a função fgets().

Função rand()

Para gerar um número aleatório em linguagem C podemos usar a função rand pertencente à biblioteca stdlib.h.

Gerar sequências de números aleatórios é comum em programação. Sendo assim a função rand() compre seu papel em gerar números randômicos.

Quando esta função é chamada ela produz um valor aleatório na faixa entre 0 e a constante RAND_MAX. O valor desta constante encontra-se definida no arquivo stdlib.h. Para gerar valores dentro de uma determinada faixa é utilizado % (módulo) do valor.

O programa abaixo gera uma sequência com 10 números aleatórios entre 0 e 100.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
     int i;

     printf("Gerando 10 valores aleatorios:\n\n");

     for (i = 0; i < 10; i++)
     {
           /* gerando valores aleatórios entre zero e 100 */
           printf("%d ", rand() % 100);
     }
     return 0;
}

Veja também sobre o número inicial ou "semente" e a função srand() em:

http://linguagemc.com.br/valores-aleatorios-em-c-com-a-funcao-rand/

Exemplo

Desafio: Gerar 100 números aleatórios de 0 a 10 (%11) e dizer que se essa função possui uma distribuição normal.

Resposta
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
     int i, j, tam=100,vetor[tam];

     printf("Gerando %d valores aleatorios:\n\n",tam);

     for (i = 0; i < tam; i++)
     {
            vetor[i]= rand() % 11;
     }
     for (i = 0; i < 11; i++)
     {
         printf("\n%d:",i);
         for (j=0;j<tam;j++)
         {
             if (vetor[j]==i) printf("*");
         }
     }
      return 0;
}

Portanto não se trata de uma distribuição normal (Gaussiana) e sim de uma distribuição "uniforme".

Vetor de Char

É possível definir vetores do tipo char. Tais vetores permitem definir cadeias de caracteres. Para marcar um final de cadeia usa-se o número 0 (NULL),

Exemplo: Fazer um programa para computar o número de caracteres de uma cadeia (string) lida pelo teclado.Use o comando while.

#include <stdio.h>
void main ()
{
   char alfa[50];

   int i=0;

   printf ("Entre com a cadeia: ");
   gets(alfa);
   while(alfa[i]!=0)
	i++;
   printf ("\nNumero de caracteres em %s = %d \n", alfa, i);
}
Exercícios
  1. Implementar um programa que computa o número de caracteres 'a' de uma string lida pelo teclado.
    #include <stdio.h>
    void main ()
    {
       char alfa[50];
       int cont;
       int i=0;
    
       printf ("Entre com a cadeia: ");
       gets(alfa);
    
       cont=0;
       while(alfa[i]!=0){
            if (alfa[i]=='a')
                cont++;
    	i++;
       }
       printf ("\nNumero de caracteres a em %s = %d \n", alfa, cont);
    }
    
  2. Implementar um programa que computa o número de ocorrências das subcadeias "ab" de uma string lida pelo teclado.
    #include <stdio.h>
    void main ()
    {
       char alfa[50];
       int cont;
       int i=0;
    
       printf ("Entre com a cadeia: ");
       gets(alfa);
    
       cont=0;
       while(alfa[i]!=0){
            if (alfa[i]=='a' && alfa[i+1]=='b') {
                cont++;
                i++; /* avançar uma posição */
            }
    	i++;
       }
       printf ("\nNumero de subcadeias ab em %s = %d \n", alfa, cont);
    }
    
  3. Implementar um programa que substitui todos os 'o' de uma cadeia por 'O.
    #include <stdio.h>
    void main ()
    {
       char alfa[50];
       int cont;
       int i=0;
    
       printf ("Entre com a cadeia: ");
       gets(alfa);
    
       cont=0;
       while(alfa[i]!=0){
            if (alfa[i]=='o')
                alfa[i]='O';
    	i++;
       }
       printf ("\nNova cadeia -> %s\n", alfa);
    }
    
  4. Implementar um programa que lê duas cadeias e conta o número de caracteres iguais ocupando a mesma posição. Exemplo: suponha as cadeias "casa" e "amora". Não existem caracteres iguais na mesma posição. Já as cadeias "casa" e "cada" possuem três caracteres iguais na mesma posição.
Solução
#include <stdio.h>
void main ()
{
   char alfa[50], beta[50];
   int cont;
   int i=0;
 
   printf ("Entre com a cadeia:\n");
   gets(alfa);

   printf ("Entre com a cadeia:\n");
   gets(beta);
    
   cont=0;
   while(alfa[i]!=0 && beta[i]!=0){
        if (alfa[i]==beta[i])
            cont++;
	i++;
   }
   printf ("\nNumero de caracteres iguai em %s e %s na mesma posicao é %d \n", alfa, beta, cont);
}
|}
a) Modificar o exercício anterior para que os caracteres não iguais sejam intercambiados (mas continue respeitando os finais das cadeias). Exemplo: "casa" e "malagueta" deve resultar em "mala" e "casagueta"
b) Implementar um programa que lê duas cadeias e imprime uma mensagem caso as cadeias seja iguais.

Exercícios parte 1

  1. Ler um vetor de 10 números inteiros e colocar em ordem crescente.
  2. Ler um vetor de char e imprimir ao contrário os caracteres lidos. Exemplo: Marrocos >> socorraM
  3. Ler um vetor de char e trocar de minúsculas para maiúsculas. Exemplo: douglas de souza >> DOUGLAS DE SOUZA.
Solução 3
#include <stdio.h>
void main ()
{
   char alfa[50];
   int i=0;
 
   printf ("Entre com a cadeia em letras minúsculas: ");
   gets(alfa);
 
   while(alfa[i]!=0){
        if (alfa[i]!=32)		// na tabela ASCII 32 é o espaço em branco ' '.
            alfa[i]=alfa[i]-32; 	// na tabela ASCII maiúscula estão separadas de minúscula por 32.
	i++;
   }
   printf ("\nNova cadeia em maiúsculas: %s\n", alfa);
}
|}
a) Modificar o programa para que ele faça também, palavras com iniciais maiúsculas. Exemplo: douglas de souza >> Douglas De Souza.
b) Modifique o programa para que ele reconheça as ligações como: de, da, dos, e,... do nome e desconsidere. Exemplo: maria da silva >> Maria da Silva.
Solução 3.a.b (contribuição do aluno: Pablo Fidelis Dias)
#include <stdio.h>
void main ()
{
   char alfa[50];
   int i=0;
 
   printf ("Entre com a cadeia em letras minúsculas: ");
   gets(alfa);
 
   alfa [0]=alfa[i]-32;

   while(alfa[i]!=0){
        if (alfa[i]==32){
            if (!(alfa[i+1]=='d' && (alfa[i+3]==32 || alfa[i+4]==32)))
                alfa[i+1]=alfa[i+1]-32; 
        }
        i++;
   }
   printf ("\nNome: %s\n", alfa);
}
|}


Solução 2
#include <stdio.h>

int tam_string(char texto[])
{
   int i=0;
   while(texto[i]!=0) 
	i++;
   return i;
}

void main()
{
   char alfa[50],beta[50];
   int tam,i;
 
   printf ("Entre com a cadeia : ");
   gets(alfa);
   tam=tam_string(alfa);	// pega o tamanho da cadeia de caracteres
   for(i=0;i<tam;i++)		// percorre o vetor até o tamanho
	beta[i]=alfa[tam-i-1];  // como começa de 0 eu preciso fazer (tam-i-1), ou seja, o primeiro é o ultimo
   beta[i]=0;			// preciso definir o final do vetor porque não vai até o ultimo que '\0'
   printf ("\nPrimeira cadeia: %s. Nova cadeia: %s\n", alfa, beta);
}
|}


Solução 1
#include <stdio.h>
 
void mostra_vet(int vet_aux[],int tam,int tipo) // tipo=0 vertical \n tipo=1 horizontal \t
{
  int i;
 
  if(tipo==0)
	printf("\n"); // vai deixar uma linha em branco só no tipo que quero.
  for(i=0;i<tam;i++)
    if(tipo==0)
      	printf("\n%d",vet_aux[i]);
    else
	printf("\t%d",vet_aux[i]);
  printf("\n");
}


void main()
{
  int i,j,num,vet_num[10];
  printf("\nDigite os números:\n");
  for(i=0;i<10;i++){
      scanf("%d",&num);
      vet_num[i]=num;
  }
  for(j=0;j<9;j++){		// varre os (10-1) vetores - o ultimo ele não tem que comparar
          for(i=0;i<(9-j);i++){ // depois da primeira passagem o ultimo elemento já é o maior...
              if(vet_num[i]>vet_num[i+1]){ 
                num=vet_num[i];
                vet_num[i]=vet_num[i+1];
                vet_num[i+1]=num;
              }
	      mostra_vet(vet_num,10,1); // mostra tipo=1 horizontal
          }
  }
  mostra_vet(vet_num,10,0); // mostrta tipo=0 verrtical
   
}
|}

Exercícios parte 2

1. O cálculo do juro composto é dado pela seguinte equação:



Onde PV é o valor presente, n o número de períodos de aplicação, i a taxa de juros e FV o valor futuro. Elabore um programa para computar o valor futuro para uma quantia aplicada de 10000 reais, dada uma taxa e o número de anos em que o valor é aplicado.

2. Refazer o exercício anterior armazenando o valor futuro de cada ano em uma posição de um vetor valores_futuros[]. Na posição 0 armazene o valor presente.
3. Gerar um vetor de 6 posições de inteiros e preenchê-lo com 6 números randômicos correspondentes a um jogo da megasena.
4. Fazer uma função adendo ao exercício anterior para ordenar o vetor gerado.
5. Adicionar uma interface para o exercício anterior para que um usuário possa entrar com 6 números de um jogo e o sistema conferir se o jogador ganhou ou não.
6. Implementar um sistema de controle de senha que permite abrir a porta para um usuário específico (userID) com uma senha específica.
Solução 2.3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
int main(void)
{
    int i;
    printf("intervalo da rand: [0,%d]\n", RAND_MAX); // para megasena é de 1 a 60
 
    for(i=0;i<6;i++) 
        printf("Numero %d: %d\n",i, rand());  // tem que ajustar para 59+1
 
}
|}




Icone voltar.png Icone menu.png Icone prox.png