Programação I

Soluções dos exercícios da aula prática 8


Programa 1

/*
 *  a8_p1: Contador de palavras
 *
 *  Input: Uma frase escrita pelo utilizador
 * Output: Numero de palavras da frase
 */

#include <stdio.h>
#include <string.h>

main()
{
    char frase[128];
    char caracter, prox_caracter;
    int n_palavras, i;

    
    do
    {
	printf("Escreva uma frase:\n");
	gets(frase);
    }
    while ( strlen(frase) == 0 );
    
    n_palavras = 0;
    i = 0;
    
    caracter = frase[i];
    prox_caracter = frase[i+1];
    
    while (caracter != '\0') 
    {
	if ( caracter != ' ' && (prox_caracter == ' ' || prox_caracter == '\0') )
	    n_palavras++;
	
	i++;
	caracter = frase[i];
	prox_caracter = frase[i+1];
    }
    
    if (n_palavras == 0)
	printf("Nao foi escrita qualquer palavra!\n");
    else if (n_palavras == 1)
	printf("Foi escrita apenas %d palavra\n", n_palavras);
    else
	printf("Foram escritas %d palavras\n", n_palavras);
}


Programa 2

/*
 *  a8_p2: Contador de vogais
 *
 *  Input: Uma frase escrita pelo utilizador
 * Output: Numero de vogais usadas na frase
 */

#include <stdio.h>
#include <string.h>

main()
{
    char frase[128];
    char caracter;
    int n_vogais, i;


    do
    {
	printf("Escreva uma frase:\n");
	gets(frase);
    }
    while ( strlen(frase) == 0 );

    n_vogais = 0;
    i = 0;
    caracter = frase[i];
    while (caracter != '\0')
    {
	if ( strchr("AEIOUaeiou", caracter) != NULL )
	    n_vogais++;
	i++;
	caracter = frase[i];
    }

    if (n_vogais == 0)
	printf("Nao foi escrita qualquer vogal!\n");
    else if (n_vogais == 1)
	printf("Foi escrita apenas %d vogal\n", n_vogais);
    else
	printf("Foram escritas %d vogais\n", n_vogais);
}

Programa 3

#include <stdio.h>
#include <string.h>

char primeiro[40];
char ultimo[40];
char nome[80];

main()
{
  printf("Escreva o primeiro nome (nome proprio): ");
  fgets(primeiro, sizeof(primeiro), stdin);
  primeiro[strlen(primeiro)-1] = '\0';

  printf("Escreva o ultimo nome (apelido): ");
  fgets(ultimo, sizeof(ultimo), stdin);
  ultimo[strlen(ultimo)-1] = '\0';

  strcpy(nome, primeiro);
  strcat(nome, " ");
  strcat(nome, ultimo);

  printf("O nome e' %s\n", nome);
}


 Programa 4

/*
 *  a8_p4a: Formata nome completo
 *
 *  Input: Nome completo
 * Output: Nome completo formatado e num de caracteres
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define SIZE 100
#define TRUE   1
#define FALSE  0

main()
{
    char nome[SIZE], buffer[SIZE];
    char caracter;
    int i, i_substr, encontrou;
    long int e_substr;


    /* Recebe um nome completo do teclado */
    do
    {
        printf("Escreva um nome completo:\n");
        fgets(nome, sizeof(nome), stdin );
    }
    while ( strlen(nome) == 0 );
    nome[strlen(nome)-1] = '\0';

    /* Converte nome para letras maiusculas */
    for( i = 0; i < SIZE; i++ )
    {
	buffer[i] = toupper(nome[i]);
    }


    /* Retira substring "E" e "&" */
    do
    {
	encontrou = TRUE;
	if ( strstr(buffer, " E "))
	    e_substr = (long int)strstr(buffer, " E ");
	else if( strstr(buffer, " & "))
	    e_substr = (long int)strstr(buffer, " & ");
	else
	    encontrou = FALSE;

	if (encontrou == TRUE)
	{
	    i_substr = e_substr - (long int)buffer;
	    for (i = i_substr; i < SIZE-2; i++)
		buffer[i] = buffer[i+2];
	}
    }
    while(encontrou == TRUE);

    /* Retira substrings "DA", "DE", "DO" */
    do
    {
	encontrou = TRUE;
	if ( strstr(buffer, " DA "))
	    e_substr = (long int)strstr(buffer, " DA ");
	else if( strstr(buffer, " DE "))
	    e_substr = (long int)strstr(buffer, " DE ");
	else if ( strstr(buffer, " DO "))
	    e_substr = (long int)strstr(buffer, " DO ");
	else
	    encontrou = FALSE;

	if (encontrou == TRUE)
	{
	    i_substr = e_substr - (long int)buffer;
	    for (i = i_substr; i < SIZE-3; i++)
		buffer[i] = buffer[i+3];
	}
    }
    while(encontrou == TRUE);

    /* Retira substrings "DAS", "DOS" */
    do
    {
	encontrou = TRUE;
	if ( strstr(buffer, " DAS "))
	    e_substr = (long int)strstr(buffer, " DAS ");
	else if ( strstr(buffer, " DOS "))
	    e_substr = (long int)strstr(buffer, " DOS ");
	else
	    encontrou = FALSE;

	if (encontrou == TRUE)
	{
	    i_substr = e_substr - (long int)buffer;
	    for (i = i_substr; i < SIZE-4; i++)
		buffer[i] = buffer[i+4];
	}
    }
    while(encontrou == TRUE);

    printf("%s\n(%d caracteres)\n", buffer, strlen(buffer));
}

Obs: Repara que esta solução, embora de leitura simples, adopta uma análise por casos que exige várias passagens pela string para a depurar completamente das substrings "de", "do",  "das", etc. A solução que se segue, faz a mesma depuração com uma só passagem pela string original e já tira partido de uma técnica que é apanágio da programação estruturada: a definição de funções e passagens de parâmetros para funções.

/*
 *  a8_p4b: Formata nome completo
 *
 *  Input: Nome completo
 * Output: Nome completo formatado e num de caracteres
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define SIZE 100
#define TRUE   1
#define FALSE  0

/*
 *  converte a string 's' para maiusculas
 */
void maiusculas( char s[] )
{
  int i;

  for( i = 0; i < strlen(s); i++ )
    s[i] = toupper(s[i]);
}

/*
 *  converte a string 's' para minusculas
 */
void minusculas( char s[] )
{
  int i;

  for( i = 0; i < strlen(s); i++ )
    s[i] = tolower(s[i]);
}

/*
 *  verifica se um caracter e branco
 *
 *  Input: Um caracter 'c'
 * Output: TRUE se 'c' for um espaco ou um 'tab', FALSE caso contrario.
 */
int eh_branco( char c )
{
  return ( c == ' ' || c == '\t' );
}

/*
 *  salta caracteres brancos num array
 *
 *  Input: Uma string 's' e uma posicao 'k'
 * Output: Devolve a primeira posicao i (i>=k) tal que s[i] nao eh branco
 */
int salta_brancos( char s[], int k )
{
  int i = k;

  while( i<strlen(s) && eh_branco(s[i]) )
    i++;

  return (i);
}

/*
 *  Input: Uma string 's' e uma posicao 'k'.
 *         A funcao assume que s[k] nao eh um caracter branco.
 * Output: 'palavra' vai ser string que contem uma sequencia maxima
 *         de caracteres s[k..i], todos eles nao brancos.
 *         Devolve a posicao i+1
 */
int apanha_palavra( char s[], int k, char palavra[] )
{
  int i, j;

  j = 0;
  i = k;
  while( i<strlen(s) && !eh_branco(s[i]) )
    {
      palavra[j] = s[i];
      j++;
      i++;
    }
  palavra[j] = '\0';

  return (i);
}

/*
 *  Input: Uma string 's'
 * Output: TRUE se 's' eh "e", "&", "de", "da", "do", "das", "dos".
 *         FALSE caso contrario.
 *
 *   Nota: a funcao nao distingue maiusculas e minusculas.
 */
int eh_e_da_de_do_das_dos( char s[] )
{
  char temp[SIZE];

  strcpy( temp, s );
  minusculas( temp );

  return( strcmp( temp, "e")   == 0 ||
	  strcmp( temp, "&")   == 0 ||
	  strcmp( temp, "da")  == 0 ||
	  strcmp( temp, "de")  == 0 ||
	  strcmp( temp, "do")  == 0 ||
	  strcmp( temp, "das") == 0 ||
	  strcmp( temp, "dos") == 0 );
}

/*
 *  A ideia do programa eh ir engolindo as palavras uma a uma
 *  e filtrar os "de", "do", "da", etc.
 *
 *  Uma frase eh uma sequencia de:
 *         0 ou mais caracteres brancos seguida de
 *         1 ou mais caracteres nao brancos seguida de
 *         1 ou mais caracteres brancos seguida de
 *         1 ou mais caracteres nao brancos seguida de
 *         ...
 *         ...
 *         seguida de '\0'
 */
main()
{
    char nome[SIZE];          /* nome completo */
    char nomef[SIZE] = "";    /* nome formatado */
    char palavra[SIZE];
    int  i;

    /* Recebe um nome completo do teclado */
    do
    {
      printf("Escreva um nome completo:\n");
      fgets(nome, sizeof(nome), stdin );
    }
    while ( strlen(nome) == 0 );
    nome[strlen(nome)-1] = '\0';   /* -1 porque o fgets mete um '\n' */

    maiusculas( nome );
    i = 0;
    i = salta_brancos( nome, i );
    while( i < strlen(nome) )
    {
      i = apanha_palavra( nome, i, palavra );
      if( !eh_e_da_de_do_das_dos( palavra ) )
	{
	  strcat( nomef, palavra );
	  strcat( nomef, " " );
	}
      i = salta_brancos( nome, i );
    }

    /* elimina o ultimo espaco */
    if( strlen(nomef) > 0 )
      nomef[ strlen(nomef) - 1 ] = '\0';

    printf("%s\n(%d caracteres)\n", nomef, strlen(nomef) );
}


Programa 5

/*
 *  a8_p5a: Formata nome
 *
 *  Input: Nome escrito descuidadamente
 * Output: Nome escrito adequadamente
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define TRUE  1
#define FALSE 0

main()
{
    char nome[80], buffer[80];
    int i, j;
    int primeira_letra, encontrou;
    long int e_substr;

    /* Recebe uma string */
    do
    {
	printf("Escreva um nome: ");
	fgets(nome, sizeof(nome), stdin);
    }
    while ( strlen(nome) == 0 );
    nome[strlen(nome)-1] = '\0';

    /* Limpa espacos e atribui maiusculas/minusculas */
    i = 0; j = 0; primeira_letra = TRUE;
    do
    {
	    while(nome[i] != ' ' && nome[i] != '\0')
	    {
                if(primeira_letra == TRUE)
                {
                    buffer[j] = toupper(nome[i]);
                    primeira_letra = FALSE;
                }
                else
                    buffer[j] = tolower(nome[i]);
		i++; j++;
	    }

	    if (nome[i] == ' ')
	    {
	          buffer[j] = ' ';
	          primeira_letra = TRUE;
	          j++;
	    }

	    while(nome[i] == ' ')
		    i++;
    }
    while(nome[i] != '\0');
    buffer[j] = '\0';

    /* Transforma "E/Da/De/Do/Das/Dos" em "e/da/de/do/das/dos" */
    do
    {
	encontrou = TRUE;
	if ( strstr(buffer, " E "))
	    e_substr = (long int)strstr(buffer, " E ");
	else if ( strstr(buffer, " Da "))
	    e_substr = (long int)strstr(buffer, " Da ");
	else if( strstr(buffer, " De "))
	    e_substr = (long int)strstr(buffer, " De ");
	else if ( strstr(buffer, " Do "))
	    e_substr = (long int)strstr(buffer, " Do ");
	else if( strstr(buffer, " Das "))
	    e_substr = (long int)strstr(buffer, " Das ");
	else if ( strstr(buffer, " Dos "))
	    e_substr = (long int)strstr(buffer, " Dos ");
	else
	    encontrou = FALSE;

	if (encontrou == TRUE)
	{
	    i = e_substr - (long int)buffer + 1;
	    buffer[i] = tolower(buffer[i]);
	}
    }
    while(encontrou == TRUE);

    strcpy(nome, buffer);
    puts(nome);
}

Obs: Repara que também esta solução adopta uma análise que exige várias passagens pela string para a formatar conforme foi pedido. A solução que se segue, faz o mesmo com uma só passagem pela string original e voltando a tirar partido das funções desenvolvidas para o programa anterior.

/*
 *  a8_p5b: Formata nome
 *
 *  Input: Nome escrito descuidadamente
 * Output: Nome escrito adequadamente
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define SIZE 100
#define TRUE   1
#define FALSE  0

/*
 *  incluir as funcoes feitas para o problema 4.
 */



/*
 *  O programa eh quase igual ao problema 4
 */
main()
{
    char nome[SIZE];          /* nome completo */
    char nomef[SIZE] = "";    /* nome formatado */
    char palavra[SIZE];
    int  i;

    /* Recebe um nome completo do teclado */
    do
    {
      printf("Escreva um nome completo:\n");
      fgets(nome, sizeof(nome), stdin );
    }
    while ( strlen(nome) == 0 );
    nome[strlen(nome)-1] = '\0';   /* -1 por causa do '\n' */

    minusculas( nome );
    i = 0;
    i = salta_brancos( nome, i );
    while( i< strlen(nome) )
    {
      i = apanha_palavra( nome, i, palavra );
      if( !eh_e_da_de_do_das_dos( palavra ) )
      {
        /* a primeira letra da palavra passa a maiuscula */
	palavra[0] = toupper( palavra[0] );
      }
      strcat( nomef, palavra );
      strcat( nomef, " " );
      i = salta_brancos( nome, i );
    }

    /* elimina o ultimo espaco */
    if( strlen(nomef) > 0 )
      nomef[ strlen(nomef) - 1 ] = '\0';

    printf("%s\n(%d caracteres)\n", nomef, strlen(nomef) );
}

 

Programa 6

/*
 *  a8_p6: Ordena lista de N palavras
 *
 *  Input: N palavras (do teclado)
 * Output: Essas N palavras escritas por ordem crescente
 */

#include <stdio.h>
#include <string.h>

#define N 10

char nomes[N][80];

void PreencheArray(void)
{
    int i;

    printf("Escreva %d palavras (fazendo Enter apos cada palavra)\n", N );
    for (i = 0; i < N; i++)
	gets(nomes[i]);

}

void MostraArray(void)
{
    int i;

    puts("");
    for (i = 0; i < N; i++)
	printf("nomes[%d] = %s\n", i, nomes[i]);

}

void OrdenaArray(void)
{
    char min_palavra[80];
    char temp[80];
    int i, k, m;

    /* Ordenar o array */
    for( k = 0; k <= N-1; k++ )
    {
        /* descobre o indice do minimo em a[k], a[k+1], ..., a[N-1] */

        strcpy(min_palavra, nomes[k]);
        m = k;
        for( i = k; i <= N-1; i++ )
            if ( strcmp(nomes[i], min_palavra) < 0 )
            {
                strcpy(min_palavra, nomes[i]);
                m = i;
            }

         /* troca a[k] com a[m] */
         strcpy(temp, nomes[k]);
         strcpy(nomes[k], nomes[m]);
         strcpy(nomes[m], temp);
     }
}

main()
{
    /* array nomes com 'global scope' */

    PreencheArray();
    MostraArray();
    printf("\nArray em ordenacao...\n");
    OrdenaArray();
    MostraArray();
}