Variáveis indexadas;

Variáveis indexadas

Variáveis indexadas

Variáveis indexadas

Declarações

   int a[4], b[5];
   #define SIZE 10
   ...
   
   int a[SIZE], b[SIZE+1];

Indexação

   a[i] = 1;
   printf("%d", a[i]);
   ++ a[i];

Indexação

for(i = 0; i < N; i++) // Colocar zeros
    a[i] = 0;

for(i = 0; i < N; i++) // Ler valores
   scanf("%d", &a[i]);

soma = 0;
for(i = 0; i < N; i++) // Somar elementos
    soma += a[i];

Índices válidos

Onde está o erro?

int main(void) {
   int a[10], i;
   
   for(i = 0; i <= 10; i++)
       a[i] = 0;
   ...
}

Indexação

  a[i+j*10] = 0;
  i = 0;
  while (i < N)
     a[i++] = 0;

Inicialização

   int a[5] = {1, 2, 3, 4, 5};

Inicialização

   int a[10] = {1, 2, 3, 4, 5};
     /* valores iniciais são
        {1, 2, 3, 4, 5, 0, 0, 0, 0, 0} */
   int a[10] = {0};
     /* valores iniciais são
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

Inicialização

   int a[] = {1, 2, 3, 4, 5};
      // equivalente a declarar a[5]

Cuidados com efeitos colaterais

Qual o problema?

i = 0;
while (i < N)
   a[i] = b[i++];

Cuidados com efeitos colaterais

Evitamos o problema separando o incremento da indexação.

i = 0;
while (i < N) {
    a[i] = b[i];
    i++;
}

Em alternativa podemos usar um ciclo for:

for (i = 0; i < N; i++)
    a[i] = b[i];

Exemplo: escrever dígitos binários

Exemplos

Decimal Binário
2 10
6 110
16 10000
20 10100
64 1000000

Ideia do algoritmo

Variáveis

n o inteiro positivo dado
bit[] variável indexada para guardar algarismos binários (bits)
size número de bits usados (0, 1, 2, … etc)

#include <stdio.h>
#define NUM_BITS 32  // número máximo de bits

int main(void) {
  unsigned n, size, bit[NUM_BITS] = {0};
  scanf("%u", &n);  // inteiro sem sinal
  /* obter os algarismos binários */
  size = 0;
  while (n > 0) {
    bit[size++] = n%2;
    n = n/2;
  }
  /* imprimir por ordem contrária */
  while(size > 0) {
    printf("%u", bit[--size]);
  }
  putchar('\n'); // terminar a linha
} 

Observações

Funções e variáveis indexadas

Argumentos de funções

   int fun(int a[]) {
      //  tamanho de a[] não especificado
      ...
   }

Exemplo: somar valores

   int somar_vec(int a[], unsigned size) {
      int i, soma = 0;
      for (i = 0; i < size; i++)
          soma += a[i];
      return soma;
   }

Usar somar_vec

Para usar esta função devemos passar dois argumentos:

    int v[100];
    ...
    s = somar_vec(v, 100);
    // somar todos os valores:

NB: na chamada passamos apenas o nome da variável (sem parêntesis rectos)

Usar somar_vec

Também podemos usar somar_vec para somar apenas um segmento inicial:

    int v[100];
    // ...
    s = somar_vec(v, 50);
    // somar os primeiros 50 valores

Desta forma podemos:

Modificar variáveis indexadas

void colocar_zeros(int a[], unsigned size) {
    int i;
    for(i = 0; i < size; i++) {
        a[i] = 0;
    }
}

Modificar variáveis indexadas

    int v[100];
    // ...
    colocar_zeros(v, 100);
    // v[0], v[1], ... v[99] são agora 0

Exemplo revisitado

Vamos rever o exemplo de conversão para binário e decompô-lo em duas funções:

compute_bits

obter os algarismos binários usando divisões sucessivas

print_bits

imprimir os algarismos binários por ordem inversa

Vamos começar pela segunda função.

Função print_bits

void print_bits(unsigned b[], unsigned size) {
    while(size > 0) {
        printf("%u", b[--size]);
    }
    putchar('\n');
}

Função compute_bits

int compute_bits(unsigned n, unsigned b[]) {
    unsigned size = 0;
    while(n > 0) {
        b[size++] = n%2;
        n = n/2;
    }
    return size;
}

Programa principal

#define NUM_BITS 32
...

int main(void) {
    unsigned n, size, bit[NUM_BITS];

    scanf("%d", &n);
      // ler um inteiro; deve ser positivo
    size = compute_bits(n, bit);
      // preencher "array" com algarismos de n
      // valor retornado é o número de bits
    print_bits(bit, size);
      // imprimir algarismos 
}

Pesquisa sequencial

Dados:

Queremos:

Pesquisa sequencial (2)

int ocorre(int vec[], int size, int val) {
    for(int i = 0; i < size; i++) {
       if(vec[i] == val)
           return 1; // encontrou
    }
    return 0;    // não encontrou
}

Alternativa

Pesquisa sequencial (alternativa)

int pesquisa(int vec[], int size, int val) {
    for(int i = 0; i < size; i++) {
       if(vec[i] == val)
           return i; // encontrou
    }
    return -1;    // não encontrou
}

Eliminar repetidos

Dado: uma variável indexada vec de inteiros

Queremos:

Exemplos:

{2, 3, 4}          ->  {2, 3, 4}
{2, 3, 2, 2, 4, 2} ->  {2, 3, 4}
{4, 3, 2, 2, 4}    ->  {4, 3, 2}
{3, 3, 3}          ->  {3}

Eliminar repetidos (2)

Eliminar repetidos (3)

Vamos definir uma função

   int elimrep(int vec[], int size);

cujo resultado será o número \(k\) de valores distintos na variável indexada vec.

Além disso, modificamos vec:

Eliminar repetidos (3)

Exemplo

int a[7] = {2, 3, 3, 2, 4, 3, 5};
k = elimrep(a, 7);
// a[] :  {2, 3, 4, 5, 4, 3, 5}
// k   :  4

Eliminar repetidos (4)

Variáveis

vec

variável indexada para eliminar repetidos

size

tamanho de vec (número de valores)

i

índice do próximo valor (possívelmente repetido)

k

número de valores diferentes já encontrados

Eliminar repetidos (5)

int elimrep(int vec[], int size) {
   int i, k = 0;
   // i: índice do próximo valor 
   // k: número de valores distintos
   for(i = 0; i < size; i++) {
      int val = vec[i];
      if(!ocorre(vec, k, val)) {
           // encontramos um novo valor
           // distinto dos anteriores
         vec[k++] = val;
      }
   }
   return k;
}

Invariantes

\[ \scriptsize \overbrace{\begin{array}{|c|c|c|} \hline \texttt{v[0]} & \cdots & \texttt{v[k-1]} \\ \hline \end{array}}^{\text{sem repetidos}} \overbrace{\begin{array}{|c|c|c|c|c|} \hline \texttt{v[k]} & \cdots &\texttt{v[i]}&\cdots & \texttt{v[size-1]} \\ \hline \end{array}}^{\text{?}} \]

  1. A sequência \(\texttt{vec[0]}, \ldots, \texttt{vec[k-1]}\) não tem repetidos
  2. O conjunto \[ \{\texttt{vec[0]}, \ldots, \texttt{vec[i-1]}\} \] é igual a \[ \{\texttt{vec[0]}, \ldots, \texttt{vec[k-1]}\} \]