Programação 23/24 S2

Teste

Autores
Afiliação
Data de Publicação

Invalid Date

Informações gerais

Regras

  • Podem consultar a folha de consulta previamente distribuida - em formato físico.
  • Pode resolver o teste a lápis.
  • A resolução do teste é individual.
  • Não podem sair da sala durante o teste.
  • Além do material estritamente necessário para resolver o teste, não podem ter mais nada em cima da mesa.

Cotação

  • [5 valores] - Parte 1
    • Cada pergunta vale 1 valor
    • Repostas erradas descontam 25% do seu valor
      • Pergunta com 1 resposta, resposta errada desconta 0.25 valores
      • Pergunta com 2 respostas, cada resposta errada desconta 0.125 valores
      • etc.
  • [14 valores] - Parte 2
    • [2.5 valores] - Problema 1
    • [2.5 valores] - Problema 2
    • [5 valores] - Problema 3
    • [5 valores] - Problema 4

Parte 1

Pergunta 1 (1 resposta)

//funcao para a media
int func(int n, int array[n]) {
    int soma = 0;
    for (int i = 0; i < n; i++) {
        soma += array[i];
    }
    return soma / n;
}

Esta função:

  1. Devolve a média dos elementos de um array de inteiros de tamanho n.
  2. Não compila porque o tamanho do array não pode ser passado como argumento.
  3. Não compila porque porque não há salvaguarda para prevenir divisão por 0.
  4. Devolve calcula a soma dos elementos de um array de inteiros de tamanho n.

Pergunta 2 (2 respostas)

int prod(int n, int array[n]) {
    int total = 0;
    for (int i = 0; i < n; i++)
        total *= array[i];
}

Esta função pretende devovler o produto dos elementos de um array de inteiros de tamanho n. A função:

  1. Não está correcta porque não devolve nenhum valor.
  2. Está bem implementada.
  3. Não está correcta porque não tem chavetas { } no ciclo for.
  4. Não está correcta porque a variável total não está inicializada corretamente inicializada.

Pergunta 3 (1 resposta)

void funcao(int val) {
    val = 1;
}

int main() {
    int x = 2;
    funcao(x);
    return 0;
}

No final da execução do seguinte código, qual é o valor da variável x? (1 resposta)

  1. 0
  2. 1
  3. 2
  4. 10
  5. Nenhuma das respostas anteriores.

Pergunta 4 (1 resposta)

Considera o seguinte programa:

int main() {
    int array[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    for (int i=0; i<10; i++) {
        val = array[i];
        if (i % 2 == 0) val += i;
        printf("%d ", val);
    }
}

Output do programa:

  1. 1 1 2 1 3 1 4 1 5 1
  2. 1 1 2 1 3 1 4 1 5 1
  3. 1 2 3 4 5 6 7 8 9 10
  4. 1 1 3 1 5 1 7 1 9 1

Pergunta 5 (1 resposta)

Considera o seguinte programa:

typedef struct
{
    int x;
    int y;
    char c; // c=0 inativo, c=1 ativo
} Ponto;

typedef struct
{
    int n;
    Ponto pontos[100];
} Pontos;

void filter(Pontos pontos, int n) {
    for (int i = 0; i < n; i++)
        if (pontos.pontos[i].y < pontos.pontos[i].x)
            pontos.pontos[i].c = 0;

}

Escolhe a resposta correcta:

  1. A função filter não altera o array original, porque recebe uma cópia do registo Pontos, e não um apontador para o Pontos original.
  2. A função filter muda o array original de forma a que todos os pontos abaixo da diagonal principal y=x fiquem inactivos.
  3. A função filter muda o array original de forma a que todos os pontos acima da diagonal principal y=x fiquem inactivos.
  4. A função não faz nada porque o ciclo não tem chavetas { }.
  5. Nenhuma das respostas anteriores.

Parte 2

Problema 1

  • Considera as 2 variantes de um programa que incrementa os valores de uma matriz.

    typedef struct {
        float valores[100][100];
        int ncols, nrows;
    } Matriz;
    
    Matriz incrementa_matriz1(Matriz m) {
        for (int i = 0; i < m.nrows; i++) {
            for (int j = 0; j < m.ncols; j++) {
                m.valores[i][j]++;
            }
        }
        return m;
    }
    
    int programa1() {
        Matriz m = = {{{0}}, 3, 3}; // matriz 3x3 com zeros
        incrementa_matriz1(m);
        // imprimir matriz
        for (int i = 0; i < m.nrows; i++) {
            for (int j = 0; j < m.ncols; j++)
                printf("%f ", m.valores[i][j]);
            printf("\n");
        }
    }
    
    void incrementa_matriz2(Matriz * m) {
        for (int i = 0; i < m->nrows; i++) {
            for (int j = 0; j < m->ncols; j++) {
                m->valores[i][j]++;
            }
        }
    }
    
    int programa2() {
        Matriz m = = {{{0}}, 3, 3}; // matriz 3x3 com zeros
        incrementa_matriz2(&m);
        // imprimir matriz
        for (int i = 0; i < m.nrows; i++) {
            for (int j = 0; j < m.ncols; j++)
                printf("%f ", m.valores[i][j]);
            printf("\n");
        }
    }
  1. O output das duas funções (programa1 e programa2) é o mesmo (Sim/Não)? [1.5 val]
    • Escreve o output de cada um dos programas (se forem iguais, basta escrever de um deles).
  2. Qual é a vantagem de passar o registo Matriz por referência como no programa2, invés de por valor como no programa1? [1 val]

Problema 2

  • Considera o seguinte código.
#include <stdio.h>
#include <string.h>
#define MAX_STRINGS 100

char *nomes_proprios[] = {
    "Maria", "Joao", "Ana", "Pedro", "Carla", "Jose",
    "Margarida", "Miguel", "Sofia", "Ricardo"
};

void print_com_filtro_char(int n_strings, char nomes[n_strings][MAX_STRINGS], char c1, char c2) {
    for (int i = 0; i < n_strings; i++)
        if (nomes[i][0] == c1 || nomes[i][strlen(nomes[i])-1] == c2)
            printf("%s\n", nomes[i]);
}

int main() {
    print_com_filtro_char(5, nomes_proprios, 'M', 'a');
    return 0;
}
  1. [1 val] Indica o output do programa na consola.
  2. [1.5 val] Explica o que o programa está a fazer.

Problema 3 - Cálculo dos limites para histograma

  • Escreve uma função chamada calcular_limites que recebe
    • um array de reais (vals) e o seu tamanho (n);
    • um array de reais (limites) e o seu tamanho n_bins+1;
  • O objetivo da função é delimitar os intervalos dos valores de vals em n_bins intervalos.
  • Para isso é necessário percorrer todo o especto de valores de vals em intervalos regulares, e.g.
    • para vals[] = {-5, 1, -2, 3, 6, 15} (valores podem não estar ordenados!) e n_bins = 4;
    • limites seria {-5, 0, 5, 10, 16};
    • porque o valor minimo é -5, o valor máximo é 15, e como queremos 4 intervalos, dividimos \frac{max - min}{n\_bins} = 5 para obter a largura de cada um dos n\_bins+1=5 intervalos;
    • como os intervalos são fechados à esquerda e abertos à direita, somamos 1 ao valor máximo para garantir que o último intervalo inclui o valor máximo;
    • se “desenrolarmos” o vetor limites, teríamos os seguintes intervalos [-5, 0[, [0, 5[, [5, 10[, [10, 16[.

Problema 4 - Histograma

  • Escreve uma função chamada calcular_histograma que devolve um inteiro e recebe
    • um array de reais (vals) e o seu tamanho (n);
    • um apontador de registo do tipo Histograma. Este registo tem os seguintes campos:
      • o número de intervalos do histograma (n_bins);
      • um array de inteiros (counts) para contar o número de elementos que existe em cada intervalo
        • o conteúdo útil deste vetor ocupa n_bins elementos;
        • assume-se que este vetor não foi previamente inicializado;
      • um array de reais (limites) para indicar os limites de cada intervalo de valores
        • o conteúdo útil deste vetor ocupa n_bins+1 elementos;
      • um inteiro limites_init que indica se os limites já foram calculados (1) ou não (0);
  • O objetivo da função é calcular o histograma dos valores do vetor vals.
  • Um histograma conta o número de elementos que se encontram em cada intervalo de valores (definido pelo vetor limites), e.g. 
    • para vals[] = {-5, 1, -2, 3, 6, 15}
    • e limites[] seria {-5, 0, 5, 10, 16}
    • e counts seria {2, 2, 1, 1}, porque há 2 elementos em [-5,0[, 2 em [0,5[, 1 em [5,10[ e 1 em [10,16[.
  • Se os limites ainda não foram calculados, a função devolve 1. Caso contrário, devolve 0.
#define MAX_BINS 100
typedef struct {
    int n_bins;
    int limites_init; // 0 se os limites não foram calculados, 1 se foram calculados
    int counts[MAX_BINS];
    float limites[MAX_BINS+1];
} Histograma;