Programação Imperativa
Aula Prática 7- Soluções
(as seguintes, são UMA solução possível a estes exercicios)

1 e 2. Escreve um programa que atribuí números aleatórios a um array de duas dimensões de 5 por 4 elementos e que apresenta esses números no ecrã por colunas. No fim apresenta também o maior e o menor dos números aleatórios geridos.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define COLS 4
#define LINHAS 5

long int a1[LINHAS][COLS];
long int min, max;

void carrega_array_um_indice(int linhas, int cols)
{
  for (int j=0; j < linhas; j++)
    for (int i=0; i < cols; i++)
    {
      a1[j][i] = random(7011) + (random(3023) / 3);
      if (a1[j][i] < min)
        min = a1[j][i];
      if (a1[j][i] > max)
        max = a1[j][i];
    }
}

void imprime_array(int lin, int col)
{
  printf("\nconteudo do array: \n");
  for (int j=0; j < lin; j++)
  {
    printf("\n");
    for (int i=0; i < col; i++)
      printf("%10li  ", a1[j][i]);
  }
  printf("\n\nValores min = %li, e max = %li", min, max);
}

/*---------------------------------------------*/
void main()
{
  int min = 999999L; max = -1;
  randomize();
  carrega_array_um_indice(LINHAS, COLS);
  imprime_array(LINHAS, COLS);
}


3. Escreve um programa que ordena uma lista de N números. N pode ir no máximo até 100.
/* TP7 exercicio 3
 ordenar numeros de menor a maior num array estatico de 1 dimensao
 utiliza metodo de ordenacao da burbulha ("bubble") 'esperto' (porque?) */
#include <stdio.h>
#include <stdlib.h>

#define TAM   100
int a[TAM];    /*definimos array de 1 dimensão */
   /* variavel global */

void inicializa_array(const int tam)
{
  for (int j=0; j < tam; j++)
    a[j] = 0;
}

void carrega_array(const int t)
{
  srand(1);
  for (int j=0; j < t; j++)
  if (j % 2)
    a[j] = random(20001/3) + (random(1103) / (random(57) +1));
  else
    a[j] = random(1001/2) + (random(1703) / (random(23) + 1) );
}

void ordena_array(const int N)  /*método de burbulha */
{
  int k, i;

  for (k = 0; k < N; k++)         /*controla ciclo de tudas as passadas */
  {
    for (i = 0; i < (N-k-1); i++) /*controla uma passada de comparações */
    {
      if (a[i] > a[i+1])          /*termina nos elementos ja ordenados*/
      trocar(&a[i], &a[i+1]);
    }
  }
}

void trocar(int *primeiro, int *segundo)
   /*troca primeiro pelo segundo*/
   /*passagem de parâmetros por referência */
{
  int temp;
  temp      = *segundo;
  *segundo  = *primeiro;
  *primeiro = temp;
}

void imprime_array(const int t, char vez)
{
  if (vez == '1')
    printf("\n\nconteudo do array ANTES de ser ordenado: \n");
  else
    printf("\n\nconteudo do array DEPOIS de ser ordenado: \n");
  for (int j=0; j < t; j++)
  {
    if (!(j % 8)) printf("\n");
      printf("%7i  ", a[j]);
  }
}

void main()
{
  inicializa_array(TAM);
  carrega_array(TAM);
  imprime_array(TAM, '1');
  ordena_array(TAM);
  imprime_array(TAM, '2');
}


4. Escreve um programa que registe o sexo e a idade de um grupo de dez pessoas. Em seguida o programa deve apresentar a média das idades de cada sexo.
/* TP7, N§ 4.
 array estatico para sexo e idade de 10 pessoas, apresentando a media
 este pgm demostra como podemos armazenar um tipo de dado na B de D e
 amostrar ao utilizador os dados numa outra forma.*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LINHAS  10
#define COLS    2   /* col 1: idade, col 2: sexo
 

int pessoas[LINHAS][COLS];  /*definimos 1 so array para idades e sexo    */
int NUM, total;
 

void limpar_arrays(int linhas, int cols)
{
  for (int j=0; j < linhas; j++)
    for (int i=0; i < cols; i++)
      pessoas[j][i] = 0;   /*exemplo de limpar um char de vez */
  NUM = 0; total = 0;   /*inicializar valores e sempre muito importante!! */
}

void carrega_arrays(int linhas)
{
  char sexc;
  printf("\nVamos carregar a idade e sexo de 10 pessoas:");
  for (int j = 0; j < linhas; ++j)
  {
    printf("\nSexo('F'/'M'): ");
    sexc = toupper(getche());
    pessoas[j][1] = armazena_sexo(sexc);
    printf(" Idade: ");
    scanf(" %i", &pessoas[j][0]);
    total = (float) total + pessoas[j][0];
    NUM++;
  }
}

int armazena_sexo(char letra_sexo)
  /*converte de letra para numero */
{
  return (letra_sexo == 'F');   /*devolve 1 para F e 0 para M */
}

void imprime_arrays(int lin)
{
    /* declaracao de uma funcao local: */
  char cvt(int tipo)    /*desconverte de numeros para letras */
  {
    if (tipo == 1)
      return 'F';
    else
      return 'M';
  }

  printf("\n\n  Listagem de pessoas indicando sexo e idade: ");
  for (int j=0; j < lin; j++)
    printf("\n%d)Idade:%i, sexo: %c",j+1, pessoas[j][0], cvt(pessoas[j][1]));
    /*agora imprimimos a media das idades: */
  printf("\nMedia das idades= %.2f", (float)(total / NUM));
}

void main()
{
  limpar_arrays(LINHAS,COLS);
  carrega_arrays(LINHAS);
  imprime_arrays(LINHAS);
}


5. Técnica de passagem por referência.
Qual será o output do programa antes e após esta mudançã?
versão com parâmetros por referência:

#include <stdio.h>

int quadrado(int *x)
{
  *x = 2 * *x;
  return(*x);
}

void main()
{
  int a, b;

  a = 10.0;
  b = quadrado(&a);
  printf("%a", a);
}


6. Escreve uma função que recebe como parâmetros a largura e comprimento de um rectângulo. A função deve calcular e devolver os seguintes pontos
   1: a área do rectângulo (lado vezes lado).
   2: o perímetro (somar os quatro lados).
A função não pode usar variáveis globais!
(Nota: porque a informação a retornar são dois valores, temos de usar ponteiros (passagem por referência). Veja aulas 15 e 14.)

#include ....

void area_e_peri(float x, float y, float *area, float *peri)
{
  *area = x * y;
  *peri = 2*(x + y);
}

void main()
{
  float a, b;
  float ar, pe;

  printf("Largo:  ");
  scanf("%f", &a);
  printf("Altura:  ");
  scanf("%f", &b);
  area_e_peri(a, b, &ar, &pe);
  printf("\nArea = %.2f, Perimetro = %.2f", ar, pe);
}


7.
void double10(double *dp)
{
  *dp = 10.0;
}

void main()
{
  float y=10.0;
  float x=10.0;

  double10((double *) &x);
  printf("%f %f\n", x, y);
}
O programa acima não corre bem (o output não será 10.0 10.0). Experimente e elimine o erro.
(aula relevante: 15)
SOLUÇÃO: Este pgm. está a misturar os tipos. Na função o parâmetro está definido como 'double', mais
a chamada  a função está a ser feita com um 'float'. Portanto, utilizar o mesmo tipo nas duas.


8. Na aula prática 3, o exercicío 8 consistia no seguinte: Faz um programa que recebe 10 valores inteiros e que indica: Quantos são pares, quantos são ímpares, quantos são positivos e quantos são negativos. Volta a escrever o programa, utilizando arrays.

/*programa para calcular numeros pares, impares, pos e neg num array.
  a rotina mostra tb. como passamos por referência um array de inteiros. */
#include <stdio.h>
#include <math.h>
#define MAX 5

int Pares(const int N)
  /*devolve 1 se N e par */
{
  if (N == 0)
    return 0;
  else
    return ((N % 2) == 0);
}

int Positivos(const int n)
  /*devolve 1 se n e positivo */
{
  return (n >= 0);
}

void imprime_resultados(int par, int pos, int max, int *nums)
{
  printf("\nOs números armazenados são:\n");
  for (int i=0; i < max; i++)
    printf("%d  ", nums[i]);

  printf("\nEm %d numeros, %d sao par(es), %d impar(e)s, %d positivo(s)\
    %d negativo(s)", max, par, (max-par), pos, (max-pos));
}

void main()
{
  int par = 0, positivo = 0;
  int numeros[MAX];         /*array para guardar os 10 numeros */

  printf("\nPrograma para calcular numeros pares, impares\
     positivos e negativos en 10 números\n");
  for (int i = 0; i < MAX; i++)
  {
    printf("%d) = :", i+1); scanf("%i", &numeros[i]);
    par += Pares(numeros[i]);
    positivo += Positivos(numeros[i]);
  }
  imprime_resultados(par, positivo, MAX, &numeros[0]);
}


9. Volta a fazer o exercício de contar 0s e 1s de um byte binário, com arrays.
/*este programa converte um decimal inteiro num array
  para qualquer outra base */
#include <stdio.h>

void conversao(const int max, int N, char *out)
    /*funcao para convertir o inteiro em binário num array.
      A passagem do array unidimensional e com um ponteiro */
{
  char modulo(int N)   /*funcao local: se nao há resto, devolve 0; senão 1 */
  {
    if ((N % 2) == 0)
      return '0';
    else
      return '1';
  }
  int n = N, indice = max-1;

  while (n >= 2)             /*enquanto o numero não estiver convertido */
   {out[indice] = modulo(n);  /*obtem o modulo (n % 2) e guarda no array */
    n = (n / 2);          /*tira do num o último dígito pela direita */
    indice--;            /*muda o indice para apontar pxmo esq. no array */
   }
 out[indice] = modulo(n);  /*o último n pode ser um 1!! */
}

void print_numero(const int max, char *e)
{
  for (int x = 0; x < max; x++)
    printf("%c", e[x]);
}

void limpar_numeros(int maximo, int *N, char *array)
{
  for (int x = 0; x < maximo; x++)
    array[x] = '0';
  *N = 0;
}

void main()
{
  int numero;                /* aqui vamos guardar o input */
  char binario[8];           /* output estara num array */
  char r = 's';
  char *ptr = &binario[0];   /*ptr aponta ao inicio do array de output */

  while (r != 'n')
  {
    limpar_numeros(8, &numero, ptr);
    printf("\nNúmero decimal a convertir: ");   scanf("%d",&numero);
    conversao(max, numero, ptr);
    printf("\nnumero: %u na base %d :",  numero, 2);
    print_numero(max, ptr);
    printf("\n\nDeseja continuar ((s/n): "); r = getche();
  }
}


11. Fazer um programa que apresente uma tabela de conversão de decimal para binário:

/*este programa apresenta uma tabela de decimais e o correspondente
  numero binario */
#include <stdio.h>

char modulo(int N)   /*se nao ha resto, devolve 0; senao 1 */
{   if ((N % 2) == 0)
    return '0';
    else return '1';
}

void print_numero(const int max, char *e)
{
  for (int x = 0; x < max; x++)
    printf("%c", e[x]);
}

void limpar_numeros(int maximo, int *N, char *array)
{
  for (int x = 0; x < maximo; x++)  array[x] = '0';
  *N = 0;
}

void control_de_linha(int n) /* controla salto de linhas no ecrÆ */
{
  if ((((n+1) % 5) == 0) && (n > 0))
    printf("\n");
  else printf(" ");
}

void conversao(const int max, int N, char *out)
    /*funcao para convertir o inteiro em binario num array.
      A passagem do array unidimensional e com um ponteiro */
{
  char modulo(int N);         /*funcao local a esta funcao. */
  int n = N, indice = max-1;

  while (n >= 2)              /*enquanto o numero nao esta convertido */
  {
    out[indice] = modulo(n);  /*obtem o modulo (n % 2) e guarda no array */
    n = (n / 2);              /*tira do num o ultimo digito pela direita */
    indice--;                 /*muda o indice para apontar pxmo esq no array */
  }
 out[indice] = modulo(n);     /* o ultimo n pode nao ser maior que 2 */
}

void main()
{
  int numero;                 /* aqui vamos guardar o input */
  char binario[max];          /* output estara num array */
  char *ptr = &binario[0];    /*ptr aponta ao inicio do array de output */
 
  for (int num=0; num <= 119; num++)
  {
    limpar_numeros(max, &numero, ptr);
    conversao(max, num, ptr);
    printf("%3d= ",num);
    print_numero(max, ptr);
    control_de_linha(num); /*cada 5 cols saltamos uma linha */
  }
}



12. Agora guardar o vosso trabalho. O seguinte programa destroi o Operating System.

#include <stdlib.h>
void main()
{
  int i;
  int *p;

  for (i=0; i<=10000; i++)
   {
     p = (int *) rand();
     *p = 0;
   }
}
(Você vai executar este programa da sua propria responsabilidade. Porque o computador vai  congelarse.   Pode destruir o sistema operativo, e por acaso, o próprio hardware.
MELHOR NÃO FAZER MOÇOS!!