pi tp 5
1. Verificação de Vogais
Existem várias formas de verificar se um caráter é uma vogal. A eficiência depende de como queres tratar maiúsculas e minúsculas.
Estratégia por Procura
int eVogal (char c){
char vogais[11] = "AaEeIiOoUu";
int i = 0;
while (c != vogais[i] && vogais[i] != '\0')
i ++;
return (i < 10);
}Estratégia por Conversão (Mais eficiente)
Esta versão converte temporariamente o caráter para maiúsculas antes de comparar.
int eVogal2(char c){
if (c >= 'a' && c <= 'z') c = c + 'A' - 'a';
return (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U');
}2. Remover Vogais de uma String
Aqui comparamos duas técnicas: usar um buffer auxiliar vs. fazer a alteração in-place (no próprio local).
Com Buffer Auxiliar (Mais simples)
int retiraVogais (char s[]){
char r[strlen(s) + 1];
int i, c = 0;
for (i = 0; s[i] != '\0'; i ++){
if (!eVogal(s[i])) r[c++] = s[i];
}
r[c] = '\0';
strcopy(s, r);
return c;
}In-place (Mais eficiente em memória)
Esta técnica usa dois índices (i e j) que percorrem a string simultaneamente.
int retiraVogais2(char s[]){
int i, j = 0;
for (i = 0; s[i] != '\0'; i++)
if (! eVogal(s[i])) s[j++] = s[i];
s[j] = '\0';
return j;
}3. Duplicar Vogais
Este exercício é o oposto do anterior: a string vai crescer. Se tentarmos fazer isto in-place sem cuidado, vamos escrever por cima de caracteres que ainda não lemos.
int dupVogais(char s[]){
int i, j = 0, conta;
for(i = 0; s[i] = '\0'; i ++){
if(eVogal(s[i])){ conta ++;
for(j = strlen(s) + 1; j != i; j --)
s[j + 1] = s[j];
s[i + 1] = s[i];
}
}
return conta;
}Estratégia de Duas Passagens
int dupVogais2(char[s]){
int i, l;
// 1ª Passagem: Calcular o novo tamanho necessário
for (i = l = 0; s[i] != '\0'; i ++; l ++)
if (eVogal(s[i])) l ++;
char r[l + 1]; // Buffer com o tamanho exato
int j = 0;
// 2ª Passagem: Preencher o buffer duplicando onde necessário
for (i = l = 0; s[i] != '\0'; i ++){
if (eVogal(s[i])){
r[j++] = s[i];
r[j++] = s[i];
} else {
r[j++] = s[i];
}
}
r[j] = '\0';
strcopy(s, r);
return j;
}Verificar Ordenação
int ordenado(int v[], int N){
int i;
for(i = 1; i < N; i ++)
if(v[i - 1] > v[i]) return 0; // Se um elemento for maior que o seguinte, não está ordenado return 1;
return 1;
}Fusão de Vetores (Merge)
Este algoritmo é a base do MergeSort. Assume que a e b já estão ordenados e junta-os num vetor r.
void merge(int a[], int na, int b[], int nb, int r[]){
int ia, ib, ir;
for(ia = ib = ir = 0; ia < na && ib < nb; ir ++){
if(a[ia] < b[ib]) r[ir] = a[ia++];
else r[ir] = rb[ib++];
}
for(; ia < na; r[ir++] = a[ia ++]);
for(; ib < nb; r[ir ++] = b[ib ++]);
}O bloco de comparação:
for(ia = ib = ir = 0; ia < na && ib < nb; ir ++){
if(a[ia] < b[ib]) r[ir] = a[ia++];
else r[ir] = rb[ib++];
}pode ser simplificado com o operador ternário:
r[ir] = (a[ia] < b[ib]) ? a[ia ++] : b[ib ++];Partição (Pivô)
Reorganiza o vetor em torno de um valor x. Todos os menores ou iguais a x ficam à esquerda.
int partition(int x, int v[], int N){
r[N];
int i; m = 0; M = N -1;
for(i = 0; i < N; i ++){
if (v[i] <= x) r[m ++] = v[i];
else r[M--] = v[i];
}
for (i = 0; i < N; i++) v[i] = r[i];
return m;
}