Mudanças entre as edições de "AULA 10 - Programação 1 - Engenharia"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 114: Linha 114:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
NOTA 1: O scanf NÃO testa se o buffer usado para leitura comporta a string. Isto pode ser uma fonte GRAVE de problemas.
+
*NOTA 1: O scanf NÃO testa se o buffer usado para leitura comporta a string. Isto pode ser uma fonte GRAVE de problemas.
NOTA 2: O scanf usa o espaço branco para separar strings na leitura. Para evitar isto pode-se usar <code>scanf("%[^\n]s",alfa) </code>
+
*NOTA 2: O scanf usa o espaço branco para separar strings na leitura. Para evitar isto pode-se usar <code>scanf("%[^\n]s",alfa) </code>
NOTA 3: A função gets pode também ser usada para leitura de strings mas a NOTA 1 se aplica também (ver discussão em  
+
*NOTA 3: A função gets pode também ser usada para leitura de strings mas a NOTA 1 se aplica também (ver discussão em  
 
[https://stackoverflow.com/questions/1247989/how-do-you-allow-spaces-to-be-entered-using-scanf] e [https://stackoverflow.com/questions/6282198/reading-string-from-input-with-space-character/6282236]). Observe que o uso de fgets é interessante para ter um controle de leitura.
 
[https://stackoverflow.com/questions/1247989/how-do-you-allow-spaces-to-be-entered-using-scanf] e [https://stackoverflow.com/questions/6282198/reading-string-from-input-with-space-character/6282236]). Observe que o uso de fgets é interessante para ter um controle de leitura.
  

Edição das 15h14min de 18 de fevereiro de 2021

Objetivos

Após esta aula o aluno deverá ser capaz de:

  • Descrever como um caracter é representado no computador e como usar a tabela ASCII para verificar a representação de caracteres em binário, decimal;
  • Reconhecer a utilidade de caracteres especiais tais como o NUL e o NEWLINE;
  • Entender o que é uma string;
  • Construir definições/declarações de vetores de char no C e iniciar estes vetores com strings;
  • Construir código em C para processamento básico de strings armazenadas em vetores, usando indexação;
  • Construir funções que recebem como parâmetro vetores de char e utilizar o passagem por referência (endereço);

Revisando o Tipo Char

Em aulas anteriores vimos 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

Nesta seção vamos discutir como armazenar caracteres em variáveis que apresentam-se como um vetor.

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 ou '\0' (note que não o caracter '0' que é o número 48 decimal em ASCII. Trata-se do inteiro 0 ou caracter NUL do ASCII que é representado como '\0'). Em inglês chama-se "string null terminated".

NOTA: O zero no final da string é uma forma de indicar que a mesma termina sem necessidade de armazenar o tamanho dela (algumas linguagens fazem isto).


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

ExplicacaoString1.jpg

Estamos assumindo que cada caracter é armazenado em um byte. Uma string terminada em 0 facilita o seu processamento pois pode-se facilmente detectar o seu final. Note que no exemplo acima, 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.

DADOS DE ENTRADA: cadeia de caracteres (string)

DADOS DE SAÍDA: tamanho da string

FluxogramaContadorCaracteresCadeia.jpg


Vetor de char no C

É possível definir vetores do tipo char. Tais vetores permitem armazenar cadeias de caracteres. Para marcar um final de cadeia usa-se o número 0 (NULL). A função scanf pode ser usada para ler strings tal como indicado no exemplo abaixo:

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>
int main ()
{
   char alfa[50];

   int i=0;

   printf ("Entre com a cadeia: ");
   scanf("%s",alfa);
   while(alfa[i]!=0)
      i++;
   printf ("\nNumero de caracteres em %s = %d \n", alfa, i);
   return 0;
}
  • NOTA 1: O scanf NÃO testa se o buffer usado para leitura comporta a string. Isto pode ser uma fonte GRAVE de problemas.
  • NOTA 2: O scanf usa o espaço branco para separar strings na leitura. Para evitar isto pode-se usar scanf("%[^\n]s",alfa)
  • NOTA 3: A função gets pode também ser usada para leitura de strings mas a NOTA 1 se aplica também (ver discussão em

[1] e [2]). Observe que o uso de fgets é interessante para ter um controle de leitura.

Existe uma sequência de controle mais flexível que o %s: o %[].

Ver em [3]


Vetor de Char Inicializado com String

Note que é possível criar um vetor já iniciado com uma string. Ver o exemplo abaixo:

#include <stdio.h>
void main ()
{
   char alfa[50]="IFSC-SJ";

   int i=0;

   while(alfa[i]!=0)
	i++;
   printf ("\nNumero de caracteres em %s = %d \n", alfa, i);
}

Passando a string como parâmetro

A função abaixo permite computar o tamanho de uma string. Observe que tudo que foi comentado quanto a passagem de parâmetro continua valendo. O vetor teste é passado como "referência", ou seja, o vetor x, na chamada da função str_len() vai operar sobre o vetor teste. Para computar o tamanho da string, cada elemento do vetor será compara com 0. Caso não seja, a variável i será incrementada.


#include <stdio.h>

int str_len(char x[])
{
  int i=0;
  while (x[i]!=0)
    i++;
  return i;
}
 
void main()
{
  char teste[]="IFSC-SJ";
  int tamanho;
 
  tamanho = str_len(teste);  
  printf("O tamanho da String %s eh: %d\n", teste, tamanho);
}

Exercícios

  1. Escreva um algoritmo que leia 5 caracteres do teclado, e depois mostre-os em ordem inversa à que foi digitada.
    Solução - Exercício 01
    //Autor: Victor Cesconetto De Pieri
    #include<stdio.h>
    
    void main()
    {
    
      char vet[5];
      int i;
    
      for(i=0;i<5;i++){
          printf("Digite um numero : \n");
          scanf(" %c", &vet[i]);
      }
      printf("Imprimindo os numeros : \n");    
      for(i=4;i>-1;i--){
          printf("%c\n", vet[i]);
      }
    }
    
  2. Implementar um programa que computa o número de caracteres 'a' de uma string lida pelo teclado.
    Solução - Exercício 02
    //Autor : Victor Cesconetto De Pieri
    #include <stdio.h>
    void main ()
    {
       char alfa[50];
       int cont;
       int i=0;
    
       printf ("Entre com a cadeia: ");
       scanf("%s",alfa);
    
       cont=0;
       while(alfa[i]!=0){
            if (alfa[i]=='a')//verifica a ocorrencia do caracter 'a' no vetor de caracteres
                cont++;
    	i++;
       }
       printf ("\nNumero de caracteres a em %s = %d \n", alfa, cont);
    }
    
  3. Implementar um programa que computa o número de ocorrências das subcadeias "ab" de uma string lida pelo teclado.
    Solução - Exercício 03
    //Autor : Victor Cesconetto De Pieri
    #include <stdio.h>
    void main ()
    {
       char alfa[50];
       int cont;
       int i=0;
    
       printf ("Entre com a cadeia: ");
       scanf("%s",alfa);
    
       cont=0;
       while(alfa[i]!=0){
            if (alfa[i]=='a'&&alfa[i+1]=='b') {//verifica se o caracter na posicao "i" corresponde a 'a' e o proximo(i+1) corresponde a 'b'
                cont++;
                i++; //avançar uma posição
            }
    	i++;
       }
       printf ("\nNumero de subcadeias ab em %s = %d \n", alfa, cont);
    }
    
  4. Implementar um programa que substitui todos os 'o' de uma cadeia por 'O.
    Solução - Exercício 04
    //Autor : Victor Cesconetto De Pieri
    #include <stdio.h>
    void main ()
    {
       char alfa[50];
       int i=0;
    
       printf ("Entre com a cadeia: \n");
       scanf("%s",alfa);
    
       i=0;
       while(alfa[i]!=0){
            if (alfa[i]=='o')
                alfa[i]='O';
    	i++;
       }
       printf ("Nova cadeia : %s\n", alfa);
    }
    
  5. 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 - Exercício 05
    //Autor : Victor Cesconetto De Pieri
    #include <stdio.h>
    void main ()
    {
       char alfa[50], beta[50];
       int cont;
       int i=0;
     
       printf ("Entre com a cadeia:\n");
       scanf("%s",alfa);
    
       printf ("Entre com a cadeia:\n");
       scanf("%s",beta);
        
       cont=0;
       while(alfa[i]!=0 && beta[i]!=0){
            if (alfa[i]==beta[i])//verifica se sao iguais, se sim soma 1 ao contador.
                cont++;
    	i++;
       }
       printf ("Numero de caracteres iguai em %s e %s na mesma posicao é %d \n", alfa, beta, cont);
    }
    
  6. 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"
  7. Solução - Exercício 06
    //Autor : Victor Cesconetto De Pieri
    
    #include <stdio.h>
    void main ()
    {
       char alfa[50], beta[50],aux,aux2;
       int cont;
       int i=0;
     
       printf ("Entre com a cadeia:\n");
       scanf("%s",alfa);
     
       printf ("Entre com a cadeia:\n");
       scanf("%s",beta);
     
       cont=0;
       while(alfa[i]!=0 && beta[i]!=0){
            if (alfa[i]==beta[i]){
                cont++;
    		}else{
    			aux = alfa[i];//conteudo da posição "i" de alfa para aux
    			aux2 = beta[i];//conteudo da posicao "i" de beta para aux2
    			beta[i] = aux;//aux que contem o conteudo de alfa sendo passado para beta na posicao "i"
    			alfa[i] = aux2;//aux2 que contem o conteudo de beta sendo passado para alfa na posicao "i"
    		}
    	i++;
       }
       printf ("\nalfa: %s beta: %s N de caracteres iguais: %d \n", alfa, beta, cont);
    }
    
  8. Implementar um programa que lê duas cadeias e imprime uma mensagem caso as cadeias seja iguais.
  9. Solução - Exercício 07
  10. Elaborar uma função para copiar uma string que está em um vetor de char para outro vetor. Fazer um exemplo de uso no main.
    #include <stdio.h>
    
    void str_cpy(char dest[],char fonte[])
    {
    }
    
    main()
    {
      char alfa[30],beta[30]="IFSC";
    
      str_cpy(alfa,beta);
      printf("%s\n", alfa);
    }
    
    Solução - Exercício 08
    //Autor : Victor Cesconetto De Pieri
    
    #include <stdio.h>
     
    void str_cpy(char dest[],char fonte[])
    {
      int i=0;
      do
         dest[i] = fonte[i];//passa o conteúdo da posição "i" do vetor fonte para o vetor dest
      while(fonte[i++]!=0); 
    }
     
    int main()
    {
      char alfa[30],beta[30]="IFSC-SJ";
     
      str_cpy(alfa,beta);
      printf("%s\n", alfa);
      str_cpy(alfa,"Teste");
      printf("%s\n", alfa);    
    }
    
  11. Fazer uma variação do str_cpy que retorna um inteiro correspondente ao tamanho da string copiada. Mostrar o funcionamento da função no main.
  12. Solução - Exercício 09
    //Autor: Victor Cesconetto De Pieri
    
    #include <stdio.h>
     
    int str_cpy(char dest[],char fonte[])
    {
      int i=0;
      do
         dest[i] = fonte[i];
      while(fonte[i++]!=0);
      return i-1;//numero de loops-1 corresponde ao tamanho da "string" copiada
    }
     
    main()
    {
      char alfa[30],beta[30]="IFSC";
      int tamanho;
      
      tamanho = str_cpy(alfa,beta);
      printf("%s %d\n", alfa, tamanho);
      tamanho = str_cpy(alfa,"Teste");
      printf("%s %d\n", alfa, tamanho);    
    }
    
  13. Fazer uma função que copia string mas que torna maiúsculo caracteres que estavam em minúsculo na string fonte.
  14. Solução - Exercício 10
    //Autor: Victor Cesconetto De Pieri
    
    #include <stdio.h>
    
    void str_caps(char dest[],char fonte[])
    {
    	int i=0;
    	do{
    		dest[i] = fonte[i]-32;//o caracter 'a' = 97 na tabela ascii e o 'A' = 65 na tabela ascii, apenas subtraindo o inteiro 32 conseguimos trocar a letra de minuscula para maiuscula.
    	}while(fonte[i++]!=0);	
    }
    
     
    main()
    {
      char alfa[30],beta[30]="aluno";
     
      str_caps(alfa,beta);
      printf("%s\n", alfa);
          
    }
    
  15. Fazer uma função que concatena duas strings colocando a segunda string no final da primeira. Mostrar o funcionamento da função no main.
  16. #include <stdio.h>
    
    void str_cat(char str1[], char str2[])
    {
    }
    main()
    {
     char alfa[30]="Alo", beta[20]=" mundo";
     
     str_cat(alfa,beta);
     printf("%s\n", alfa);
     str_cat(alfa," cruel");
    }
    
    Solução - Exercício 11
    //Autor: Victor Cesconetto De Pieri
    
    #include < stdio.h > 
    #include < string.h > //para o uso da funcao strlen() é necessario declarar sua lib.
    
      void str_cat(char str1[], char str2[]) {
        int i = 0;
        do {
          str1[strlen(str1)] = str2[i]; //strlen() pega o tamanho da string, cada vez que é adicionado um caracter ele aumenta(tamanho).
          // Entao é só adicionar a cadeia de caracter "str2" ao final da "str1" que estaremos concatenando as strings.
        } while (str2[i++] != 0);
      }
    main() {
      char alfa[30] = "Voce é", beta[20] = " um";
    
      str_cat(alfa, beta);
      printf("%s\n", alfa);
      str_cat(alfa, " vencedor");
      printf("%s\n", alfa);
    }
    
  17. Fazer uma função que recebe como parâmetro uma string. Esta função deve remover a primeira vogal presente nesta string (da esquerda para a direita). Esta função deve também retornar o número de caracteres da string sem a vogal. Apresente na função main() um exemplo de funcionamento da função, usando o seu primeiro nome. Siga o esqueleto mostrado abaixo:
    /* o vetor x contém a string a ser processada */ 
    int remove_caracter(char x[])
    {
    }
    
    int main()
    {
      /* fazer um exemplo aqui usando o seu primeiro nome como teste */
      return 0;
    }
    

    Exemplo de possível saída:

    • Foi passada a string "ifsc". Após a chamada da função, a string será "fsc". A função retorna 3.
    • Foi passada a string "delta". Após a chamada da função, a string será "dlta". A função retorna 4.
  18. Implementar uma função para remover os n primeiros caracteres de uma string. Se preferir use o esqueleto da função abaixo.
    #include <stdio.h>
    #include <string.h>
    
    int remove_n_char(char x[], int n)
    {
        int tam, i;
        /* remover os n primeiros caracteres da string armazenada em x[]
        */
    
        tam = strlen(x);
        if (n>=tam) { /* se n for maior ou igual ao tamanho da string então deixar string NULL */
            tam = 
        } else {
            tam = tam - n;  /* ajusta o tamanho da nova string, descontando os n caracteres */
            /* fazer um loop para deslocar tam caracteres a esquerda */
            /* ajustar o final da string */
        }
        return tam;
    }
    int main()
    {
        char nome[10]="IFSC-SJ";
        int tam;
    
        tam = remove_n_char(nome, 2);
        printf("%s - Tamanho %d\n", nome, tam); /* deve imprimir:  SC-SJ 5 */
    
        /* testar a função aqui usando o seu primeiro nome */
        return 0;
    }